[PATCH v2 7/7] erofs-utils: mkfs: use per-worker tmpfile for multi-threaded mkfs
Yifan Zhao
zhaoyifan at sjtu.edu.cn
Tue Feb 20 18:55:25 AEDT 2024
Currently, multi-threaded mkfs.erofs creates tmpfiles for each segment
to store the intermediate compression result, reaching the limit of open
files when the number of segments is large.
This patch uses per-worker tmpfiles to avoid this problem if possible,
i.e., the environment supports the fallocate() syscall and
FALLOC_FL_PUNCH_HOLE flag.
Signed-off-by: Yifan Zhao <zhaoyifan at sjtu.edu.cn>
---
lib/compress.c | 68 +++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 54 insertions(+), 14 deletions(-)
diff --git a/lib/compress.c b/lib/compress.c
index d5a5f16..3fae260 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -8,6 +8,9 @@
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
@@ -23,6 +26,13 @@
#ifdef EROFS_MT_ENABLED
#include "erofs/workqueue.h"
#endif
+#ifdef HAVE_LINUX_FALLOC_H
+#include <linux/falloc.h>
+#endif
+
+#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_PUNCH_HOLE)
+#define USE_PER_WORKER_TMPFILE 1
+#endif
/* compressing configuration specified by users */
struct erofs_compress_cfg {
@@ -59,6 +69,7 @@ struct z_erofs_vle_compress_ctx {
int seg_num, seg_idx;
FILE *tmpfile;
+ off_t tmpfile_off;
};
struct z_erofs_write_index_ctx {
@@ -75,6 +86,7 @@ struct erofs_compress_wq_private {
u8 *queue;
char *destbuf;
struct erofs_compress_cfg *ccfg;
+ FILE* tmpfile;
};
struct erofs_compress_work {
@@ -402,6 +414,7 @@ static int write_uncompressed_extent(struct z_erofs_vle_compress_ctx *ctx,
ret = fwrite(dst, erofs_blksiz(sbi), 1, ctx->tmpfile);
if (ret != 1)
return -EIO;
+ fflush(ctx->tmpfile);
} else {
erofs_dbg("Writing %u uncompressed data to block %u", count,
ctx->blkaddr);
@@ -1073,6 +1086,7 @@ void z_erofs_init_ctx(struct z_erofs_vle_compress_ctx *ctx,
ctx->tof_chksum = tof_chksum;
ctx->fd = fd;
ctx->tmpfile = NULL;
+ ctx->tmpfile_off = 0;
init_list_head(&ctx->extents);
}
@@ -1169,7 +1183,7 @@ int z_erofs_mt_private_init(struct erofs_sb_info *sbi,
struct erofs_compress_cfg *lc;
int ret;
- if (!priv->init) {
+ if (unlikely(!priv->init)) {
priv->init = true;
priv->queue = malloc(EROFS_COMPR_QUEUE_SZ);
@@ -1185,6 +1199,16 @@ int z_erofs_mt_private_init(struct erofs_sb_info *sbi,
sizeof(struct erofs_compress_cfg));
if (!priv->ccfg)
return -ENOMEM;
+
+#ifdef USE_PER_WORKER_TMPFILE
+#ifndef HAVE_TMPFILE64
+ priv->tmpfile = tmpfile();
+#else
+ priv->tmpfile = tmpfile64();
+#endif
+ if (!priv->tmpfile)
+ return -errno;
+#endif
}
lc = &priv->ccfg[alg_id];
@@ -1214,6 +1238,9 @@ void z_erofs_mt_private_fini(void *private)
free(priv->ccfg);
free(priv->destbuf);
free(priv->queue);
+#ifdef USE_PER_WORKER_TMPFILE
+ fclose(priv->tmpfile);
+#endif
priv->init = false;
}
}
@@ -1237,24 +1264,30 @@ void z_erofs_mt_work(struct erofs_work *work)
ctx->queue = priv->queue;
ctx->destbuf = priv->destbuf;
ctx->chandle = &priv->ccfg[cwork->alg_id].handle;
-
+#ifdef USE_PER_WORKER_TMPFILE
+ ctx->tmpfile = priv->tmpfile;
+ ctx->tmpfile_off = ftell(ctx->tmpfile);
+ if (ctx->tmpfile_off == -1) {
+ ret = -errno;
+ goto out;
+ }
+#else
#ifdef HAVE_TMPFILE64
ctx->tmpfile = tmpfile64();
#else
ctx->tmpfile = tmpfile();
#endif
-
if (!ctx->tmpfile) {
ret = -errno;
goto out;
}
+ ctx->tmpfile_off = 0;
+#endif
ret = z_erofs_compress_file(ctx, offset, blkaddr);
if (ret)
goto out;
- fflush(ctx->tmpfile);
-
if (ctx->seg_idx == ctx->seg_num - 1)
ret = z_erofs_handle_fragments(ctx);
@@ -1274,6 +1307,7 @@ int z_erofs_mt_merge(struct erofs_compress_file *cfile, erofs_blk_t blkaddr,
struct erofs_sb_info *sbi = cur->ctx.inode->sbi;
struct z_erofs_write_index_ctx *ictx = cfile->ictx;
char *memblock = NULL;
+ size_t size = 0;
int ret = 0, lret;
while (cur != NULL) {
@@ -1290,28 +1324,32 @@ int z_erofs_mt_merge(struct erofs_compress_file *cfile, erofs_blk_t blkaddr,
goto out;
}
- memblock = realloc(memblock,
- ctx->compressed_blocks * erofs_blksiz(sbi));
+ size = ctx->compressed_blocks * erofs_blksiz(sbi);
+ memblock = realloc(memblock, size);
if (!memblock) {
if (!ret)
ret = -ENOMEM;
goto out;
}
- lret = fseek(ctx->tmpfile, 0, SEEK_SET);
- if (lret) {
+ lret = pread(fileno(ctx->tmpfile), memblock, size,
+ ctx->tmpfile_off);
+ if (lret != size) {
if (!ret)
- ret = lret;
+ ret = -errno;
goto out;
}
- lret = fread(memblock, erofs_blksiz(sbi),
- ctx->compressed_blocks, ctx->tmpfile);
- if (lret != ctx->compressed_blocks) {
+#ifdef USE_PER_WORKER_TMPFILE
+ lret = fallocate(fileno(ctx->tmpfile),
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ ctx->tmpfile_off, size);
+ if (lret) {
if (!ret)
- ret = -EIO;
+ ret = -errno;
goto out;
}
+#endif
lret = blk_write(sbi, memblock, blkaddr + *compressed_blocks,
ctx->compressed_blocks);
@@ -1323,7 +1361,9 @@ int z_erofs_mt_merge(struct erofs_compress_file *cfile, erofs_blk_t blkaddr,
*compressed_blocks += ctx->compressed_blocks;
out:
+#ifndef USE_PER_WORKER_TMPFILE
fclose(ctx->tmpfile);
+#endif
tmp = cur->next;
pthread_mutex_lock(&work_mutex);
--
2.43.2
More information about the Linux-erofs
mailing list