[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