- erofs_mkfs_format_fs Create a new filesystem - erofs_mkfs_load_fs Load an existing filesystem, especially for incremental builds;
Unlike importer APIs (designed for multiple data sources), this can only be executed once. Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com> --- include/erofs/compress.h | 3 +- include/erofs/internal.h | 6 ++- lib/cache.c | 1 + lib/compress.c | 5 +- lib/importer.c | 4 ++ lib/super.c | 55 +++++++++++++++++++++- mkfs/main.c | 99 ++++++++++++---------------------------- 7 files changed, 98 insertions(+), 75 deletions(-) diff --git a/include/erofs/compress.h b/include/erofs/compress.h index d5b2519..00e7715 100644 --- a/include/erofs/compress.h +++ b/include/erofs/compress.h @@ -23,8 +23,7 @@ void z_erofs_drop_inline_pcluster(struct erofs_inode *inode); void *erofs_begin_compressed_file(struct erofs_inode *inode, int fd, u64 fpos); int erofs_write_compressed_file(struct z_erofs_compress_ictx *ictx); -int z_erofs_compress_init(struct erofs_sb_info *sbi, - struct erofs_buffer_head *bh); +int z_erofs_compress_init(struct erofs_sb_info *sbi); int z_erofs_compress_exit(struct erofs_sb_info *sbi); const char *z_erofs_list_supported_algorithms(int i, unsigned int *mask); diff --git a/include/erofs/internal.h b/include/erofs/internal.h index 92e83fd..a609fbd 100644 --- a/include/erofs/internal.h +++ b/include/erofs/internal.h @@ -150,6 +150,7 @@ struct erofs_sb_info { struct z_erofs_mgr *zmgr; struct erofs_metaboxmgr *m2gr; struct erofs_packed_inode *packedinode; + struct erofs_buffer_head *bh_sb; struct erofs_buffer_head *bh_devt; bool useqpl; }; @@ -432,12 +433,15 @@ void liberofs_global_exit(void); /* 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); +int erofs_writesb(struct erofs_sb_info *sbi); 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); int erofs_superblock_csum_verify(struct erofs_sb_info *sbi); +int erofs_mkfs_format_fs(struct erofs_sb_info *sbi, + unsigned int blkszbits, unsigned int dsunit); +int erofs_mkfs_load_fs(struct erofs_sb_info *sbi, unsigned int dsunit); /* namei.c */ int erofs_read_inode_from_disk(struct erofs_inode *vi); diff --git a/lib/cache.c b/lib/cache.c index 079465e..cd11737 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -533,5 +533,6 @@ erofs_blk_t erofs_total_metablocks(struct erofs_bufmgr *bmgr) void erofs_buffer_exit(struct erofs_bufmgr *bmgr) { + DBG_BUGON(!list_empty(&bmgr->blkh.list)); free(bmgr); } diff --git a/lib/compress.c b/lib/compress.c index 0bfad3f..0049199 100644 --- a/lib/compress.c +++ b/lib/compress.c @@ -2035,11 +2035,12 @@ static int z_erofs_build_compr_cfgs(struct erofs_sb_info *sbi, return ret; } -int z_erofs_compress_init(struct erofs_sb_info *sbi, struct erofs_buffer_head *sb_bh) +int z_erofs_compress_init(struct erofs_sb_info *sbi) { - int i, ret, id; + struct erofs_buffer_head *sb_bh = sbi->bh_sb; u32 max_dict_size[Z_EROFS_COMPRESSION_MAX] = {}; u32 available_compr_algs = 0; + int i, ret, id; if (!sbi->zmgr) { sbi->zmgr = calloc(1, sizeof(*sbi->zmgr)); diff --git a/lib/importer.c b/lib/importer.c index a65fa39..95f006d 100644 --- a/lib/importer.c +++ b/lib/importer.c @@ -39,6 +39,7 @@ void erofs_importer_global_init(void) int erofs_importer_init(struct erofs_importer *im) { struct erofs_sb_info *sbi = im->sbi; + struct erofs_importer_params *params = im->params; const char *subsys = NULL; int err; @@ -67,6 +68,9 @@ int erofs_importer_init(struct erofs_importer *im) if (err) goto out_err; } + + if (params->dot_omitted) + erofs_sb_set_48bit(sbi); return 0; out_err: diff --git a/lib/super.c b/lib/super.c index 57849fb..97d955f 100644 --- a/lib/super.c +++ b/lib/super.c @@ -172,8 +172,9 @@ void erofs_put_super(struct erofs_sb_info *sbi) } } -int erofs_writesb(struct erofs_sb_info *sbi, struct erofs_buffer_head *sb_bh) +int erofs_writesb(struct erofs_sb_info *sbi) { + struct erofs_buffer_head *sb_bh = sbi->bh_sb; struct erofs_super_block sb = { .magic = cpu_to_le32(EROFS_SUPER_MAGIC_V1), .blkszbits = sbi->blkszbits, @@ -408,3 +409,55 @@ out: sbi->total_blocks = nblocks; return 0; } + +int erofs_mkfs_format_fs(struct erofs_sb_info *sbi, + unsigned int blkszbits, unsigned int dsunit) +{ + struct erofs_buffer_head *bh; + struct erofs_bufmgr *bmgr; + + sbi->blkszbits = blkszbits; + bmgr = erofs_buffer_init(sbi, 0, NULL); + if (!bmgr) + return -ENOMEM; + sbi->bmgr = bmgr; + bmgr->dsunit = dsunit; + + bh = erofs_reserve_sb(bmgr); + if (IS_ERR(bh)) + return PTR_ERR(bh); + sbi->bh_sb = bh; + return 0; +} + +int erofs_mkfs_load_fs(struct erofs_sb_info *sbi, unsigned int dsunit) +{ + union { + struct stat st; + erofs_blk_t startblk; + } u; + struct erofs_bufmgr *bmgr; + int err; + + sbi->bh_sb = NULL; + erofs_warn("EXPERIMENTAL incremental build in use. Use at your own risk!"); + err = erofs_read_superblock(sbi); + if (err) { + erofs_err("failed to read superblock of %s: %s", sbi->devname, + erofs_strerror(err)); + return err; + } + + err = erofs_io_fstat(&sbi->bdev, &u.st); + if (!err && S_ISREG(u.st.st_mode)) + u.startblk = DIV_ROUND_UP(u.st.st_size, erofs_blksiz(sbi)); + else + u.startblk = sbi->primarydevice_blocks; + + bmgr = erofs_buffer_init(sbi, u.startblk, NULL); + if (!bmgr) + return -ENOMEM; + sbi->bmgr = bmgr; + bmgr->dsunit = dsunit; + return 0; +} diff --git a/mkfs/main.c b/mkfs/main.c index 0a8f477..d2950b7 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -372,6 +372,7 @@ static int erofs_mkfs_feat_set_48bit(bool en, const char *val, } static bool mkfs_dot_omitted; +static unsigned char mkfs_blkszbits; static int erofs_mkfs_feat_set_dot_omitted(bool en, const char *val, unsigned int vallen) @@ -884,7 +885,7 @@ static int mkfs_parse_options_cfg(struct erofs_importer_params *params, erofs_err("invalid block size %s", optarg); return -EINVAL; } - g_sbi.blkszbits = ilog2(i); + mkfs_blkszbits = ilog2(i); break; case 'd': @@ -1234,7 +1235,7 @@ static int mkfs_parse_options_cfg(struct erofs_importer_params *params, } } - if (cfg.c_blobdev_path && cfg.c_chunkbits < g_sbi.blkszbits) { + if (cfg.c_blobdev_path && cfg.c_chunkbits < mkfs_blkszbits) { erofs_err("--blobdev must be used together with --chunksize"); return -EINVAL; } @@ -1283,8 +1284,8 @@ static int mkfs_parse_options_cfg(struct erofs_importer_params *params, } if (pclustersize_max) { - if (pclustersize_max < erofs_blksiz(&g_sbi) || - pclustersize_max % erofs_blksiz(&g_sbi)) { + if (pclustersize_max < (1U << mkfs_blkszbits) || + pclustersize_max % (1U << mkfs_blkszbits)) { erofs_err("invalid physical clustersize %u", pclustersize_max); return -EINVAL; @@ -1292,15 +1293,15 @@ static int mkfs_parse_options_cfg(struct erofs_importer_params *params, cfg.c_mkfs_pclustersize_max = pclustersize_max; cfg.c_mkfs_pclustersize_def = cfg.c_mkfs_pclustersize_max; } - if (cfg.c_chunkbits && cfg.c_chunkbits < g_sbi.blkszbits) { + if (cfg.c_chunkbits && cfg.c_chunkbits < mkfs_blkszbits) { erofs_err("chunksize %u must be larger than block size", 1u << cfg.c_chunkbits); return -EINVAL; } if (pclustersize_packed) { - if (pclustersize_packed < erofs_blksiz(&g_sbi) || - pclustersize_packed % erofs_blksiz(&g_sbi)) { + if (pclustersize_packed < (1U << mkfs_blkszbits) || + pclustersize_packed % (1U << mkfs_blkszbits)) { erofs_err("invalid pcluster size for the packed file %u", pclustersize_packed); return -EINVAL; @@ -1310,8 +1311,8 @@ static int mkfs_parse_options_cfg(struct erofs_importer_params *params, if (pclustersize_metabox >= 0) { if (pclustersize_metabox && - (pclustersize_metabox < erofs_blksiz(&g_sbi) || - pclustersize_metabox % erofs_blksiz(&g_sbi))) { + (pclustersize_metabox < (1U << mkfs_blkszbits) || + pclustersize_metabox % (1U << mkfs_blkszbits))) { erofs_err("invalid pcluster size %u for the metabox inode", pclustersize_metabox); return -EINVAL; @@ -1334,8 +1335,8 @@ static void erofs_mkfs_default_options(void) cfg.c_mt_workers = erofs_get_available_processors(); cfg.c_mkfs_segment_size = 16ULL * 1024 * 1024; #endif - g_sbi.blkszbits = ilog2(min_t(u32, getpagesize(), EROFS_MAX_BLOCK_SIZE)); - cfg.c_mkfs_pclustersize_max = erofs_blksiz(&g_sbi); + mkfs_blkszbits = ilog2(min_t(u32, getpagesize(), EROFS_MAX_BLOCK_SIZE)); + cfg.c_mkfs_pclustersize_max = 1U << mkfs_blkszbits; cfg.c_mkfs_pclustersize_def = cfg.c_mkfs_pclustersize_max; g_sbi.feature_incompat = EROFS_FEATURE_INCOMPAT_ZERO_PADDING; g_sbi.feature_compat = EROFS_FEATURE_COMPAT_SB_CHKSUM | @@ -1468,7 +1469,7 @@ static void erofs_mkfs_showsummaries(void) "Filesystem total inodes: %llu\n" "Filesystem %s metadata blocks: %llu\n" "Filesystem %s deduplicated bytes (of source files): %llu\n", - uuid_str, g_sbi.total_blocks | 0ULL, 1U << g_sbi.blkszbits, + uuid_str, g_sbi.total_blocks | 0ULL, 1U << mkfs_blkszbits, g_sbi.inos | 0ULL, incr, erofs_total_metablocks(g_sbi.bmgr) | 0ULL, incr, g_sbi.saved_by_deduplication | 0ULL); @@ -1481,7 +1482,6 @@ int main(int argc, char **argv) .params = &importer_params, .sbi = &g_sbi, }; - struct erofs_buffer_head *sb_bh; struct erofs_inode *root = NULL; bool tar_index_512b = false; struct timeval t; @@ -1539,16 +1539,6 @@ int main(int argc, char **argv) #endif erofs_show_config(); - importer_params.source = cfg.c_src_path; - importer_params.no_datainline = mkfs_no_datainline; - importer_params.dot_omitted = mkfs_dot_omitted; - if (importer_params.dot_omitted) - erofs_sb_set_48bit(&g_sbi); - - err = erofs_importer_init(&importer); - if (err) - goto exit; - #ifndef NDEBUG if (cfg.c_random_pclusterblks) srand(time(NULL)); @@ -1570,7 +1560,7 @@ int main(int argc, char **argv) * If mapfile is unspecified for tarfs index mode, * 512-byte block size is enforced here. */ - g_sbi.blkszbits = 9; + mkfs_blkszbits = 9; tar_index_512b = true; } } else if (source_mode == EROFS_MKFS_SOURCE_REBUILD) { @@ -1586,46 +1576,15 @@ int main(int argc, char **argv) erofs_err("failed to read superblock of %s", src->devname); goto exit; } - g_sbi.blkszbits = src->blkszbits; + mkfs_blkszbits = src->blkszbits; } - if (!incremental_mode) { - g_sbi.bmgr = erofs_buffer_init(&g_sbi, 0, NULL); - if (!g_sbi.bmgr) { - err = -ENOMEM; - goto exit; - } - sb_bh = erofs_reserve_sb(g_sbi.bmgr); - if (IS_ERR(sb_bh)) { - err = PTR_ERR(sb_bh); - goto exit; - } - } else { - union { - struct stat st; - erofs_blk_t startblk; - } u; - - erofs_warn("EXPERIMENTAL incremental build in use. Use at your own risk!"); - err = erofs_read_superblock(&g_sbi); - if (err) { - erofs_err("failed to read superblock of %s", g_sbi.devname); - goto exit; - } - - err = erofs_io_fstat(&g_sbi.bdev, &u.st); - if (!err && S_ISREG(u.st.st_mode)) - u.startblk = DIV_ROUND_UP(u.st.st_size, erofs_blksiz(&g_sbi)); - else - u.startblk = g_sbi.primarydevice_blocks; - g_sbi.bmgr = erofs_buffer_init(&g_sbi, u.startblk, NULL); - if (!g_sbi.bmgr) { - err = -ENOMEM; - goto exit; - } - sb_bh = NULL; - } - g_sbi.bmgr->dsunit = dsunit; + if (!incremental_mode) + err = erofs_mkfs_format_fs(&g_sbi, mkfs_blkszbits, dsunit); + else + err = erofs_mkfs_load_fs(&g_sbi, dsunit); + if (err) + goto exit; /* Use the user-defined UUID or generate one for clean builds */ if (valid_fixeduuid) @@ -1650,13 +1609,20 @@ int main(int argc, char **argv) goto exit; } - err = z_erofs_compress_init(&g_sbi, sb_bh); + err = z_erofs_compress_init(&g_sbi); if (err) { erofs_err("failed to initialize compressor: %s", erofs_strerror(err)); goto exit; } + importer_params.source = cfg.c_src_path; + importer_params.no_datainline = mkfs_no_datainline; + importer_params.dot_omitted = mkfs_dot_omitted; + err = erofs_importer_init(&importer); + if (err) + goto exit; + if (cfg.c_dedupe) { if (!cfg.c_compr_opts[0].alg) { erofs_err("Compression is not enabled. Turn on chunk-based data deduplication instead."); @@ -1771,12 +1737,7 @@ int main(int argc, char **argv) erofs_iput(root); root = NULL; - err = erofs_writesb(&g_sbi, sb_bh); - if (err) - goto exit; - - /* flush all remaining buffers */ - err = erofs_bflush(g_sbi.bmgr, NULL); + err = erofs_writesb(&g_sbi); if (err) goto exit; -- 2.43.5