Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 45814
b: refs/heads/master
c: ecdfc97
h: refs/heads/master
v: v3
  • Loading branch information
Linus Torvalds committed Jan 26, 2007
1 parent d5a79c8 commit 56a5549
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5ad0d383ddbf0d2fce43b8aac267a6c299fd2dff
refs/heads/master: ecdfc9787fe527491baefc22dce8b2dbd5b2908d
15 changes: 14 additions & 1 deletion trunk/fs/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2834,7 +2834,7 @@ int try_to_free_buffers(struct page *page)
int ret = 0;

BUG_ON(!PageLocked(page));
if (PageDirty(page) || PageWriteback(page))
if (PageWriteback(page))
return 0;

if (mapping == NULL) { /* can this still happen? */
Expand All @@ -2845,6 +2845,19 @@ int try_to_free_buffers(struct page *page)
spin_lock(&mapping->private_lock);
ret = drop_buffers(page, &buffers_to_free);
spin_unlock(&mapping->private_lock);

/*
* 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 the VM will never notice
* that the filesystem did any IO at all.
*
* Also, during truncate, discard_buffer will have marked all
* the page's buffers clean. We discover that here and clean
* the page also.
*/
if (ret)
cancel_dirty_page(page, PAGE_CACHE_SIZE);
out:
if (buffers_to_free) {
struct buffer_head *bh = buffers_to_free;
Expand Down
21 changes: 14 additions & 7 deletions trunk/mm/truncate.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,22 @@ static inline void truncate_partial_page(struct page *page, unsigned partial)
do_invalidatepage(page, partial);
}

/*
* This cancels just the dirty bit on the kernel page itself, it
* does NOT actually remove dirty bits on any mmap's that may be
* around. It also leaves the page tagged dirty, so any sync
* activity will still find it on the dirty lists, and in particular,
* clear_page_dirty_for_io() will still look at the dirty bits in
* the VM.
*
* Doing this should *normally* only ever be done when a page
* is truncated, and is not actually mapped anywhere at all. However,
* fs/buffer.c does this when it notices that somebody has cleaned
* out all the buffers on a page without actually doing it through
* the VM. Can you say "ext3 is horribly ugly"? Tought you could.
*/
void cancel_dirty_page(struct page *page, unsigned int account_size)
{
/* If we're cancelling the page, it had better not be mapped any more */
if (page_mapped(page)) {
static unsigned int warncount;

WARN_ON(++warncount < 5);
}

if (TestClearPageDirty(page)) {
struct address_space *mapping = page->mapping;
if (mapping && mapping_cap_account_dirty(mapping)) {
Expand Down

0 comments on commit 56a5549

Please sign in to comment.