From: Yue Hu <[email protected]> We should reuse the main part of erofs_read_raw_data() and z_erofs_read_data() to avoid duplicated code.
Note that fragment feature is supported correspondingly as well after this change. Signed-off-by: Yue Hu <[email protected]> --- fsck/main.c | 149 +++++++++++++++++---------------------- include/erofs/internal.h | 4 ++ lib/data.c | 8 +-- 3 files changed, 71 insertions(+), 90 deletions(-) diff --git a/fsck/main.c b/fsck/main.c index 2a9c501..6c43816 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -361,36 +361,14 @@ out: return ret; } -static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd) +static int erofs_verify_inode_data_mapping(struct erofs_inode *inode, + bool compressed) { struct erofs_map_blocks map = { .index = UINT_MAX, }; - struct erofs_map_dev mdev; int ret = 0; - bool compressed; erofs_off_t pos = 0; - u64 pchunk_len = 0; - unsigned int raw_size = 0, buffer_size = 0; - char *raw = NULL, *buffer = NULL; - - erofs_dbg("verify data chunk of nid(%llu): type(%d)", - inode->nid | 0ULL, inode->datalayout); - - switch (inode->datalayout) { - case EROFS_INODE_FLAT_PLAIN: - case EROFS_INODE_FLAT_INLINE: - case EROFS_INODE_CHUNK_BASED: - compressed = false; - break; - case EROFS_INODE_FLAT_COMPRESSION_LEGACY: - case EROFS_INODE_FLAT_COMPRESSION: - compressed = true; - break; - default: - erofs_err("unknown datalayout"); - return -EINVAL; - } while (pos < inode->i_size) { map.m_la = pos; @@ -401,102 +379,101 @@ static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd) ret = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_FIEMAP); if (ret) - goto out; + return ret; if (!compressed && map.m_llen != map.m_plen) { erofs_err("broken chunk length m_la %" PRIu64 " m_llen %" PRIu64 " m_plen %" PRIu64, map.m_la, map.m_llen, map.m_plen); - ret = -EFSCORRUPTED; - goto out; + return -EFSCORRUPTED; } /* the last lcluster can be divided into 3 parts */ if (map.m_la + map.m_llen > inode->i_size) map.m_llen = inode->i_size - map.m_la; - pchunk_len += map.m_plen; pos += map.m_llen; + } + return 0; +} - /* should skip decomp? */ - if (!(map.m_flags & EROFS_MAP_MAPPED) || !fsckcfg.check_decomp) - continue; +static int erofs_do_verify_inode_data(struct erofs_inode *inode, int outfd, + bool compressed) +{ + int ret = 0; + erofs_off_t pos = 0; + unsigned int buffer_size = 0; + char *buffer = NULL; - if (map.m_plen > raw_size) { - raw_size = map.m_plen; - raw = realloc(raw, raw_size); - BUG_ON(!raw); - } + /* no option --extract */ + if (!fsckcfg.check_decomp) + return erofs_verify_inode_data_mapping(inode, compressed); - mdev = (struct erofs_map_dev) { - .m_deviceid = map.m_deviceid, - .m_pa = map.m_pa, - }; - ret = erofs_map_dev(&sbi, &mdev); - if (ret) { - erofs_err("failed to map device of m_pa %" PRIu64 ", m_deviceid %u @ nid %llu: %d", - map.m_pa, map.m_deviceid, inode->nid | 0ULL, - ret); - goto out; - } + while (pos < inode->i_size) { + erofs_off_t maxsize = min_t(erofs_off_t, inode->i_size - pos, + EROFS_CONFIG_COMPR_MAX_SZ); - if (compressed && map.m_llen > buffer_size) { - buffer_size = map.m_llen; + if (maxsize > buffer_size) { + buffer_size = maxsize; buffer = realloc(buffer, buffer_size); BUG_ON(!buffer); } - ret = dev_read(mdev.m_deviceid, raw, mdev.m_pa, map.m_plen); - if (ret < 0) { - erofs_err("failed to read data of m_pa %" PRIu64 ", m_plen %" PRIu64 " @ nid %llu: %d", - mdev.m_pa, map.m_plen, inode->nid | 0ULL, - ret); + if (compressed) + ret = z_erofs_read_data(inode, buffer, maxsize, pos); + else + ret = erofs_read_raw_data(inode, buffer, maxsize, pos); + if (ret) goto out; - } - if (compressed) { - struct z_erofs_decompress_req rq = { - .in = raw, - .out = buffer, - .decodedskip = 0, - .interlaced_offset = - map.m_algorithmformat == Z_EROFS_COMPRESSION_INTERLACED ? - erofs_blkoff(map.m_la) : 0, - .inputsize = map.m_plen, - .decodedlength = map.m_llen, - .alg = map.m_algorithmformat, - .partial_decoding = 0 - }; - - ret = z_erofs_decompress(&rq); - if (ret < 0) { - erofs_err("failed to decompress data of m_pa %" PRIu64 ", m_plen %" PRIu64 " @ nid %llu: %s", - mdev.m_pa, map.m_plen, - inode->nid | 0ULL, strerror(-ret)); - goto out; - } - } + pos += maxsize; - if (outfd >= 0 && write(outfd, compressed ? buffer : raw, - map.m_llen) < 0) { + if (outfd >= 0 && write(outfd, buffer, maxsize) < 0) { erofs_err("I/O error occurred when verifying data chunk @ nid %llu", inode->nid | 0ULL); ret = -EIO; goto out; } } - - if (fsckcfg.print_comp_ratio) { - fsckcfg.logical_blocks += BLK_ROUND_UP(inode->i_size); - fsckcfg.physical_blocks += BLK_ROUND_UP(pchunk_len); - } out: - if (raw) - free(raw); if (buffer) free(buffer); return ret < 0 ? ret : 0; } +static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd) +{ + int ret; + bool compressed; + + erofs_dbg("verify data chunk of nid(%llu): type(%d)", + inode->nid | 0ULL, inode->datalayout); + + switch (inode->datalayout) { + case EROFS_INODE_FLAT_PLAIN: + case EROFS_INODE_FLAT_INLINE: + case EROFS_INODE_CHUNK_BASED: + compressed = false; + break; + case EROFS_INODE_FLAT_COMPRESSION_LEGACY: + case EROFS_INODE_FLAT_COMPRESSION: + compressed = true; + break; + default: + erofs_err("unknown datalayout"); + return -EINVAL; + } + ret = erofs_do_verify_inode_data(inode, outfd, compressed); + if (ret < 0) + return ret; + + if (fsckcfg.print_comp_ratio) { + fsckcfg.logical_blocks += BLK_ROUND_UP(inode->i_size); + fsckcfg.physical_blocks += compressed ? inode->u.i_blocks : + BLK_ROUND_UP(inode->i_size); + } + return 0; +} + static inline int erofs_extract_dir(struct erofs_inode *inode) { int ret; diff --git a/include/erofs/internal.h b/include/erofs/internal.h index 947894d..4b962af 100644 --- a/include/erofs/internal.h +++ b/include/erofs/internal.h @@ -352,6 +352,10 @@ int erofs_read_inode_from_disk(struct erofs_inode *vi); /* data.c */ int erofs_pread(struct erofs_inode *inode, char *buf, erofs_off_t count, erofs_off_t offset); +int erofs_read_raw_data(struct erofs_inode *inode, char *buffer, + erofs_off_t size, erofs_off_t offset); +int z_erofs_read_data(struct erofs_inode *inode, char *buffer, + erofs_off_t size, erofs_off_t offset); 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/lib/data.c b/lib/data.c index 76a6677..a9b2240 100644 --- a/lib/data.c +++ b/lib/data.c @@ -158,8 +158,8 @@ int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map) return 0; } -static int erofs_read_raw_data(struct erofs_inode *inode, char *buffer, - erofs_off_t size, erofs_off_t offset) +int erofs_read_raw_data(struct erofs_inode *inode, char *buffer, + erofs_off_t size, erofs_off_t offset) { struct erofs_map_blocks map = { .index = UINT_MAX, @@ -217,8 +217,8 @@ static int erofs_read_raw_data(struct erofs_inode *inode, char *buffer, return 0; } -static int z_erofs_read_data(struct erofs_inode *inode, char *buffer, - erofs_off_t size, erofs_off_t offset) +int z_erofs_read_data(struct erofs_inode *inode, char *buffer, + erofs_off_t size, erofs_off_t offset) { erofs_off_t end, length, skip; struct erofs_map_blocks map = { -- 2.17.1
