diff options
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r-- | fs/gfs2/ops_address.c | 50 |
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 | ||
619 | static 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 | |||
619 | static void gfs2_invalidatepage(struct page *page, unsigned long offset) | 641 | static 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); | ||
660 | out: | ||
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); |