diff options
| author | Andrew Morton <akpm@zip.com.au> | 2002-05-05 01:09:45 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-05-05 01:09:45 -0700 |
| commit | 21bd2dfd804ff4a4cc0e55d846a5633a3e22c97d (patch) | |
| tree | 9be490a4468689947302a692205d9ceba5374b38 /fs/buffer.c | |
| parent | 6c8dd3365680e292d2cfbb435e02dae667fb31df (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.c | 19 |
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; } |
