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.c33
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
121static 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);
665out: 684out:
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);