It's also used for the upcoming fragment cache.

Signed-off-by: Gao Xiang <hsiang...@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

Reply via email to