[PATCH 08/14] Add ngnfs_dir_get_dirent() and debugfs lookup command

Valerie Aurora val at versity.com
Thu Feb 27 11:24:59 PST 2025


On Thu, Feb 27, 2025 at 3:17 PM Valerie Aurora <val at versity.com> wrote:
>
> Add function to return ngnfs directory entries and associated debugfs
> command for debugging purposes.
>
> Signed-off-by: Valerie Aurora <val at versity.com>
> ---
>  cli/debugfs.c |  47 ++++++++++++++++++-
>  shared/dir.c  | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  shared/dir.h  |   8 ++++
>  3 files changed, 181 insertions(+), 1 deletion(-)
>
> diff --git a/cli/debugfs.c b/cli/debugfs.c
> index 1972f13..9d3bd5d 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"
> @@ -48,6 +48,50 @@ static void cmd_create(struct debugfs_context *ctx, int argc, char **argv)
>                 printf("create error: "ENOF"\n", ENOA(-ret));
>  }
>
> +static void cmd_lookup(struct debugfs_context *ctx, int argc, char **argv)
> +{
> +       struct ngnfs_dirent *dent;
> +       char *name;
> +       int ret;
> +
> +       if (argc != 2) {
> +               printf("usage: lookup <pathname>\n");
> +               return;
> +       }
> +
> +       name = argv[1];
> +
> +       dent = malloc(offsetof(struct ngnfs_dirent, name) + strlen(name));
> +       if (!dent) {
> +               log("lookup error: "ENOF"\n", ENOA(ENOENT));
> +               return;
> +       }
> +
> +
> +       ret = ngnfs_dir_get_dirent(ctx->nfi, ctx->cwd_ino, name, strlen(name), dent);
> +       if (ret < 0) {
> +               if (ret == -ENAMETOOLONG)
> +                       printf("lookup: %s name too long\n", name);
> +               else if (ret == -ENOENT)
> +                       printf("lookup: %s does not exist\n", name);
> +               else
> +                       log("lookup error: "ENOF"\n", ENOA(-ret));
> +               return;
> +       }
> +
> +       printf("name: %.*s\n"
> +              "name_len: %d\n"
> +              "dtype: %o\n"
> +              "ino: %llu\n"
> +              "gen: %llu\n",
> +              dent->name_len,
> +              dent->name,
> +              dent->name_len,
> +              ngnfs_type_to_dtype(dent->type),
> +              le64_to_cpu(dent->ino),
> +              le64_to_cpu(dent->version));
> +}
> +
>  static void cmd_mkfs(struct debugfs_context *ctx, int argc, char **argv)
>  {
>         int ret;
> @@ -158,6 +202,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 0439816..4b95835 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"
> @@ -446,3 +447,129 @@ int ngnfs_dir_readdir(struct ngnfs_fs_info *nfi, u64 dir_ino, u64 pos,
>  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 *dst = &da->dent;
> +       struct ngnfs_dirent *src = val;
> +
> +       if (!src)
> +               return -ENOENT;
> +
> +       if (!names_equal(src->name, src->name_len, dst->name, dst->name_len))
> +               return NGNFS_BTREE_ITER_CONTINUE;
> +
> +       da->dent_size = offsetof(struct ngnfs_dirent, name) + src->name_len;
> +       memcpy(dst, src, da->dent_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_inode_txn_ref parent_dir;
> +       int ret;
> +
> +       if (da->hash >= NGNFS_DIRENT_MIN_HASH)
> +               return -ENOENT;
> +
> +       if (da->hash == NGNFS_DIRENT_DOT_HASH) {
> +               fill_dent(dir->ninode->ino, dir->ninode->version,
> +                         mode_to_type(le32_to_cpu(dir->ninode->mode)), ".", 1, &da->dent);
> +               return 0;
> +       }
> +
> +       /* remaining case is .. */
> +       ret = ngnfs_inode_get(nfi, txn, NBF_READ, le64_to_cpu(dir->ninode->parent_ino),
> +                             &parent_dir);
> +       if (ret < 0)
> +               return ret;
> +
> +       fill_dent(parent_dir.ninode->ino, parent_dir.ninode->version,
> +                 mode_to_type(le32_to_cpu(parent_dir.ninode->mode)), "..", 2, &da->dent);
> +
> +       return 0;
> +}
> +
> +static int lookup_iter(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;
> +
> +       init_dirent_key(&key, da->hash);
> +       init_dirent_key(&last, da->hash | NGNFS_DIRENT_COLL_BIT);
> +
> +       ret = lookup_dots(nfi, txn, dir, da);
> +       if (ret == 0)
> +               return ret;
> +
> +       return ngnfs_btree_read_iter(nfi, txn, &dir->ninode->dirents, &key, NULL, &last,
> +                                    fill_lookup_rd, da);

Oops, already found a bug - this and lookup_dirent() need a:

        if (da->dent.ino == 0)
                ret = -ENOENT;

        return ret;

And the null test in fill_lookup_rd() needs to go away. I was mixing
this up with the ngnfs_btree_write_iter which will call the iter func
with a null item if the item doesn't exist. Will resend!

Valerie



More information about the ngnfs-devel mailing list