[PATCH v2 4/4] erofs-utils: mkfs: support data alignment

Gao Xiang hsiangkao at linux.alibaba.com
Thu Dec 19 17:43:31 AEDT 2024


The underlay block storage could work in a stripe-like manner to improve
performance and space efficiency.

EROFS on-disk layout is flexible enough for such use cases.

Cc: Changpeng Liu <changpeliu at tencent.com>
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 include/erofs/cache.h |  3 +++
 lib/cache.c           | 25 ++++++++++++++++++++-----
 man/mkfs.erofs.1      |  3 +++
 mkfs/main.c           | 11 +++++++++++
 4 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/include/erofs/cache.h b/include/erofs/cache.h
index d8559a8..6ff80ab 100644
--- a/include/erofs/cache.h
+++ b/include/erofs/cache.h
@@ -67,6 +67,9 @@ struct erofs_bufmgr {
 
 	/* last mapped buffer block to accelerate erofs_mapbh() */
 	struct erofs_buffer_block *last_mapped_block;
+
+	/* align data block addresses to multiples of `dsunit` */
+	unsigned int dsunit;
 };
 
 static inline const int get_alignsize(struct erofs_sb_info *sbi, int type,
diff --git a/lib/cache.c b/lib/cache.c
index cb05466..d3e2e62 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -156,10 +156,15 @@ static int erofs_bfind_for_attach(struct erofs_bufmgr *bmgr,
 	bb = NULL;
 
 	/* try to find a most-fit mapped buffer block first */
-	if (size + inline_ext >= blksiz)
+
+	if (__erofs_unlikely(bmgr->dsunit > 1)) {
+		used_before = blksiz - alignsize;
+	} else if (size + inline_ext >= blksiz) {
 		goto skip_mapped;
+	} else {
+		used_before = rounddown(blksiz - (size + inline_ext), alignsize);
+	}
 
-	used_before = rounddown(blksiz - (size + inline_ext), alignsize);
 	for (; used_before; --used_before) {
 		struct list_head *bt = bmgr->mapped_buckets[type] + used_before;
 
@@ -181,7 +186,7 @@ static int erofs_bfind_for_attach(struct erofs_bufmgr *bmgr,
 		ret = __erofs_battach(cur, NULL, size, alignsize,
 				      inline_ext, true);
 		if (ret < 0) {
-			DBG_BUGON(1);
+			DBG_BUGON(!(bmgr->dsunit > 1));
 			continue;
 		}
 
@@ -324,10 +329,20 @@ struct erofs_buffer_head *erofs_battach(struct erofs_buffer_head *bh,
 static void __erofs_mapbh(struct erofs_buffer_block *bb)
 {
 	struct erofs_bufmgr *bmgr = bb->buffers.fsprivate;
-	erofs_blk_t blkaddr;
+	erofs_blk_t blkaddr = bmgr->tail_blkaddr;
 
 	if (bb->blkaddr == NULL_ADDR) {
-		bb->blkaddr = bmgr->tail_blkaddr;
+		bb->blkaddr = blkaddr;
+		if (__erofs_unlikely(bmgr->dsunit > 1) && bb->type == DATA) {
+			struct erofs_buffer_block *pb = list_prev_entry(bb, list);
+
+			bb->blkaddr = roundup(blkaddr, bmgr->dsunit);
+			if (pb != &bmgr->blkh &&
+			    pb->blkaddr + pb->buffers.nblocks >= blkaddr) {
+				DBG_BUGON(pb->blkaddr + pb->buffers.nblocks > blkaddr);
+				pb->buffers.nblocks = bb->blkaddr - pb->blkaddr;
+			}
+		}
 		bmgr->last_mapped_block = bb;
 		erofs_bupdate_mapped(bb);
 	}
diff --git a/man/mkfs.erofs.1 b/man/mkfs.erofs.1
index 0093839..ee84163 100644
--- a/man/mkfs.erofs.1
+++ b/man/mkfs.erofs.1
@@ -149,6 +149,9 @@ the given primary algorithm, alternative algorithms can be specified with
 are extended regular expressions, matched against absolute paths within
 the output filesystem, with no leading /.
 .TP
+.BI "\-\-dsunit=" #
+Align all data block addresses to multiples of #.
+.TP
 .BI "\-\-exclude-path=" path
 Ignore file that matches the exact literal path.
 You may give multiple
diff --git a/mkfs/main.c b/mkfs/main.c
index 9ca7dad..1f4b7c6 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -86,6 +86,7 @@ static struct option long_options[] = {
 	{"all-time", no_argument, NULL, 526},
 	{"sort", required_argument, NULL, 527},
 	{"hard-dereference", no_argument, NULL, 528},
+	{"dsunit", required_argument, NULL, 529},
 	{0, 0, 0, 0},
 };
 
@@ -162,6 +163,7 @@ static void usage(int argc, char **argv)
 		" --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"
+		" --dsunit=#            align all data block addresses to multiples of #\n"
 		" --incremental=X       run incremental build\n"
 		"                       (X = data|rvsp; data=full data, rvsp=space is allocated\n"
 		"                                       and filled with zeroes)\n"
@@ -243,6 +245,7 @@ static unsigned int rebuild_src_count;
 static LIST_HEAD(rebuild_src_list);
 static u8 fixeduuid[16];
 static bool valid_fixeduuid;
+static unsigned int dsunit;
 
 static int erofs_mkfs_feat_set_legacy_compress(bool en, const char *val,
 					       unsigned int vallen)
@@ -856,6 +859,13 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 		case 528:
 			cfg.c_hard_dereference = true;
 			break;
+		case 529:
+			dsunit = strtoul(optarg, &endptr, 0);
+			if (*endptr != '\0') {
+				erofs_err("invalid dsunit %s", optarg);
+				return -EINVAL;
+			}
+			break;
 		case 'V':
 			version();
 			exit(0);
@@ -1318,6 +1328,7 @@ int main(int argc, char **argv)
 		}
 		sb_bh = NULL;
 	}
+	g_sbi.bmgr->dsunit = dsunit;
 
 	/* Use the user-defined UUID or generate one for clean builds */
 	if (valid_fixeduuid)
-- 
2.43.5



More information about the Linux-erofs mailing list