diff options
author | Mingming Cao <cmm@us.ibm.com> | 2008-07-12 01:27:31 +0200 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-07-12 01:27:31 +0200 |
commit | 61628a3f3a37af2bf25daf8e26fd6b76a78c4f76 (patch) | |
tree | 25375b739b2e3f65c8dff3d3dd2a78e0724d0f96 /fs/ext4/extents.c | |
parent | mm: Add range_cont mode for writeback (diff) | |
download | linux-61628a3f3a37af2bf25daf8e26fd6b76a78c4f76.tar.xz linux-61628a3f3a37af2bf25daf8e26fd6b76a78c4f76.zip |
ext4: Invert lock ordering of page_lock and transaction start in delalloc
With the reverse locking, we need to start a transation before taking
the page lock, so in ext4_da_writepages() we need to break the write-out
into chunks, and restart the journal for each chunck to ensure the
write-out fits in a single transaction.
Updated patch from Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
which fixes delalloc sync hang with journal lock inversion, and address
the performance regression issue.
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index dabc3b68d249..42c4c0c892ed 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2565,6 +2565,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, int err = 0, depth, ret; unsigned long allocated = 0; struct ext4_allocation_request ar; + loff_t disksize; __clear_bit(BH_New, &bh_result->b_state); ext_debug("blocks %u/%lu requested for inode %u\n", @@ -2755,8 +2756,13 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, newblock = ext_pblock(&newex); allocated = ext4_ext_get_actual_len(&newex); outnew: - if (extend_disksize && inode->i_size > EXT4_I(inode)->i_disksize) - EXT4_I(inode)->i_disksize = inode->i_size; + if (extend_disksize) { + disksize = ((loff_t) iblock + ar.len) << inode->i_blkbits; + if (disksize > i_size_read(inode)) + disksize = i_size_read(inode); + if (disksize > EXT4_I(inode)->i_disksize) + EXT4_I(inode)->i_disksize = disksize; + } set_buffer_new(bh_result); |