1 ext4: move_extent improve bh vanishing success factor
3 From: Dmitry Monakhov <dmonakhov@openvz.org>
5 Xiaoguang Wang has reported sporadic EBUSY failures of ext4/302
6 Unfortunetly there is nothing we can do if some other task holds BH's
7 refenrence. So we must return EBUSY in this case. But we can try
8 kicking the journal to see if the other task releases the bh reference
9 after the commit is complete. Also decrease false positives by
10 properly checking for ENOSPC and retrying the allocation after kicking
11 the journal --- which is done by ext4_should_retry_alloc().
13 [ Modified by tytso to properly check for ENOSPC. ]
15 Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
16 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
18 fs/ext4/move_extent.c | 8 ++++++--
19 1 file changed, 6 insertions(+), 2 deletions(-)
21 diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
22 index 9f2311b..503ea15 100644
23 --- a/fs/ext4/move_extent.c
24 +++ b/fs/ext4/move_extent.c
25 @@ -273,6 +273,7 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
26 int replaced_count = 0;
27 int from = data_offset_in_page << orig_inode->i_blkbits;
28 int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
29 + struct super_block *sb = orig_inode->i_sb;
32 * It needs twice the amount of ordinary journal buffers because
33 @@ -405,10 +406,13 @@ unlock_pages:
34 page_cache_release(pagep[1]);
36 ext4_journal_stop(handle);
37 + if (*err == -ENOSPC &&
38 + ext4_should_retry_alloc(sb, &retries))
40 /* Buffer was busy because probably is pinned to journal transaction,
41 * force transaction commit may help to free it. */
42 - if (*err == -EBUSY && ext4_should_retry_alloc(orig_inode->i_sb,
44 + if (*err == -EBUSY && retries++ < 4 && EXT4_SB(sb)->s_journal &&
45 + jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal))
47 return replaced_count;