diff options
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r-- | fs/gfs2/ops_address.c | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 48720421c796..0de7a9523633 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -118,6 +118,25 @@ static int get_block_noalloc(struct inode *inode, sector_t lblock, | |||
118 | return error; | 118 | return error; |
119 | } | 119 | } |
120 | 120 | ||
121 | static int get_block_direct(struct inode *inode, sector_t lblock, | ||
122 | struct buffer_head *bh_result, int create) | ||
123 | { | ||
124 | int new = 0; | ||
125 | u64 dblock; | ||
126 | int error, boundary; | ||
127 | |||
128 | error = gfs2_block_map(inode, lblock, &new, &dblock, &boundary); | ||
129 | if (error) | ||
130 | return error; | ||
131 | |||
132 | if (dblock) { | ||
133 | map_bh(bh_result, inode->i_sb, dblock); | ||
134 | if (boundary) | ||
135 | set_buffer_boundary(bh_result); | ||
136 | } | ||
137 | |||
138 | return 0; | ||
139 | } | ||
121 | /** | 140 | /** |
122 | * gfs2_writepage - Write complete page | 141 | * gfs2_writepage - Write complete page |
123 | * @page: Page to write | 142 | * @page: Page to write |
@@ -661,7 +680,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, | |||
661 | rv = blockdev_direct_IO_own_locking(rw, iocb, inode, | 680 | rv = blockdev_direct_IO_own_locking(rw, iocb, inode, |
662 | inode->i_sb->s_bdev, | 681 | inode->i_sb->s_bdev, |
663 | iov, offset, nr_segs, | 682 | iov, offset, nr_segs, |
664 | gfs2_get_block, NULL); | 683 | get_block_direct, NULL); |
665 | out: | 684 | out: |
666 | gfs2_glock_dq_m(1, &gh); | 685 | gfs2_glock_dq_m(1, &gh); |
667 | gfs2_holder_uninit(&gh); | 686 | gfs2_holder_uninit(&gh); |
@@ -724,7 +743,7 @@ static unsigned limit = 0; | |||
724 | } | 743 | } |
725 | 744 | ||
726 | /** | 745 | /** |
727 | * gfs2_aspace_releasepage - free the metadata associated with a page | 746 | * gfs2_releasepage - free the metadata associated with a page |
728 | * @page: the page that's being released | 747 | * @page: the page that's being released |
729 | * @gfp_mask: passed from Linux VFS, ignored by us | 748 | * @gfp_mask: passed from Linux VFS, ignored by us |
730 | * | 749 | * |
@@ -761,16 +780,22 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
761 | } | 780 | } |
762 | 781 | ||
763 | gfs2_assert_warn(sdp, !buffer_pinned(bh)); | 782 | gfs2_assert_warn(sdp, !buffer_pinned(bh)); |
783 | gfs2_assert_warn(sdp, !buffer_dirty(bh)); | ||
764 | 784 | ||
785 | gfs2_log_lock(sdp); | ||
765 | bd = bh->b_private; | 786 | bd = bh->b_private; |
766 | if (bd) { | 787 | if (bd) { |
767 | gfs2_assert_warn(sdp, bd->bd_bh == bh); | 788 | gfs2_assert_warn(sdp, bd->bd_bh == bh); |
768 | gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr)); | 789 | gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr)); |
769 | gfs2_assert_warn(sdp, list_empty(&bd->bd_le.le_list)); | ||
770 | gfs2_assert_warn(sdp, !bd->bd_ail); | 790 | gfs2_assert_warn(sdp, !bd->bd_ail); |
771 | kmem_cache_free(gfs2_bufdata_cachep, bd); | 791 | bd->bd_bh = NULL; |
792 | if (!list_empty(&bd->bd_le.le_list)) | ||
793 | bd = NULL; | ||
772 | bh->b_private = NULL; | 794 | bh->b_private = NULL; |
773 | } | 795 | } |
796 | gfs2_log_unlock(sdp); | ||
797 | if (bd) | ||
798 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
774 | 799 | ||
775 | bh = bh->b_this_page; | 800 | bh = bh->b_this_page; |
776 | } while (bh != head); | 801 | } while (bh != head); |