如果映射是固定的,即 512 字节扇区i始终在文件f i扇区b i中,那么您可以使用设备映射表设备 via dmsetup
。
表文件中的每一行都指定一个映射。在您的情况下,它们可能只是
i 1 线性 f i b i
创建dm-switch的派生类,比如 dm-chunkmap,重新定义region_table
为每块映射(具有可配置的数量,每块 2 n 512 字节扇区)可能会很有趣:低位指定设备/文件,和高位该设备上的目标扇区。
每个表条目使用 32 位,最大大小为 2 TB(但映射需要每 GB 8 MiB 的内核 RAM);使用 16 TiB 的 8 个扇区组(并且每 GB 块设备只需要 1 MB 的内核 RAM)。
类似的东西
/* Each chunk has device index in low bits,
and target sector number in upper bits. */
typedef unsigned chunk_t;
/*
* Context block for a dm chunk-mapping device.
*/
struct chunkmap_ctx {
struct dm_target *ti;
unsigned nr_paths; /* Number of paths (devices) in path_list. */
unsigned dev_shift; /* nr_paths <= 1 << dev_shift */
unsigned dev_mask; /* (1 << dev_shift) - 1 */
unsigned chunk_shift; /* 1 << chunk_shift sectors per region */
unsigned chunk_mask; /* (1 << chunk_shift) - 1 */
unsigned long nr_chunks; /* Number of regions making up the device */
chunk_t *chunk_table;
struct dm_dev *dev_list[]; /* Devices */
};
static int chunkmap_map(struct dm_target *ti, struct bio *bio)
{
struct chunkmap_ctx *rctx = ti->private;
sector_t offset = dm_target_offset(ti, bio->bi_iter.bi_sector);
chunk_t chunk = READ_ONCE(rctx->chunk_table[offset >> rctx->chunk_shift]);
bio_set_dev(bio, rctx->dev_list[chunk & rctx->dev_mask]);
bio->bi_iter.bi_sector = (sector_t)(chunk >> rctx->dev_shift) << rctx->chunk_mask
+ (offset & rctx->chunk_mask);
}
static struct target_type chunkmap_target = {
.name = "chunkmap",
.version = {1, 1, 0},
.module = THIS_MODULE,
.ctr = /* chunkmap_ctr */,
.dtr = /* chunkmap_dtr */,
.map = chunkmap_map,
.message = /* chunkmap_message */,
.status = /* chunkmap_status */,
.prepare_ioctl = /* chunkmap_prepare_ioctl */,
.iterate_devices = /* chunkmap_iterate_devices */,
};
它允许每个块使用 2 个chunk_shift扇区(2 9 + chunk_shift字节)的块,以及最多 2 个dev_shift目标设备/路径,这些块在目标设备上完全任意排序。
应该注意的是,该结构确实允许将不同的扇区映射到同一个目标设备扇区,但这应该被视为错误,因为它可能导致错误。换句话说,只允许唯一chunk_table
条目是个好主意。
如果有这样的用例,在一次性实验之外,我很确定它可以通过dm-devel邮件列表推送到主线内核中。