[PATCH 12/23] Add ngnfs_dir_lookup() and debugfs lookup command

Valerie Aurora val at versity.com
Fri Apr 4 11:45:28 PDT 2025


Add ngnfs_dir_lookup() to return ngnfs directory entry information and
the associated debugfs lookup command for debugging purposes.

Signed-off-by: Valerie Aurora <val at versity.com>
---
 cli/debugfs.c |  37 +++++++++++++++++-
 shared/dir.c  | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++
 shared/dir.h  |  12 ++++++
 3 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/cli/debugfs.c b/cli/debugfs.c
index fb0a82c..b6b63cd 100644
--- a/cli/debugfs.c
+++ b/cli/debugfs.c
@@ -14,8 +14,8 @@
 #include "shared/lk/kernel.h"
 #include "shared/lk/types.h"
 
-#include "shared/format-block.h"
 #include "shared/dir.h"
+#include "shared/format-block.h"
 #include "shared/inode.h"
 #include "shared/log.h"
 #include "shared/mkfs.h"
@@ -69,6 +69,40 @@ static void cmd_create(struct debugfs_context *ctx, int argc, char **argv)
 		print_err("create", ret);
 }
 
+static void cmd_lookup(struct debugfs_context *ctx, int argc, char **argv)
+{
+	struct ngnfs_dir_lookup_entry lent;
+	char *name;
+	int name_len;
+	int ret;
+
+	if (argc != 2) {
+		printf("usage: lookup <pathname>\n");
+		return;
+	}
+
+	name = argv[1];
+	name_len = strlen(name);
+
+	ret = ngnfs_dir_lookup(ctx->nfi, &ctx->cwd_ig, name, name_len, &lent);
+	if (ret < 0) {
+		print_err("lookup", ret);
+		return;
+	}
+
+	printf("name: %.*s\n"
+	       "name_len: %d\n"
+	       "dtype: %o\n"
+	       "ino: %llu\n"
+	       "gen: %llu\n",
+	       name_len,
+	       name,
+	       name_len,
+	       lent.dtype,
+	       lent.ig.ino,
+	       lent.ig.gen);
+}
+
 static void cmd_mkfs(struct debugfs_context *ctx, int argc, char **argv)
 {
 	int ret;
@@ -199,6 +233,7 @@ static struct command {
 	void (*func)(struct debugfs_context *ctx, int argc, char **argv);
 } commands[] = {
 	{ "create", cmd_create, },
+	{ "lookup", cmd_lookup, },
 	{ "mkfs", cmd_mkfs, },
 	{ "quit", cmd_quit, },
 	{ "readdir", cmd_readdir, },
diff --git a/shared/dir.c b/shared/dir.c
index c1054e6..af5fd55 100644
--- a/shared/dir.c
+++ b/shared/dir.c
@@ -6,6 +6,7 @@
 #include "shared/lk/bug.h"
 #include "shared/lk/byteorder.h"
 #include "shared/lk/container_of.h"
+#include "shared/lk/err.h"
 #include "shared/lk/errno.h"
 #include "shared/lk/fs_types.h"
 #include "shared/lk/kernel.h"
@@ -448,3 +449,107 @@ int ngnfs_dir_readdir(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *dir
 out:
 	return ret ?: ra.nr;
 }
+
+static int fill_lookup_rd(struct ngnfs_btree_key *key, void *val, size_t val_size, void *arg)
+{
+	struct dirent_args *da = arg;
+	struct ngnfs_dirent *dent = val;
+
+	if (!names_equal(dent->name, dent->name_len, (u8 *) da->dent.name, da->dent.name_len))
+		return NGNFS_BTREE_ITER_CONTINUE;
+
+	da->ig.ino = le64_to_cpu(dent->ig.ino);
+	da->ig.gen = le64_to_cpu(dent->ig.gen);
+	memcpy(&da->dent, dent, val_size);
+
+	return 0;
+}
+
+static int lookup_dots(struct ngnfs_fs_info *nfi, struct ngnfs_transaction *txn,
+		       struct ngnfs_inode_txn_ref *dir, struct dirent_args *da)
+{
+	struct ngnfs_btree_key key;
+
+	if (da->hash >= NGNFS_DIRENT_MIN_HASH)
+		return -ENOENT;
+
+	init_dirent_key(&key, da->hash);
+	fill_dot_dirent(da->hash, &da->dent, dir);
+
+	return 0;
+}
+
+static int lookup_dirent(struct ngnfs_fs_info *nfi, struct ngnfs_transaction *txn,
+			 struct ngnfs_inode_txn_ref *dir, struct dirent_args *da)
+{
+	struct ngnfs_btree_key key;
+	struct ngnfs_btree_key last;
+	int ret;
+
+	ret = lookup_dots(nfi, txn, dir, da);
+	if (ret == 0)
+		goto out;
+
+	init_dirent_key(&key, da->hash);
+	init_dirent_key(&last, da->hash | NGNFS_DIRENT_COLL_BIT);
+
+	ret = ngnfs_btree_read_iter(nfi, txn, &dir->ninode->dirents, &key, NULL, &last,
+				    fill_lookup_rd, da);
+	if (ret < 0)
+		goto out;
+
+	if (da->ig.ino == 0)
+		ret = -ENOENT;
+out:
+	return ret;
+}
+
+static int copy_dent_to_lent(struct ngnfs_dirent *dent, struct ngnfs_dir_lookup_entry *lent)
+{
+	lent->ig.ino = le64_to_cpu(dent->ig.ino);
+	lent->ig.gen = le64_to_cpu(dent->ig.gen);
+	lent->dtype = pers_dtype_to_abi_dtype(dent->pers_dtype);
+
+	return 0;
+}
+
+int ngnfs_dir_lookup(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *dir_ig, char *name,
+		     size_t name_len, struct ngnfs_dir_lookup_entry *lent)
+{
+	struct {
+		struct ngnfs_transaction txn;
+		struct ngnfs_inode_txn_ref dir;
+		struct dirent_args da;
+	} *op;
+	int ret;
+
+	if (name_len > NGNFS_NAME_MAX) {
+		ret = -ENAMETOOLONG;
+		goto out;
+	}
+
+	op = kmalloc(sizeof(*op), GFP_NOFS);
+	if (!op) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ngnfs_txn_init(&op->txn);
+	init_dirent_args(&op->da, name, name_len, 0);
+
+	do {
+		ret = ngnfs_inode_get(nfi, &op->txn, NBF_READ, dir_ig, &op->dir)		?:
+		      check_ifmt(op->dir.ninode, S_IFDIR, -ENOTDIR)				?:
+		      lookup_dirent(nfi, &op->txn, &op->dir, &op->da);
+
+	} while (ngnfs_txn_retry(nfi, &op->txn, &ret));
+
+	ngnfs_txn_teardown(nfi, &op->txn);
+
+	if (ret == 0)
+		copy_dent_to_lent(&op->da.dent, lent);
+
+	kfree(op);
+out:
+	return ret;
+}
diff --git a/shared/dir.h b/shared/dir.h
index d56641f..38c3095 100644
--- a/shared/dir.h
+++ b/shared/dir.h
@@ -39,4 +39,16 @@ struct ngnfs_readdir_entry {
 int ngnfs_dir_readdir(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *dir_ig, u64 pos,
 		      struct ngnfs_readdir_entry *buf, size_t size);
 
+/*
+ * Lookup returns only the inode number, generation, and the POSIX ABI
+ * type.
+ */
+struct ngnfs_dir_lookup_entry {
+	struct ngnfs_inode_ino_gen ig;
+	u8 dtype;
+};
+
+int ngnfs_dir_lookup(struct ngnfs_fs_info *nfi, struct ngnfs_inode_ino_gen *dir_ig, char *name,
+		     size_t name_len, struct ngnfs_dir_lookup_entry *lent);
+
 #endif
-- 
2.48.1




More information about the ngnfs-devel mailing list