Skip to content

Commit

Permalink
[S390] page_mkclean data corruption.
Browse files Browse the repository at this point in the history
The git commit c2fda5f which
added the page_test_and_clear_dirty call to page_mkclean and the
git commit 7658cc2 which fixes
the "nasty and subtle race in shared mmap'ed page writeback"
problem in clear_page_dirty_for_io cause data corruption on s390.

The effect of the two changes is that for every call to
clear_page_dirty_for_io a page_test_and_clear_dirty is done. If
the per page dirty bit is set set_page_dirty is called. Strangly
clear_page_dirty_for_io is called for not-uptodate pages, e.g.
over this call-chain:

 [<000000000007c0f2>] clear_page_dirty_for_io+0x12a/0x130
 [<000000000007c494>] generic_writepages+0x258/0x3e0
 [<000000000007c692>] do_writepages+0x76/0x7c
 [<00000000000c7a26>] __writeback_single_inode+0xba/0x3e4
 [<00000000000c831a>] sync_sb_inodes+0x23e/0x398
 [<00000000000c8802>] writeback_inodes+0x12e/0x140
 [<000000000007b9ee>] wb_kupdate+0xd2/0x178
 [<000000000007cca2>] pdflush+0x162/0x23c

The bad news now is that page_test_and_clear_dirty might claim
that a not-uptodate page is dirty since SetPageUptodate which
resets the per page dirty bit has not yet been called. The page
writeback that follows clobbers the data on disk.

The simplest solution to this problem is to move the call to
page_test_and_clear_dirty under the "if (page_mapped(page))".
If a file backed page is mapped it is uptodate.

Signed-off-by: Martin Schwidefsky <[email protected]>
  • Loading branch information
Martin Schwidefsky committed Apr 4, 2007
1 parent 348e3fd commit 6e1beb3
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions mm/rmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,9 @@ int page_mkclean(struct page *page)
struct address_space *mapping = page_mapping(page);
if (mapping)
ret = page_mkclean_file(mapping, page);
if (page_test_and_clear_dirty(page))
ret = 1;
}
if (page_test_and_clear_dirty(page))
ret = 1;

return ret;
}
Expand Down

0 comments on commit 6e1beb3

Please sign in to comment.