From cac4dcfbdf7347a27a9f7c1841a048a2b5cc075a Mon Sep 17 00:00:00 2001 From: Jia Zhu Date: Thu, 2 Mar 2023 15:17:51 +0800 Subject: [PATCH] BACKPORT: erofs: support flattened block device for multi-blob images In order to support mounting multi-blobs container image as a single block device, add flattened block device feature for EROFS. In this mode, all meta/data contents will be mapped into one block space. User could compose a block device(by nbd/ublk/virtio-blk/ vhost-user-blk) from multiple sources and mount the block device by EROFS directly. It can reduce the number of block devices used, and it's also benefits in both VM file passthrough and distributed storage scenarios. You can test this using the method mentioned by: https://github.com/dragonflyoss/image-service/pull/1139 1. Compose a (nbd)block device from multi-blobs. 2. Mount EROFS on mntdir/. 3. Compare the md5sum between source dir and mntdir/. Later, we could also use it to refer original tar blobs. Signed-off-by: Jia Zhu Signed-off-by: Xin Yin Reviewed-by: Jingbo Xu Acked-by: Chao Yu Tested-by: Jiang Liu Link: https://lore.kernel.org/r/20230302071751.48425-1-zhujia.zj@bytedance.com [ Gao Xiang: refine commit message and use erofs_pos(). ] Signed-off-by: Gao Xiang --- fs/erofs/data.c | 8 ++++++-- fs/erofs/internal.h | 1 + fs/erofs/super.c | 17 ++++++++++------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 2d68f61faa..2cbc280d9e 100755 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -192,7 +192,6 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map) struct erofs_device_info *dif; int id; - /* primary device by default */ map->m_bdev = sb->s_bdev; if (map->m_deviceid) { @@ -202,9 +201,14 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map) up_read(&devs->rwsem); return -ENODEV; } + if (devs->flatdev) { + map->m_pa += erofs_pos(sb, dif->mapped_blkaddr); + up_read(&devs->rwsem); + return 0; + } map->m_bdev = dif->bdev; up_read(&devs->rwsem); - } else if (devs->extra_devices) { + } else if (devs->extra_devices && !devs->flatdev) { down_read(&devs->rwsem); idr_for_each_entry(&devs->tree, dif, id) { erofs_off_t startoff, length; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index cda2d49843..9e83b64d78 100755 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -67,6 +67,7 @@ struct erofs_dev_context { struct rw_semaphore rwsem; unsigned int extra_devices; + bool flatdev; }; /* all filesystem-wide lz4 configurations */ diff --git a/fs/erofs/super.c b/fs/erofs/super.c index a8fc6db654..c4a8e18d90 100755 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -252,6 +252,9 @@ static int erofs_init_devices(struct super_block *sb, if (!ondisk_extradevs) return 0; + if (!sbi->devs->extra_devices) + sbi->devs->flatdev = true; + sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1; pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE; down_read(&sbi->devs->rwsem); @@ -265,14 +268,14 @@ static int erofs_init_devices(struct super_block *sb, } dis = ptr + erofs_blkoff(sb, pos); - bdev = blkdev_get_by_path(dif->path, - FMODE_READ | FMODE_EXCL, - sb->s_type); - if (IS_ERR(bdev)) { - err = PTR_ERR(bdev); - break; + if (!sbi->devs->flatdev) { + bdev = blkdev_get_by_path(dif->path, FMODE_READ | FMODE_EXCL, sb->s_type); + if (IS_ERR(bdev)) { + err = PTR_ERR(bdev); + break; + } + dif->bdev = bdev; } - dif->bdev = bdev; dif->blocks = le32_to_cpu(dis->blocks); dif->mapped_blkaddr = le32_to_cpu(dis->mapped_blkaddr); sbi->total_blocks += dif->blocks;