[PATCH 4/7] erofs-utils: lib: switch to vfile interfaces for fragments
Gao Xiang
hsiangkao at linux.alibaba.com
Thu Oct 16 13:48:12 AEDT 2025
Avoid using raw FDs for the upcoming directory data compression.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
lib/compress.c | 21 ++++++++------
lib/fragments.c | 62 ++++++++++++++++++----------------------
lib/liberofs_fragments.h | 10 ++++---
3 files changed, 47 insertions(+), 46 deletions(-)
diff --git a/lib/compress.c b/lib/compress.c
index 20f511e..74d40b1 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -1258,13 +1258,14 @@ int z_erofs_compress_segment(struct z_erofs_compress_sctx *ctx,
bool frag = params->fragments && !erofs_is_packed_inode(inode) &&
!erofs_is_metabox_inode(inode) &&
ctx->seg_idx >= ictx->seg_num - 1;
- int fd = ictx->fd;
+ struct erofs_vfile vf = { .fd = ictx->fd };
int ret;
DBG_BUGON(offset != -1 && frag && inode->fragment_size);
if (offset != -1 && frag && !inode->fragment_size &&
params->fragdedupe != EROFS_FRAGDEDUPE_OFF) {
- ret = erofs_fragment_findmatch(inode, fd, ictx->tofh);
+ ret = erofs_fragment_findmatch(inode,
+ &vf, ictx->fpos, ictx->tofh);
if (ret < 0)
return ret;
if (inode->fragment_size > ctx->remaining)
@@ -1280,9 +1281,9 @@ int z_erofs_compress_segment(struct z_erofs_compress_sctx *ctx,
int ret;
ret = (offset == -1 ?
- read(fd, ctx->queue + ctx->tail, rx) :
- pread(fd, ctx->queue + ctx->tail, rx,
- ictx->fpos + offset));
+ erofs_io_read(&vf, ctx->queue + ctx->tail, rx) :
+ erofs_io_pread(&vf, ctx->queue + ctx->tail, rx,
+ ictx->fpos + offset));
if (ret != rx)
return -errno;
@@ -1848,14 +1849,17 @@ void *erofs_begin_compressed_file(struct erofs_importer *im,
inode->z_advise |= Z_EROFS_ADVISE_INTERLACED_PCLUSTER;
if (frag) {
- ictx->tofh = z_erofs_fragments_tofh(inode, fd, fpos);
+ struct erofs_vfile vf = { .fd = fd };
+
+ ictx->tofh = z_erofs_fragments_tofh(inode, &vf, fpos);
if (ictx == &g_ictx &&
params->fragdedupe != EROFS_FRAGDEDUPE_OFF) {
/*
* Handle tails in advance to avoid writing duplicated
* parts into the packed inode.
*/
- ret = erofs_fragment_findmatch(inode, fd, ictx->tofh);
+ ret = erofs_fragment_findmatch(inode,
+ &vf, fpos, ictx->tofh);
if (ret < 0)
goto err_free_ictx;
@@ -1874,7 +1878,8 @@ void *erofs_begin_compressed_file(struct erofs_importer *im,
ictx->dedupe = false;
if (all_fragments && !inode->fragment_size) {
- ret = erofs_pack_file_from_fd(inode, fd, ictx->tofh);
+ ret = erofs_pack_file_from_fd(inode,
+ &((struct erofs_vfile){ .fd = fd }), fpos, ictx->tofh);
if (ret)
goto err_free_idata;
}
diff --git a/lib/fragments.c b/lib/fragments.c
index 244608f..15092e1 100644
--- a/lib/fragments.c
+++ b/lib/fragments.c
@@ -53,7 +53,8 @@ struct erofs_packed_inode {
const char *erofs_frags_packedname = "packed_file";
-u32 z_erofs_fragments_tofh(struct erofs_inode *inode, int fd, erofs_off_t fpos)
+u32 z_erofs_fragments_tofh(struct erofs_inode *inode,
+ struct erofs_vfile *vf, erofs_off_t fpos)
{
u8 data_to_hash[EROFS_TOF_HASHLEN];
u32 hash;
@@ -62,10 +63,10 @@ u32 z_erofs_fragments_tofh(struct erofs_inode *inode, int fd, erofs_off_t fpos)
if (inode->i_size <= EROFS_TOF_HASHLEN)
return ~0U;
- ret = pread(fd, data_to_hash, EROFS_TOF_HASHLEN,
- fpos + inode->i_size - EROFS_TOF_HASHLEN);
+ ret = erofs_io_pread(vf, data_to_hash, EROFS_TOF_HASHLEN,
+ fpos + inode->i_size - EROFS_TOF_HASHLEN);
if (ret < 0)
- return -errno;
+ return ret;
if (ret != EROFS_TOF_HASHLEN) {
DBG_BUGON(1);
return -EIO;
@@ -76,7 +77,9 @@ u32 z_erofs_fragments_tofh(struct erofs_inode *inode, int fd, erofs_off_t fpos)
static erofs_off_t erofs_fragment_longmatch(struct erofs_inode *inode,
struct erofs_fragmentitem *fi,
- erofs_off_t matched, int fd)
+ erofs_off_t matched,
+ struct erofs_vfile *vf,
+ erofs_off_t fpos)
{
struct erofs_packed_inode *epi = inode->sbi->packedinode;
erofs_off_t total = min_t(erofs_off_t, fi->length, inode->i_size);
@@ -99,7 +102,8 @@ static erofs_off_t erofs_fragment_longmatch(struct erofs_inode *inode,
return matched;
}
sz = min_t(u64, total - matched, sizeof(buf[0]));
- if (pread(fd, buf[0], sz, inode->i_size - matched - sz) != sz)
+ if (erofs_io_pread(vf, buf[0], sz,
+ fpos + inode->i_size - matched - sz) != sz)
break;
if (!inmem) {
@@ -116,7 +120,8 @@ static erofs_off_t erofs_fragment_longmatch(struct erofs_inode *inode,
return matched;
}
-int erofs_fragment_findmatch(struct erofs_inode *inode, int fd, u32 tofh)
+int erofs_fragment_findmatch(struct erofs_inode *inode,
+ struct erofs_vfile *vf, erofs_off_t fpos, u32 tofh)
{
struct erofs_packed_inode *epi = inode->sbi->packedinode;
struct erofs_fragmentitem *cur, *fi = NULL;
@@ -136,7 +141,7 @@ int erofs_fragment_findmatch(struct erofs_inode *inode, int fd, u32 tofh)
if (!data)
return -ENOMEM;
- ret = pread(fd, data, s1, inode->i_size - s1);
+ ret = erofs_io_pread(vf, data, s1, fpos + inode->i_size - s1);
if (ret != s1) {
free(data);
return -errno;
@@ -167,7 +172,7 @@ int erofs_fragment_findmatch(struct erofs_inode *inode, int fd, u32 tofh)
i += EROFS_TOF_HASHLEN;
if (i >= s1) { /* full short match */
DBG_BUGON(i > s1);
- i = erofs_fragment_longmatch(inode, cur, s1, fd);
+ i = erofs_fragment_longmatch(inode, cur, s1, vf, fpos);
}
if (i <= deduped)
@@ -229,7 +234,8 @@ int erofs_fragment_pack(struct erofs_inode *inode, void *data,
return 0;
}
-int erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofh)
+int erofs_pack_file_from_fd(struct erofs_inode *inode,
+ struct erofs_vfile *vf, erofs_off_t fpos, u32 tofh)
{
struct erofs_packed_inode *epi = inode->sbi->packedinode;
s64 offset, rc, sz;
@@ -243,33 +249,27 @@ int erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofh)
if (offset < 0)
return -errno;
- memblock = mmap(NULL, inode->i_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (vf->ops)
+ memblock = NULL;
+ else
+ memblock = mmap(NULL, inode->i_size, PROT_READ,
+ MAP_SHARED, vf->fd, fpos);
if (memblock == MAP_FAILED || !memblock) {
erofs_off_t remaining = inode->i_size;
- struct erofs_vfile vin = { .fd = fd };
+ struct erofs_vfile vout = { .fd = epi->fd };
+ off_t pos = fpos;
-#if defined(HAVE_SYS_SENDFILE_H) && defined(HAVE_SENDFILE)
do {
sz = min_t(u64, remaining, UINT_MAX);
- rc = sendfile(epi->fd, fd, NULL, sz);
+ rc = erofs_io_sendfile(&vout, vf, &pos, sz);
if (rc <= 0)
break;
remaining -= rc;
} while (remaining);
-#endif
- while (remaining) {
- char buf[32768];
-
- sz = min_t(u64, remaining, sizeof(buf));
- rc = erofs_io_read(&vin, buf, sz);
- if (rc < 0)
- goto out;
- if (rc > 0) {
- rc = write(epi->fd, buf, rc);
- if (rc < 0)
- goto out;
- }
- remaining -= rc;
+
+ if (remaining && rc >= 0) {
+ rc = -EIO;
+ goto out;
}
sz = min_t(u64, inode->i_size, EROFS_FRAGMENT_INMEM_SZ_MAX);
@@ -288,12 +288,6 @@ int erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofh)
}
goto out;
}
-
- rc = lseek(fd, 0, SEEK_SET);
- if (rc < 0) {
- rc = -errno;
- goto out;
- }
} else {
rc = __erofs_io_write(epi->fd, memblock, inode->i_size);
if (rc != inode->i_size) {
diff --git a/lib/liberofs_fragments.h b/lib/liberofs_fragments.h
index ca71e52..11833eb 100644
--- a/lib/liberofs_fragments.h
+++ b/lib/liberofs_fragments.h
@@ -10,10 +10,12 @@
struct erofs_importer;
-u32 z_erofs_fragments_tofh(struct erofs_inode *inode, int fd, erofs_off_t fpos);
-int erofs_fragment_findmatch(struct erofs_inode *inode, int fd, u32 tofh);
-
-int erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofcrc);
+u32 z_erofs_fragments_tofh(struct erofs_inode *inode,
+ struct erofs_vfile *vf, erofs_off_t fpos);
+int erofs_fragment_findmatch(struct erofs_inode *inode,
+ struct erofs_vfile *vf, erofs_off_t fpos, u32 tofh);
+int erofs_pack_file_from_fd(struct erofs_inode *inode,
+ struct erofs_vfile *vf, erofs_off_t fpos, u32 tofh);
int erofs_fragment_pack(struct erofs_inode *inode, void *data,
erofs_off_t pos, erofs_off_t len, u32 tofh, bool tail);
int erofs_fragment_commit(struct erofs_inode *inode, u32 tofh);
--
2.43.5
More information about the Linux-erofs
mailing list