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

Reply via email to