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 <changpe...@tencent.com> Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com> --- include/erofs/cache.h | 3 +++ lib/cache.c | 2 ++ man/mkfs.erofs.1 | 3 +++ mkfs/main.c | 11 +++++++++++ 4 files changed, 19 insertions(+) diff --git a/include/erofs/cache.h b/include/erofs/cache.h index 5411eed..bd32602 100644 --- a/include/erofs/cache.h +++ b/include/erofs/cache.h @@ -64,6 +64,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 3208e9f..b782f25 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -330,6 +330,8 @@ static erofs_blk_t __erofs_mapbh(struct erofs_buffer_block *bb) if (bb->blkaddr == NULL_ADDR) { bb->blkaddr = bmgr->tail_blkaddr; + if (__erofs_unlikely(bmgr->dsunit) && bb->type == DATA) + bb->blkaddr = roundup(bb->blkaddr, bmgr->dsunit); bmgr->last_mapped_block = bb; erofs_bupdate_mapped(bb); } diff --git a/man/mkfs.erofs.1 b/man/mkfs.erofs.1 index abdd9b9..e7da588 100644 --- a/man/mkfs.erofs.1 +++ b/man/mkfs.erofs.1 @@ -138,6 +138,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 d422787..c92f408 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -85,6 +85,7 @@ static struct option long_options[] = { {"mkfs-time", no_argument, NULL, 525}, {"all-time", no_argument, NULL, 526}, {"sort", required_argument, NULL, 527}, + {"dsunit", required_argument, NULL, 528}, {0, 0, 0, 0}, }; @@ -161,6 +162,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" @@ -241,6 +243,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) @@ -846,6 +849,13 @@ static int mkfs_parse_options_cfg(int argc, char *argv[]) if (!strcmp(optarg, "none")) erofstar.try_no_reorder = true; break; + case 528: + dsunit = strtoul(optarg, &endptr, 0); + if (*endptr != '\0') { + erofs_err("invalid dsunit %s", optarg); + return -EINVAL; + } + break; case 'V': version(); exit(0); @@ -1308,6 +1318,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