[Ocfs2-tools-devel] [PATCH 3/3] ocfs2-tools: Add extended attribute support in debugfs.ocfs2.

Tiger Yang tiger.yang at oracle.com
Mon Aug 25 22:03:16 PDT 2008


This patch add new command xattr in debugfs.ocfs2.
xattr <filespec> could show all extended attributes related to this file.

Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
---
 debugfs.ocfs2/commands.c     |   43 +++++++++++
 debugfs.ocfs2/dump.c         |  170 ++++++++++++++++++++++++++++++++++++++++++
 debugfs.ocfs2/include/dump.h |    3 +
 3 files changed, 216 insertions(+), 0 deletions(-)

diff --git a/debugfs.ocfs2/commands.c b/debugfs.ocfs2/commands.c
index 83cb5b6..2708aea 100644
--- a/debugfs.ocfs2/commands.c
+++ b/debugfs.ocfs2/commands.c
@@ -73,6 +73,7 @@ static void do_bmap (char **args);
 static void do_icheck (char **args);
 static void do_dlm_locks (char **args);
 static void do_controld(char **args);
+static void do_xattr(char **args);
 
 dbgfs_gbls gbls;
 
@@ -106,6 +107,7 @@ static Command commands[] = {
 	{ "slotmap",	do_slotmap },
 	{ "stat",	do_stat },
 	{ "stats",	do_stats },
+	{ "xattr",	do_xattr },
 	{ "encode",	do_encode_lockres },
 	{ "decode",	do_decode_lockres }
 };
@@ -852,6 +854,7 @@ static void do_help (char **args)
 	printf ("slotmap\t\t\t\t\tShow slot map\n");
 	printf ("stat <filespec>\t\t\t\tShow inode\n");
 	printf ("stats [-h]\t\t\t\tShow superblock\n");
+	printf ("xattr\t\t\t\t\tShow Extended Attributes\n");
 }
 
 /*
@@ -1678,3 +1681,43 @@ static void do_icheck(char **args)
 
 	return;
 }
+/*
+ * do_xattr()
+ *
+ */
+static void do_xattr(char **args)
+{
+	struct ocfs2_dinode *inode;
+	uint64_t blkno;
+	char *buf = NULL;
+	FILE *out;
+	errcode_t ret = 0;
+
+	if (process_inode_args(args, &blkno))
+		return ;
+
+	buf = gbls.blockbuf;
+	ret = ocfs2_read_inode(gbls.fs, blkno, buf);
+	if (ret) {
+		com_err(args[0], ret, "while reading inode %"PRIu64"", blkno);
+		return ;
+	}
+
+	inode = (struct ocfs2_dinode *)buf;
+
+	out = open_pager(gbls.interactive);
+	if (inode->i_dyn_features & OCFS2_HAS_XATTR_FL) {
+		if (inode->i_dyn_features & OCFS2_INLINE_XATTR_FL)
+			dump_xattr_ibody(out, gbls.fs, inode);
+		if (inode->i_xattr_loc)
+			ret = dump_xattr_block(out, gbls.fs, inode);
+	}
+
+	if (ret)
+		com_err(args[0], ret, "while traversing inode at block "
+			"%"PRIu64, blkno);
+
+	close_pager(out);
+
+	return ;
+}
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index b8e0aba..d19cb46 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -88,11 +88,15 @@ void dump_super_block(FILE *out, struct ocfs2_super_block *sb)
 
 	fprintf(out, "\tMax Node Slots: %u\n", sb->s_max_slots);
 
+	fprintf(out, "\tXattr Inline Size: %u\n", sb->s_xattr_inline_size);
+
 	fprintf(out, "\tLabel: %s\n", sb->s_label);
 	fprintf(out, "\tUUID: ");
 	for (i = 0; i < 16; i++)
 		fprintf(out, "%02X", sb->s_uuid[i]);
 	fprintf(out, "\n");
+	fprintf(out, "\tUUID_hash: %u (0x%x)\n", sb->s_uuid_hash,
+		sb->s_uuid_hash);
 	if (ocfs2_userspace_stack(sb))
 		fprintf(out,
 			"\tCluster stack: %s\n"
@@ -236,6 +240,10 @@ void dump_inode(FILE *out, struct ocfs2_dinode *in)
 	fprintf(out, "\tDynamic Features: (0x%x) %s\n", in->i_dyn_features,
 		dyn_features->str);
 
+	if (in->i_dyn_features & OCFS2_HAS_XATTR_FL)
+		fprintf(out, "\tXattr Block: %"PRIu64"  Xattr Inline size: %u\n",
+			(uint64_t)in->i_xattr_loc, in->i_xattr_inline_size);
+
 	pw = getpwuid(in->i_uid);
 	gr = getgrgid(in->i_gid);
 	fprintf(out, "\tUser: %d (%s)   Group: %d (%s)   Size: %"PRIu64"\n",
@@ -732,3 +740,165 @@ void dump_icheck(FILE *out, int hdr, uint64_t blkno, uint64_t inode,
 
 	fprintf(out, "\t%-15"PRIu64"   %-15s   %-15s\n", blkno, inostr, offstr);
 }
+
+static void dump_xattr(FILE *out, struct ocfs2_xattr_header *xh)
+{
+	int i;
+
+	fprintf(out, "\t###   %-4s   %-6s  %-13s  %s\n", "Type",
+		"Inline", "Name Length", "Value Length");
+	for (i = 0 ; i < xh->xh_count; i++) {
+		struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
+
+		fprintf(out,
+			"\n\t#%-2d   %-4u   %-6u  %-13u  %-13"PRIu64"\n",
+			i, ocfs2_xattr_get_type(xe),
+			ocfs2_xattr_is_local(xe) ? 1 : 0,
+			xe->xe_name_len, (uint64_t)xe->xe_value_size);
+
+		if (!ocfs2_xattr_is_local(xe)) {
+			struct ocfs2_xattr_value_root *xv =
+				(struct ocfs2_xattr_value_root *)
+				((void *)xh + xe->xe_name_offset +
+				OCFS2_XATTR_SIZE(xe->xe_name_len));
+			struct ocfs2_extent_list *el = &xv->xr_list;
+			dump_extent_list(out, el);
+		}
+	}
+	return;
+}
+
+static errcode_t dump_xattr_buckets(FILE *out,
+				    ocfs2_filesys *fs,
+				    struct ocfs2_dinode *di,
+				    uint64_t blkno,
+				    uint32_t clusters)
+{
+	int i;
+	errcode_t ret = 0;
+	char *bucket = NULL;
+	struct ocfs2_xattr_header *xh;
+	int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(fs);
+	uint32_t bpc = ocfs2_xattr_buckets_per_cluster(fs);
+	uint32_t num_buckets = clusters * bpc;
+
+	ret = ocfs2_malloc_blocks(fs->fs_io, blk_per_bucket, &bucket);
+	if (ret)
+		goto out;
+
+	for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) {
+
+		ret = io_read_block(fs->fs_io, blkno, blk_per_bucket, bucket);
+		if (ret)
+			goto out;
+
+		xh = (struct ocfs2_xattr_header *)bucket;
+		ocfs2_swap_xattr_header(xh);
+		ocfs2_swap_xattr_entries_to_cpu(xh);
+		/*
+		 * The real bucket num in this series of blocks is stored
+		 * in the 1st bucket.
+		 */
+		if (i == 0)
+			num_buckets = xh->xh_num_buckets;
+
+		fprintf(out, "\n\tXattr In Bucket #%d Count: %u\n",
+			i, xh->xh_count);
+		dump_xattr(out, xh);
+		if (ret)
+			break;
+	}
+
+out:
+	ocfs2_free(&bucket);
+
+	return ret;
+}
+
+
+static errcode_t dump_xattr_index_block(FILE *out,
+					ocfs2_filesys *fs,
+					struct ocfs2_dinode *di,
+					struct ocfs2_xattr_tree_root *xt)
+{
+	struct ocfs2_extent_list *el = &xt->xt_list;
+	errcode_t ret = 0;
+	uint32_t name_hash = UINT_MAX, e_cpos = 0, num_clusters = 0;
+	uint64_t p_blkno = 0;
+
+	if (el->l_next_free_rec == 0)
+		return 0;
+
+	while (name_hash > 0) {
+		ret = ocfs2_xattr_get_rec(fs, di, name_hash, &p_blkno,
+					  &e_cpos, &num_clusters, el);
+		if (ret)
+			goto out;
+
+		fprintf(out, "\n\tXattr In Index Block\n");
+		ret = dump_xattr_buckets(out, fs, di, p_blkno,
+					 num_clusters);
+		if (ret)
+			goto out;
+
+		if (e_cpos == 0)
+			break;
+
+		name_hash = e_cpos - 1;
+	}
+
+out:
+	return ret;
+}
+
+/*
+ * dump_xattr_block()
+ *
+ */
+errcode_t dump_xattr_block(FILE *out, ocfs2_filesys *fs,
+			   struct ocfs2_dinode *in)
+{
+	errcode_t ret;
+	char *blk = NULL;
+	struct ocfs2_xattr_block *xb = NULL;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &blk);
+	if (ret)
+		return ret;
+
+	ret = ocfs2_read_xattr_block(fs, in->i_xattr_loc, blk);
+	if (ret)
+		return ret;
+
+	xb = (struct ocfs2_xattr_block *)blk;
+
+	if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
+		struct ocfs2_xattr_header *xh = &xb->xb_attrs.xb_header;
+
+		fprintf(out, "\n\tXattr In Block Count: %u\n", xh->xh_count);
+		dump_xattr(out, xh);
+	} else {
+		struct ocfs2_xattr_tree_root *xt = &xb->xb_attrs.xb_root;
+
+		ret = dump_xattr_index_block(out, fs, in, xt);
+	}
+
+	return ret;
+}
+/*
+ * dump_xattr_ibody()
+ *
+ */
+void dump_xattr_ibody(FILE *out, ocfs2_filesys *fs, struct ocfs2_dinode *in)
+{
+	struct ocfs2_xattr_header *xh = NULL;
+
+	xh = (struct ocfs2_xattr_header *)
+		((void *)in + fs->fs_blocksize -
+		 in->i_xattr_inline_size);
+
+	fprintf(out, "\n\tXattr Inline Count: %u\n", xh->xh_count);
+	dump_xattr(out, xh);
+
+	return ;
+}
diff --git a/debugfs.ocfs2/include/dump.h b/debugfs.ocfs2/include/dump.h
index 5310d36..ca8b3dd 100644
--- a/debugfs.ocfs2/include/dump.h
+++ b/debugfs.ocfs2/include/dump.h
@@ -56,5 +56,8 @@ void dump_inode_path (FILE *out, uint64_t blkno, char *path);
 void dump_logical_blkno(FILE *out, uint64_t blkno);
 void dump_icheck(FILE *out, int hdr, uint64_t blkno, uint64_t inode,
 		 int validoffset, uint64_t offset, int status);
+void dump_xattr_ibody(FILE *out, ocfs2_filesys *fs, struct ocfs2_dinode *in);
+errcode_t dump_xattr_block(FILE *out, ocfs2_filesys *fs,
+			   struct ocfs2_dinode *in);
 
 #endif		/* __DUMP_H__ */
-- 
1.5.4.1




More information about the Ocfs2-tools-devel mailing list