From: Hisashi Hifumi DIO invalidates page cache through invalidate_inode_pages2_range(). invalidate_inode_pages2_range() sets ret=-EIO when invalidate_complete_page2() fails, but this ret is cleared if do_launder_page() succeed on a page of next index. In this case, dio is carried out even if invalidate_complete_page2() fails on some pages. This can cause inconsistency between memory and blocks on HDD because the page cache still exists. Signed-off-by: Hisashi Hifumi Cc: Badari Pulavarty Cc: Ken Chen Cc: Zach Brown Cc: Nick Piggin Cc: Trond Myklebust Cc: "J. Bruce Fields" Cc: Chuck Lever Signed-off-by: Andrew Morton --- mm/truncate.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff -puN mm/truncate.c~fix-invalidate_inode_pages2_range-to-not-clear-ret mm/truncate.c --- a/mm/truncate.c~fix-invalidate_inode_pages2_range-to-not-clear-ret +++ a/mm/truncate.c @@ -391,6 +391,7 @@ int invalidate_inode_pages2_range(struct pgoff_t next; int i; int ret = 0; + int ret2 = 0; int did_range_unmap = 0; int wrapped = 0; @@ -438,9 +439,11 @@ int invalidate_inode_pages2_range(struct } } BUG_ON(page_mapped(page)); - ret = do_launder_page(mapping, page); - if (ret == 0 && !invalidate_complete_page2(mapping, page)) - ret = -EIO; + ret2 = do_launder_page(mapping, page); + if (ret2 == 0 && !invalidate_complete_page2(mapping, page)) + ret2 = -EIO; + if (ret2 < 0) + ret = ret2; unlock_page(page); } pagevec_release(&pvec); _