/* 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,
+ inline_ext > blkmask)
return -ENOSPC;
- oob = cmpsgn(roundup(boff, alignsize) + incr + inline_ext,
+ oob = cmpsgn(alignedoffset + incr + inline_ext,
bb->buffers.nblocks << sbi->blkszbits);
if (oob >= 0) {
/* the next buffer block should be NULL_ADDR all the time */
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;
ret = __erofs_battach(cur, NULL, size, alignsize,
inline_ext, true);
if (ret < 0) {
- DBG_BUGON(1);
+ DBG_BUGON(!(bmgr->dsunit > 1));
continue;
}
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);
}
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
{"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},
};
" (X = data|rvsp; data=full data, rvsp=space is allocated\n"
" and filled with zeroes)\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
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)
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);
}
sb_bh = NULL;
}
+ g_sbi.bmgr->dsunit = dsunit;
/* Use the user-defined UUID or generate one for clean builds */
if (valid_fixeduuid)