[Ocfs2-tools-devel] [PATCH 25/50] libocfs2: Add function for changing refcount flag.

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


In fsck.ocfs2, we need the ability to clear/set refcount
flag for some exetent record. So this function adds
a new function named ocfs2_change_refcount_flag.

Note:
It only have the parameter tuple(v_cpos, p_cpos, clusters),
so we have to iterate dinode and xattr to find the dest
extent tree we want to change.

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

diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 6589523..c1954bb 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -424,6 +424,10 @@ errcode_t ocfs2_refcount_cow_xattr(ocfs2_cached_inode *ci,
 				   uint64_t value_blkno,
 				   struct ocfs2_xattr_value_root *xv,
 				   uint32_t cpos, uint32_t write_len);
+errcode_t ocfs2_change_refcount_flag(ocfs2_filesys *fs, uint64_t i_blkno,
+				     uint32_t v_cpos, uint32_t clusters,
+				     uint64_t p_cpos,
+				     int new_flags, int clear_flags);
 errcode_t ocfs2_refcount_tree_get_rec(ocfs2_filesys *fs,
 				      struct ocfs2_refcount_block *rb,
 				      uint32_t phys_cpos,
diff --git a/libocfs2/refcount.c b/libocfs2/refcount.c
index a659fe6..1218738 100644
--- a/libocfs2/refcount.c
+++ b/libocfs2/refcount.c
@@ -1946,6 +1946,146 @@ out:
 	return ret;
 }
 
+struct xattr_value_obj {
+	errcode_t errcode;
+	uint64_t p_cpos;
+	uint32_t v_cpos;
+	uint32_t clusters;
+	int new_flags;
+	int clear_flags;
+};
+
+static int change_xattr_refcount(ocfs2_cached_inode *ci,
+				 char *xe_buf,
+				 uint64_t xe_blkno,
+				 struct ocfs2_xattr_entry *xe,
+				 char *value_buf,
+				 uint64_t value_blkno,
+				 void *value,
+				 int in_bucket,
+				 void *priv_data)
+{
+	uint32_t p_cluster, num_clusters;
+	uint16_t ext_flags;
+	struct xattr_value_obj *obj = priv_data;
+	struct ocfs2_extent_tree et;
+	ocfs2_root_write_func write_func = NULL;
+	struct ocfs2_xattr_value_root *xv;
+
+	if (ocfs2_xattr_is_local(xe))
+		return 0;
+
+	xv = (struct ocfs2_xattr_value_root *)value;
+	obj->errcode = ocfs2_xattr_get_clusters(ci->ci_fs, &xv->xr_list,
+						value_blkno, value_buf,
+						obj->v_cpos, &p_cluster,
+						&num_clusters, &ext_flags);
+	if (obj->errcode)
+		return OCFS2_XATTR_ERROR;
+
+	if (p_cluster != obj->p_cpos)
+		return 0;
+
+	assert(num_clusters >= obj->clusters);
+
+	if (xe_blkno == ci->ci_inode->i_blkno)
+		write_func = ocfs2_write_inode;
+	else if (xe_blkno == ci->ci_inode->i_xattr_loc)
+		write_func = ocfs2_write_xattr_block;
+
+	ocfs2_init_xattr_value_extent_tree(&et, ci->ci_fs, value_buf,
+					   value_blkno, write_func, xv);
+	obj->errcode = ocfs2_change_extent_flag(ci->ci_fs, &et,
+					obj->v_cpos, obj->clusters,
+					ocfs2_clusters_to_blocks(ci->ci_fs,
+								 obj->p_cpos),
+					obj->new_flags, obj->clear_flags);
+	if (obj->errcode)
+		goto out;
+
+	if (!write_func) {
+		assert(in_bucket);
+		obj->errcode = ocfs2_write_xattr_bucket(ci->ci_fs,
+							xe_blkno, xe_buf);
+		if (obj->errcode)
+			goto out;
+	}
+
+	return OCFS2_XATTR_ABORT;
+
+out:
+	return 	OCFS2_XATTR_ERROR;
+}
+
+static errcode_t ocfs2_xattr_change_ext_refcount(ocfs2_filesys *fs,
+						 ocfs2_cached_inode *ci,
+						 uint32_t v_cpos,
+						 uint32_t clusters,
+						 uint64_t p_cpos,
+						 int new_flags,
+						 int clear_flags)
+{
+	int iret;
+	errcode_t ret = 0;
+	struct xattr_value_obj obj = {
+		.v_cpos = v_cpos,
+		.p_cpos = p_cpos,
+		.clusters = clusters,
+		.new_flags = new_flags,
+		.clear_flags = clear_flags,
+	};
+
+	iret = ocfs2_xattr_iterate(ci, change_xattr_refcount, &obj);
+	if (iret & OCFS2_XATTR_ERROR)
+		ret = obj.errcode;
+
+	return ret;
+}
+
+/*
+ * Clear the refcount flag for an extent rec (v_cpos, clusters) of the file.
+ * This extent rec can be found either in dinode or xattr.
+ */
+errcode_t ocfs2_change_refcount_flag(ocfs2_filesys *fs, uint64_t i_blkno,
+				     uint32_t v_cpos, uint32_t clusters,
+				     uint64_t p_cpos,
+				     int new_flags, int clear_flags)
+{
+	errcode_t ret;
+	ocfs2_cached_inode *ci = NULL;
+	struct ocfs2_extent_tree et;
+	uint32_t p_cluster, num_clusters;
+	uint16_t ext_flags;
+
+	ret = ocfs2_read_cached_inode(fs, i_blkno, &ci);
+	if (ret)
+		goto out;
+
+	ret = ocfs2_get_clusters(ci, v_cpos, &p_cluster,
+				 &num_clusters, &ext_flags);
+	if (ret)
+		goto out;
+
+	if (p_cluster == p_cpos) {
+		/* OK, the p_cpos is in the dinode. */
+		assert(num_clusters >= clusters);
+		ocfs2_init_dinode_extent_tree(&et, fs,
+					      (char *)ci->ci_inode, i_blkno);
+		ret = ocfs2_change_extent_flag(fs, &et, v_cpos, clusters,
+					ocfs2_clusters_to_blocks(fs, p_cpos),
+					new_flags, clear_flags);
+		goto out;
+	}
+
+	ret = ocfs2_xattr_change_ext_refcount(fs, ci, v_cpos, clusters, p_cpos,
+					      new_flags, clear_flags);
+
+out:
+	if (ci)
+		ocfs2_free_cached_inode(fs, ci);
+	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