summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.com>2015-12-07 14:29:17 -0500
committerTheodore Ts'o <tytso@mit.edu>2015-12-07 14:29:17 -0500
commit17048e8a083fec7ad841d88ef0812707fbc7e39f (patch)
treea5f6ac206edfbe5807e6f9834d6dfe663e9b31c6
parentea3d7209ca01da209cda6f0dea8be9cc4b7a933b (diff)
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>
-rw-r--r--fs/ext4/extents.c21
1 files 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,
4685 if (len <= EXT_UNWRITTEN_MAX_LEN) 4685 if (len <= EXT_UNWRITTEN_MAX_LEN)
4686 flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; 4686 flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
4687 4687
4688 /* Wait all existing dio workers, newcomers will block on i_mutex */
4689 ext4_inode_block_unlocked_dio(inode);
4690 inode_dio_wait(inode);
4691
4692 /* 4688 /*
4693 * credits to insert 1 extent into extent tree 4689 * credits to insert 1 extent into extent tree
4694 */ 4690 */
@@ -4752,8 +4748,6 @@ retry:
4752 goto retry; 4748 goto retry;
4753 } 4749 }
4754 4750
4755 ext4_inode_resume_unlocked_dio(inode);
4756
4757 return ret > 0 ? ret2 : ret; 4751 return ret > 0 ? ret2 : ret;
4758} 4752}
4759 4753
@@ -4827,6 +4821,10 @@ static long ext4_zero_range(struct file *file, loff_t offset,
4827 if (mode & FALLOC_FL_KEEP_SIZE) 4821 if (mode & FALLOC_FL_KEEP_SIZE)
4828 flags |= EXT4_GET_BLOCKS_KEEP_SIZE; 4822 flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
4829 4823
4824 /* Wait all existing dio workers, newcomers will block on i_mutex */
4825 ext4_inode_block_unlocked_dio(inode);
4826 inode_dio_wait(inode);
4827
4830 /* Preallocate the range including the unaligned edges */ 4828 /* Preallocate the range including the unaligned edges */
4831 if (partial_begin || partial_end) { 4829 if (partial_begin || partial_end) {
4832 ret = ext4_alloc_file_blocks(file, 4830 ret = ext4_alloc_file_blocks(file,
@@ -4835,7 +4833,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
4835 round_down(offset, 1 << blkbits)) >> blkbits, 4833 round_down(offset, 1 << blkbits)) >> blkbits,
4836 new_size, flags, mode); 4834 new_size, flags, mode);
4837 if (ret) 4835 if (ret)
4838 goto out_mutex; 4836 goto out_dio;
4839 4837
4840 } 4838 }
4841 4839
@@ -4844,10 +4842,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
4844 flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | 4842 flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN |
4845 EXT4_EX_NOCACHE); 4843 EXT4_EX_NOCACHE);
4846 4844
4847 /* Wait all existing dio workers, newcomers will block on i_mutex */
4848 ext4_inode_block_unlocked_dio(inode);
4849 inode_dio_wait(inode);
4850
4851 /* 4845 /*
4852 * Prevent page faults from reinstantiating pages we have 4846 * Prevent page faults from reinstantiating pages we have
4853 * released from page cache. 4847 * released from page cache.
@@ -4992,8 +4986,13 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
4992 goto out; 4986 goto out;
4993 } 4987 }
4994 4988
4989 /* Wait all existing dio workers, newcomers will block on i_mutex */
4990 ext4_inode_block_unlocked_dio(inode);
4991 inode_dio_wait(inode);
4992
4995 ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, 4993 ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
4996 flags, mode); 4994 flags, mode);
4995 ext4_inode_resume_unlocked_dio(inode);
4997 if (ret) 4996 if (ret)
4998 goto out; 4997 goto out;
4999 4998