In hard core test-cases such as ext4/301, ext4/302 some bh may becomes dirty so try_to_release_page() will fail and result in false positive EBUSY failures. We can easily fix that by explicit ->invalidatepage() after we holds page which is locked and uptodate. Tested-by: Xiaoguang Wang<wangxg.fnst@xxxxxxxxxxxxxx> Signed-off-by: Dmitry Monakhov <dmonakhov@xxxxxxxxxx> --- fs/ext4/move_extent.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index c2b2b02..76c45b6 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -348,8 +348,9 @@ again: !try_to_release_page(pagep[0], 0)) || (page_has_private(pagep[1]) && !try_to_release_page(pagep[1], 0))) { - *err = -EBUSY; - goto drop_data_sem; + /* One of buffers is busy, fall back data copy */ + ext4_double_up_write_data_sem(orig_inode, donor_inode); + goto data_copy; } replaced_count = ext4_swap_extents(handle, orig_inode, donor_inode, orig_blk_offset, @@ -360,12 +361,15 @@ again: goto unlock_pages; } data_copy: - *err = mext_page_mkuptodate(pagep[0], from, from + replaced_size); + /* In order to drop all buffers we have to make page fully uptodate */ + *err = mext_page_mkuptodate(pagep[0], 0, PAGE_CACHE_SIZE); if (*err) goto unlock_pages; /* At this point all buffers in range are uptodate, old mapping layout * is no longer required, try to drop it now. */ + do_invalidatepage(pagep[0], 0, PAGE_CACHE_SIZE); + do_invalidatepage(pagep[1], 0, PAGE_CACHE_SIZE); if ((page_has_private(pagep[0]) && !try_to_release_page(pagep[0], 0)) || (page_has_private(pagep[1]) && !try_to_release_page(pagep[1], 0))) { *err = -EBUSY; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html