aboutsummaryrefslogtreecommitdiffstats
path: root/fs/reiserfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-10-17 02:29:44 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:42:57 -0400
commit398c95bdf2c24d7866692a40ba04425aef238cdd (patch)
treed0c54706f98e8c031453e3bb235ca9be22206fed /fs/reiserfs
parente82ce352335b643755a7fa4130b11d6d7adcf10c (diff)
try to reap reiserfs pages left around by invalidatepage
reiserfs_invalidatepage will refuse to free pages if they have been logged in data=journal mode, or were pinned down by a data=ordered operation. For data=journal, this is fairly easy to trigger just with fsx-linux, and it results in a large number of pages hanging around on the LRUs with page->mapping == NULL. Calling try_to_free_buffers when reiserfs decides it is done with the page allows it to be freed earlier, and with much less VM thrashing. Lock ordering rules mean that reiserfs can't call lock_page when it is releasing the buffers, so TestSetPageLocked is used instead. Contention on these pages should be rare, so it should be sufficient most of the time. Signed-off-by: Chris Mason <chris.mason@oracle.com> Cc: "Vladimir V. Saveliev" <vs@namesys.com> Cc: Jeff Mahoney <jeffm@suse.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/reiserfs')
-rw-r--r--fs/reiserfs/journal.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index ca8d9e86571f..6c1d0c35f9e9 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -615,6 +615,31 @@ static int journal_list_still_alive(struct super_block *s,
615 return 0; 615 return 0;
616} 616}
617 617
618/*
619 * If page->mapping was null, we failed to truncate this page for
620 * some reason. Most likely because it was truncated after being
621 * logged via data=journal.
622 *
623 * This does a check to see if the buffer belongs to one of these
624 * lost pages before doing the final put_bh. If page->mapping was
625 * null, it tries to free buffers on the page, which should make the
626 * final page_cache_release drop the page from the lru.
627 */
628static void release_buffer_page(struct buffer_head *bh)
629{
630 struct page *page = bh->b_page;
631 if (!page->mapping && !TestSetPageLocked(page)) {
632 page_cache_get(page);
633 put_bh(bh);
634 if (!page->mapping)
635 try_to_free_buffers(page);
636 unlock_page(page);
637 page_cache_release(page);
638 } else {
639 put_bh(bh);
640 }
641}
642
618static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate) 643static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
619{ 644{
620 char b[BDEVNAME_SIZE]; 645 char b[BDEVNAME_SIZE];
@@ -628,8 +653,9 @@ static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
628 set_buffer_uptodate(bh); 653 set_buffer_uptodate(bh);
629 else 654 else
630 clear_buffer_uptodate(bh); 655 clear_buffer_uptodate(bh);
656
631 unlock_buffer(bh); 657 unlock_buffer(bh);
632 put_bh(bh); 658 release_buffer_page(bh);
633} 659}
634 660
635static void reiserfs_end_ordered_io(struct buffer_head *bh, int uptodate) 661static void reiserfs_end_ordered_io(struct buffer_head *bh, int uptodate)
@@ -1547,9 +1573,10 @@ static int flush_journal_list(struct super_block *s,
1547 BUG_ON(!test_clear_buffer_journal_dirty 1573 BUG_ON(!test_clear_buffer_journal_dirty
1548 (cn->bh)); 1574 (cn->bh));
1549 1575
1550 /* undo the inc from journal_mark_dirty */ 1576 /* drop one ref for us */
1551 put_bh(cn->bh); 1577 put_bh(cn->bh);
1552 brelse(cn->bh); 1578 /* drop one ref for journal_mark_dirty */
1579 release_buffer_page(cn->bh);
1553 } 1580 }
1554 cn = cn->next; 1581 cn = cn->next;
1555 } 1582 }
@@ -3709,13 +3736,8 @@ int journal_mark_freed(struct reiserfs_transaction_handle *th,
3709 } 3736 }
3710 } 3737 }
3711 3738
3712 if (bh) { 3739 if (bh)
3713 put_bh(bh); /* get_hash grabs the buffer */ 3740 release_buffer_page(bh); /* get_hash grabs the buffer */
3714 if (atomic_read(&(bh->b_count)) < 0) {
3715 reiserfs_warning(p_s_sb,
3716 "journal-2165: bh->b_count < 0");
3717 }
3718 }
3719 return 0; 3741 return 0;
3720} 3742}
3721 3743