When `vf->ops` is not null, `vf->ops->pread` returns the number of bytes successfully read, which is inconsistent with the semantics of `erofs_io_pread`. Similar situation occurs in `erofs_io_pwrite`. This fixes this issue.
This also fixes `erofs_dev_close`. Signed-off-by: Hongzhen Luo <hongz...@linux.alibaba.com> --- v2: https://lore.kernel.org/all/20240618093843.912278-1-hongz...@linux.alibaba.com/ v1: https://lore.kernel.org/all/20240617023433.3446706-1-hongz...@linux.alibaba.com/ --- include/erofs/internal.h | 5 ++++- lib/io.c | 47 ++++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/include/erofs/internal.h b/include/erofs/internal.h index f8a01ce..dfbd958 100644 --- a/include/erofs/internal.h +++ b/include/erofs/internal.h @@ -460,7 +460,10 @@ ssize_t erofs_dev_read(struct erofs_sb_info *sbi, int device_id, static inline int erofs_dev_write(struct erofs_sb_info *sbi, const void *buf, u64 offset, size_t len) { - return erofs_io_pwrite(&sbi->bdev, buf, offset, len); + ssize_t ret; + + ret = erofs_io_pwrite(&sbi->bdev, buf, offset, len); + return (size_t)ret == len ? 0 : -EIO; } static inline int erofs_dev_fillzero(struct erofs_sb_info *sbi, u64 offset, diff --git a/lib/io.c b/lib/io.c index c523f00..3417b46 100644 --- a/lib/io.c +++ b/lib/io.c @@ -30,6 +30,7 @@ ssize_t erofs_io_pwrite(struct erofs_vfile *vf, const void *buf, u64 pos, size_t len) { ssize_t ret; + size_t write = 0; if (unlikely(cfg.c_dry_run)) return 0; @@ -51,9 +52,10 @@ ssize_t erofs_io_pwrite(struct erofs_vfile *vf, const void *buf, len -= ret; buf += ret; pos += ret; + write += ret; } while (len); - return 0; + return write; } int erofs_io_fsync(struct erofs_vfile *vf) @@ -92,13 +94,15 @@ ssize_t erofs_io_fallocate(struct erofs_vfile *vf, u64 offset, return 0; #endif while (len > EROFS_MAX_BLOCK_SIZE) { - ret = erofs_io_pwrite(vf, zero, offset, EROFS_MAX_BLOCK_SIZE); + ret = erofs_io_pwrite(vf, zero, offset, + EROFS_MAX_BLOCK_SIZE) == EROFS_MAX_BLOCK_SIZE ? + 0 : -EIO; if (ret) return ret; len -= EROFS_MAX_BLOCK_SIZE; offset += EROFS_MAX_BLOCK_SIZE; } - return erofs_io_pwrite(vf, zero, offset, len); + return erofs_io_pwrite(vf, zero, offset, len) == len ? 0 : -EIO; } int erofs_io_ftruncate(struct erofs_vfile *vf, u64 length) @@ -126,6 +130,7 @@ int erofs_io_ftruncate(struct erofs_vfile *vf, u64 length) ssize_t erofs_io_pread(struct erofs_vfile *vf, void *buf, u64 pos, size_t len) { ssize_t ret; + ssize_t read = 0; if (unlikely(cfg.c_dry_run)) return 0; @@ -142,9 +147,7 @@ ssize_t erofs_io_pread(struct erofs_vfile *vf, void *buf, u64 pos, size_t len) #endif if (ret <= 0) { if (!ret) { - erofs_info("reach EOF of device"); - memset(buf, 0, len); - return 0; + return read; } if (errno != EINTR) { erofs_err("failed to read: %s", strerror(errno)); @@ -155,8 +158,11 @@ ssize_t erofs_io_pread(struct erofs_vfile *vf, void *buf, u64 pos, size_t len) pos += ret; len -= ret; buf += ret; + read += ret; + } while (len); - return 0; + + return read; } static int erofs_get_bdev_size(int fd, u64 *bytes) @@ -287,7 +293,8 @@ out: void erofs_dev_close(struct erofs_sb_info *sbi) { - close(sbi->bdev.fd); + if (!sbi->bdev.ops) + close(sbi->bdev.fd); free(sbi->devname); sbi->devname = NULL; sbi->bdev.fd = -1; @@ -320,11 +327,29 @@ int erofs_blob_open_ro(struct erofs_sb_info *sbi, const char *dev) ssize_t erofs_dev_read(struct erofs_sb_info *sbi, int device_id, void *buf, u64 offset, size_t len) { - if (device_id) - return erofs_io_pread(&((struct erofs_vfile) { + ssize_t ret; + + if (device_id) { + ret = erofs_io_pread(&((struct erofs_vfile) { .fd = sbi->blobfd[device_id - 1], }), buf, offset, len); - return erofs_io_pread(&sbi->bdev, buf, offset, len); + if (ret < 0) + return ret; + if (ret < len) { + erofs_info("reach EOF of device"); + memset(buf + ret, 0, len - ret); + } + return 0; + } + + ret = erofs_io_pread(&sbi->bdev, buf, offset, len); + if (ret < 0) + return ret; + if (ret < len) { + erofs_info("reach EOF of device"); + memset(buf + ret, 0, len - ret); + } + return 0; } static ssize_t __erofs_copy_file_range(int fd_in, u64 *off_in, -- 2.39.3