diff options
| author | Andrew Morton <akpm@zip.com.au> | 2002-07-04 08:31:56 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-07-04 08:31:56 -0700 |
| commit | ea66b69c3ec03a6762c0949af67123d8a278f49d (patch) | |
| tree | ed3bb16144de5a0ff2fe93eac9239304d9ef5786 /mm | |
| parent | 8b00e4fac18298dce49b78d25c5ea2399aeb6fa2 (diff) | |
[PATCH] fix invalidate_inode_pages2() race
Fix a buglet in invalidate_list_pages2(): there is a small window in
which writeback could start against the page before this function locks
it.
The patch closes the race by performing the PageWriteback test inside
PageLocked.
Testing PageWriteback inside PageLocked is "definitive" - when a page
is locked, writeback cannot start against it.
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/filemap.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index bcbe3e71e0ef..319392662ab5 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -367,16 +367,18 @@ static int invalidate_list_pages2(struct address_space * mapping, while (curr != head) { page = list_entry(curr, struct page, list); - if (PageWriteback(page)) { - write_unlock(&mapping->page_lock); - wait_on_page_writeback(page); - unlocked = 1; - write_lock(&mapping->page_lock); - goto restart; - } if (!TestSetPageLocked(page)) { int __unlocked; + if (PageWriteback(page)) { + write_unlock(&mapping->page_lock); + wait_on_page_writeback(page); + unlocked = 1; + write_lock(&mapping->page_lock); + unlock_page(page); + goto restart; + } + __unlocked = invalidate_this_page2(mapping, page, curr, head); unlock_page(page); unlocked |= __unlocked; |
