[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