创建设备映射器目标

时间:2014-06-13 21:53:11

标签: linux-kernel linux-device-driver device-mapper

我试图通过引用现有的dm-linear,dm-snapshot,dm-cache等来实现设备映射器目标。在我的实现中,我需要对某个扇区执行读/修改/写操作范围。由于器件映射器直接与块层对话,我不确定用什么数据结构/函数来读取存储器中的扇区,修改缓冲区并将其写回另一个扇区范围。 在应用程序级别,我们有系统调用,下面我们有vfs_read / vfs_write。设备映射器层有什么类似的东西吗? 我被困在这里很久了。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:9)

注意:我的答案与内核版本< 3.14,因为自3.14以来API略有变化。

在内核中,您使用struct bio读/写某些扇区。此结构用于所有块级I / O.可以在in kernellwn找到全面的文档。这些是该结构中几个最重要的成员:

  • bio->bi_sector - 块I / O请求的第一个扇区
  • bio->bi_size - I / O请求的大小
  • bio->bi_bdev - 要读/写的设备
  • bio->bi_end_io - 内核将在请求结束时调用的回调

您在设备映射器目标中执行的操作是映射传入bio 。在创建设备映射器目标时,您至少提供2个回调:ctrmap。例如,最简单的设备映射器目标 dm-zero 声明它的回调as following

static struct target_type zero_target = {
         .name   = "zero",
         .version = {1, 1, 0},
         .module = THIS_MODULE,
         .ctr    = zero_ctr,
         .map    = zero_map,
};

map是一个关键的回调 - 它是每个设备映射器目标的核心。 map接收传入的bio,它可以对其执行任何操作。例如,dm-linear只是将每个传入bio的扇区移位预定义的偏移量。见代码:

static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector)
{
        struct linear_c *lc = ti->private;

        return lc->start + dm_target_offset(ti, bi_sector);
}

static void linear_map_bio(struct dm_target *ti, struct bio *bio)
{
        struct linear_c *lc = ti->private;

        bio->bi_bdev = lc->dev->bdev;
        if (bio_sectors(bio))
                bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
}

static int linear_map(struct dm_target *ti, struct bio *bio)
{
        linear_map_bio(ti, bio);

        return DM_MAPIO_REMAPPED;
}

因为map接收指向bio的指针,所以它可以改变该指针下的值,就是这样。

这就是你映射I / O请求的方式。如果要创建自己的请求,则必须分配bio,填写扇区,设备,大小,结束回调并添加缓冲区以读取/写入。基本上,它只是几个步骤:

  • 调用bio_alloc分配bio。
  • 设置bio->bi_bdevbio->bi_sectorbio->bi_sizebio->bi_end_io
  • 通过bio_add_page添加网页。
  • 致电submit_bio
  • 处理bio->bi_end_io回调
  • 中的结果和错误

示例可以在crypt_alloc_buffer函数的 dm-crypt 目标中找到。