Optionally print out xattr values

We cannot validate that totl keys have the correct count/value without
also extracting and printing the value for xattrs, which by default
is omitted (a sane default). Add a default-disabled --xattr-values/-V
flag to enable printing these out.

Because xattr values can span multiple items, this only will print
out the first one, and ellipsize it if it continues elsewhere. It is
filtered through isprint() to avoid printing non-printable characters.

Signed-off-by: Auke Kok <auke.kok@versity.com>
This commit is contained in:
Auke Kok
2026-04-16 11:26:29 -07:00
parent 8c4e9bfa3e
commit 4e2c1e83be
2 changed files with 45 additions and 6 deletions

View File

@@ -402,7 +402,7 @@ before destroying an old empty data device.
.PD
.TP
.BI "print {-a|--allocs} {-i|--items ITEMS} {-r|--roots ROOTS} {-S|--skip-likely-huge} META-DEVICE"
.BI "print {-a|--allocs} {-i|--items ITEMS} {-r|--roots ROOTS} {-S|--skip-likely-huge} {-V|--xattr-values} META-DEVICE"
.sp
Prints out some or all of the metadata in the file system. This makes no effort
to ensure that the structures are consistent as they're traversed and
@@ -430,6 +430,11 @@ more of the following items: inode, xattr, dirent, symlink, backref, extent,
totl, indx, inoindex, orphan, quota.
Default is all items.
.TP
.B "-V, --xattr-values"
Print xattr values alongside the xattr item. Non-printable bytes are
rendered as '.'. A trailing '...' indicates the value continues in
additional item parts that aren't shown.
.TP
.B "-S, --skip-likely-huge"
Skip printing structures that are likely to be very large. The
structures that are skipped tend to be global and whose size tends to be

View File

@@ -50,6 +50,7 @@ struct print_args {
bool print_inode_index;
bool print_orphan;
bool print_quota;
bool print_xattr_values;
};
static struct print_args print_args = {
@@ -72,7 +73,8 @@ static struct print_args print_args = {
.print_indx = true,
.print_inode_index = true,
.print_orphan = true,
.print_quota = true
.print_quota = true,
.print_xattr_values = false
};
static void print_block_header(struct scoutfs_block_header *hdr, int size)
@@ -181,15 +183,42 @@ static u8 *global_printable_name(u8 *name, int name_len)
static void print_xattr(struct scoutfs_key *key, void *val, int val_len)
{
struct scoutfs_xattr *xat = val;
unsigned int full_val_len;
int avail;
int show;
int i;
printf(" xattr: ino %llu name_hash %08x id %llu part %u\n",
le64_to_cpu(key->skx_ino), (u32)le64_to_cpu(key->skx_name_hash),
le64_to_cpu(key->skx_id), key->skx_part);
if (key->skx_part == 0)
printf(" name_len %u val_len %u name %s\n",
xat->name_len, le16_to_cpu(xat->val_len),
global_printable_name(xat->name, xat->name_len));
if (key->skx_part != 0)
return;
full_val_len = le16_to_cpu(xat->val_len);
printf(" name_len %u val_len %u name %s",
xat->name_len, full_val_len,
global_printable_name(xat->name, xat->name_len));
if (!print_args.print_xattr_values) {
putchar('\n');
return;
}
avail = val_len - (int)sizeof(*xat) - xat->name_len;
if (avail < 0)
avail = 0;
show = avail < (int)full_val_len ? avail : (int)full_val_len;
printf(" value ");
for (i = 0; i < show; i++) {
u8 c = xat->name[xat->name_len + i];
putchar(isprint(c) ? c : '.');
}
if (show < (int)full_val_len)
printf("...");
putchar('\n');
}
static void print_dirent(struct scoutfs_key *key, void *val, int val_len)
@@ -1331,6 +1360,10 @@ static int parse_opt(int key, char *arg, struct argp_state *state)
args->walk_allocs = true;
break;
case 'V':
args->print_xattr_values = true;
break;
case 'i':
/* Specific items being requested- clear them all to start */
if (!args->items_requested) {
@@ -1449,6 +1482,7 @@ static struct argp_option options[] = {
{ "items", 'i', "ITEMS", 0, "Item(s) to print (inode, xattr, dirent, symlink, backref, extent, totl, indx, inoindex, orphan, quota)" },
{ "roots", 'r', "ROOTS", 0, "Tree root(s) to walk (logs, srch, fs)" },
{ "skip-likely-huge", 'S', NULL, 0, "Skip allocs, srch root and fs root to minimize output size" },
{ "xattr-values", 'V', NULL, 0, "Print xattr values (non-printable bytes rendered as '.')" },
{ NULL }
};