aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/bmap.c149
1 files changed, 71 insertions, 78 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index e60296137707..9d3a0c26df28 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -36,11 +36,6 @@ struct metapath {
36 __u16 mp_list[GFS2_MAX_META_HEIGHT]; 36 __u16 mp_list[GFS2_MAX_META_HEIGHT];
37}; 37};
38 38
39typedef int (*block_call_t) (struct gfs2_inode *ip, struct buffer_head *dibh,
40 struct buffer_head *bh, __be64 *top,
41 __be64 *bottom, unsigned int height,
42 void *data);
43
44struct strip_mine { 39struct strip_mine {
45 int sm_first; 40 int sm_first;
46 unsigned int sm_height; 41 unsigned int sm_height;
@@ -668,76 +663,6 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
668} 663}
669 664
670/** 665/**
671 * recursive_scan - recursively scan through the end of a file
672 * @ip: the inode
673 * @dibh: the dinode buffer
674 * @mp: the path through the metadata to the point to start
675 * @height: the height the recursion is at
676 * @block: the indirect block to look at
677 * @first: 1 if this is the first block
678 * @bc: the call to make for each piece of metadata
679 * @data: data opaque to this function to pass to @bc
680 *
681 * When this is first called @height and @block should be zero and
682 * @first should be 1.
683 *
684 * Returns: errno
685 */
686
687static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
688 struct metapath *mp, unsigned int height,
689 u64 block, int first, block_call_t bc,
690 void *data)
691{
692 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
693 struct buffer_head *bh = NULL;
694 __be64 *top, *bottom;
695 u64 bn;
696 int error;
697 int mh_size = sizeof(struct gfs2_meta_header);
698
699 if (!height) {
700 error = gfs2_meta_inode_buffer(ip, &bh);
701 if (error)
702 return error;
703 dibh = bh;
704
705 top = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0];
706 bottom = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs;
707 } else {
708 error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh);
709 if (error)
710 return error;
711
712 top = (__be64 *)(bh->b_data + mh_size) +
713 (first ? mp->mp_list[height] : 0);
714
715 bottom = (__be64 *)(bh->b_data + mh_size) + sdp->sd_inptrs;
716 }
717
718 error = bc(ip, dibh, bh, top, bottom, height, data);
719 if (error)
720 goto out;
721
722 if (height < ip->i_height - 1)
723 for (; top < bottom; top++, first = 0) {
724 if (!*top)
725 continue;
726
727 bn = be64_to_cpu(*top);
728
729 error = recursive_scan(ip, dibh, mp, height + 1, bn,
730 first, bc, data);
731 if (error)
732 break;
733 }
734
735out:
736 brelse(bh);
737 return error;
738}
739
740/**
741 * do_strip - Look for a layer a particular layer of the file and strip it off 666 * do_strip - Look for a layer a particular layer of the file and strip it off
742 * @ip: the inode 667 * @ip: the inode
743 * @dibh: the dinode buffer 668 * @dibh: the dinode buffer
@@ -752,9 +677,8 @@ out:
752 677
753static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, 678static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
754 struct buffer_head *bh, __be64 *top, __be64 *bottom, 679 struct buffer_head *bh, __be64 *top, __be64 *bottom,
755 unsigned int height, void *data) 680 unsigned int height, struct strip_mine *sm)
756{ 681{
757 struct strip_mine *sm = data;
758 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 682 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
759 struct gfs2_rgrp_list rlist; 683 struct gfs2_rgrp_list rlist;
760 u64 bn, bstart; 684 u64 bn, bstart;
@@ -886,6 +810,75 @@ out:
886} 810}
887 811
888/** 812/**
813 * recursive_scan - recursively scan through the end of a file
814 * @ip: the inode
815 * @dibh: the dinode buffer
816 * @mp: the path through the metadata to the point to start
817 * @height: the height the recursion is at
818 * @block: the indirect block to look at
819 * @first: 1 if this is the first block
820 * @sm: data opaque to this function to pass to @bc
821 *
822 * When this is first called @height and @block should be zero and
823 * @first should be 1.
824 *
825 * Returns: errno
826 */
827
828static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
829 struct metapath *mp, unsigned int height,
830 u64 block, int first, struct strip_mine *sm)
831{
832 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
833 struct buffer_head *bh = NULL;
834 __be64 *top, *bottom;
835 u64 bn;
836 int error;
837 int mh_size = sizeof(struct gfs2_meta_header);
838
839 if (!height) {
840 error = gfs2_meta_inode_buffer(ip, &bh);
841 if (error)
842 return error;
843 dibh = bh;
844
845 top = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0];
846 bottom = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs;
847 } else {
848 error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh);
849 if (error)
850 return error;
851
852 top = (__be64 *)(bh->b_data + mh_size) +
853 (first ? mp->mp_list[height] : 0);
854
855 bottom = (__be64 *)(bh->b_data + mh_size) + sdp->sd_inptrs;
856 }
857
858 error = do_strip(ip, dibh, bh, top, bottom, height, sm);
859 if (error)
860 goto out;
861
862 if (height < ip->i_height - 1)
863 for (; top < bottom; top++, first = 0) {
864 if (!*top)
865 continue;
866
867 bn = be64_to_cpu(*top);
868
869 error = recursive_scan(ip, dibh, mp, height + 1, bn,
870 first, sm);
871 if (error)
872 break;
873 }
874
875out:
876 brelse(bh);
877 return error;
878}
879
880
881/**
889 * gfs2_block_truncate_page - Deal with zeroing out data for truncate 882 * gfs2_block_truncate_page - Deal with zeroing out data for truncate
890 * 883 *
891 * This is partly borrowed from ext3. 884 * This is partly borrowed from ext3.
@@ -1024,7 +1017,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
1024 sm.sm_first = !!size; 1017 sm.sm_first = !!size;
1025 sm.sm_height = height; 1018 sm.sm_height = height;
1026 1019
1027 error = recursive_scan(ip, NULL, &mp, 0, 0, 1, do_strip, &sm); 1020 error = recursive_scan(ip, NULL, &mp, 0, 0, 1, &sm);
1028 if (error) 1021 if (error)
1029 break; 1022 break;
1030 } 1023 }