aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 71c7ad0c6723..a7eb8bb4bdd4 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -308,7 +308,7 @@ static int ext4_block_to_path(struct inode *inode,
308 final = ptrs; 308 final = ptrs;
309 } else { 309 } else {
310 ext4_warning(inode->i_sb, "ext4_block_to_path", 310 ext4_warning(inode->i_sb, "ext4_block_to_path",
311 "block %u > max", 311 "block %lu > max",
312 i_block + direct_blocks + 312 i_block + direct_blocks +
313 indirect_blocks + double_blocks); 313 indirect_blocks + double_blocks);
314 } 314 }
@@ -345,7 +345,7 @@ static int ext4_block_to_path(struct inode *inode,
345 * the whole chain, all way to the data (returns %NULL, *err == 0). 345 * the whole chain, all way to the data (returns %NULL, *err == 0).
346 * 346 *
347 * Need to be called with 347 * Need to be called with
348 * mutex_lock(&EXT4_I(inode)->truncate_mutex) 348 * down_read(&EXT4_I(inode)->i_data_sem)
349 */ 349 */
350static Indirect *ext4_get_branch(struct inode *inode, int depth, 350static Indirect *ext4_get_branch(struct inode *inode, int depth,
351 ext4_lblk_t *offsets, 351 ext4_lblk_t *offsets,
@@ -777,7 +777,8 @@ err_out:
777 * 777 *
778 * 778 *
779 * Need to be called with 779 * Need to be called with
780 * mutex_lock(&EXT4_I(inode)->truncate_mutex) 780 * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system block
781 * (ie, create is zero). Otherwise down_write(&EXT4_I(inode)->i_data_sem)
781 */ 782 */
782int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, 783int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
783 ext4_lblk_t iblock, unsigned long maxblocks, 784 ext4_lblk_t iblock, unsigned long maxblocks,
@@ -865,7 +866,7 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
865 err = ext4_splice_branch(handle, inode, iblock, 866 err = ext4_splice_branch(handle, inode, iblock,
866 partial, indirect_blks, count); 867 partial, indirect_blks, count);
867 /* 868 /*
868 * i_disksize growing is protected by truncate_mutex. Don't forget to 869 * i_disksize growing is protected by i_data_sem. Don't forget to
869 * protect it if you're about to implement concurrent 870 * protect it if you're about to implement concurrent
870 * ext4_get_block() -bzzz 871 * ext4_get_block() -bzzz
871 */ 872 */
@@ -895,6 +896,31 @@ out:
895 896
896#define DIO_CREDITS (EXT4_RESERVE_TRANS_BLOCKS + 32) 897#define DIO_CREDITS (EXT4_RESERVE_TRANS_BLOCKS + 32)
897 898
899int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
900 unsigned long max_blocks, struct buffer_head *bh,
901 int create, int extend_disksize)
902{
903 int retval;
904 if (create) {
905 down_write((&EXT4_I(inode)->i_data_sem));
906 } else {
907 down_read((&EXT4_I(inode)->i_data_sem));
908 }
909 if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
910 retval = ext4_ext_get_blocks(handle, inode, block, max_blocks,
911 bh, create, extend_disksize);
912 } else {
913 retval = ext4_get_blocks_handle(handle, inode, block,
914 max_blocks, bh, create, extend_disksize);
915 }
916 if (create) {
917 up_write((&EXT4_I(inode)->i_data_sem));
918 } else {
919 up_read((&EXT4_I(inode)->i_data_sem));
920 }
921 return retval;
922}
923
898static int ext4_get_block(struct inode *inode, sector_t iblock, 924static int ext4_get_block(struct inode *inode, sector_t iblock,
899 struct buffer_head *bh_result, int create) 925 struct buffer_head *bh_result, int create)
900{ 926{
@@ -1399,7 +1425,7 @@ static int jbd2_journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)
1399 * ext4_file_write() -> generic_file_write() -> __alloc_pages() -> ... 1425 * ext4_file_write() -> generic_file_write() -> __alloc_pages() -> ...
1400 * 1426 *
1401 * Same applies to ext4_get_block(). We will deadlock on various things like 1427 * Same applies to ext4_get_block(). We will deadlock on various things like
1402 * lock_journal and i_truncate_mutex. 1428 * lock_journal and i_data_sem
1403 * 1429 *
1404 * Setting PF_MEMALLOC here doesn't work - too many internal memory 1430 * Setting PF_MEMALLOC here doesn't work - too many internal memory
1405 * allocations fail. 1431 * allocations fail.
@@ -2325,7 +2351,7 @@ void ext4_truncate(struct inode *inode)
2325 * From here we block out all ext4_get_block() callers who want to 2351 * From here we block out all ext4_get_block() callers who want to
2326 * modify the block allocation tree. 2352 * modify the block allocation tree.
2327 */ 2353 */
2328 mutex_lock(&ei->truncate_mutex); 2354 down_write(&ei->i_data_sem);
2329 2355
2330 if (n == 1) { /* direct blocks */ 2356 if (n == 1) { /* direct blocks */
2331 ext4_free_data(handle, inode, NULL, i_data+offsets[0], 2357 ext4_free_data(handle, inode, NULL, i_data+offsets[0],
@@ -2389,7 +2415,7 @@ do_indirects:
2389 2415
2390 ext4_discard_reservation(inode); 2416 ext4_discard_reservation(inode);
2391 2417
2392 mutex_unlock(&ei->truncate_mutex); 2418 up_write(&ei->i_data_sem);
2393 inode->i_mtime = inode->i_ctime = ext4_current_time(inode); 2419 inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
2394 ext4_mark_inode_dirty(handle, inode); 2420 ext4_mark_inode_dirty(handle, inode);
2395 2421