Now erofs_pread() is simply a wrapper around erofs_io_pread(), and erofs_iopen() is used to obtain a virtual file for erofs_pread().
Signed-off-by: Gao Xiang <[email protected]> --- dump/main.c | 10 +++++++-- fsck/main.c | 7 +++++- fuse/main.c | 23 ++++++++++++++----- include/erofs/internal.h | 3 +-- include/erofs/io.h | 11 +++++++++ lib/data.c | 48 ++++++++++++++++++++++------------------ lib/dir.c | 12 ++++++---- lib/fragments.c | 20 +++++++++++++---- lib/inode.c | 7 +++++- lib/namei.c | 7 +++++- lib/rebuild.c | 10 +++++++-- lib/super.c | 3 ++- 12 files changed, 116 insertions(+), 45 deletions(-) diff --git a/dump/main.c b/dump/main.c index 632075a2..f0dab02e 100644 --- a/dump/main.c +++ b/dump/main.c @@ -679,6 +679,7 @@ static void erofsdump_show_file_content(void) erofs_off_t pending_size; erofs_off_t read_offset; erofs_off_t read_size; + struct erofs_vfile vf; if (dumpcfg.inode_path) { err = erofs_ilookup(dumpcfg.inode_path, &inode); @@ -694,6 +695,10 @@ static void erofsdump_show_file_content(void) } } + err = erofs_iopen(&vf, &inode); + if (err) + return; + buffer_size = erofs_blksiz(inode.sbi); buffer_ptr = malloc(buffer_size); if (!buffer_ptr) { @@ -704,8 +709,9 @@ static void erofsdump_show_file_content(void) pending_size = inode.i_size; read_offset = 0; while (pending_size > 0) { - read_size = pending_size > buffer_size? buffer_size: pending_size; - err = erofs_pread(&inode, buffer_ptr, read_size, read_offset); + read_size = pending_size > buffer_size ? + buffer_size : pending_size; + err = erofs_pread(&vf, buffer_ptr, read_size, read_offset); if (err) { erofs_err("read file failed @ nid %llu", inode.nid | 0ULL); goto out; diff --git a/fsck/main.c b/fsck/main.c index 96096a91..44719b95 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -775,6 +775,7 @@ again: static inline int erofs_extract_symlink(struct erofs_inode *inode) { + struct erofs_vfile vf; bool tryagain = true; int ret; char *buf = NULL; @@ -792,7 +793,11 @@ static inline int erofs_extract_symlink(struct erofs_inode *inode) goto out; } - ret = erofs_pread(inode, buf, inode->i_size, 0); + ret = erofs_iopen(&vf, inode); + if (ret) + goto out; + + ret = erofs_pread(&vf, buf, inode->i_size, 0); if (ret) { erofs_err("I/O error occurred when reading symlink @ nid %llu: %d", inode->nid | 0ULL, ret); diff --git a/fuse/main.c b/fuse/main.c index db4f3236..001d1fde 100644 --- a/fuse/main.c +++ b/fuse/main.c @@ -366,11 +366,15 @@ out: static void erofsfuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { - int ret; - char *buf = NULL; struct erofs_inode *vi = (struct erofs_inode *)fi->fh; + struct erofs_vfile vf; + char *buf = NULL; + int ret; erofs_dbg("read(%llu): size = %zu, off = %lu", ino | 0ULL, size, off); + ret = erofs_iopen(&vf, vi); + if (ret) + return ret; buf = malloc(size); if (!buf) { @@ -378,7 +382,7 @@ static void erofsfuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, return; } - ret = erofs_pread(vi, buf, size, off); + ret = erofs_pread(&vf, buf, size, off); if (ret) { fuse_reply_err(req, -ret); goto out; @@ -398,9 +402,10 @@ out: static void erofsfuse_readlink(fuse_req_t req, fuse_ino_t ino) { - int ret; - char *buf = NULL; struct erofs_inode vi = { .sbi = &g_sbi, .nid = erofsfuse_to_nid(ino) }; + struct erofs_vfile vf; + char *buf = NULL; + int ret; ret = erofs_read_inode_from_disk(&vi); if (ret < 0) { @@ -408,13 +413,19 @@ static void erofsfuse_readlink(fuse_req_t req, fuse_ino_t ino) return; } + ret = erofs_iopen(&vf, &vi); + if (ret) { + fuse_reply_err(req, -ret); + return; + } + buf = malloc(vi.i_size + 1); if (!buf) { fuse_reply_err(req, ENOMEM); return; } - ret = erofs_pread(&vi, buf, vi.i_size, 0); + ret = erofs_pread(&vf, buf, vi.i_size, 0); if (ret < 0) { fuse_reply_err(req, -ret); goto out; diff --git a/include/erofs/internal.h b/include/erofs/internal.h index 0a49394d..3439a183 100644 --- a/include/erofs/internal.h +++ b/include/erofs/internal.h @@ -440,8 +440,7 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, bool need_kmap); void erofs_init_metabuf(struct erofs_buf *buf, struct erofs_sb_info *sbi); void *erofs_read_metabuf(struct erofs_buf *buf, struct erofs_sb_info *sbi, erofs_off_t offset); -int erofs_pread(struct erofs_inode *inode, char *buf, - erofs_off_t count, erofs_off_t offset); +int erofs_iopen(struct erofs_vfile *vf, struct erofs_inode *inode); int erofs_map_blocks(struct erofs_inode *inode, struct erofs_map_blocks *map, int flags); int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map); diff --git a/include/erofs/io.h b/include/erofs/io.h index 01a7ff44..cc7a3cd2 100644 --- a/include/erofs/io.h +++ b/include/erofs/io.h @@ -70,6 +70,17 @@ ssize_t erofs_copy_file_range(int fd_in, u64 *off_in, int fd_out, u64 *off_out, int erofs_io_xcopy(struct erofs_vfile *vout, off_t pos, struct erofs_vfile *vin, unsigned int len, bool noseek); +static inline int erofs_pread(struct erofs_vfile *vf, void *buf, + size_t len, u64 offset) +{ + ssize_t read; + + read = erofs_io_pread(vf, buf, len, offset); + if (read < 0) + return read; + return read != len ? -EIO : 0; +} + #ifdef __cplusplus } #endif diff --git a/lib/data.c b/lib/data.c index 83cc5d5d..87ced24f 100644 --- a/lib/data.c +++ b/lib/data.c @@ -22,12 +22,10 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, bool need_kmap) blknr = erofs_blknr(sbi, offset); if (blknr != buf->blocknr) { buf->blocknr = ~0ULL; - err = erofs_io_pread(buf->vf, buf->base, blksiz, - round_down(offset, blksiz)); - if (err < 0) + err = erofs_pread(buf->vf, buf->base, blksiz, + round_down(offset, blksiz)); + if (err) return ERR_PTR(err); - if (err != blksiz) - return ERR_PTR(-EIO); buf->blocknr = blknr; } return buf->base + erofs_blkoff(sbi, offset); @@ -364,27 +362,31 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer, return ret < 0 ? ret : 0; } -int erofs_pread(struct erofs_inode *inode, char *buf, - erofs_off_t count, erofs_off_t offset) +ssize_t erofs_preadi(struct erofs_vfile *vf, void *buf, size_t len, u64 offset) { - switch (inode->datalayout) { - case EROFS_INODE_FLAT_PLAIN: - case EROFS_INODE_FLAT_INLINE: - case EROFS_INODE_CHUNK_BASED: - return erofs_read_raw_data(inode, buf, count, offset); - case EROFS_INODE_COMPRESSED_FULL: - case EROFS_INODE_COMPRESSED_COMPACT: - return z_erofs_read_data(inode, buf, count, offset); - default: - break; - } - return -EINVAL; + struct erofs_inode *inode = *(struct erofs_inode **)vf->payload; + + if (erofs_inode_is_data_compressed(inode->datalayout)) + return z_erofs_read_data(inode, buf, len, offset) ?: len; + return erofs_read_raw_data(inode, buf, len, offset) ?: len; +} + +int erofs_iopen(struct erofs_vfile *vf, struct erofs_inode *inode) +{ + static struct erofs_vfops ops = { + .pread = erofs_preadi, + }; + + vf->ops = &ops; + *(struct erofs_inode **)vf->payload = inode; + return 0; } static void *erofs_read_metadata_nid(struct erofs_sb_info *sbi, erofs_nid_t nid, erofs_off_t *offset, int *lengthp) { struct erofs_inode vi = { .sbi = sbi, .nid = nid }; + struct erofs_vfile vf; __le16 __len; int ret, len; char *buffer; @@ -393,8 +395,12 @@ static void *erofs_read_metadata_nid(struct erofs_sb_info *sbi, erofs_nid_t nid, if (ret) return ERR_PTR(ret); + ret = erofs_iopen(&vf, &vi); + if (ret) + return ERR_PTR(ret); + *offset = round_up(*offset, 4); - ret = erofs_pread(&vi, (void *)&__len, sizeof(__le16), *offset); + ret = erofs_pread(&vf, (void *)&__len, sizeof(__le16), *offset); if (ret) return ERR_PTR(ret); @@ -408,7 +414,7 @@ static void *erofs_read_metadata_nid(struct erofs_sb_info *sbi, erofs_nid_t nid, *offset += sizeof(__le16); *lengthp = len; - ret = erofs_pread(&vi, buffer, len, *offset); + ret = erofs_pread(&vf, buffer, len, *offset); if (ret) { free(buffer); return ERR_PTR(ret); diff --git a/lib/dir.c b/lib/dir.c index 9c6849d8..98edb8e1 100644 --- a/lib/dir.c +++ b/lib/dir.c @@ -142,9 +142,10 @@ int erofs_iterate_dir(struct erofs_dir_context *ctx, bool fsck) { struct erofs_inode *dir = ctx->dir; struct erofs_sb_info *sbi = dir->sbi; - int err = 0; + struct erofs_vfile vf; erofs_off_t pos; char buf[EROFS_MAX_BLOCK_SIZE]; + int err = 0; if (!S_ISDIR(dir->i_mode)) return -ENOTDIR; @@ -152,15 +153,18 @@ int erofs_iterate_dir(struct erofs_dir_context *ctx, bool fsck) ctx->flags &= ~EROFS_READDIR_ALL_SPECIAL_FOUND; if (dir->dot_omitted) ctx->flags |= EROFS_READDIR_DOT_FOUND; - pos = 0; - while (pos < dir->i_size) { + err = erofs_iopen(&vf, dir); + if (err) + return err; + + for (pos = 0; pos < dir->i_size; ) { erofs_blk_t lblk = erofs_blknr(sbi, pos); erofs_off_t maxsize = min_t(erofs_off_t, dir->i_size - pos, erofs_blksiz(sbi)); const struct erofs_dirent *de = (const void *)buf; unsigned int nameoff; - err = erofs_pread(dir, buf, maxsize, pos); + err = erofs_pread(&vf, buf, maxsize, pos); if (err) { erofs_err("I/O error when reading dirents @ nid %llu, lblk %llu: %s", dir->nid | 0ULL, lblk | 0ULL, diff --git a/lib/fragments.c b/lib/fragments.c index 887c2530..0221a538 100644 --- a/lib/fragments.c +++ b/lib/fragments.c @@ -510,6 +510,7 @@ static void *erofs_packedfile_preload(struct erofs_inode *pi, struct erofs_sb_info *sbi = pi->sbi; struct erofs_packed_inode *epi = sbi->packedinode; unsigned int bsz = erofs_blksiz(sbi); + struct erofs_vfile vf; char *buffer; erofs_off_t pos, end; ssize_t err; @@ -529,13 +530,17 @@ static void *erofs_packedfile_preload(struct erofs_inode *pi, else DBG_BUGON(map->m_la > pos); + err = erofs_iopen(&vf, pi); + if (err) + return ERR_PTR(err); + map->m_llen = end - map->m_la; DBG_BUGON(!map->m_llen); buffer = malloc(map->m_llen); if (!buffer) return ERR_PTR(-ENOMEM); - err = erofs_pread(pi, buffer, map->m_llen, map->m_la); + err = erofs_pread(&vf, buffer, map->m_llen, map->m_la); if (err) goto err_out; @@ -572,13 +577,17 @@ int erofs_packedfile_read(struct erofs_sb_info *sbi, struct erofs_map_blocks map = { .buf = __EROFS_BUF_INITIALIZER }; unsigned int bsz = erofs_blksiz(sbi); erofs_off_t end = pos + len; + struct erofs_vfile vf; char *buffer = NULL; int err; if (!epi) { err = erofs_load_packedinode_from_disk(&pi); - if (!err) - err = erofs_pread(&pi, buf, len, pos); + if (!err) { + err = erofs_iopen(&vf, &pi); + if (!err) + err = erofs_pread(&vf, buf, len, pos); + } return err; } @@ -632,8 +641,11 @@ int erofs_packedfile_read(struct erofs_sb_info *sbi, } else { fallback: err = erofs_load_packedinode_from_disk(&pi); + if (err) + break; + err = erofs_iopen(&vf, &pi); if (!err) - err = erofs_pread(&pi, buf, len, pos); + err = erofs_pread(&vf, buf, len, pos); if (err) break; } diff --git a/lib/inode.c b/lib/inode.c index f7c6b87f..5f50c09f 100644 --- a/lib/inode.c +++ b/lib/inode.c @@ -371,6 +371,7 @@ static int erofs_rebuild_inode_fix_pnid(struct erofs_inode *parent, }; unsigned int bsz = erofs_blksiz(dir.sbi); unsigned int err, isz; + struct erofs_vfile vf; erofs_off_t boff, off; erofs_nid_t pnid; bool fixed = false; @@ -386,6 +387,10 @@ static int erofs_rebuild_inode_fix_pnid(struct erofs_inode *parent, dir.datalayout != EROFS_INODE_FLAT_PLAIN) return -EOPNOTSUPP; + err = erofs_iopen(&vf, &dir); + if (err) + return err; + pnid = erofs_lookupnid(parent); isz = dir.inode_isize + dir.xattr_isize; boff = erofs_pos(dir.sbi, dir.u.i_blkaddr); @@ -395,7 +400,7 @@ static int erofs_rebuild_inode_fix_pnid(struct erofs_inode *parent, unsigned int nameoff, count, de_nameoff; count = min_t(erofs_off_t, bsz, dir.i_size - off); - err = erofs_pread(&dir, buf, count, off); + err = erofs_pread(&vf, buf, count, off); if (err) return err; diff --git a/lib/namei.c b/lib/namei.c index c3ddd590..8de0a908 100644 --- a/lib/namei.c +++ b/lib/namei.c @@ -224,12 +224,17 @@ int erofs_namei(struct nameidata *nd, const char *name, unsigned int len) char buf[EROFS_MAX_BLOCK_SIZE]; struct erofs_sb_info *sbi = nd->sbi; struct erofs_inode vi = { .sbi = sbi, .nid = nid }; + struct erofs_vfile vf; erofs_off_t offset; ret = erofs_read_inode_from_disk(&vi); if (ret) return ret; + ret = erofs_iopen(&vf, &vi); + if (ret) + return ret; + offset = 0; while (offset < vi.i_size) { erofs_off_t maxsize = min_t(erofs_off_t, @@ -237,7 +242,7 @@ int erofs_namei(struct nameidata *nd, const char *name, unsigned int len) struct erofs_dirent *de = (void *)buf; unsigned int nameoff; - ret = erofs_pread(&vi, buf, maxsize, offset); + ret = erofs_pread(&vf, buf, maxsize, offset); if (ret) return ret; diff --git a/lib/rebuild.c b/lib/rebuild.c index 33857fd6..7ad0658a 100644 --- a/lib/rebuild.c +++ b/lib/rebuild.c @@ -243,13 +243,19 @@ static int erofs_rebuild_update_inode(struct erofs_sb_info *dst_sb, case S_IFDIR: err = erofs_init_empty_dir(inode); break; - case S_IFLNK: + case S_IFLNK: { + struct erofs_vfile vf; + inode->i_link = malloc(inode->i_size + 1); if (!inode->i_link) return -ENOMEM; - err = erofs_pread(inode, inode->i_link, inode->i_size, 0); + err = erofs_iopen(&vf, inode); + if (err) + return err; + err = erofs_pread(&vf, inode->i_link, inode->i_size, 0); erofs_dbg("\tsymlink: %s -> %s", inode->i_srcpath, inode->i_link); break; + } case S_IFREG: if (!inode->i_size) { inode->u.i_blkaddr = EROFS_NULL_ADDR; diff --git a/lib/super.c b/lib/super.c index 8c0abafd..1d13e6e3 100644 --- a/lib/super.c +++ b/lib/super.c @@ -81,7 +81,8 @@ int erofs_read_superblock(struct erofs_sb_info *sbi) read = erofs_io_pread(&sbi->bdev, data, EROFS_MAX_BLOCK_SIZE, 0); if (read < EROFS_SUPER_END) { ret = read < 0 ? read : -EIO; - erofs_err("cannot read erofs superblock: %d", ret); + erofs_err("cannot read erofs superblock: %s", + erofs_strerror(ret)); return ret; } dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET); -- 2.43.5
