aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_address.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r--fs/gfs2/ops_address.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 8407d1db4eac..dd1ea491ddcb 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -616,13 +616,50 @@ static sector_t gfs2_bmap(struct address_space *mapping, sector_t lblock)
616 return dblock; 616 return dblock;
617} 617}
618 618
619static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
620{
621 struct gfs2_bufdata *bd;
622
623 lock_buffer(bh);
624 gfs2_log_lock(sdp);
625 clear_buffer_dirty(bh);
626 bd = bh->b_private;
627 if (bd) {
628 if (!list_empty(&bd->bd_le.le_list)) {
629 if (!buffer_pinned(bh))
630 list_del_init(&bd->bd_le.le_list);
631 }
632 }
633 bh->b_bdev = NULL;
634 clear_buffer_mapped(bh);
635 clear_buffer_req(bh);
636 clear_buffer_new(bh);
637 gfs2_log_unlock(sdp);
638 unlock_buffer(bh);
639}
640
619static void gfs2_invalidatepage(struct page *page, unsigned long offset) 641static void gfs2_invalidatepage(struct page *page, unsigned long offset)
620{ 642{
643 struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
644 struct buffer_head *bh, *head;
645 unsigned long pos = 0;
646
621 BUG_ON(!PageLocked(page)); 647 BUG_ON(!PageLocked(page));
622 if (offset == 0) 648 if (offset == 0)
623 ClearPageChecked(page); 649 ClearPageChecked(page);
650 if (!page_has_buffers(page))
651 goto out;
624 652
625 block_invalidatepage(page, offset); 653 bh = head = page_buffers(page);
654 do {
655 if (offset <= pos)
656 gfs2_discard(sdp, bh);
657 pos += bh->b_size;
658 bh = bh->b_this_page;
659 } while (bh != head);
660out:
661 if (offset == 0)
662 try_to_release_page(page, 0);
626} 663}
627 664
628/** 665/**
@@ -732,9 +769,14 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
732 if (bd) { 769 if (bd) {
733 gfs2_assert_warn(sdp, bd->bd_bh == bh); 770 gfs2_assert_warn(sdp, bd->bd_bh == bh);
734 gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr)); 771 gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr));
735 bd->bd_bh = NULL; 772 if (!list_empty(&bd->bd_le.le_list)) {
736 if (!list_empty(&bd->bd_le.le_list)) 773 if (!buffer_pinned(bh))
737 bd = NULL; 774 list_del_init(&bd->bd_le.le_list);
775 else
776 bd = NULL;
777 }
778 if (bd)
779 bd->bd_bh = NULL;
738 bh->b_private = NULL; 780 bh->b_private = NULL;
739 } 781 }
740 gfs2_log_unlock(sdp); 782 gfs2_log_unlock(sdp);