diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-05-22 08:00:42 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-05-22 08:00:42 -0700 |
| commit | d61ae266b334dfdd64697d4d5b5df9e3440666d8 (patch) | |
| tree | bcbb1dd3670e96e1ac1922d95263962ce3d9af01 /include/linux | |
| parent | e6dfd92e48a0d3d2738e30dc762233d85ac98612 (diff) | |
[PATCH] __set_page_dirty_nobuffers race fix
Running __mark_inode_dirty() against a swapcache page is illegal and will
oops.
I see a race in set_page_dirty() wherein it can be called with a PageSwapCache
page, but if the page is removed from swapcache after
__set_page_dirty_nobuffers() drops tree_lock(), we have the situation where
PageSwapCache() is false, but local variable `mapping' points at swapcache.
Handle that by checking for non-null mapping->host. We don't care about the
page state at this point - we're only interested in the inode.
There is a converse case: what if a page is added to swapcache as we are
running set_page_dirty() against it?
In this case the page gets its PG_dirty flag set but it is not tagged as dirty
in the swapper_space radix tree. The swap writeout code will handle this OK
and test_clear_page_dirty()'s call to
radix_tree_tag_clear(PAGECACHE_TAG_DIRTY) will silently have no effect. The
only downside is that future radix-tree-based writearound won't notice that
such pages are dirty and swap IO scheduling will be a teensy bit worse.
The patch also fixes the (silly) testing of local variable `mapping' to see if
the page was truncated. We should test page_mapping() for that.
Diffstat (limited to 'include/linux')
0 files changed, 0 insertions, 0 deletions
