[PATCH v2 4/4] erofs-utils: mkfs: add `--inode-digest-xattr` option

Hongbo Li lihongbo22 at huawei.com
Tue Dec 30 14:44:48 AEDT 2025



On 2025/12/30 2:06, Gao Xiang wrote:
> Based on the original Hongbo's version [1], it enables storing the
> SHA-256 digest of each inode as an extended attribute, in preparation
> for the upcoming page cache sharing feature.
> 
> Example usage:
>   $ mkfs.erofs --xattr-inode-digest=trusted.erofs.fingerprint [-zlz4hc] foo.erofs foo/
> 
> Co-developed-by: Hongbo Li <lihongbo22 at huawei.com>
> [1] https://lore.kernel.org/r/20251118015849.228939-1-lihongbo22@huawei.com
> Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>

Maybe the subject should be changed to "erofs-utils: mkfs: add 
`--xattr-inode-digest` option".

Tested-by: Hongbo Li <lihongbo22 at huawei.com>

Thanks,
Hongbo

> ---
>   - address Hongbo's comment:
>      https://lore.kernel.org/r/9b732162-18a4-442a-b862-50a2cdd4a1a9@huawei.com
> 
>   include/erofs/internal.h |   2 +
>   include/erofs/xattr.h    |   2 +
>   include/erofs_fs.h       |   4 +-
>   lib/inode.c              |  46 +++++++++-
>   lib/super.c              |  13 ++-
>   lib/xattr.c              |  14 ++-
>   mkfs/main.c              | 186 ++++++++++++++++++++++-----------------
>   7 files changed, 178 insertions(+), 89 deletions(-)
> 
> diff --git a/include/erofs/internal.h b/include/erofs/internal.h
> index 62594b877151..5798f10e89c2 100644
> --- a/include/erofs/internal.h
> +++ b/include/erofs/internal.h
> @@ -130,6 +130,7 @@ struct erofs_sb_info {
>   
>   	u32 xattr_prefix_start;
>   	u8 xattr_prefix_count;
> +	u8 ishare_xattr_prefix_id;
>   	struct erofs_xattr_prefix_item *xattr_prefixes;
>   
>   	struct erofs_vfile bdev;
> @@ -189,6 +190,7 @@ EROFS_FEATURE_FUNCS(metabox, incompat, INCOMPAT_METABOX)
>   EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
>   EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER)
>   EROFS_FEATURE_FUNCS(plain_xattr_pfx, compat, COMPAT_PLAIN_XATTR_PFX)
> +EROFS_FEATURE_FUNCS(ishare_xattrs, compat, COMPAT_ISHARE_XATTRS)
>   
>   #define EROFS_I_EA_INITED_BIT	0
>   #define EROFS_I_Z_INITED_BIT	1
> diff --git a/include/erofs/xattr.h b/include/erofs/xattr.h
> index 941bed778956..96546364f316 100644
> --- a/include/erofs/xattr.h
> +++ b/include/erofs/xattr.h
> @@ -33,6 +33,8 @@ char *erofs_export_xattr_ibody(struct erofs_inode *inode);
>   int erofs_load_shared_xattrs_from_path(struct erofs_sb_info *sbi, const char *path,
>   				       long inlinexattr_tolerance);
>   int erofs_xattr_insert_name_prefix(const char *prefix);
> +int erofs_xattr_set_ishare_prefix(struct erofs_sb_info *sbi,
> +				  const char *prefix);
>   void erofs_xattr_cleanup_name_prefixes(void);
>   int erofs_xattr_flush_name_prefixes(struct erofs_importer *im, bool plain);
>   int erofs_xattr_prefixes_init(struct erofs_sb_info *sbi);
> diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> index 887f37faba59..8b0d155f8c4c 100644
> --- a/include/erofs_fs.h
> +++ b/include/erofs_fs.h
> @@ -17,6 +17,7 @@
>   #define EROFS_FEATURE_COMPAT_MTIME              0x00000002
>   #define EROFS_FEATURE_COMPAT_XATTR_FILTER	0x00000004
>   #define EROFS_FEATURE_COMPAT_PLAIN_XATTR_PFX	0x00000010
> +#define EROFS_FEATURE_COMPAT_ISHARE_XATTRS	0x00000020
>   
>   /*
>    * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should
> @@ -82,7 +83,8 @@ struct erofs_super_block {
>   	__le32 xattr_prefix_start;	/* start of long xattr prefixes */
>   	__le64 packed_nid;	/* nid of the special packed inode */
>   	__u8 xattr_filter_reserved; /* reserved for xattr name filter */
> -	__u8 reserved[3];
> +	__u8 ishare_xattr_prefix_id;
> +	__u8 reserved[2];
>   	__le32 build_time;	/* seconds added to epoch for mkfs time */
>   	__le64 rootnid_8b;	/* (48BIT on) nid of root directory */
>   	__le64 reserved2;
> diff --git a/lib/inode.c b/lib/inode.c
> index 7ee16f4db183..fa0665c4faca 100644
> --- a/lib/inode.c
> +++ b/lib/inode.c
> @@ -31,6 +31,7 @@
>   #include "liberofs_metabox.h"
>   #include "liberofs_private.h"
>   #include "liberofs_rebuild.h"
> +#include "sha256.h"
>   
>   static inline bool erofs_is_special_identifier(const char *path)
>   {
> @@ -1898,6 +1899,37 @@ static int erofs_prepare_dir_inode(const struct erofs_mkfs_btctx *ctx,
>   	return 0;
>   }
>   
> +static int erofs_set_inode_fingerprint(struct erofs_inode *inode, int fd,
> +				       erofs_off_t pos)
> +{
> +	u8 ishare_xattr_prefix_id = inode->sbi->ishare_xattr_prefix_id;
> +	erofs_off_t remaining = inode->i_size;
> +	struct erofs_vfile vf = { .fd = fd };
> +	struct sha256_state md;
> +	u8 out[32 + sizeof("sha256:") - 1];
> +	int ret;
> +
> +	if (!ishare_xattr_prefix_id)
> +		return 0;
> +	erofs_sha256_init(&md);
> +	do {
> +		u8 buf[32768];
> +
> +		ret = erofs_io_pread(&vf, buf,
> +				     min_t(u64, remaining, sizeof(buf)), pos);
> +		if (ret < 0)
> +			return ret;
> +		if (ret > 0)
> +			erofs_sha256_process(&md, buf, ret);
> +		remaining -= ret;
> +		pos += ret;
> +	} while (remaining);
> +	erofs_sha256_done(&md, out + sizeof("sha256:") - 1);
> +	memcpy(out, "sha256:", sizeof("sha256:") - 1);
> +	return erofs_setxattr(inode, ishare_xattr_prefix_id, "",
> +			      out, sizeof(out));
> +}
> +
>   static int erofs_mkfs_begin_nondirectory(const struct erofs_mkfs_btctx *btctx,
>   					 struct erofs_inode *inode)
>   {
> @@ -1917,11 +1949,18 @@ static int erofs_mkfs_begin_nondirectory(const struct erofs_mkfs_btctx *btctx,
>   			ctx.fd = open(inode->i_srcpath, O_RDONLY | O_BINARY);
>   			if (ctx.fd < 0)
>   				return -errno;
> -			__erofs_fallthrough;
> -		default:
>   			break;
> +		default:
> +			goto out;
>   		}
> -		if (ctx.fd >= 0 && cfg.c_compr_opts[0].alg &&
> +
> +		if (S_ISREG(inode->i_mode) && inode->i_size) {
> +			ret = erofs_set_inode_fingerprint(inode, ctx.fd, ctx.fpos);
> +			if (ret < 0)
> +				return ret;
> +		}
> +
> +		if (cfg.c_compr_opts[0].alg &&
>   		    erofs_file_is_compressible(im, inode)) {
>   			ctx.ictx = erofs_prepare_compressed_file(im, inode);
>   			if (IS_ERR(ctx.ictx))
> @@ -1933,6 +1972,7 @@ static int erofs_mkfs_begin_nondirectory(const struct erofs_mkfs_btctx *btctx,
>   				return ret;
>   		}
>   	}
> +out:
>   	return erofs_mkfs_go(btctx, EROFS_MKFS_JOB_NDIR, &ctx, sizeof(ctx));
>   }
>   
> diff --git a/lib/super.c b/lib/super.c
> index e54aff2d4ab7..a4837e5702ed 100644
> --- a/lib/super.c
> +++ b/lib/super.c
> @@ -146,7 +146,15 @@ int erofs_read_superblock(struct erofs_sb_info *sbi)
>   	sbi->build_time = le32_to_cpu(dsb->build_time);
>   
>   	memcpy(&sbi->uuid, dsb->uuid, sizeof(dsb->uuid));
> -
> +	if (erofs_sb_has_ishare_xattrs(sbi)) {
> +		if (dsb->ishare_xattr_prefix_id >= sbi->xattr_prefix_count) {
> +			erofs_err("invalid ishare xattr prefix id %d",
> +				  dsb->ishare_xattr_prefix_id);
> +			return -EFSCORRUPTED;
> +		}
> +		sbi->ishare_xattr_prefix_id =
> +			dsb->ishare_xattr_prefix_id | EROFS_XATTR_LONG_PREFIX;
> +	}
>   	ret = z_erofs_parse_cfgs(sbi, dsb);
>   	if (ret)
>   		return ret;
> @@ -160,7 +168,6 @@ int erofs_read_superblock(struct erofs_sb_info *sbi)
>   		free(sbi->devs);
>   		sbi->devs = NULL;
>   	}
> -
>   	sbi->sb_valid = !ret;
>   	return ret;
>   }
> @@ -206,6 +213,8 @@ int erofs_writesb(struct erofs_sb_info *sbi)
>   		.extra_devices = cpu_to_le16(sbi->extra_devices),
>   		.devt_slotoff = cpu_to_le16(sbi->devt_slotoff),
>   		.packed_nid = cpu_to_le64(sbi->packed_nid),
> +		.ishare_xattr_prefix_id = sbi->ishare_xattr_prefix_id &
> +			EROFS_XATTR_LONG_PREFIX_MASK,
>   	};
>   	char *buf;
>   	int ret;
> diff --git a/lib/xattr.c b/lib/xattr.c
> index b6b1a5e600fb..764aee3be3c3 100644
> --- a/lib/xattr.c
> +++ b/lib/xattr.c
> @@ -1495,9 +1495,21 @@ int erofs_xattr_insert_name_prefix(const char *prefix)
>   	}
>   
>   	tnode->index = EROFS_XATTR_LONG_PREFIX | ea_prefix_count;
> -	ea_prefix_count++;
>   	init_list_head(&tnode->list);
>   	list_add_tail(&tnode->list, &ea_name_prefixes);
> +	return ea_prefix_count++;
> +}
> +
> +int erofs_xattr_set_ishare_prefix(struct erofs_sb_info *sbi,
> +				  const char *prefix)
> +{
> +	int err;
> +
> +	err = erofs_xattr_insert_name_prefix(prefix);
> +	if (err < 0)
> +		return err;
> +	sbi->ishare_xattr_prefix_id = EROFS_XATTR_LONG_PREFIX | err;
> +	erofs_sb_set_ishare_xattrs(sbi);
>   	return 0;
>   }
>   
> diff --git a/mkfs/main.c b/mkfs/main.c
> index aaa0300bca1b..b7cd3a6b986f 100644
> --- a/mkfs/main.c
> +++ b/mkfs/main.c
> @@ -61,7 +61,6 @@ static struct option long_options[] = {
>   	{"tar", optional_argument, NULL, 20},
>   	{"aufs", no_argument, NULL, 21},
>   	{"mount-point", required_argument, NULL, 512},
> -	{"xattr-prefix", required_argument, NULL, 19},
>   #ifdef WITH_ANDROID
>   	{"product-out", required_argument, NULL, 513},
>   	{"fs-config-file", required_argument, NULL, 514},
> @@ -102,6 +101,8 @@ static struct option long_options[] = {
>   #endif
>   	{"zD", optional_argument, NULL, 536},
>   	{"ZI", optional_argument, NULL, 537},
> +	{"xattr-prefix", required_argument, NULL, 538},
> +	{"xattr-inode-digest", required_argument, NULL, 539},
>   	{0, 0, 0, 0},
>   };
>   
> @@ -167,95 +168,96 @@ static void usage(int argc, char **argv)
>   		}
>   	}
>   	printf(
> -		" -C#                   specify the size of compress physical cluster in bytes\n"
> -		" -EX[,...]             X=extended options\n"
> -		" -L volume-label       set the volume label (maximum 15 bytes)\n"
> -		" -m#[:X]               enable metadata compression (# = physical cluster size in bytes;\n"
> -		"                                                    X = another compression algorithm for metadata)\n"
> -		" -T#                   specify a fixed UNIX timestamp # as build time\n"
> -		"    --all-time         the timestamp is also applied to all files (default)\n"
> -		"    --mkfs-time        the timestamp is applied as build time only\n"
> -		" -UX                   use a given filesystem UUID\n"
> -		" --zD[=<0|1>]          specify directory compression: 0=disable [default], 1=enable\n"
> -		" --ZI[=<0|1>]          specify the separate inode metadata zone availability: 0=disable [default], 1=enable\n"
> -		" --all-root            make all files owned by root\n"
> +		" -C#                    specify the size of compress physical cluster in bytes\n"
> +		" -EX[,...]              X=extended options\n"
> +		" -L volume-label        set the volume label (maximum 15 bytes)\n"
> +		" -m#[:X]                enable metadata compression (# = physical cluster size in bytes;\n"
> +		"                                                     X = another compression algorithm for metadata)\n"
> +		" -T#                    specify a fixed UNIX timestamp # as build time\n"
> +		"    --all-time          the timestamp is also applied to all files (default)\n"
> +		"    --mkfs-time         the timestamp is applied as build time only\n"
> +		" -UX                    use a given filesystem UUID\n"
> +		" --zD[=<0|1>]           specify directory compression: 0=disable [default], 1=enable\n"
> +		" --ZI[=<0|1>]           specify the separate inode metadata zone availability: 0=disable [default], 1=enable\n"
> +		" --all-root             make all files owned by root\n"
>   #ifdef EROFS_MT_ENABLED
> -		" --async-queue-limit=# specify the maximum number of entries in the multi-threaded job queue\n"
> +		" --async-queue-limit=#  specify the maximum number of entries in the multi-threaded job queue\n"
>   #endif
> -		" --blobdev=X           specify an extra device X to store chunked data\n"
> -		" --chunksize=#         generate chunk-based files with #-byte chunks\n"
> -		" --clean=X             run full clean build (default) or:\n"
> -		" --incremental=X       run incremental build\n"
> -		"                       X = data|rvsp|0 (data: full data, rvsp: space fallocated\n"
> -		"                                        0: inodes zeroed)\n"
> -		" --compress-hints=X    specify a file to configure per-file compression strategy\n"
> -		" --dsunit=#            align all data block addresses to multiples of #\n"
> -		" --exclude-path=X      avoid including file X (X = exact literal path)\n"
> -		" --exclude-regex=X     avoid including files that match X (X = regular expression)\n"
> +		" --blobdev=X            specify an extra device X to store chunked data\n"
> +		" --chunksize=#          generate chunk-based files with #-byte chunks\n"
> +		" --clean=X              run full clean build (default) or:\n"
> +		" --incremental=X        run incremental build\n"
> +		"                        X = data|rvsp|0 (data: full data, rvsp: space fallocated\n"
> +		"                                         0: inodes zeroed)\n"
> +		" --compress-hints=X     specify a file to configure per-file compression strategy\n"
> +		" --dsunit=#             align all data block addresses to multiples of #\n"
> +		" --exclude-path=X       avoid including file X (X = exact literal path)\n"
> +		" --exclude-regex=X      avoid including files that match X (X = regular expression)\n"
>   #ifdef HAVE_LIBSELINUX
> -		" --file-contexts=X     specify a file contexts file to setup selinux labels\n"
> +		" --file-contexts=X      specify a file contexts file to setup selinux labels\n"
>   #endif
> -		" --force-uid=#         set all file uids to # (# = UID)\n"
> -		" --force-gid=#         set all file gids to # (# = GID)\n"
> -		" --fsalignblks=#       specify the alignment of the primary device size in blocks\n"
> -		" --uid-offset=#        add offset # to all file uids (# = id offset)\n"
> -		" --gid-offset=#        add offset # to all file gids (# = id offset)\n"
> -		" --hard-dereference    dereference hardlinks, add links as separate inodes\n"
> -		" --ignore-mtime        use build time instead of strict per-file modification time\n"
> -		" --max-extent-bytes=#  set maximum decompressed extent size # in bytes\n"
> -		" --mount-point=X       X=prefix of target fs path (default: /)\n"
> -		" --preserve-mtime      keep per-file modification time strictly\n"
> -		" --offset=#            skip # bytes at the beginning of IMAGE.\n"
> -		" --root-xattr-isize=#  ensure the inline xattr size of the root directory is # bytes at least\n"
> -		" --aufs                replace aufs special files with overlayfs metadata\n"
> -		" --sort=<path,none>    data sorting order for tarballs as input (default: path)\n"
> +		" --force-uid=#          set all file uids to # (# = UID)\n"
> +		" --force-gid=#          set all file gids to # (# = GID)\n"
> +		" --fsalignblks=#        specify the alignment of the primary device size in blocks\n"
> +		" --uid-offset=#         add offset # to all file uids (# = id offset)\n"
> +		" --gid-offset=#         add offset # to all file gids (# = id offset)\n"
> +		" --hard-dereference     dereference hardlinks, add links as separate inodes\n"
> +		" --ignore-mtime         use build time instead of strict per-file modification time\n"
> +		" --max-extent-bytes=#   set maximum decompressed extent size # in bytes\n"
> +		" --mount-point=X        X=prefix of target fs path (default: /)\n"
> +		" --preserve-mtime       keep per-file modification time strictly\n"
> +		" --offset=#             skip # bytes at the beginning of IMAGE.\n"
> +		" --root-xattr-isize=#   ensure the inline xattr size of the root directory is # bytes at least\n"
> +		" --aufs                 replace aufs special files with overlayfs metadata\n"
> +		" --sort=<path,none>     data sorting order for tarballs as input (default: path)\n"
>   #ifdef S3EROFS_ENABLED
> -		" --s3=X                generate an image from S3-compatible object store\n"
> -		"   [,passwd_file=Y]    X=endpoint, Y=s3fs-compatible password file\n"
> -		"   [,urlstyle=Z]       S3 API calling style (Z = vhost|path) (default: vhost)\n"
> -		"   [,sig=<2,4>]        S3 API signature version (default: 2)\n"
> -		"   [,region=W]         W=region code in which endpoint belongs to (required for sig=4)\n"
> +		" --s3=X                 generate an image from S3-compatible object store\n"
> +		"   [,passwd_file=Y]     X=endpoint, Y=s3fs-compatible password file\n"
> +		"   [,urlstyle=Z]        S3 API calling style (Z = vhost|path) (default: vhost)\n"
> +		"   [,sig=<2,4>]         S3 API signature version (default: 2)\n"
> +		"   [,region=W]          W=region code in which endpoint belongs to (required for sig=4)\n"
>   #endif
>   #ifdef OCIEROFS_ENABLED
> -		" --oci=[f|i]           generate a full (f) or index-only (i) image from OCI remote source\n"
> -		"   [,platform=X]       X=platform (default: linux/amd64)\n"
> -		"   [,layer=#]          #=layer index to extract (0-based; omit to extract all layers)\n"
> -		"   [,blob=Y]           Y=blob digest to extract (omit to extract all layers)\n"
> -		"   [,username=Z]       Z=username for authentication (optional)\n"
> -		"   [,password=W]       W=password for authentication (optional)\n"
> -		"   [,insecure]         use HTTP instead of HTTPS (optional)\n"
> +		" --oci=[f|i]            generate a full (f) or index-only (i) image from OCI remote source\n"
> +		"   [,platform=X]        X=platform (default: linux/amd64)\n"
> +		"   [,layer=#]           #=layer index to extract (0-based; omit to extract all layers)\n"
> +		"   [,blob=Y]            Y=blob digest to extract (omit to extract all layers)\n"
> +		"   [,username=Z]        Z=username for authentication (optional)\n"
> +		"   [,password=W]        W=password for authentication (optional)\n"
> +		"   [,insecure]          use HTTP instead of HTTPS (optional)\n"
>   #endif
> -		" --tar=X               generate a full or index-only image from a tarball(-ish) source\n"
> -		"                       (X = f|i|headerball; f=full mode, i=index mode,\n"
> -		"                                            headerball=file data is omited in the source stream)\n"
> -		" --ovlfs-strip=<0,1>   strip overlayfs metadata in the target image (e.g. whiteouts)\n"
> -		" --quiet               quiet execution (do not write anything to standard output.)\n"
> +		" --tar=X                generate a full or index-only image from a tarball(-ish) source\n"
> +		"                        (X = f|i|headerball; f=full mode, i=index mode,\n"
> +		"                                             headerball=file data is omitted in the source stream)\n"
> +		" --ovlfs-strip=<0,1>    strip overlayfs metadata in the target image (e.g. whiteouts)\n"
> +		" --quiet                quiet execution (do not write anything to standard output.)\n"
>   #ifndef NDEBUG
> -		" --random-pclusterblks randomize pclusterblks for big pcluster (debugging only)\n"
> -		" --random-algorithms   randomize per-file algorithms (debugging only)\n"
> +		" --random-pclusterblks  randomize pclusterblks for big pcluster (debugging only)\n"
> +		" --random-algorithms    randomize per-file algorithms (debugging only)\n"
>   #endif
>   #ifdef HAVE_ZLIB
> -		" --ungzip[=X]          try to filter the tarball stream through gzip\n"
> -		"                       (and optionally dump the raw stream to X together)\n"
> +		" --ungzip[=X]           try to filter the tarball stream through gzip\n"
> +		"                        (and optionally dump the raw stream to X together)\n"
>   #endif
>   #ifdef HAVE_LIBLZMA
> -		" --unxz[=X]            try to filter the tarball stream through xz/lzma/lzip\n"
> -		"                       (and optionally dump the raw stream to X together)\n"
> +		" --unxz[=X]             try to filter the tarball stream through xz/lzma/lzip\n"
> +		"                        (and optionally dump the raw stream to X together)\n"
>   #endif
>   #ifdef HAVE_ZLIB
> -		" --gzinfo[=X]          generate AWS SOCI-compatible zinfo in order to support random gzip access\n"
> +		" --gzinfo[=X]           generate AWS SOCI-compatible zinfo in order to support random gzip access\n"
>   #endif
> -		" --vmdk-desc=X         generate a VMDK descriptor file to merge sub-filesystems\n"
> +		" --vmdk-desc=X          generate a VMDK descriptor file to merge sub-filesystems\n"
>   #ifdef EROFS_MT_ENABLED
> -		" --workers=#           set the number of worker threads to # (default: %u)\n"
> +		" --workers=#            set the number of worker threads to # (default: %u)\n"
>   #endif
> -		" --xattr-prefix=X      X=extra xattr name prefix\n"
> -		" --zfeature-bits=#     toggle filesystem compression features according to given bits #\n"
> +		" --xattr-inode-digest=X specify extended attribute name X to record inode digests\n"
> +		" --xattr-prefix=X       X=extra xattr name prefix\n"
> +		" --zfeature-bits=#      toggle filesystem compression features according to given bits #\n"
>   #ifdef WITH_ANDROID
>   		"\n"
>   		"Android-specific options:\n"
> -		" --product-out=X       X=product_out directory\n"
> -		" --fs-config-file=X    X=fs_config file\n"
> +		" --product-out=X        X=product_out directory\n"
> +		" --fs-config-file=X     X=fs_config file\n"
>   #endif
>   #ifdef EROFS_MT_ENABLED
>   		, erofs_get_available_processors() /* --workers= */
> @@ -1259,16 +1261,6 @@ static int mkfs_parse_options_cfg(struct erofs_importer_params *params,
>   				return -EINVAL;
>   			}
>   			break;
> -		case 19:
> -			errno = 0;
> -			opt = erofs_xattr_insert_name_prefix(optarg);
> -			if (opt) {
> -				erofs_err("failed to parse xattr name prefix: %s",
> -					  erofs_strerror(opt));
> -				return opt;
> -			}
> -			cfg.c_extra_ea_name_prefixes = true;
> -			break;
>   		case 20:
>   			mkfs_parse_tar_cfg(optarg);
>   			break;
> @@ -1424,6 +1416,24 @@ static int mkfs_parse_options_cfg(struct erofs_importer_params *params,
>   			else
>   				mkfscfg.inode_metazone = false;
>   			break;
> +		case 538:
> +			errno = 0;
> +			opt = erofs_xattr_insert_name_prefix(optarg);
> +			if (opt < 0) {
> +				erofs_err("failed to parse xattr name prefix: %s",
> +					  erofs_strerror(opt));
> +				return opt;
> +			}
> +			cfg.c_extra_ea_name_prefixes = true;
> +			break;
> +		case 539:
> +			err = erofs_xattr_set_ishare_prefix(&g_sbi, optarg);
> +			if (err < 0) {
> +				erofs_err("failed to parse ishare name: %s",
> +					  erofs_strerror(err));
> +				return err;
> +			}
> +			break;
>   		case 'V':
>   			version();
>   			exit(0);
> @@ -1878,9 +1888,13 @@ int main(int argc, char **argv)
>   			goto exit;
>   		}
>   
> -		if (cfg.c_extra_ea_name_prefixes)
> -			erofs_xattr_flush_name_prefixes(&importer,
> -							mkfs_plain_xattr_pfx);
> +		err = erofs_xattr_flush_name_prefixes(&importer,
> +						      mkfs_plain_xattr_pfx);
> +		if (err) {
> +			erofs_err("failed to flush long xattr prefixes: %s",
> +				  erofs_strerror(err));
> +			goto exit;
> +		}
>   
>   		root = erofs_new_inode(&g_sbi);
>   		if (IS_ERR(root)) {
> @@ -1888,6 +1902,14 @@ int main(int argc, char **argv)
>   			goto exit;
>   		}
>   	} else {
> +		err = erofs_xattr_flush_name_prefixes(&importer,
> +						      mkfs_plain_xattr_pfx);
> +		if (err) {
> +			erofs_err("failed to flush long xattr prefixes: %s",
> +				  erofs_strerror(err));
> +			goto exit;
> +		}
> +
>   		root = erofs_rebuild_make_root(&g_sbi);
>   		if (IS_ERR(root)) {
>   			err = PTR_ERR(root);


More information about the Linux-erofs mailing list