Sometimes, we'd like the filesystem image aligned with a specific value. For example, specifying 8 with 512-byte filesystem blocks aligns the filesystem size to 4096 bytes instead of 512 bytes.
Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com> --- include/erofs/blobchunk.h | 1 - include/erofs/internal.h | 6 ++-- lib/blobchunk.c | 56 ++----------------------------- lib/super.c | 69 ++++++++++++++++++++++++++++++++++++--- man/mkfs.erofs.1 | 4 +++ mkfs/main.c | 30 +++++++++++++---- 6 files changed, 99 insertions(+), 67 deletions(-) diff --git a/include/erofs/blobchunk.h b/include/erofs/blobchunk.h index ebe2efe..619155f 100644 --- a/include/erofs/blobchunk.h +++ b/include/erofs/blobchunk.h @@ -24,7 +24,6 @@ int tarerofs_write_chunkes(struct erofs_inode *inode, erofs_off_t data_offset); int erofs_mkfs_dump_blobs(struct erofs_sb_info *sbi); void erofs_blob_exit(void); int erofs_blob_init(const char *blobfile_path, erofs_off_t chunksize); -int erofs_mkfs_init_devices(struct erofs_sb_info *sbi, unsigned int devices); #ifdef __cplusplus } diff --git a/include/erofs/internal.h b/include/erofs/internal.h index e89a1e4..5e86943 100644 --- a/include/erofs/internal.h +++ b/include/erofs/internal.h @@ -144,6 +144,7 @@ struct erofs_sb_info { struct erofs_bufmgr *bmgr; struct z_erofs_mgr *zmgr; struct erofs_packed_inode *packedinode; + struct erofs_buffer_head *bh_devt; bool useqpl; }; @@ -412,9 +413,10 @@ struct erofs_map_dev { /* super.c */ int erofs_read_superblock(struct erofs_sb_info *sbi); void erofs_put_super(struct erofs_sb_info *sbi); -int erofs_writesb(struct erofs_sb_info *sbi, struct erofs_buffer_head *sb_bh, - erofs_blk_t *blocks); +int erofs_writesb(struct erofs_sb_info *sbi, struct erofs_buffer_head *sb_bh); struct erofs_buffer_head *erofs_reserve_sb(struct erofs_bufmgr *bmgr); +int erofs_mkfs_init_devices(struct erofs_sb_info *sbi, unsigned int devices); +int erofs_write_device_table(struct erofs_sb_info *sbi); int erofs_enable_sb_chksum(struct erofs_sb_info *sbi, u32 *crc); /* namei.c */ diff --git a/lib/blobchunk.c b/lib/blobchunk.c index 4fc6c77..8c55277 100644 --- a/lib/blobchunk.c +++ b/lib/blobchunk.c @@ -31,8 +31,6 @@ static struct hashmap blob_hashmap; static int blobfile = -1; static erofs_blk_t remapped_base; static erofs_off_t datablob_size; -static bool multidev; -static struct erofs_buffer_head *bh_devt; struct erofs_blobchunk erofs_holechunk = { .blkaddr = EROFS_NULL_ADDR, }; @@ -493,30 +491,8 @@ int erofs_mkfs_dump_blobs(struct erofs_sb_info *sbi) datablob_size = length; } - if (sbi->extra_devices) { - unsigned int i, ret; - erofs_blk_t nblocks; - - nblocks = erofs_mapbh(sbi->bmgr, NULL); - pos_out = erofs_btell(bh_devt, false); - i = 0; - do { - struct erofs_deviceslot dis = { - .mapped_blkaddr = cpu_to_le32(nblocks), - .blocks = cpu_to_le32(sbi->devs[i].blocks), - }; - - memcpy(dis.tag, sbi->devs[i].tag, sizeof(dis.tag)); - ret = erofs_dev_write(sbi, &dis, pos_out, sizeof(dis)); - if (ret) - return ret; - pos_out += sizeof(dis); - nblocks += sbi->devs[i].blocks; - } while (++i < sbi->extra_devices); - bh_devt->op = &erofs_drop_directly_bhops; - erofs_bdrop(bh_devt, false); + if (sbi->extra_devices) return 0; - } bh = erofs_balloc(sbi->bmgr, DATA, datablob_size, 0); if (IS_ERR(bh)) @@ -612,40 +588,14 @@ static int erofs_insert_zerochunk(erofs_off_t chunksize) int erofs_blob_init(const char *blobfile_path, erofs_off_t chunksize) { - if (!blobfile_path) { + if (!blobfile_path) blobfile = erofs_tmpfile(); - multidev = false; - } else { + else blobfile = open(blobfile_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); - multidev = true; - } if (blobfile < 0) return -errno; hashmap_init(&blob_hashmap, erofs_blob_hashmap_cmp, 0); return erofs_insert_zerochunk(chunksize); } - -int erofs_mkfs_init_devices(struct erofs_sb_info *sbi, unsigned int devices) -{ - if (!devices) - return 0; - - sbi->devs = calloc(devices, sizeof(sbi->devs[0])); - if (!sbi->devs) - return -ENOMEM; - - bh_devt = erofs_balloc(sbi->bmgr, DEVT, - sizeof(struct erofs_deviceslot) * devices, 0); - if (IS_ERR(bh_devt)) { - free(sbi->devs); - return PTR_ERR(bh_devt); - } - erofs_mapbh(NULL, bh_devt->block); - bh_devt->op = &erofs_skip_write_bhops; - sbi->devt_slotoff = erofs_btell(bh_devt, false) / EROFS_DEVT_SLOT_SIZE; - sbi->extra_devices = devices; - erofs_sb_set_device_table(sbi); - return 0; -} diff --git a/lib/super.c b/lib/super.c index 6c8fa52..1541838 100644 --- a/lib/super.c +++ b/lib/super.c @@ -155,8 +155,7 @@ void erofs_put_super(struct erofs_sb_info *sbi) } } -int erofs_writesb(struct erofs_sb_info *sbi, struct erofs_buffer_head *sb_bh, - erofs_blk_t *blocks) +int erofs_writesb(struct erofs_sb_info *sbi, struct erofs_buffer_head *sb_bh) { struct erofs_super_block sb = { .magic = cpu_to_le32(EROFS_SUPER_MAGIC_V1), @@ -180,8 +179,7 @@ int erofs_writesb(struct erofs_sb_info *sbi, struct erofs_buffer_head *sb_bh, char *buf; int ret; - *blocks = erofs_mapbh(sbi->bmgr, NULL); - sb.blocks = cpu_to_le32(*blocks); + sb.blocks = cpu_to_le32(sbi->primarydevice_blocks); memcpy(sb.uuid, sbi->uuid, sizeof(sb.uuid)); memcpy(sb.volume_name, sbi->volume_name, sizeof(sb.volume_name)); @@ -283,3 +281,66 @@ int erofs_enable_sb_chksum(struct erofs_sb_info *sbi, u32 *crc) return 0; } + +int erofs_mkfs_init_devices(struct erofs_sb_info *sbi, unsigned int devices) +{ + struct erofs_buffer_head *bh; + + if (!devices) + return 0; + + sbi->devs = calloc(devices, sizeof(sbi->devs[0])); + if (!sbi->devs) + return -ENOMEM; + + bh = erofs_balloc(sbi->bmgr, DEVT, + sizeof(struct erofs_deviceslot) * devices, 0); + if (IS_ERR(bh)) { + free(sbi->devs); + sbi->devs = NULL; + return PTR_ERR(bh); + } + erofs_mapbh(NULL, bh->block); + bh->op = &erofs_skip_write_bhops; + sbi->bh_devt = bh; + sbi->devt_slotoff = erofs_btell(bh, false) / EROFS_DEVT_SLOT_SIZE; + sbi->extra_devices = devices; + erofs_sb_set_device_table(sbi); + return 0; +} + +int erofs_write_device_table(struct erofs_sb_info *sbi) +{ + erofs_blk_t nblocks = sbi->primarydevice_blocks; + struct erofs_buffer_head *bh = sbi->bh_devt; + erofs_off_t pos; + unsigned int i, ret; + + if (!sbi->extra_devices) + goto out; + if (!bh) + return -EINVAL; + + pos = erofs_btell(bh, false); + i = 0; + do { + struct erofs_deviceslot dis = { + .mapped_blkaddr = cpu_to_le32(nblocks), + .blocks = cpu_to_le32(sbi->devs[i].blocks), + }; + + memcpy(dis.tag, sbi->devs[i].tag, sizeof(dis.tag)); + ret = erofs_dev_write(sbi, &dis, pos, sizeof(dis)); + if (ret) + return ret; + pos += sizeof(dis); + nblocks += sbi->devs[i].blocks; + } while (++i < sbi->extra_devices); + + bh->op = &erofs_drop_directly_bhops; + erofs_bdrop(bh, false); + sbi->bh_devt = NULL; +out: + sbi->total_blocks = nblocks; + return 0; +} diff --git a/man/mkfs.erofs.1 b/man/mkfs.erofs.1 index ae8411d..48202b6 100644 --- a/man/mkfs.erofs.1 +++ b/man/mkfs.erofs.1 @@ -192,6 +192,10 @@ Set all file UIDs to \fIUID\fR. .BI "\-\-force-gid=" GID Set all file GIDs to \fIGID\fR. .TP +.BI "\-\-fsalignblks=" # +Specify the alignment of the primary device size (usually the filesystem size) +in blocks. +.TP .BI "\-\-gid-offset=" GIDOFFSET Add \fIGIDOFFSET\fR to all file GIDs. When this option is used together with diff --git a/mkfs/main.c b/mkfs/main.c index 79de7a1..16de894 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -89,6 +89,7 @@ static struct option long_options[] = { #ifdef EROFS_MT_ENABLED {"async-queue-limit", required_argument, NULL, 530}, #endif + {"fsalignblks", required_argument, NULL, 531}, {0, 0, 0, 0}, }; @@ -180,6 +181,7 @@ static void usage(int argc, char **argv) #endif " --force-uid=# set all file uids to # (# = UID)\n" " --force-gid=# set all file gids to # (# = GID)\n" + " --fsalignblks=# specify the alignment of the primary device size in blocks\n" " --uid-offset=# add offset # to all file uids (# = id offset)\n" " --gid-offset=# add offset # to all file gids (# = id offset)\n" " --hard-dereference dereference hardlinks, add links as separate inodes\n" @@ -250,6 +252,7 @@ static LIST_HEAD(rebuild_src_list); static u8 fixeduuid[16]; static bool valid_fixeduuid; static unsigned int dsunit; +static unsigned int fsalignblks = 1; static int erofs_mkfs_feat_set_legacy_compress(bool en, const char *val, unsigned int vallen) @@ -896,6 +899,13 @@ static int mkfs_parse_options_cfg(int argc, char *argv[]) } break; #endif + case 531: + fsalignblks = strtoul(optarg, &endptr, 0); + if (*endptr != '\0') { + erofs_err("invalid fsalignblks %s", optarg); + return -EINVAL; + } + break; case 'V': version(); exit(0); @@ -1183,7 +1193,7 @@ static int erofs_mkfs_rebuild_load_trees(struct erofs_inode *root) return 0; } -static void erofs_mkfs_showsummaries(erofs_blk_t nblocks) +static void erofs_mkfs_showsummaries(void) { char uuid_str[37] = {}; char *incr = incremental_mode ? "new" : "total"; @@ -1194,11 +1204,12 @@ static void erofs_mkfs_showsummaries(erofs_blk_t nblocks) erofs_uuid_unparse_lower(g_sbi.uuid, uuid_str); fprintf(stdout, "------\nFilesystem UUID: %s\n" - "Filesystem total blocks: %u (of %u-byte blocks)\n" + "Filesystem total blocks: %llu (of %u-byte blocks)\n" "Filesystem total inodes: %llu\n" "Filesystem %s metadata blocks: %u\n" "Filesystem %s deduplicated bytes (of source files): %llu\n", - uuid_str, nblocks, 1U << g_sbi.blkszbits, g_sbi.inos | 0ULL, + uuid_str, g_sbi.total_blocks | 0ULL, 1U << g_sbi.blkszbits, + g_sbi.inos | 0ULL, incr, erofs_total_metablocks(g_sbi.bmgr), incr, g_sbi.saved_by_deduplication | 0ULL); } @@ -1208,7 +1219,6 @@ int main(int argc, char **argv) int err = 0; struct erofs_buffer_head *sb_bh; struct erofs_inode *root = NULL; - erofs_blk_t nblocks = 0; struct timeval t; FILE *blklst = NULL; u32 crc; @@ -1478,6 +1488,12 @@ int main(int argc, char **argv) goto exit; } + g_sbi.primarydevice_blocks = + roundup(erofs_mapbh(g_sbi.bmgr, NULL), fsalignblks); + err = erofs_write_device_table(&g_sbi); + if (err) + goto exit; + /* flush all buffers except for the superblock */ err = erofs_bflush(g_sbi.bmgr, NULL); if (err) @@ -1487,7 +1503,7 @@ int main(int argc, char **argv) erofs_iput(root); root = NULL; - err = erofs_writesb(&g_sbi, sb_bh, &nblocks); + err = erofs_writesb(&g_sbi, sb_bh); if (err) goto exit; @@ -1496,7 +1512,7 @@ int main(int argc, char **argv) if (err) goto exit; - err = erofs_dev_resize(&g_sbi, nblocks); + err = erofs_dev_resize(&g_sbi, g_sbi.primarydevice_blocks); if (!err && erofs_sb_has_sb_chksum(&g_sbi)) { err = erofs_enable_sb_chksum(&g_sbi, &crc); @@ -1534,7 +1550,7 @@ exit: return 1; } erofs_update_progressinfo("Build completed.\n"); - erofs_mkfs_showsummaries(nblocks); + erofs_mkfs_showsummaries(); erofs_put_super(&g_sbi); return 0; } -- 2.43.5