[PATCH] erofs-utils: support --blobdev with block map

Ajay Rajera <[email protected]>
Newsgroups org.ozlabs.lists.linux-erofs
Message-ID <[email protected]>
Add support for using --blobdev with the FORCE_INODE_BLOCK_MAP
chunk format. Previously this combination returned -EINVAL with
a TODO noting it could be implemented via deviceslot mapped_blkaddr.

This implements it by utilizing the deviceslot unified addressing
(uniaddr) to map external blob device blocks into a contiguous
address space, bypassing the need for 8-byte chunk indexes.

For block map format, chunk addresses are encoded as:
  blkaddr = devs[0].uniaddr + erofs_blknr(data_offset)

At mount time, the kernel's erofs_map_dev() resolves these unified
addresses back to the correct external device transparently.

Changes:
- mkfs/main.c: remove the error blocking blobdev + block map
- lib/super.c: initialize uniaddr with primarydevice_blocks
- lib/blobchunk.c: encode unified addresses in 4-byte block maps
- lib/data.c: fix erofs_map_dev() to set m_deviceid when resolving
  unified addresses, so userspace tools (fsck, dump) work correctly

Signed-off-by: Ajay Rajera <[email protected]>
---
 lib/blobchunk.c | 19 +++++++++++++++++--
 lib/data.c      |  1 +
 lib/super.c     |  5 +++++
 mkfs/main.c     |  9 ++++++---
 4 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/lib/blobchunk.c b/lib/blobchunk.c
index 96c161b..e666d2b 100644
--- a/lib/blobchunk.c
+++ b/lib/blobchunk.c
@@ -95,7 +95,14 @@ static struct erofs_blobchunk *erofs_blob_getchunk(struct erofs_sb_info *sbi,
 		chunk->device_id = 1;
 	else
 		chunk->device_id = 0;
-	chunk->blkaddr = erofs_blknr(sbi, blkpos);
+	
+	/* For block map with blobdev, use unified addressing */
+	if (sbi->extra_devices && cfg.c_force_chunkformat == FORCE_INODE_BLOCK_MAP) {
+		chunk->blkaddr = sbi->devs[0].uniaddr + erofs_blknr(sbi, blkpos);
+		chunk->device_id = 0;  /* unified address space */
+	} else {
+		chunk->blkaddr = erofs_blknr(sbi, blkpos);
+	}
 
 	erofs_dbg("Writing chunk (%llu bytes) to %llu", chunksize | 0ULL,
 		  chunk->blkaddr | 0ULL);
@@ -324,7 +331,7 @@ int erofs_blob_write_chunked_file(struct erofs_inode *inode, int fd,
 	chunksize = 1ULL << chunkbits;
 	count = DIV_ROUND_UP(inode->i_size, chunksize);
 
-	if (sbi->extra_devices)
+	if (sbi->extra_devices && cfg.c_force_chunkformat != FORCE_INODE_BLOCK_MAP)
 		inode->u.chunkformat |= EROFS_CHUNK_FORMAT_INDEXES;
 	if (inode->u.chunkformat & EROFS_CHUNK_FORMAT_INDEXES)
 		unit = sizeof(struct erofs_inode_chunk_index);
@@ -498,6 +505,14 @@ int tarerofs_write_chunkes(struct erofs_inode *inode, erofs_off_t data_offset)
 		unit = sizeof(struct erofs_inode_chunk_index);
 		DBG_BUGON(erofs_blkoff(sbi, data_offset));
 		blkaddr = erofs_blknr(sbi, data_offset);
+	} else if (cfg.c_blobdev_path && 
+		   cfg.c_force_chunkformat == FORCE_INODE_BLOCK_MAP) {
+		/* Block map with blobdev: use unified addressing via deviceslot */
+		device_id = 0;  /* unified address space, no device_id needed */
+		unit = EROFS_BLOCK_MAP_ENTRY_SIZE;
+		DBG_BUGON(erofs_blkoff(sbi, data_offset));
+		/* Map to unified address space using device's uniaddr base */
+		blkaddr = sbi->devs[0].uniaddr + erofs_blknr(sbi, data_offset);
 	} else {
 		device_id = 0;
 		unit = EROFS_BLOCK_MAP_ENTRY_SIZE;
diff --git a/lib/data.c b/lib/data.c
index 6fd1389..5aeb0c1 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -184,6 +184,7 @@ int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map)
 			if (map->m_pa >= startoff &&
 			    map->m_pa < startoff + length) {
 				map->m_pa -= startoff;
+				map->m_deviceid = id + 1;
 				break;
 			}
 		}
diff --git a/lib/super.c b/lib/super.c
index 088c9a0..55d5dd1 100644
--- a/lib/super.c
+++ b/lib/super.c
@@ -393,6 +393,11 @@ int erofs_mkfs_init_devices(struct erofs_sb_info *sbi, unsigned int devices)
 	sbi->bh_devt = bh;
 	sbi->devt_slotoff = erofs_btell(bh, false) / EROFS_DEVT_SLOT_SIZE;
 	sbi->extra_devices = devices;
+	
+	/* Initialize uniaddr for block map with blobdev support */
+	if (devices > 0)
+		sbi->devs[0].uniaddr = sbi->primarydevice_blocks;
+	
 	erofs_sb_set_device_table(sbi);
 	return 0;
 }
diff --git a/mkfs/main.c b/mkfs/main.c
index b84d1b4..3cccd60 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1565,11 +1565,14 @@ static int mkfs_parse_options_cfg(struct erofs_importer_params *params,
 		return -EINVAL;
 	}
 
-	/* TODO: can be implemented with (deviceslot) mapped_blkaddr */
+	/* Blobdev with block map uses deviceslot unified addressing */
 	if (cfg.c_blobdev_path &&
 	    cfg.c_force_chunkformat == FORCE_INODE_BLOCK_MAP) {
-		erofs_err("--blobdev cannot work with block map currently");
-		return -EINVAL;
+		/* Block map format can work with blobdev using unified addressing */
+		if (!g_sbi.extra_devices) {
+			erofs_err("--blobdev requires device table setup");
+			return -EINVAL;
+		}
 	}
 
 	if (optind >= argc) {
-- 
2.51.0.windows.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.