erofs-utils: lib: fix multi-threaded compression in tarerofs mode
authorGao Xiang <hsiangkao@linux.alibaba.com>
Tue, 19 Mar 2024 08:24:55 +0000 (16:24 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Sun, 7 Apr 2024 07:36:01 +0000 (15:36 +0800)
Since pread() can be used during multi-threaded compression, it's
necessary to pass `fpos` in to indicate the absolute offset.

Fixes: aec8487dce4c ("erofs-utils: mkfs: introduce inner-file multi-threaded compression")
Link: https://lore.kernel.org/r/20240319082455.4115493-1-hsiangkao@linux.alibaba.com
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
include/erofs/compress.h
lib/compress.c
lib/inode.c

index 3253611e29363267c90dc291790c5dd64f9ff6e7..871db54c85999726ea5a1df560dc503f77f5cb3e 100644 (file)
@@ -18,7 +18,7 @@ extern "C"
 #define Z_EROFS_COMPR_QUEUE_SZ         (EROFS_CONFIG_COMPR_MAX_SZ * 2)
 
 void z_erofs_drop_inline_pcluster(struct erofs_inode *inode);
-int erofs_write_compressed_file(struct erofs_inode *inode, int fd);
+int erofs_write_compressed_file(struct erofs_inode *inode, int fd, u64 fpos);
 
 int z_erofs_compress_init(struct erofs_sb_info *sbi,
                          struct erofs_buffer_head *bh);
index f9c51e1dd85e5a5f42ebf56f09b26b2b98302f4f..f24e8ccaf24b0238b68fb8af3416265fce0f9d45 100644 (file)
@@ -38,8 +38,9 @@ struct z_erofs_extent_item {
 
 struct z_erofs_compress_ictx {         /* inode context */
        struct erofs_inode *inode;
-       int fd;
        unsigned int pclustersize;
+       int fd;
+       u64 fpos;
 
        u32 tof_chksum;
        bool fix_dedupedfrag;
@@ -990,7 +991,8 @@ void z_erofs_drop_inline_pcluster(struct erofs_inode *inode)
 int z_erofs_compress_segment(struct z_erofs_compress_sctx *ctx,
                             u64 offset, erofs_blk_t blkaddr)
 {
-       int fd = ctx->ictx->fd;
+       struct z_erofs_compress_ictx *ictx = ctx->ictx;
+       int fd = ictx->fd;
 
        ctx->blkaddr = blkaddr;
        while (ctx->remaining) {
@@ -1000,7 +1002,8 @@ int z_erofs_compress_segment(struct z_erofs_compress_sctx *ctx,
 
                ret = (offset == -1 ?
                        read(fd, ctx->queue + ctx->tail, rx) :
-                       pread(fd, ctx->queue + ctx->tail, rx, offset));
+                       pread(fd, ctx->queue + ctx->tail, rx,
+                             ictx->fpos + offset));
                if (ret != rx)
                        return -errno;
 
@@ -1238,7 +1241,7 @@ int z_erofs_mt_compress(struct z_erofs_compress_ictx *ictx,
 }
 #endif
 
-int erofs_write_compressed_file(struct erofs_inode *inode, int fd)
+int erofs_write_compressed_file(struct erofs_inode *inode, int fd, u64 fpos)
 {
        static u8 g_queue[Z_EROFS_COMPR_QUEUE_SZ];
        struct erofs_buffer_head *bh;
@@ -1313,9 +1316,10 @@ int erofs_write_compressed_file(struct erofs_inode *inode, int fd)
        blkaddr = erofs_mapbh(bh->block);       /* start_blkaddr */
        ctx.inode = inode;
        ctx.pclustersize = z_erofs_get_max_pclustersize(inode);
+       ctx.fd = fd;
+       ctx.fpos = fpos;
        ctx.metacur = compressmeta + Z_EROFS_LEGACY_MAP_HEADER_SIZE;
        init_list_head(&ctx.extents);
-       ctx.fd = fd;
        ctx.fix_dedupedfrag = false;
        ctx.fragemitted = false;
        sctx = (struct z_erofs_compress_sctx) { .ictx = &ctx, };
index ac00228e711968bb605a1836ae21711890d800c6..4c29aa7619a402deb074a162de61c4f4dc2674f8 100644 (file)
@@ -493,7 +493,7 @@ int erofs_write_file(struct erofs_inode *inode, int fd, u64 fpos)
        }
 
        if (cfg.c_compr_opts[0].alg && erofs_file_is_compressible(inode)) {
-               ret = erofs_write_compressed_file(inode, fd);
+               ret = erofs_write_compressed_file(inode, fd, fpos);
                if (!ret || ret != -ENOSPC)
                        return ret;
 
@@ -1340,7 +1340,7 @@ struct erofs_inode *erofs_mkfs_build_special_from_fd(int fd, const char *name)
                inode->nid = inode->sbi->packed_nid;
        }
 
-       ret = erofs_write_compressed_file(inode, fd);
+       ret = erofs_write_compressed_file(inode, fd, 0);
        if (ret == -ENOSPC) {
                ret = lseek(fd, 0, SEEK_SET);
                if (ret < 0)