[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