diff options
Diffstat (limited to 'ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch')
-rw-r--r-- | ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch b/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch new file mode 100644 index 000000000..3bf6765fa --- /dev/null +++ b/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch @@ -0,0 +1,93 @@ +From 17048e8a083fec7ad841d88ef0812707fbc7e39f Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.com> +Date: Mon, 7 Dec 2015 14:29:17 -0500 +Subject: [PATCH 2/4] ext4: move unlocked dio protection from + ext4_alloc_file_blocks() + +Currently ext4_alloc_file_blocks() was handling protection against +unlocked DIO. However we now need to sometimes call it under i_mmap_sem +and sometimes not and DIO protection ranks above it (although strictly +speaking this cannot currently create any deadlocks). Also +ext4_zero_range() was actually getting & releasing unlocked DIO +protection twice in some cases. Luckily it didn't introduce any real bug +but it was a land mine waiting to be stepped on. So move DIO protection +out from ext4_alloc_file_blocks() into the two callsites. + +Signed-off-by: Jan Kara <jack@suse.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +--- + fs/ext4/extents.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 5be9ca5a8a7a..65b5ada2833f 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4685,10 +4685,6 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset, + if (len <= EXT_UNWRITTEN_MAX_LEN) + flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; + +- /* Wait all existing dio workers, newcomers will block on i_mutex */ +- ext4_inode_block_unlocked_dio(inode); +- inode_dio_wait(inode); +- + /* + * credits to insert 1 extent into extent tree + */ +@@ -4752,8 +4748,6 @@ retry: + goto retry; + } + +- ext4_inode_resume_unlocked_dio(inode); +- + return ret > 0 ? ret2 : ret; + } + +@@ -4827,6 +4821,10 @@ static long ext4_zero_range(struct file *file, loff_t offset, + if (mode & FALLOC_FL_KEEP_SIZE) + flags |= EXT4_GET_BLOCKS_KEEP_SIZE; + ++ /* Wait all existing dio workers, newcomers will block on i_mutex */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); ++ + /* Preallocate the range including the unaligned edges */ + if (partial_begin || partial_end) { + ret = ext4_alloc_file_blocks(file, +@@ -4835,7 +4833,7 @@ static long ext4_zero_range(struct file *file, loff_t offset, + round_down(offset, 1 << blkbits)) >> blkbits, + new_size, flags, mode); + if (ret) +- goto out_mutex; ++ goto out_dio; + + } + +@@ -4844,10 +4842,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, + flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | + EXT4_EX_NOCACHE); + +- /* Wait all existing dio workers, newcomers will block on i_mutex */ +- ext4_inode_block_unlocked_dio(inode); +- inode_dio_wait(inode); +- + /* + * Prevent page faults from reinstantiating pages we have + * released from page cache. +@@ -4992,8 +4986,13 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) + goto out; + } + ++ /* Wait all existing dio workers, newcomers will block on i_mutex */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); ++ + ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, + flags, mode); ++ ext4_inode_resume_unlocked_dio(inode); + if (ret) + goto out; + +-- +2.5.5 + |