[PATCH 21/23] Add ngnfs_xattr_list() and debugfs command
Valerie Aurora
val at versity.com
Fri Apr 4 11:45:37 PDT 2025
Add ability to list extended attributes and associated debugfs
command.
Signed-off-by: Valerie Aurora <val at versity.com>
---
cli/debugfs.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
shared/xattr.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
shared/xattr.h | 2 ++
3 files changed, 122 insertions(+)
diff --git a/cli/debugfs.c b/cli/debugfs.c
index 2ea1fb5..3097b21 100644
--- a/cli/debugfs.c
+++ b/cli/debugfs.c
@@ -232,6 +232,62 @@ out:
return;
}
+static void cmd_listxattr(struct debugfs_context *ctx, int argc, char **argv)
+{
+ struct ngnfs_dir_lookup_entry lent;
+ char *filename;
+ char *buf, *next;
+ u64 buf_size = 64 * 1024; /* default max name list */
+ ssize_t bytes, name_len;
+ int nr;
+ int ret;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("usage: listxattr <filename> [buf size]\n");
+ return;
+ }
+
+ filename = argv[1];
+ if (argc == 3) {
+ ret = parse_ull(&buf_size, argv[2], 0, buf_size);
+ if (ret < 0)
+ return;
+ }
+
+ buf = malloc(buf_size);
+ if (!buf) {
+ printf("malloc error");
+ return;
+ }
+
+ ret = ngnfs_dir_lookup(ctx->nfi, &ctx->cwd_ig, filename, strlen(filename), &lent);
+ if (ret < 0) {
+ print_err("listxattr", ret);
+ goto out;
+ }
+
+ bytes = ngnfs_xattr_list(ctx->nfi, &lent.ig, buf, buf_size);
+ if (bytes < 0) {
+ print_err("listxattr", bytes);
+ goto out;
+ }
+
+ if (buf_size > 0) {
+ nr = 0;
+ for (next = buf; next < buf + bytes; next += name_len + 1) {
+ name_len = strlen(next);
+ nr++;
+ printf("%s\n", next);
+ }
+ printf("total xattrs: %d\n", nr);
+ } else {
+ printf("bytes needed to list xattrs: %ld\n", bytes);
+ }
+out:
+ free(buf);
+ return;
+}
+
static void cmd_lookup(struct debugfs_context *ctx, int argc, char **argv)
{
struct ngnfs_dir_lookup_entry lent;
@@ -559,6 +615,7 @@ static struct command {
{ "cd", cmd_cd, },
{ "create", cmd_create, },
{ "getxattr", cmd_getxattr, },
+ { "listxattr", cmd_listxattr, },
{ "lookup", cmd_lookup, },
{ "mkdir", cmd_mkdir, },
{ "mkfs", cmd_mkfs, },
diff --git a/shared/xattr.c b/shared/xattr.c
index 6a0fafe..2229eeb 100644
--- a/shared/xattr.c
+++ b/shared/xattr.c
@@ -367,3 +367,66 @@ int ngnfs_xattr_set(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *ig, c
kfree(xattr);
return ret;
}
+
+struct listxattr_args {
+ void *buf;
+ size_t size;
+ size_t used;
+};
+
+/*
+ * Copy one xattr name into the buf, followed by a null byte, unless the
+ * buf is zero size, in which case just increment the size counter.
+ */
+static int fill_listxattr_rd(struct ngnfs_btree_key *key, void *val, size_t val_size, void *args)
+{
+ struct listxattr_args *la = args;
+ struct ngnfs_xattr *xattr = val;
+ size_t bytes;
+
+ bytes = xattr->name_len + 1;
+ if (la->size == 0) /* just counting the bytes, not copying them */
+ goto out;
+
+ if (bytes > (la->size - la->used))
+ return -ERANGE;
+
+ memcpy(la->buf + la->used, xattr->name, xattr->name_len);
+ memset(la->buf + la->used + xattr->name_len + 1, 0, 1);
+out:
+ la->used = la->used + xattr->name_len + 1;
+ return NGNFS_BTREE_ITER_CONTINUE;
+}
+
+/*
+ * Return a list of names of extended attributes, separated by nulls, or
+ * if the size of the buf is zero, the size that would be required to
+ * return the list.
+ */
+ssize_t ngnfs_xattr_list(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *ig, void *buf,
+ size_t size)
+{
+ struct ngnfs_inode_txn_ref ino;
+ struct ngnfs_transaction txn;
+ struct ngnfs_btree_key key;
+ struct listxattr_args la;
+ int ret;
+
+ la.buf = buf;
+ la.size = size;
+ la.used = 0;
+
+ ngnfs_txn_init(&txn);
+ init_xattr_key(&key, 0);
+
+ do {
+ ret = ngnfs_inode_get(nfi, &txn, NBF_READ, ig, &ino) ?:
+ ngnfs_btree_read_iter(nfi, &txn, &ino.ninode->xattrs, &key,
+ NULL, NULL, fill_listxattr_rd, &la);
+
+ } while (ngnfs_txn_retry(nfi, &txn, &ret));
+
+ ngnfs_txn_teardown(nfi, &txn);
+
+ return ret ?: la.used;
+}
diff --git a/shared/xattr.h b/shared/xattr.h
index da3eeb4..97f5c77 100644
--- a/shared/xattr.h
+++ b/shared/xattr.h
@@ -10,5 +10,7 @@ ssize_t ngnfs_xattr_get(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *i
int ngnfs_xattr_remove(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *ig, char *name);
int ngnfs_xattr_set(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *ig, char *name,
void *value, size_t val_size, int flags);
+ssize_t ngnfs_xattr_list(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *ig, void *buf,
+ size_t size);
#endif
--
2.48.1
More information about the ngnfs-devel
mailing list