aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2008-01-28 23:58:26 -0500
committerTheodore Ts'o <tytso@mit.edu>2008-01-28 23:58:26 -0500
commit0e855ac8b103ef579052936b59fe7c599ac422a4 (patch)
treeec29f82e1d7bb1987dcadc00497daf69d6955483 /fs/ext4/inode.c
parentc278bfecebfb1ed67c326ef472660878baa745cd (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.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