[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