[Ocfs2-tools-devel] [PATCH 6/9] ocfs2-tools: add xattr support in debugfs.ocfs2
Tiger Yang
tiger.yang at oracle.com
Sat Jan 24 00:03:44 PST 2009
This patch add showing xattrs which setted in a file in debugfs.ocfs2.
The new command "xattr [-v] <filespec>" in debugfs.ocfs2 could show
xattrs in inode, block or buckets in summary or in verbose mode.
Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
---
debugfs.ocfs2/commands.c | 72 ++++++++++++++++
debugfs.ocfs2/dump.c | 193 ++++++++++++++++++++++++++++++++++++++++++
debugfs.ocfs2/include/dump.h | 7 ++
3 files changed, 272 insertions(+), 0 deletions(-)
diff --git a/debugfs.ocfs2/commands.c b/debugfs.ocfs2/commands.c
index 7f2e4bc..d2ad5ca 100644
--- a/debugfs.ocfs2/commands.c
+++ b/debugfs.ocfs2/commands.c
@@ -74,6 +74,7 @@ static void do_icheck (char **args);
static void do_dlm_locks (char **args);
static void do_controld(char **args);
static void do_dirblocks(char **args);
+static void do_xattr(char **args);
dbgfs_gbls gbls;
@@ -107,6 +108,7 @@ static Command commands[] = {
{ "slotmap", do_slotmap },
{ "stat", do_stat },
{ "stats", do_stats },
+ { "xattr", do_xattr },
{ "encode", do_encode_lockres },
{ "decode", do_decode_lockres },
{ "dirblocks", do_dirblocks },
@@ -855,6 +857,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 [-v] <filespec>\t\t\tShow Extended Attributes\n");
}
/*
@@ -1769,3 +1772,72 @@ static void do_icheck(char **args)
return;
}
+/*
+ * do_xattr()
+ *
+ */
+static void do_xattr(char **args)
+{
+ struct ocfs2_dinode *inode;
+ char *buf = NULL;
+ FILE *out;
+ char *usage = "usage: xattr [-v] <filespec>";
+ uint64_t blkno, xattrs_bucket = 0;
+ uint32_t xattrs_ibody = 0, xattrs_block = 0;
+ int ind = 1, verbose = 0;
+ errcode_t ret = 0;
+
+ if (check_device_open())
+ return;
+
+ if (!args[1]) {
+ fprintf(stderr, "%s\n", usage);
+ return;
+ }
+
+ if (!strcmp(args[1], "-v")) {
+ ++ind;
+ ++verbose;
+ }
+
+ if (!args[ind]) {
+ fprintf(stderr, "%s\n", usage);
+ return;
+ }
+
+ ret = string_to_inode(gbls.fs, gbls.root_blkno, gbls.cwd_blkno,
+ args[ind], &blkno);
+ if (ret) {
+ com_err(args[0], ret, "while translating %s", args[ind]);
+ 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;
+ if (!inode->i_dyn_features & OCFS2_HAS_XATTR_FL)
+ return;
+
+ out = open_pager(gbls.interactive);
+
+ xattrs_ibody = dump_xattr_ibody(out, gbls.fs, inode, verbose);
+
+ if (inode->i_xattr_loc)
+ ret = dump_xattr_block(out, gbls.fs, inode, &xattrs_block,
+ &xattrs_bucket, verbose);
+
+ if (ret)
+ com_err(args[0], ret, "while traversing inode at block "
+ "%"PRIu64, blkno);
+ else
+ fprintf(out, "\n\tXattrs in total: %"PRIu64"\n",
+ xattrs_ibody + xattrs_block + xattrs_bucket);
+ close_pager(out);
+
+ return ;
+}
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index 371b87e..c0fa325 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -90,11 +90,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", OCFS2_MAX_VOL_LABEL_LEN, 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"
@@ -250,6 +254,11 @@ 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",
@@ -817,3 +826,187 @@ 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,
+ "\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,
+ uint64_t blkno,
+ uint32_t clusters,
+ uint64_t *xattrs_bucket,
+ int verbose)
+{
+ 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;
+
+ fprintf(out, "\tXattr extent record start at #%"PRIu64
+ " Has clusters: %u", blkno, clusters);
+ 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_xattrs_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, " Has buckets: %d\n", num_buckets);
+ }
+ fprintf(out, "\t\tXattrs in bucket #%d: %u\n", i, xh->xh_count);
+ if (verbose)
+ dump_xattr(out, xh);
+ *xattrs_bucket += xh->xh_count;
+ }
+
+out:
+ if (bucket)
+ ocfs2_free(&bucket);
+
+ return ret;
+}
+
+
+static errcode_t dump_xattr_index_block(FILE *out,
+ ocfs2_filesys *fs,
+ struct ocfs2_dinode *di,
+ struct ocfs2_xattr_block *xb,
+ uint64_t *xattrs_bucket,
+ int verbose)
+{
+ struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.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)
+ return 0;
+
+ fprintf(out, "\tXattr extent tree in index block #%"PRIu64" Depth: %d"
+ " Records: %d\n", (uint64_t)di->i_xattr_loc,
+ el->l_tree_depth, el->l_next_free_rec);
+ if (verbose)
+ dump_extent_list(out, el);
+
+ while (name_hash > 0) {
+ ret = ocfs2_xattr_get_rec(fs, xb, name_hash, &p_blkno,
+ &e_cpos, &num_clusters);
+ if (ret)
+ goto out;
+
+ ret = dump_xattr_buckets(out, fs, p_blkno, num_clusters,
+ xattrs_bucket, verbose);
+ 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,
+ uint32_t *xattrs_block,
+ uint64_t *xattrs_bucket,
+ int verbose)
+{
+ errcode_t ret;
+ char *blk = NULL;
+ struct ocfs2_xattr_block *xb = NULL;
+
+ ret = ocfs2_malloc_block(fs->fs_io, &blk);
+ if (ret)
+ goto out;
+
+ ret = ocfs2_read_xattr_block(fs, in->i_xattr_loc, blk);
+ if (ret)
+ goto out;
+
+ xb = (struct ocfs2_xattr_block *)blk;
+
+ if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
+ struct ocfs2_xattr_header *xh = &xb->xb_attrs.xb_header;
+ *xattrs_block = xh->xh_count;
+ fprintf(out, "\tXattrs in block #%"PRIu64": %u\n",
+ (uint64_t)in->i_xattr_loc, *xattrs_block);
+ if (verbose)
+ dump_xattr(out, xh);
+ } else {
+ ret = dump_xattr_index_block(out, fs, in, xb,
+ xattrs_bucket, verbose);
+ }
+
+out:
+ if (blk)
+ ocfs2_free(&blk);
+ return ret;
+}
+/*
+ * dump_xattr_ibody()
+ *
+ */
+uint32_t dump_xattr_ibody(FILE *out, ocfs2_filesys *fs,
+ struct ocfs2_dinode *in, int verbose)
+{
+ if (in->i_dyn_features & OCFS2_INLINE_XATTR_FL) {
+ struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)
+ ((void *)in + fs->fs_blocksize
+ - in->i_xattr_inline_size);
+
+ ocfs2_swap_xattrs_to_cpu(xh);
+ fprintf(out, "\tXattrs inline: %u\n", xh->xh_count);
+ if (verbose)
+ dump_xattr(out, xh);
+ return xh->xh_count;
+ } else {
+ fprintf(out, "\tXattrs inline: 0\n");
+ return 0;
+ }
+}
diff --git a/debugfs.ocfs2/include/dump.h b/debugfs.ocfs2/include/dump.h
index f9ccb27..0abccbc 100644
--- a/debugfs.ocfs2/include/dump.h
+++ b/debugfs.ocfs2/include/dump.h
@@ -69,5 +69,12 @@ 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_block_check(FILE *out, struct ocfs2_block_check *bc);
+uint32_t dump_xattr_ibody(FILE *out, ocfs2_filesys *fs,
+ struct ocfs2_dinode *in, int verbose);
+errcode_t dump_xattr_block(FILE *out, ocfs2_filesys *fs,
+ struct ocfs2_dinode *in,
+ uint32_t *xattrs_block,
+ uint64_t *xattrs_bucket,
+ int verbose);
#endif /* __DUMP_H__ */
--
1.5.4.4
More information about the Ocfs2-tools-devel
mailing list