On Thu, Feb 26, 2026 at 10:50 AM Gao Xiang <[email protected]> wrote:
>
> Hi Inseob,
>
> On 2026/2/26 08:59, Inseob Kim wrote:
> > Add --nid and --path options to fsck.erofs to allow users to check
> > or extract specific sub-directories or files instead of the entire
> > filesystem.
> >
> > This is useful for targeted data recovery or verifying specific
> > image components without the overhead of a full traversal.
>
> Thanks for the patch!

Thank *you* for quick response!

>
> >
> > Signed-off-by: Inseob Kim <[email protected]>
> > ---
> >   fsck/main.c | 50 ++++++++++++++++++++++++++++++++++++++++----------
> >   1 file changed, 40 insertions(+), 10 deletions(-)
> >
> > diff --git a/fsck/main.c b/fsck/main.c
> > index ab697be..a7d9f46 100644
> > --- a/fsck/main.c
> > +++ b/fsck/main.c
> > @@ -39,6 +39,8 @@ struct erofsfsck_cfg {
> >       bool preserve_owner;
> >       bool preserve_perms;
> >       bool dump_xattrs;
> > +     erofs_nid_t nid;
> > +     const char *inode_path;
> >       bool nosbcrc;
> >   };
> >   static struct erofsfsck_cfg fsckcfg;
> > @@ -59,6 +61,8 @@ static struct option long_options[] = {
> >       {"offset", required_argument, 0, 12},
> >       {"xattrs", no_argument, 0, 13},
> >       {"no-xattrs", no_argument, 0, 14},
> > +     {"nid", required_argument, 0, 15},
> > +     {"path", required_argument, 0, 16},
> >       {"no-sbcrc", no_argument, 0, 512},
> >       {0, 0, 0, 0},
> >   };
> > @@ -110,6 +114,8 @@ static void usage(int argc, char **argv)
> >               " --extract[=X]          check if all files are well encoded, 
> > optionally\n"
> >               "                        extract to X\n"
> >               " --offset=#             skip # bytes at the beginning of 
> > IMAGE\n"
> > +             " --nid=#                check or extract from the target 
> > inode of nid #\n"
> > +             " --path=X               check or extract from the target 
> > inode of path X\n"
> >               " --no-sbcrc             bypass the superblock checksum 
> > verification\n"
> >               " --[no-]xattrs          whether to dump extended attributes 
> > (default off)\n"
> >               "\n"
> > @@ -245,6 +251,12 @@ static int erofsfsck_parse_options_cfg(int argc, char 
> > **argv)
> >               case 14:
> >                       fsckcfg.dump_xattrs = false;
> >                       break;
> > +             case 15:
> > +                     fsckcfg.nid = (erofs_nid_t)atoll(optarg);
> > +                     break;
> > +             case 16:
> > +                     fsckcfg.inode_path = optarg;
> > +                     break;
> >               case 512:
> >                       fsckcfg.nosbcrc = true;
> >                       break;
> > @@ -981,7 +993,8 @@ static int erofsfsck_check_inode(erofs_nid_t pnid, 
> > erofs_nid_t nid)
> >
> >       if (S_ISDIR(inode.i_mode)) {
> >               struct erofs_dir_context ctx = {
> > -                     .flags = EROFS_READDIR_VALID_PNID,
> > +                     .flags = (pnid == nid && nid != g_sbi.root_nid) ?
>
> Does it relax the validatation check?
>
> and does (nid == pnid && nid == fsckcfg.nid) work?

It shouldn't relax the existing validation check.
`erofsfsck_check_inode` is called with `err =
erofsfsck_check_inode(fsckcfg.nid, fsckcfg.nid);`.

* If a given path is not the root, `nid`'s parent `..` will differ
from `pnid`, causing failure. This condition only relaxes the starting
directory.
* In the case of the root, `nid`'s parent `..` should indeed be
itself. So we can still validate.

If you have any better suggestions, I'll follow them.

>
> > +                             0 : EROFS_READDIR_VALID_PNID,
> >                       .pnid = pnid,
> >                       .dir = &inode,
> >                       .cb = erofsfsck_dirent_iter,
> > @@ -1033,6 +1046,8 @@ int main(int argc, char *argv[])
> >       fsckcfg.preserve_owner = fsckcfg.superuser;
> >       fsckcfg.preserve_perms = fsckcfg.superuser;
> >       fsckcfg.dump_xattrs = false;
> > +     fsckcfg.nid = 0;
> > +     fsckcfg.inode_path = NULL;
> >
> >       err = erofsfsck_parse_options_cfg(argc, argv);
> >       if (err) {
> > @@ -1068,22 +1083,37 @@ int main(int argc, char *argv[])
> >       if (fsckcfg.extract_path)
> >               erofsfsck_hardlink_init();
> >
> > -     if (erofs_sb_has_fragments(&g_sbi) && g_sbi.packed_nid > 0) {
> > -             err = erofs_packedfile_init(&g_sbi, false);
> > +     if (fsckcfg.inode_path) {
> > +             struct erofs_inode inode = { .sbi = &g_sbi };
> > +
> > +             err = erofs_ilookup(fsckcfg.inode_path, &inode);
> >               if (err) {
> > -                     erofs_err("failed to initialize packedfile: %s",
> > -                               erofs_strerror(err));
> > +                     erofs_err("failed to lookup %s", fsckcfg.inode_path);
> >                       goto exit_hardlink;
> >               }
>
> It would be better to check if it's a directory.

My intention was that we support both directories and files. Or should
I create a separate flag like `--cat` in dump.erofs?

>
> Thanks,
> Gao Xiang
>
> > +             fsckcfg.nid = inode.nid;
> > +     } else if (!fsckcfg.nid) {
> > +             fsckcfg.nid = g_sbi.root_nid;
> > +     }
> >
> > -             err = erofsfsck_check_inode(g_sbi.packed_nid, 
> > g_sbi.packed_nid);
> > -             if (err) {
> > -                     erofs_err("failed to verify packed file");
> > -                     goto exit_packedinode;
> > +     if (!fsckcfg.inode_path && fsckcfg.nid == g_sbi.root_nid) {
> > +             if (erofs_sb_has_fragments(&g_sbi) && g_sbi.packed_nid > 0) {
> > +                     err = erofs_packedfile_init(&g_sbi, false);
> > +                     if (err) {
> > +                             erofs_err("failed to initialize packedfile: 
> > %s",
> > +                                       erofs_strerror(err));
> > +                             goto exit_hardlink;
> > +                     }
> > +
> > +                     err = erofsfsck_check_inode(g_sbi.packed_nid, 
> > g_sbi.packed_nid);
> > +                     if (err) {
> > +                             erofs_err("failed to verify packed file");
> > +                             goto exit_packedinode;
> > +                     }
> >               }
> >       }
> >
> > -     err = erofsfsck_check_inode(g_sbi.root_nid, g_sbi.root_nid);
> > +     err = erofsfsck_check_inode(fsckcfg.nid, fsckcfg.nid);
> >       if (fsckcfg.corrupted) {
> >               if (!fsckcfg.extract_path)
> >                       erofs_err("Found some filesystem corruption");
>

-- 
Inseob Kim | Software Engineer | [email protected]

Reply via email to