From: Yifan Zhao <stopire@gmail.com>
To: Gao Xiang <xiang.gao@docker.com>, linux-erofs@lists.ozlabs.org
Subject: Re: [PATCH 1/5] erofs-utils: lib: track packed inode position explicitly
Date: Tue, 3 Nov 2026 11:56:46 +0800 [thread overview]
Message-ID: <6f29b317-9df0-4e96-94c0-e3c3858f41e5@gmail.com> (raw)
In-Reply-To: <20261103004547.15053-1-xiang.gao@docker.com>
On 3/11/26 08:45, Gao Xiang wrote:
> Track the packed inode position in memory instead of querying the
> file offset. Use positional writes for fragment data and seek
> explicitly before the sendfile fallback.
>
> Factor out __erofs_io_pwrite() and fix its short-write handling.
>
> Assisted-by: ChatGPT:gpt-6.1-sol
> Signed-off-by: Gao Xiang <xiang.gao@docker.com>
> ---
> include/erofs/io.h | 2 +-
> lib/fragments.c | 44 +++++++++++++++++++++-----------------------
> lib/io.c | 29 ++++++++++++++---------------
> 3 files changed, 36 insertions(+), 39 deletions(-)
>
> diff --git a/include/erofs/io.h b/include/erofs/io.h
> index 96309fd..f3d4899 100644
> --- a/include/erofs/io.h
> +++ b/include/erofs/io.h
> @@ -68,7 +68,7 @@ struct erofs_vfile {
> };
> };
>
> -ssize_t __erofs_io_write(int fd, const void *buf, size_t len);
> +ssize_t __erofs_io_pwrite(int fd, const void *buf, size_t len, u64 pos);
> int __erofs_0write(int fd, size_t len);
>
> int erofs_io_fstat(struct erofs_vfile *vf, struct stat *buf);
> diff --git a/lib/fragments.c b/lib/fragments.c
> index f137e41..bb9ef72 100644
> --- a/lib/fragments.c
> +++ b/lib/fragments.c
> @@ -49,6 +49,7 @@ struct erofs_packed_inode {
> unsigned long *uptodate;
> erofs_mutex_t mutex;
> u64 uptodate_bits;
> + erofs_off_t pos;
erofs_xattr_flush_name_prefixes() also manipulates the packed inode's fd
offset.
if (bh) {
bh->op = &erofs_drop_directly_bhops;
err = erofs_bh_balloon(bh, offset - start);
if (err < 0)
return err;
bh->op = &erofs_drop_directly_bhops;
erofs_bdrop(bh, false);
} else {
DBG_BUGON(bmgr);
if (lseek(vf->fd, offset, SEEK_SET) < 0) // maybe a packedinode
return -errno;
}
Introducing a separate pos field would leave the two out of sync; how
should this be handled?
Thanks,
Yifan Zhao
> };
>
> const char *erofs_frags_packedname = "packed_file";
> @@ -245,9 +246,7 @@ int erofs_pack_file_from_fd(struct erofs_inode *inode,
> if (__erofs_unlikely(!inode->i_size))
> return 0;
>
> - offset = lseek(epi->fd, 0, SEEK_CUR);
> - if (offset < 0)
> - return -errno;
> + offset = epi->pos;
>
> if (vf->ops)
> memblock = NULL;
> @@ -260,20 +259,24 @@ int erofs_pack_file_from_fd(struct erofs_inode *inode,
> bool noseek = vf->ops && !vf->ops->pread;
> off_t pos = fpos;
>
> + memblock = NULL;
> + rc = lseek(epi->fd, offset, SEEK_SET);
> + if (rc < 0) {
> + rc = -errno;
> + goto out;
> + }
> do {
> sz = min_t(u64, remaining, UINT_MAX);
> rc = erofs_io_sendfile(&vout, vf,
> noseek ? NULL : &pos, sz);
> - if (rc <= 0)
> - break;
> + if (rc <= 0) {
> + if (!rc)
> + rc = -EIO;
> + goto out;
> + }
> remaining -= rc;
> } while (remaining);
>
> - if (remaining && rc >= 0) {
> - rc = -EIO;
> - goto out;
> - }
> -
> sz = min_t(u64, inode->i_size, EROFS_FRAGMENT_INMEM_SZ_MAX);
> memblock = malloc(sz);
> if (!memblock) {
> @@ -291,7 +294,7 @@ int erofs_pack_file_from_fd(struct erofs_inode *inode,
> goto out;
> }
> } else {
> - rc = __erofs_io_write(epi->fd, memblock, inode->i_size);
> + rc = __erofs_io_pwrite(epi->fd, memblock, inode->i_size, offset);
> if (rc != inode->i_size) {
> if (rc >= 0)
> rc = -EIO;
> @@ -299,6 +302,7 @@ int erofs_pack_file_from_fd(struct erofs_inode *inode,
> }
> }
>
> + epi->pos = offset + inode->i_size;
> rc = erofs_fragment_pack(inode, memblock, offset, inode->i_size,
> tofh, onheap);
> out:
> @@ -332,17 +336,16 @@ int erofs_fragment_commit(struct erofs_inode *inode, u32 tofh)
> return 0;
> }
>
> - offset = lseek(epi->fd, 0, SEEK_CUR);
> - if (offset < 0)
> - return -errno;
> + offset = epi->pos;
>
> - ret = write(epi->fd, fi->data, fi->length);
> + ret = __erofs_io_pwrite(epi->fd, fi->data, fi->length, offset);
> if (ret != fi->length) {
> if (ret < 0)
> return -errno;
> return -EIO;
> }
> offset += fi->length;
> + epi->pos = offset;
>
> if (!list_empty(&fi->list)) {
> struct erofs_fragment_bucket *bk = &epi->bks[FRAGMENT_HASH(tofh)];
> @@ -380,7 +383,7 @@ int erofs_flush_packed_inode(struct erofs_importer *im)
> if (!epi || !erofs_sb_has_fragments(sbi))
> return 0;
>
> - if (lseek(epi->fd, 0, SEEK_CUR) <= 0)
> + if (!epi->pos)
> return 0;
>
> erofs_update_progressinfo("Processing packed data ...");
> @@ -460,7 +463,6 @@ int erofs_packedfile_init(struct erofs_sb_info *sbi, bool fragments_mkfs)
> .sbi = sbi,
> .nid = sbi->packed_nid,
> };
> - s64 offset;
>
> err = erofs_read_inode_from_disk(&ei);
> if (err) {
> @@ -469,11 +471,7 @@ int erofs_packedfile_init(struct erofs_sb_info *sbi, bool fragments_mkfs)
> goto err_out;
> }
>
> - offset = lseek(epi->fd, ei.i_size, SEEK_SET);
> - if (offset < 0) {
> - err = -errno;
> - goto err_out;
> - }
> + epi->pos = ei.i_size;
> epi->uptodate_bits = round_up(BLK_ROUND_UP(sbi, ei.i_size),
> sizeof(epi->uptodate) * 8);
> epi->uptodate = calloc(1, epi->uptodate_bits >> 3);
> @@ -548,7 +546,7 @@ static void *erofs_packedfile_preload(struct erofs_inode *pi,
> if (err)
> goto err_out;
>
> - err = pwrite(epi->fd, buffer, map->m_llen, map->m_la);
> + err = __erofs_io_pwrite(epi->fd, buffer, map->m_llen, map->m_la);
> if (err < 0) {
> err = -errno;
> if (err == -ENOSPC) {
> diff --git a/lib/io.c b/lib/io.c
> index 3333170..14253af 100644
> --- a/lib/io.c
> +++ b/lib/io.c
> @@ -26,7 +26,7 @@
> #define EROFS_MODNAME "erofs_io"
> #include "erofs/print.h"
>
> -ssize_t __erofs_io_write(int fd, const void *buf, size_t len)
> +static ssize_t __erofs_io_write(int fd, const void *buf, size_t len)
> {
> ssize_t ret, written = 0;
>
> @@ -61,24 +61,12 @@ int erofs_io_fstat(struct erofs_vfile *vf, struct stat *buf)
> return fstat(vf->fd, buf);
> }
>
> -ssize_t erofs_io_pwrite(struct erofs_vfile *vf, const void *buf,
> - u64 pos, size_t len)
> +ssize_t __erofs_io_pwrite(int fd, const void *buf, size_t len, u64 pos)
> {
> ssize_t ret, written = 0;
>
> - if (__erofs_unlikely(cfg.c_dry_run))
> - return 0;
> -
> - if (vf->ops)
> - return vf->ops->pwrite(vf, buf, pos, len);
> -
> - pos += vf->offset;
> do {
> -#ifdef HAVE_PWRITE64
> - ret = pwrite64(vf->fd, buf, len, (off64_t)pos);
> -#else
> - ret = pwrite(vf->fd, buf, len, (off_t)pos);
> -#endif
> + ret = pwrite(fd, buf, len - written, (off_t)pos);
> if (ret <= 0) {
> if (!ret)
> break;
> @@ -96,6 +84,17 @@ ssize_t erofs_io_pwrite(struct erofs_vfile *vf, const void *buf,
> return written;
> }
>
> +ssize_t erofs_io_pwrite(struct erofs_vfile *vf, const void *buf,
> + u64 pos, size_t len)
> +{
> + if (__erofs_unlikely(cfg.c_dry_run))
> + return 0;
> +
> + if (vf->ops)
> + return vf->ops->pwrite(vf, buf, pos, len);
> + return __erofs_io_pwrite(vf->fd, buf, len, pos + vf->offset);
> +}
> +
> ssize_t erofs_io_pwritev(struct erofs_vfile *vf, const struct iovec *iov,
> int iovcnt, u64 pos)
> {
prev parent reply other threads:[~2026-11-03 3:56 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 0:45 [PATCH 1/5] erofs-utils: lib: track packed inode position explicitly Gao Xiang
2026-11-03 0:45 ` [PATCH 2/5] erofs-utils: lib: use positional reads for single-threaded compression Gao Xiang
2026-11-03 0:45 ` [PATCH 3/5] erofs-utils: lib: fix S3 and OCI portability Gao Xiang
2026-11-03 0:45 ` [PATCH 4/5] erofs-utils: add native Windows support Gao Xiang
2026-11-03 0:45 ` [PATCH 5/5] erofs-utils: lib: reject seeks on Windows pipes Gao Xiang
2026-11-03 3:56 ` Yifan Zhao [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6f29b317-9df0-4e96-94c0-e3c3858f41e5@gmail.com \
--to=stopire@gmail.com \
--cc=linux-erofs@lists.ozlabs.org \
--cc=xiang.gao@docker.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox