|
@@ -36,11 +36,6 @@ struct metapath {
|
|
|
__u16 mp_list[GFS2_MAX_META_HEIGHT];
|
|
|
};
|
|
|
|
|
|
-typedef int (*block_call_t) (struct gfs2_inode *ip, struct buffer_head *dibh,
|
|
|
- struct buffer_head *bh, __be64 *top,
|
|
|
- __be64 *bottom, unsigned int height,
|
|
|
- void *data);
|
|
|
-
|
|
|
struct strip_mine {
|
|
|
int sm_first;
|
|
|
unsigned int sm_height;
|
|
@@ -667,76 +662,6 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * recursive_scan - recursively scan through the end of a file
|
|
|
- * @ip: the inode
|
|
|
- * @dibh: the dinode buffer
|
|
|
- * @mp: the path through the metadata to the point to start
|
|
|
- * @height: the height the recursion is at
|
|
|
- * @block: the indirect block to look at
|
|
|
- * @first: 1 if this is the first block
|
|
|
- * @bc: the call to make for each piece of metadata
|
|
|
- * @data: data opaque to this function to pass to @bc
|
|
|
- *
|
|
|
- * When this is first called @height and @block should be zero and
|
|
|
- * @first should be 1.
|
|
|
- *
|
|
|
- * Returns: errno
|
|
|
- */
|
|
|
-
|
|
|
-static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
|
|
|
- struct metapath *mp, unsigned int height,
|
|
|
- u64 block, int first, block_call_t bc,
|
|
|
- void *data)
|
|
|
-{
|
|
|
- struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
- struct buffer_head *bh = NULL;
|
|
|
- __be64 *top, *bottom;
|
|
|
- u64 bn;
|
|
|
- int error;
|
|
|
- int mh_size = sizeof(struct gfs2_meta_header);
|
|
|
-
|
|
|
- if (!height) {
|
|
|
- error = gfs2_meta_inode_buffer(ip, &bh);
|
|
|
- if (error)
|
|
|
- return error;
|
|
|
- dibh = bh;
|
|
|
-
|
|
|
- top = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0];
|
|
|
- bottom = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs;
|
|
|
- } else {
|
|
|
- error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh);
|
|
|
- if (error)
|
|
|
- return error;
|
|
|
-
|
|
|
- top = (__be64 *)(bh->b_data + mh_size) +
|
|
|
- (first ? mp->mp_list[height] : 0);
|
|
|
-
|
|
|
- bottom = (__be64 *)(bh->b_data + mh_size) + sdp->sd_inptrs;
|
|
|
- }
|
|
|
-
|
|
|
- error = bc(ip, dibh, bh, top, bottom, height, data);
|
|
|
- if (error)
|
|
|
- goto out;
|
|
|
-
|
|
|
- if (height < ip->i_height - 1)
|
|
|
- for (; top < bottom; top++, first = 0) {
|
|
|
- if (!*top)
|
|
|
- continue;
|
|
|
-
|
|
|
- bn = be64_to_cpu(*top);
|
|
|
-
|
|
|
- error = recursive_scan(ip, dibh, mp, height + 1, bn,
|
|
|
- first, bc, data);
|
|
|
- if (error)
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-out:
|
|
|
- brelse(bh);
|
|
|
- return error;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* do_strip - Look for a layer a particular layer of the file and strip it off
|
|
|
* @ip: the inode
|
|
@@ -752,9 +677,8 @@ out:
|
|
|
|
|
|
static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
|
|
|
struct buffer_head *bh, __be64 *top, __be64 *bottom,
|
|
|
- unsigned int height, void *data)
|
|
|
+ unsigned int height, struct strip_mine *sm)
|
|
|
{
|
|
|
- struct strip_mine *sm = data;
|
|
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
struct gfs2_rgrp_list rlist;
|
|
|
u64 bn, bstart;
|
|
@@ -885,6 +809,75 @@ out:
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * recursive_scan - recursively scan through the end of a file
|
|
|
+ * @ip: the inode
|
|
|
+ * @dibh: the dinode buffer
|
|
|
+ * @mp: the path through the metadata to the point to start
|
|
|
+ * @height: the height the recursion is at
|
|
|
+ * @block: the indirect block to look at
|
|
|
+ * @first: 1 if this is the first block
|
|
|
+ * @sm: data opaque to this function to pass to @bc
|
|
|
+ *
|
|
|
+ * When this is first called @height and @block should be zero and
|
|
|
+ * @first should be 1.
|
|
|
+ *
|
|
|
+ * Returns: errno
|
|
|
+ */
|
|
|
+
|
|
|
+static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
|
|
|
+ struct metapath *mp, unsigned int height,
|
|
|
+ u64 block, int first, struct strip_mine *sm)
|
|
|
+{
|
|
|
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
+ struct buffer_head *bh = NULL;
|
|
|
+ __be64 *top, *bottom;
|
|
|
+ u64 bn;
|
|
|
+ int error;
|
|
|
+ int mh_size = sizeof(struct gfs2_meta_header);
|
|
|
+
|
|
|
+ if (!height) {
|
|
|
+ error = gfs2_meta_inode_buffer(ip, &bh);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+ dibh = bh;
|
|
|
+
|
|
|
+ top = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + mp->mp_list[0];
|
|
|
+ bottom = (__be64 *)(bh->b_data + sizeof(struct gfs2_dinode)) + sdp->sd_diptrs;
|
|
|
+ } else {
|
|
|
+ error = gfs2_meta_indirect_buffer(ip, height, block, 0, &bh);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+
|
|
|
+ top = (__be64 *)(bh->b_data + mh_size) +
|
|
|
+ (first ? mp->mp_list[height] : 0);
|
|
|
+
|
|
|
+ bottom = (__be64 *)(bh->b_data + mh_size) + sdp->sd_inptrs;
|
|
|
+ }
|
|
|
+
|
|
|
+ error = do_strip(ip, dibh, bh, top, bottom, height, sm);
|
|
|
+ if (error)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ if (height < ip->i_height - 1)
|
|
|
+ for (; top < bottom; top++, first = 0) {
|
|
|
+ if (!*top)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ bn = be64_to_cpu(*top);
|
|
|
+
|
|
|
+ error = recursive_scan(ip, dibh, mp, height + 1, bn,
|
|
|
+ first, sm);
|
|
|
+ if (error)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+out:
|
|
|
+ brelse(bh);
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* gfs2_block_truncate_page - Deal with zeroing out data for truncate
|
|
|
*
|
|
@@ -1024,7 +1017,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
|
|
|
sm.sm_first = !!size;
|
|
|
sm.sm_height = height;
|
|
|
|
|
|
- error = recursive_scan(ip, NULL, &mp, 0, 0, 1, do_strip, &sm);
|
|
|
+ error = recursive_scan(ip, NULL, &mp, 0, 0, 1, &sm);
|
|
|
if (error)
|
|
|
break;
|
|
|
}
|