[PATCH] erofs-utils: fsck: support extracting subtrees
Gao Xiang
hsiangkao at linux.alibaba.com
Thu Feb 26 12:50:53 AEDT 2026
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!
>
> Signed-off-by: Inseob Kim <inseob at google.com>
> ---
> 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?
> + 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.
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");
More information about the Linux-erofs
mailing list