[PATCH] erofs-utils: mkfs,fsck,dump: support `--offset` option

Gao Xiang hsiangkao at linux.alibaba.com
Tue Nov 7 17:21:17 AEDT 2023


Add `--offset` option to allows users to specify an offset in the file
where the filesystem will begin.

Suggested-by: Pavel Otchertsov <pavel.otchertsov at gmail.com>
Closes: https://lore.kernel.org/r/CAAxnTOGTD2NkKnBphZ+vEr7NVnWvT0u02E+c8pN8ZVFcXp5uhg@mail.gmail.com
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
Hi Pavel,
Could you check if the following patch resolves your requirement?

 dump/main.c              | 11 +++++++++++
 fsck/main.c              | 11 +++++++++++
 fuse/main.c              |  5 ++---
 include/erofs/config.h   |  3 ---
 include/erofs/internal.h |  2 ++
 lib/blobchunk.c          |  1 +
 lib/io.c                 | 12 +++++++-----
 mkfs/main.c              | 10 ++++++++++
 8 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/dump/main.c b/dump/main.c
index 293093d..8da9cbc 100644
--- a/dump/main.c
+++ b/dump/main.c
@@ -80,6 +80,7 @@ static struct option long_options[] = {
 	{"device", required_argument, NULL, 3},
 	{"path", required_argument, NULL, 4},
 	{"ls", no_argument, NULL, 5},
+	{"offset", required_argument, NULL, 6},
 	{0, 0, 0, 0},
 };
 
@@ -124,6 +125,7 @@ static void usage(int argc, char **argv)
 		" --device=X      specify an extra device to be used together\n"
 		" --ls            show directory contents (INODE required)\n"
 		" --nid=#         show the target inode info of nid #\n"
+		" --offset=#      skip # bytes at the beginning of IMAGE\n"
 		" --path=X        show the target inode info of path X\n",
 		argv[0]);
 }
@@ -136,6 +138,7 @@ static void erofsdump_print_version(void)
 static int erofsdump_parse_options_cfg(int argc, char **argv)
 {
 	int opt, err;
+	char *endptr;
 
 	while ((opt = getopt_long(argc, argv, "SVesh",
 				  long_options, NULL)) != -1) {
@@ -177,6 +180,14 @@ static int erofsdump_parse_options_cfg(int argc, char **argv)
 		case 5:
 			dumpcfg.show_subdirectories = true;
 			break;
+		case 6:
+			err = strtoull(optarg, &endptr, 0);
+			if (*endptr != '\0') {
+				erofs_err("invalid disk offset %s", optarg);
+				return -EINVAL;
+			}
+			sbi.diskoffset = err;
+			break;
 		default:
 			return -EINVAL;
 		}
diff --git a/fsck/main.c b/fsck/main.c
index 26cd131..1e45b61 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -48,6 +48,7 @@ static struct option long_options[] = {
 	{"no-preserve", no_argument, 0, 9},
 	{"no-preserve-owner", no_argument, 0, 10},
 	{"no-preserve-perms", no_argument, 0, 11},
+	{"offset", required_argument, 0, 12},
 	{0, 0, 0, 0},
 };
 
@@ -97,6 +98,7 @@ static void usage(int argc, char **argv)
 		" --device=X             specify an extra device to be used together\n"
 		" --extract[=X]          check if all files are well encoded, optionally\n"
 		"                        extract to X\n"
+		" --offset=#             skip # bytes at the beginning of IMAGE\n"
 		"\n"
 		" -a, -A, -y             no-op, for compatibility with fsck of other filesystems\n"
 		"\n"
@@ -123,6 +125,7 @@ static void erofsfsck_print_version(void)
 
 static int erofsfsck_parse_options_cfg(int argc, char **argv)
 {
+	char *endptr;
 	int opt, ret;
 	bool has_opt_preserve = false;
 
@@ -216,6 +219,14 @@ static int erofsfsck_parse_options_cfg(int argc, char **argv)
 			fsckcfg.preserve_perms = false;
 			has_opt_preserve = true;
 			break;
+		case 12:
+			ret = strtoull(optarg, &endptr, 0);
+			if (*endptr != '\0') {
+				erofs_err("invalid disk offset %s", optarg);
+				return -EINVAL;
+			}
+			sbi.diskoffset = ret;
+			break;
 		default:
 			return -EINVAL;
 		}
diff --git a/fuse/main.c b/fuse/main.c
index 5b2c64d..f07165c 100644
--- a/fuse/main.c
+++ b/fuse/main.c
@@ -547,7 +547,7 @@ static void usage(void)
 #endif
 	fputs("usage: [options] IMAGE MOUNTPOINT\n\n"
 	      "Options:\n"
-	      "    --offset=#             skip # bytes when reading IMAGE\n"
+	      "    --offset=#             skip # bytes at the beginning of IMAGE\n"
 	      "    --dbglevel=#           set output message level to # (maximum 9)\n"
 	      "    --device=#             specify an extra device to be used together\n"
 #if FUSE_MAJOR_VERSION < 3
@@ -676,8 +676,7 @@ int main(int argc, char *argv[])
 	if (fusecfg.odebug && cfg.c_dbg_lvl < EROFS_DBG)
 		cfg.c_dbg_lvl = EROFS_DBG;
 
-	cfg.c_offset = fusecfg.offset;
-
+	sbi.diskoffset = fusecfg.offset;
 	ret = dev_open_ro(&sbi, fusecfg.disk);
 	if (ret) {
 		fprintf(stderr, "failed to open: %s\n", fusecfg.disk);
diff --git a/include/erofs/config.h b/include/erofs/config.h
index e342722..89fe522 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -83,9 +83,6 @@ struct erofs_configure {
 	char *fs_config_file;
 	char *block_list_file;
 #endif
-
-	/* offset when reading multi partition images */
-	u64 c_offset;
 };
 
 extern struct erofs_configure cfg;
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 4d794ae..78b9f32 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -110,6 +110,8 @@ struct erofs_sb_info {
 	struct erofs_xattr_prefix_item *xattr_prefixes;
 
 	int devfd, devblksz;
+	/* offset when reading multi-part images */
+	u64 diskoffset;
 	u64 devsz;
 	dev_t dev;
 	unsigned int nblobs;
diff --git a/lib/blobchunk.c b/lib/blobchunk.c
index e4d0bad..6d2501e 100644
--- a/lib/blobchunk.c
+++ b/lib/blobchunk.c
@@ -448,6 +448,7 @@ int erofs_mkfs_dump_blobs(struct erofs_sb_info *sbi)
 
 	pos_out = erofs_btell(bh, false);
 	remapped_base = erofs_blknr(sbi, pos_out);
+	pos_out += sbi->diskoffset;
 	if (blobfile) {
 		pos_in = 0;
 		ret = erofs_copy_file_range(fileno(blobfile), &pos_in,
diff --git a/lib/io.c b/lib/io.c
index c92f16c..85d5156 100644
--- a/lib/io.c
+++ b/lib/io.c
@@ -194,6 +194,7 @@ int dev_write(struct erofs_sb_info *sbi, const void *buf, u64 offset, size_t len
 		return -EINVAL;
 	}
 
+	offset += sbi->diskoffset;
 	if (offset >= sbi->devsz || len > sbi->devsz ||
 	    offset > sbi->devsz - len) {
 		erofs_err("Write posion[%" PRIu64 ", %zd] is too large beyond the end of device(%" PRIu64 ").",
@@ -230,7 +231,7 @@ int dev_fillzero(struct erofs_sb_info *sbi, u64 offset, size_t len, bool padding
 
 #if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_PUNCH_HOLE)
 	if (!padding && fallocate(sbi->devfd, FALLOC_FL_PUNCH_HOLE |
-				  FALLOC_FL_KEEP_SIZE, offset, len) >= 0)
+	    FALLOC_FL_KEEP_SIZE, offset + sbi->diskoffset, len) >= 0)
 		return 0;
 #endif
 	while (len > erofs_blksiz(sbi)) {
@@ -255,7 +256,7 @@ int dev_fsync(struct erofs_sb_info *sbi)
 	return 0;
 }
 
-int dev_resize(struct erofs_sb_info *sbi, unsigned int blocks)
+int dev_resize(struct erofs_sb_info *sbi, erofs_blk_t blocks)
 {
 	int ret;
 	struct stat st;
@@ -271,6 +272,7 @@ int dev_resize(struct erofs_sb_info *sbi, unsigned int blocks)
 	}
 
 	length = (u64)blocks * erofs_blksiz(sbi);
+	length += sbi->diskoffset;
 	if (st.st_size == length)
 		return 0;
 	if (st.st_size > length)
@@ -281,7 +283,8 @@ int dev_resize(struct erofs_sb_info *sbi, unsigned int blocks)
 	if (fallocate(sbi->devfd, 0, st.st_size, length) >= 0)
 		return 0;
 #endif
-	return dev_fillzero(sbi, st.st_size, length, true);
+	return dev_fillzero(sbi, st.st_size - sbi->diskoffset,
+			    length, true);
 }
 
 int dev_read(struct erofs_sb_info *sbi, int device_id,
@@ -292,8 +295,7 @@ int dev_read(struct erofs_sb_info *sbi, int device_id,
 	if (cfg.c_dry_run)
 		return 0;
 
-	offset += cfg.c_offset;
-
+	offset += sbi->diskoffset;
 	if (!buf) {
 		erofs_err("buf is NULL");
 		return -EINVAL;
diff --git a/mkfs/main.c b/mkfs/main.c
index f024026..ea871b2 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -71,6 +71,7 @@ static struct option long_options[] = {
 #ifdef HAVE_ZLIB
 	{"gzip", no_argument, NULL, 517},
 #endif
+	{"offset", required_argument, NULL, 518},
 	{0, 0, 0, 0},
 };
 
@@ -151,6 +152,7 @@ static void usage(int argc, char **argv)
 		" --ignore-mtime        use build time instead of strict per-file modification time\n"
 		" --max-extent-bytes=#  set maximum decompressed extent size # in bytes\n"
 		" --preserve-mtime      keep per-file modification time strictly\n"
+		" --offset=#            skip # bytes at the beginning of IMAGE.\n"
 		" --aufs                replace aufs special files with overlayfs metadata\n"
 		" --tar=[fi]            generate an image from tarball(s)\n"
 		" --ovlfs-strip=<0,1>   strip overlayfs metadata in the target image (e.g. whiteouts)\n"
@@ -571,6 +573,14 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 		case 517:
 			gzip_supported = true;
 			break;
+		case 518:
+			i = strtoull(optarg, &endptr, 0);
+			if (*endptr != '\0') {
+				erofs_err("invalid disk offset %s", optarg);
+				return -EINVAL;
+			}
+			sbi.diskoffset = i;
+			break;
 		case 'V':
 			version();
 			exit(0);
-- 
2.39.3



More information about the Linux-erofs mailing list