[PATCH 2/3] erofs-utils: lib: rework per-sb fragment generator
Gao Xiang
hsiangkao at linux.alibaba.com
Fri Jan 17 18:46:01 AEDT 2025
It's also used for the upcoming fragment cache.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
include/erofs/fragments.h | 14 ++--
include/erofs/internal.h | 3 +
include/erofs/xattr.h | 2 +-
lib/fragments.c | 150 +++++++++++++++++++++++---------------
lib/xattr.c | 3 +-
mkfs/main.c | 20 ++---
6 files changed, 109 insertions(+), 83 deletions(-)
diff --git a/include/erofs/fragments.h b/include/erofs/fragments.h
index 65910f5..e92b7c7 100644
--- a/include/erofs/fragments.h
+++ b/include/erofs/fragments.h
@@ -15,17 +15,17 @@ extern "C"
extern const char *erofs_frags_packedname;
#define EROFS_PACKED_INODE erofs_frags_packedname
-FILE *erofs_packedfile_init(void);
-void erofs_packedfile_exit(void);
-int erofs_flush_packed_inode(struct erofs_sb_info *sbi);
-
int z_erofs_fragments_dedupe(struct erofs_inode *inode, int fd, u32 *tofcrc);
+
+void z_erofs_fragments_commit(struct erofs_inode *inode);
int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofcrc);
int z_erofs_pack_fragments(struct erofs_inode *inode, void *data,
unsigned int len, u32 tofcrc);
-void z_erofs_fragments_commit(struct erofs_inode *inode);
-int z_erofs_fragments_init(void);
-void z_erofs_fragments_exit(void);
+int erofs_flush_packed_inode(struct erofs_sb_info *sbi);
+FILE *erofs_packedfile(struct erofs_sb_info *sbi);
+
+int erofs_packedfile_init(struct erofs_sb_info *sbi, bool fragments_mkfs);
+void erofs_packedfile_exit(struct erofs_sb_info *sbi);
#ifdef __cplusplus
}
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 5d7d022..eb665e2 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -81,6 +81,8 @@ struct erofs_xattr_prefix_item {
#define EROFS_PACKED_NID_UNALLOCATED -1
struct erofs_mkfs_dfops;
+struct erofs_packed_inode;
+
struct erofs_sb_info {
struct erofs_sb_lz4_info lz4;
struct erofs_device_info *devs;
@@ -139,6 +141,7 @@ struct erofs_sb_info {
struct erofs_mkfs_dfops *mkfs_dfops;
#endif
struct erofs_bufmgr *bmgr;
+ struct erofs_packed_inode *packedinode;
bool useqpl;
};
diff --git a/include/erofs/xattr.h b/include/erofs/xattr.h
index 804f565..81604b6 100644
--- a/include/erofs/xattr.h
+++ b/include/erofs/xattr.h
@@ -50,7 +50,7 @@ int erofs_build_shared_xattrs_from_path(struct erofs_sb_info *sbi, const char *p
int erofs_xattr_insert_name_prefix(const char *prefix);
void erofs_xattr_cleanup_name_prefixes(void);
-int erofs_xattr_write_name_prefixes(struct erofs_sb_info *sbi, FILE *f);
+int erofs_xattr_flush_name_prefixes(struct erofs_sb_info *sbi);
void erofs_xattr_prefixes_cleanup(struct erofs_sb_info *sbi);
int erofs_xattr_prefixes_init(struct erofs_sb_info *sbi);
diff --git a/lib/fragments.c b/lib/fragments.c
index e2d3343..43cebe0 100644
--- a/lib/fragments.c
+++ b/lib/fragments.c
@@ -37,8 +37,11 @@ struct erofs_fragment_dedupe_item {
#define FRAGMENT_HASHSIZE 65536
#define FRAGMENT_HASH(c) ((c) & (FRAGMENT_HASHSIZE - 1))
-static struct list_head dupli_frags[FRAGMENT_HASHSIZE];
-static FILE *packedfile;
+struct erofs_packed_inode {
+ struct list_head *hash;
+ FILE *file;
+};
+
const char *erofs_frags_packedname = "packed_file";
#ifndef HAVE_LSEEK64
@@ -50,14 +53,14 @@ const char *erofs_frags_packedname = "packed_file";
static int z_erofs_fragments_dedupe_find(struct erofs_inode *inode, int fd,
u32 crc)
{
+ struct erofs_packed_inode *epi = inode->sbi->packedinode;
struct erofs_fragment_dedupe_item *cur, *di = NULL;
- struct list_head *head;
+ struct list_head *head = &epi->hash[FRAGMENT_HASH(crc)];
u8 *data;
unsigned int length, e2, deduped;
erofs_off_t pos;
int ret;
- head = &dupli_frags[FRAGMENT_HASH(crc)];
if (list_empty(head))
return 0;
@@ -115,14 +118,14 @@ static int z_erofs_fragments_dedupe_find(struct erofs_inode *inode, int fd,
pos = di->pos + di->length - deduped;
/* let's read more to dedupe as long as we can */
if (deduped == di->length) {
- fflush(packedfile);
+ fflush(epi->file);
while(deduped < inode->i_size && pos) {
char buf[2][16384];
unsigned int sz = min_t(unsigned int, pos,
sizeof(buf[0]));
- if (pread(fileno(packedfile), buf[0], sz,
+ if (pread(fileno(epi->file), buf[0], sz,
pos - sz) != sz)
break;
if (pread(fd, buf[1], sz,
@@ -170,8 +173,8 @@ int z_erofs_fragments_dedupe(struct erofs_inode *inode, int fd, u32 *tofcrc)
return 0;
}
-static int z_erofs_fragments_dedupe_insert(void *data, unsigned int len,
- erofs_off_t pos, u32 crc)
+static int z_erofs_fragments_dedupe_insert(struct list_head *hash, void *data,
+ unsigned int len, erofs_off_t pos)
{
struct erofs_fragment_dedupe_item *di;
@@ -190,33 +193,10 @@ static int z_erofs_fragments_dedupe_insert(void *data, unsigned int len,
di->length = len;
di->pos = pos;
- list_add_tail(&di->list, &dupli_frags[FRAGMENT_HASH(crc)]);
+ list_add_tail(&di->list, hash);
return 0;
}
-int z_erofs_fragments_init(void)
-{
- unsigned int i;
-
- for (i = 0; i < FRAGMENT_HASHSIZE; ++i)
- init_list_head(&dupli_frags[i]);
- return 0;
-}
-
-void z_erofs_fragments_exit(void)
-{
- struct erofs_fragment_dedupe_item *di, *n;
- struct list_head *head;
- unsigned int i;
-
- for (i = 0; i < FRAGMENT_HASHSIZE; ++i) {
- head = &dupli_frags[i];
-
- list_for_each_entry_safe(di, n, head, list)
- free(di);
- }
-}
-
void z_erofs_fragments_commit(struct erofs_inode *inode)
{
if (!inode->fragment_size)
@@ -232,13 +212,13 @@ void z_erofs_fragments_commit(struct erofs_inode *inode)
erofs_sb_set_fragments(inode->sbi);
}
-int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd,
- u32 tofcrc)
+int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofcrc)
{
+ struct erofs_packed_inode *epi = inode->sbi->packedinode;
#ifdef HAVE_FTELLO64
- off64_t offset = ftello64(packedfile);
+ off64_t offset = ftello64(epi->file);
#else
- off_t offset = ftello(packedfile);
+ off_t offset = ftello(epi->file);
#endif
char *memblock;
int rc;
@@ -267,7 +247,7 @@ int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd,
rc = -EAGAIN;
goto out;
}
- if (fwrite(buf, sz, 1, packedfile) != 1) {
+ if (fwrite(buf, sz, 1, epi->file) != 1) {
rc = -EIO;
goto out;
}
@@ -278,7 +258,7 @@ int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd,
rc = -errno;
goto out;
}
- } else if (fwrite(memblock, inode->fragment_size, 1, packedfile) != 1) {
+ } else if (fwrite(memblock, inode->fragment_size, 1, epi->file) != 1) {
rc = -EIO;
goto out;
}
@@ -287,8 +267,9 @@ int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd,
inode->fragment_size | 0ULL, inode->fragmentoff | 0ULL);
if (memblock)
- rc = z_erofs_fragments_dedupe_insert(memblock,
- inode->fragment_size, inode->fragmentoff, tofcrc);
+ rc = z_erofs_fragments_dedupe_insert(
+ &epi->hash[FRAGMENT_HASH(tofcrc)], memblock,
+ inode->fragment_size, inode->fragmentoff);
else
rc = 0;
out:
@@ -300,10 +281,11 @@ out:
int z_erofs_pack_fragments(struct erofs_inode *inode, void *data,
unsigned int len, u32 tofcrc)
{
+ struct erofs_packed_inode *epi = inode->sbi->packedinode;
#ifdef HAVE_FTELLO64
- off64_t offset = ftello64(packedfile);
+ off64_t offset = ftello64(epi->file);
#else
- off_t offset = ftello(packedfile);
+ off_t offset = ftello(epi->file);
#endif
int ret;
@@ -313,14 +295,14 @@ int z_erofs_pack_fragments(struct erofs_inode *inode, void *data,
inode->fragmentoff = (erofs_off_t)offset;
inode->fragment_size = len;
- if (fwrite(data, len, 1, packedfile) != 1)
+ if (fwrite(data, len, 1, epi->file) != 1)
return -EIO;
erofs_dbg("Recording %llu fragment data at %llu",
inode->fragment_size | 0ULL, inode->fragmentoff | 0ULL);
- ret = z_erofs_fragments_dedupe_insert(data, len, inode->fragmentoff,
- tofcrc);
+ ret = z_erofs_fragments_dedupe_insert(&epi->hash[FRAGMENT_HASH(tofcrc)],
+ data, len, inode->fragmentoff);
if (ret)
return ret;
return len;
@@ -328,35 +310,85 @@ int z_erofs_pack_fragments(struct erofs_inode *inode, void *data,
int erofs_flush_packed_inode(struct erofs_sb_info *sbi)
{
+ struct erofs_packed_inode *epi = sbi->packedinode;
struct erofs_inode *inode;
- if (!erofs_sb_has_fragments(sbi))
+ if (!epi || !erofs_sb_has_fragments(sbi))
return -EINVAL;
- fflush(packedfile);
- if (!ftello(packedfile))
- return 0;
- inode = erofs_mkfs_build_special_from_fd(sbi, fileno(packedfile),
+ fflush(epi->file);
+ if (!ftello(epi->file))
+ return 0;
+ inode = erofs_mkfs_build_special_from_fd(sbi, fileno(epi->file),
EROFS_PACKED_INODE);
sbi->packed_nid = erofs_lookupnid(inode);
erofs_iput(inode);
return 0;
}
-void erofs_packedfile_exit(void)
+FILE *erofs_packedfile(struct erofs_sb_info *sbi)
+{
+ return sbi->packedinode->file;
+}
+
+void erofs_packedfile_exit(struct erofs_sb_info *sbi)
{
- if (packedfile)
- fclose(packedfile);
+ struct erofs_packed_inode *epi = sbi->packedinode;
+ struct erofs_fragment_dedupe_item *di, *n;
+ int i;
+
+ if (!epi)
+ return;
+
+ if (epi->hash) {
+ for (i = 0; i < FRAGMENT_HASHSIZE; ++i)
+ list_for_each_entry_safe(di, n, &epi->hash[i], list)
+ free(di);
+ free(epi->hash);
+ }
+
+ if (epi->file)
+ fclose(epi->file);
+ free(epi);
+ sbi->packedinode = NULL;
}
-FILE *erofs_packedfile_init(void)
+int erofs_packedfile_init(struct erofs_sb_info *sbi, bool fragments_mkfs)
{
+ struct erofs_packed_inode *epi;
+ int err, i;
+
+ if (sbi->packedinode)
+ return -EINVAL;
+
+ epi = calloc(1, sizeof(*epi));
+ if (!epi)
+ return -ENOMEM;
+
+ sbi->packedinode = epi;
+ if (fragments_mkfs) {
+ epi->hash = malloc(sizeof(*epi->hash) * FRAGMENT_HASHSIZE);
+ if (!epi->hash) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ for (i = 0; i < FRAGMENT_HASHSIZE; ++i)
+ init_list_head(&epi->hash[i]);
+ }
+
+ epi->file =
#ifdef HAVE_TMPFILE64
- packedfile = tmpfile64();
+ tmpfile64();
#else
- packedfile = tmpfile();
+ tmpfile();
#endif
- if (!packedfile)
- return ERR_PTR(-ENOMEM);
- return packedfile;
+ if (!epi->file) {
+ err = -errno;
+ goto err_out;
+ }
+ return 0;
+
+err_out:
+ erofs_packedfile_exit(sbi);
+ return err;
}
diff --git a/lib/xattr.c b/lib/xattr.c
index c20c9a2..063b01a 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -809,8 +809,9 @@ static int comp_shared_xattr_item(const void *a, const void *b)
return la > lb;
}
-int erofs_xattr_write_name_prefixes(struct erofs_sb_info *sbi, FILE *f)
+int erofs_xattr_flush_name_prefixes(struct erofs_sb_info *sbi)
{
+ FILE *f = erofs_packedfile(sbi);
struct ea_type_node *tnode;
off_t offset;
diff --git a/mkfs/main.c b/mkfs/main.c
index 624b191..a0fce35 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1197,7 +1197,6 @@ int main(int argc, char **argv)
struct erofs_inode *root = NULL;
erofs_blk_t nblocks = 0;
struct timeval t;
- FILE *packedfile = NULL;
FILE *blklst = NULL;
u32 crc;
@@ -1253,17 +1252,10 @@ int main(int argc, char **argv)
if (!cfg.c_mkfs_pclustersize_packed)
cfg.c_mkfs_pclustersize_packed = cfg.c_mkfs_pclustersize_def;
- packedfile = erofs_packedfile_init();
- if (IS_ERR(packedfile)) {
- erofs_err("failed to initialize packedfile");
- return 1;
- }
- }
-
- if (cfg.c_fragments) {
- err = z_erofs_fragments_init();
+ err = erofs_packedfile_init(&g_sbi, cfg.c_fragments);
if (err) {
- erofs_err("failed to initialize fragments");
+ erofs_err("failed to initialize packedfile: %s",
+ strerror(-err));
return 1;
}
}
@@ -1445,7 +1437,7 @@ int main(int argc, char **argv)
}
if (cfg.c_extra_ea_name_prefixes)
- erofs_xattr_write_name_prefixes(&g_sbi, packedfile);
+ erofs_xattr_flush_name_prefixes(&g_sbi);
root = erofs_mkfs_build_tree_from_path(&g_sbi, cfg.c_src_path);
if (IS_ERR(root)) {
@@ -1510,9 +1502,7 @@ exit:
erofs_cleanup_exclude_rules();
if (cfg.c_chunkbits)
erofs_blob_exit();
- if (cfg.c_fragments)
- z_erofs_fragments_exit();
- erofs_packedfile_exit();
+ erofs_packedfile_exit(&g_sbi);
erofs_xattr_cleanup_name_prefixes();
erofs_rebuild_cleanup();
erofs_diskbuf_exit();
--
2.43.5
More information about the Linux-erofs
mailing list