[Ocfs2-tools-devel] [PATCH 24/50] libocfs2: Add function for punch hole in refcount tree.

Tao Ma tao.ma at oracle.com
Mon Jan 11 07:31:10 PST 2010


In fsck.ocfs2, sometimes we need to remove the refcount
from the tree, so this patch add a new function named
ocfs2_refcount_punch_hole which will do like this.

We add a new parameter value to ocfs2_decrease_refcount_rec,
so that in case of punching hole, we just need to set
value to -r_refcount and it will work for us.

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 include/ocfs2/ocfs2.h |    2 +
 libocfs2/refcount.c   |   59 +++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index e8173ca..6589523 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -430,6 +430,8 @@ errcode_t ocfs2_refcount_tree_get_rec(ocfs2_filesys *fs,
 				      uint64_t *p_blkno,
 				      uint32_t *e_cpos,
 				      uint32_t *num_clusters);
+errcode_t ocfs2_refcount_punch_hole(ocfs2_filesys *fs, uint64_t rf_blkno,
+				    uint64_t p_start, uint32_t len);
 errcode_t ocfs2_swap_dir_entries_from_cpu(void *buf, uint64_t bytes);
 errcode_t ocfs2_swap_dir_entries_to_cpu(void *buf, uint64_t bytes);
 void ocfs2_swap_dir_trailer(struct ocfs2_dir_block_trailer *trailer);
diff --git a/libocfs2/refcount.c b/libocfs2/refcount.c
index 794143c..a659fe6 100644
--- a/libocfs2/refcount.c
+++ b/libocfs2/refcount.c
@@ -1176,7 +1176,8 @@ out:
 static int ocfs2_decrease_refcount_rec(ocfs2_filesys *fs,
 				char *ref_root_buf,
 				char *ref_leaf_buf,
-				int index, uint64_t cpos, unsigned int len)
+				int index, uint64_t cpos, unsigned int len,
+				int value)
 {
 	int ret;
 	struct ocfs2_refcount_block *rb =
@@ -1189,13 +1190,14 @@ static int ocfs2_decrease_refcount_rec(ocfs2_filesys *fs,
 	assert(cpos + len <= rec->r_cpos + rec->r_clusters);
 
 	if (cpos == rec->r_cpos && len == rec->r_clusters)
-		ret = ocfs2_change_refcount_rec(fs, ref_leaf_buf, index, 1, -1);
+		ret = ocfs2_change_refcount_rec(fs, ref_leaf_buf,
+						index, 1, -value);
 	else {
 		struct ocfs2_refcount_rec split = *rec;
 		split.r_cpos = cpos;
 		split.r_clusters = len;
 
-		split.r_refcount -= 1;
+		split.r_refcount -= value;
 
 		ret = ocfs2_split_refcount_rec(fs, ref_root_buf, ref_leaf_buf,
 					       &split, index, 1);
@@ -1248,7 +1250,7 @@ static int __ocfs2_decrease_refcount(ocfs2_filesys *fs, char *ref_root_buf,
 
 		ret = ocfs2_decrease_refcount_rec(fs, ref_root_buf,
 						  ref_leaf_buf, index,
-						  cpos, r_len);
+						  cpos, r_len, 1);
 		if (ret)
 			goto out;
 
@@ -1895,6 +1897,55 @@ out:
 	return ret;
 }
 
+errcode_t ocfs2_refcount_punch_hole(ocfs2_filesys *fs, uint64_t rf_blkno,
+				    uint64_t p_start, uint32_t len)
+{
+	errcode_t ret;
+	char *root_buf = NULL, *buf = NULL;
+	struct ocfs2_refcount_rec rec;
+	int index;
+	uint32_t dec_len;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &root_buf);
+	if (ret)
+		goto out;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	if (ret)
+		goto out;
+
+	ret = ocfs2_read_refcount_block(fs, rf_blkno, root_buf);
+	if (ret)
+		goto out;
+
+	while (len) {
+		ret = ocfs2_get_refcount_rec(fs, root_buf, p_start,
+					     len, &rec, &index, buf);
+		if (!rec.r_refcount) {
+			/* There is no refcount for p_start. */
+			len -= rec.r_clusters;
+			p_start += rec.r_clusters;
+			continue;
+		}
+
+		dec_len = (p_start + len < rec.r_cpos + rec.r_clusters) ?
+				len : (rec.r_cpos + rec.r_clusters - p_start);
+		ret = ocfs2_decrease_refcount_rec(fs, root_buf, buf,
+						  index, p_start, dec_len,
+						  rec.r_refcount);
+		if (ret)
+			goto out;
+		len -= rec.r_clusters;
+		p_start += rec.r_clusters;
+	}
+out:
+	if (root_buf)
+		ocfs2_free(&root_buf);
+	if (buf)
+		ocfs2_free(&buf);
+	return ret;
+}
+
 struct xattr_value_cow_object {
 	struct ocfs2_xattr_value_root *xv;
 	uint64_t xe_blkno;
-- 
1.5.5




More information about the Ocfs2-tools-devel mailing list