[PATCH] erofs-utils: tar: all regular inodes should be zeroed in headerball mode
Gao Xiang
hsiangkao at linux.alibaba.com
Fri Mar 22 19:50:07 AEDT 2024
.. Instead of reporting IO errors which implies a corrupted image.
Fixes: 6894ca9623e7 ("erofs-utils: mkfs: Support tar source without data")
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
include/erofs/blobchunk.h | 1 +
lib/blobchunk.c | 41 +++++++++++++++++++++++++++++++++++++++
lib/tar.c | 6 ++++--
mkfs/main.c | 18 +++++++++--------
4 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/include/erofs/blobchunk.h b/include/erofs/blobchunk.h
index 89c8048..a674640 100644
--- a/include/erofs/blobchunk.h
+++ b/include/erofs/blobchunk.h
@@ -19,6 +19,7 @@ struct erofs_blobchunk *erofs_get_unhashed_chunk(unsigned int device_id,
int erofs_blob_write_chunk_indexes(struct erofs_inode *inode, erofs_off_t off);
int erofs_blob_write_chunked_file(struct erofs_inode *inode, int fd,
erofs_off_t startoff);
+int erofs_write_zero_inode(struct erofs_inode *inode);
int tarerofs_write_chunkes(struct erofs_inode *inode, erofs_off_t data_offset);
int erofs_mkfs_dump_blobs(struct erofs_sb_info *sbi);
void erofs_blob_exit(void);
diff --git a/lib/blobchunk.c b/lib/blobchunk.c
index 6d2501e..ee12194 100644
--- a/lib/blobchunk.c
+++ b/lib/blobchunk.c
@@ -338,6 +338,47 @@ err:
return ret;
}
+int erofs_write_zero_inode(struct erofs_inode *inode)
+{
+ struct erofs_sb_info *sbi = inode->sbi;
+ unsigned int chunkbits = ilog2(inode->i_size - 1) + 1;
+ unsigned int count;
+ erofs_off_t chunksize, len, pos;
+ struct erofs_inode_chunk_index *idx;
+
+ if (chunkbits < sbi->blkszbits)
+ chunkbits = sbi->blkszbits;
+ if (chunkbits - sbi->blkszbits > EROFS_CHUNK_FORMAT_BLKBITS_MASK)
+ chunkbits = EROFS_CHUNK_FORMAT_BLKBITS_MASK + sbi->blkszbits;
+
+ inode->u.chunkformat |= chunkbits - sbi->blkszbits;
+
+ chunksize = 1ULL << chunkbits;
+ count = DIV_ROUND_UP(inode->i_size, chunksize);
+
+ inode->extent_isize = count * EROFS_BLOCK_MAP_ENTRY_SIZE;
+ idx = calloc(count, max(sizeof(*idx), sizeof(void *)));
+ if (!idx)
+ return -ENOMEM;
+ inode->chunkindexes = idx;
+
+ for (pos = 0; pos < inode->i_size; pos += len) {
+ struct erofs_blobchunk *chunk;
+
+ len = min_t(erofs_off_t, inode->i_size - pos, chunksize);
+ chunk = erofs_get_unhashed_chunk(0, EROFS_NULL_ADDR, -1);
+ if (IS_ERR(chunk)) {
+ free(inode->chunkindexes);
+ inode->chunkindexes = NULL;
+ return PTR_ERR(chunk);
+ }
+
+ *(void **)idx++ = chunk;
+ }
+ inode->datalayout = EROFS_INODE_CHUNK_BASED;
+ return 0;
+}
+
int tarerofs_write_chunkes(struct erofs_inode *inode, erofs_off_t data_offset)
{
struct erofs_sb_info *sbi = inode->sbi;
diff --git a/lib/tar.c b/lib/tar.c
index fe7fdd3..7c271f6 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -645,7 +645,7 @@ static int tarerofs_write_file_index(struct erofs_inode *inode,
ret = tarerofs_write_chunkes(inode, data_offset);
if (ret)
return ret;
- if (!tar->headeronly_mode && erofs_iostream_lskip(&tar->ios, inode->i_size))
+ if (erofs_iostream_lskip(&tar->ios, inode->i_size))
return -EIO;
return 0;
}
@@ -1002,7 +1002,9 @@ new_inode:
inode->i_link = malloc(inode->i_size + 1);
memcpy(inode->i_link, eh.link, inode->i_size + 1);
} else if (inode->i_size) {
- if (tar->index_mode)
+ if (tar->headeronly_mode)
+ ret = erofs_write_zero_inode(inode);
+ else if (tar->index_mode)
ret = tarerofs_write_file_index(inode, tar,
data_offset);
else
diff --git a/mkfs/main.c b/mkfs/main.c
index e9f0522..2fb4a57 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1260,12 +1260,14 @@ int main(int argc, char **argv)
return 1;
}
- if ((erofstar.index_mode && !erofstar.mapfile) || cfg.c_blobdev_path)
+ if (((erofstar.index_mode && !erofstar.headeronly_mode) &&
+ !erofstar.mapfile) || cfg.c_blobdev_path) {
err = erofs_mkfs_init_devices(&sbi, 1);
- if (err) {
- erofs_err("failed to generate device table: %s",
- erofs_strerror(err));
- goto exit;
+ if (err) {
+ erofs_err("failed to generate device table: %s",
+ erofs_strerror(err));
+ goto exit;
+ }
}
erofs_inode_manager_init();
@@ -1318,10 +1320,10 @@ int main(int argc, char **argv)
root_nid = erofs_lookupnid(root_inode);
erofs_iput(root_inode);
+ if (erofstar.index_mode && sbi.extra_devices && !erofstar.mapfile)
+ sbi.devs[0].blocks = BLK_ROUND_UP(&sbi, erofstar.offset);
+
if (erofstar.index_mode || cfg.c_chunkbits || sbi.extra_devices) {
- if (erofstar.index_mode && !erofstar.mapfile)
- sbi.devs[0].blocks =
- BLK_ROUND_UP(&sbi, erofstar.offset);
err = erofs_mkfs_dump_blobs(&sbi);
if (err)
goto exit;
--
2.39.3
More information about the Linux-erofs
mailing list