I am trying to implement device mapper target by referring to the already existing ones dm-linear, dm-snapshot, dm-cache etc. In my implementation, I need to perform a read/modi
NOTE: My answer is related to kernel version < 3.14, because since 3.14 API is slightly changed.
In kernel you read/write certain sectors with struct bio. This struct is used for all block level I/O. Comprehensive documentation can be found in kernel and on lwn. These are the several most significant members of this structure:
bio->bi_sector
- first sector of block I/O requestbio->bi_size
- size of I/O requestbio->bi_bdev
- device to read/writebio->bi_end_io
- callback that kernel will call on the end of requestWhat you do in device mapper target is map incoming bio
. When you creating your device mapper target you supply at least 2 callbacks: ctr
, and map
. For example, the simplest device-mapper target dm-zero declares it's callbacks as following:
static struct target_type zero_target = {
.name = "zero",
.version = {1, 1, 0},
.module = THIS_MODULE,
.ctr = zero_ctr,
.map = zero_map,
};
map
is a key callback - it's a heart of every device-mapper target. map
receive incoming bio
and it can do anything with it. For example, dm-linear just shift sector of every incoming bio
by predefined offset. See the code:
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;
}
Because map receives pointer to bio
it can change value under that pointer and that's it.
That's how you map I/O requests. If you want to create your own requests then you must allocate bio
, fill it's sector, device, size, end callback and add buffers to read into/write from. Basically, it's just a few steps:
bio->bi_bdev
, bio->bi_sector
, bio->bi_size
, bio->bi_end_io
bio_add_page
.submit_bio
.bio->bi_end_io
callbackExample can be found in dm-crypt target in crypt_alloc_buffer function.