[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