aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Monakhov <dmonakhov@openvz.org>2014-11-05 11:52:38 -0500
committerTheodore Ts'o <tytso@mit.edu>2014-11-05 11:52:38 -0500
commit88c6b61ff1cfb4013a3523227d91ad11b2892388 (patch)
tree370f7015b4a53cabc2547a2bb59141cc5219d21a
parent0df1f2487d2f0d04703f142813d53615d62a1da4 (diff)
ext4: move_extent improve bh vanishing success factor
Xiaoguang Wang has reported sporadic EBUSY failures of ext4/302 Unfortunetly there is nothing we can do if some other task holds BH's refenrence. So we must return EBUSY in this case. But we can try kicking the journal to see if the other task releases the bh reference after the commit is complete. Also decrease false positives by properly checking for ENOSPC and retrying the allocation after kicking the journal --- which is done by ext4_should_retry_alloc(). [ Modified by tytso to properly check for ENOSPC. ] Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/ext4/move_extent.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 9f2311bc9c4f..503ea15dc5db 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -273,6 +273,7 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
273 int replaced_count = 0; 273 int replaced_count = 0;
274 int from = data_offset_in_page << orig_inode->i_blkbits; 274 int from = data_offset_in_page << orig_inode->i_blkbits;
275 int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits; 275 int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
276 struct super_block *sb = orig_inode->i_sb;
276 277
277 /* 278 /*
278 * It needs twice the amount of ordinary journal buffers because 279 * It needs twice the amount of ordinary journal buffers because
@@ -405,10 +406,13 @@ unlock_pages:
405 page_cache_release(pagep[1]); 406 page_cache_release(pagep[1]);
406stop_journal: 407stop_journal:
407 ext4_journal_stop(handle); 408 ext4_journal_stop(handle);
409 if (*err == -ENOSPC &&
410 ext4_should_retry_alloc(sb, &retries))
411 goto again;
408 /* Buffer was busy because probably is pinned to journal transaction, 412 /* Buffer was busy because probably is pinned to journal transaction,
409 * force transaction commit may help to free it. */ 413 * force transaction commit may help to free it. */
410 if (*err == -EBUSY && ext4_should_retry_alloc(orig_inode->i_sb, 414 if (*err == -EBUSY && retries++ < 4 && EXT4_SB(sb)->s_journal &&
411 &retries)) 415 jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal))
412 goto again; 416 goto again;
413 return replaced_count; 417 return replaced_count;
414 418