summaryrefslogtreecommitdiffstats
path: root/ext4-move-unlocked-dio-protection-from-ext4_alloc_fi.patch
diff options
context:
space:
mode:
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.patch93
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
+