summaryrefslogtreecommitdiff
path: root/fs/buffer.c
diff options
context:
space:
mode:
authorAndrew Morton <akpm@zip.com.au>2002-05-05 01:09:45 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-05-05 01:09:45 -0700
commit21bd2dfd804ff4a4cc0e55d846a5633a3e22c97d (patch)
tree9be490a4468689947302a692205d9ceba5374b38 /fs/buffer.c
parent6c8dd3365680e292d2cfbb435e02dae667fb31df (diff)
[PATCH] decouple swapper_space treatment from other address_spaces
swapper_space is different. Its pages are locked during writeout, it uses PAGE_SIZE rather than PAGE_CACHE_SIZE. Converting swap to look more like the other address_spaces is a separate project. This patch fully restores the old swap behaviour. - Don't dirty swapcache page buffers in set_page_dirty(). Fixes a problem where __free_pte() runs set_page_dirty() and then immediately runs ClearPageDirty(). The pages ends up clean, with dirty buffers, and is unfreeable. - Hence, don't mark the page clean if its buffers are clean - swap does not have page/buffers dirty state coherency.
Diffstat (limited to 'fs/buffer.c')
-rw-r--r--fs/buffer.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index 74674c70dc04..8db1bd8f0b84 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2159,14 +2159,6 @@ static void check_ttfb_buffer(struct page *page, struct buffer_head *bh)
* total exclusion from __set_page_dirty_buffers(). That is obtained with
* i_bufferlist_lock.
*
- * Nobody should be calling try_to_free_buffers against a page which is
- * eligible for set_page_dirty() treatment anyway - the page is clearly
- * not freeable. So we could just test page_count(page) here and complain
- * then scram if it's wrong.
- *
- * If any buffer is not uptodate then the entire page is set not uptodate,
- * as the partial uptodateness information is about to be lost.
- *
* try_to_free_buffers() is non-blocking.
*/
static inline int buffer_busy(struct buffer_head *bh)
@@ -2222,8 +2214,17 @@ int try_to_free_buffers(struct page *page)
inode = page->mapping->host;
spin_lock(&inode->i_bufferlist_lock);
ret = drop_buffers(page);
- if (ret)
+ if (ret && !PageSwapCache(page)) {
+ /*
+ * If the filesystem writes its buffers by hand (eg ext3)
+ * then we can have clean buffers against a dirty page. We
+ * clean the page here; otherwise later reattachment of buffers
+ * could encounter a non-uptodate page, which is unresolvable.
+ * This only applies in the rare case where try_to_free_buffers
+ * succeeds but the page is not freed.
+ */
ClearPageDirty(page);
+ }
spin_unlock(&inode->i_bufferlist_lock);
return ret;
}