diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2008-01-28 23:58:26 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-01-28 23:58:26 -0500 |
commit | 0e855ac8b103ef579052936b59fe7c599ac422a4 (patch) | |
tree | ec29f82e1d7bb1987dcadc00497daf69d6955483 /fs/ext4/inode.c | |
parent | c278bfecebfb1ed67c326ef472660878baa745cd (diff) |
ext4: Convert truncate_mutex to read write semaphore.
We are currently taking the truncate_mutex for every read. This would have
performance impact on large CPU configuration. Convert the lock to read write
semaphore and take read lock when we are trying to read the file.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 40 |
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 | */ |
350 | static Indirect *ext4_get_branch(struct inode *inode, int depth, | 350 | static 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 | */ |
782 | int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, | 783 | int 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 | ||
899 | int 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 | |||
898 | static int ext4_get_block(struct inode *inode, sector_t iblock, | 924 | static 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 | ||