summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@zip.com.au>2002-05-05 01:10:05 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-05-05 01:10:05 -0700
commitd028eab535bd8c1597391fd850f93501ff06f044 (patch)
tree81b28667207a23421f81881948d71cfc85c96fef
parent49c7cfe7dcd6c6a31b8ed3a82f6d947013b8cdf6 (diff)
[PATCH] Fix SMP race in truncate
Closes a small race window: testing PageWriteback() outside the page lock introduces the possibility that page could be redirtied and have writeback started after we've inspected PageWriteback.
-rw-r--r--mm/filemap.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index c61488b41864..9c5002f1e2d5 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -201,18 +201,18 @@ static int truncate_list_pages(struct address_space *mapping,
int failed;
page_cache_get(page);
- if (PageWriteback(page)) {
- /*
- * urgggh. This function is utterly foul,
- * and this addition doesn't help. Kill.
- */
+ failed = TestSetPageLocked(page);
+ if (!failed && PageWriteback(page)) {
+ unlock_page(page);
+ list_del(head);
+ list_add_tail(head, curr);
write_unlock(&mapping->page_lock);
wait_on_page_writeback(page);
+ page_cache_release(page);
unlocked = 1;
write_lock(&mapping->page_lock);
goto restart;
}
- failed = TestSetPageLocked(page);
list_del(head);
if (!failed)