NOTE. My answer is related to kernel version <3.14, because since API 3.14 is slightly modified.
In the kernel, you read / write specific sectors with struct bio . This structure is used for all block-level I / O. Comprehensive documentation can be found in the kernel and lwn . These are some of the most significant members of this structure:
bio->bi_sector - the first sector of the block I / O requestbio->bi_size - I / O request sizebio->bi_bdev - reader / writerbio->bi_end_io - callback that calls the kernel at the end of the request
What you do on the target device map is display incoming bio . When you create a target device map, you provide at least two callbacks: ctr and map . For example, the simplest target, dm-zero device-mapper, declares callbacks as follows :
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 is the heart of every goal of a mapmaker. map receives the incoming bio , and it can do something with it. For example, a dm-linear sector of shift shift for each incoming bio at a predefined offset. See 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; }
Since map receives a pointer to bio , it can change the value under that pointer and that it is.
The way you map I / O requests. If you want to create your own queries, you must select bio , fill in its sector, device, size, end of the callback and add read / write buffers. Basically, these are just a few steps:
- Call bio_alloc to highlight biographies.
- Set
bio->bi_bdev , bio->bi_sector , bio->bi_size , bio->bi_end_io - Add pages via
bio_add_page . - Call
submit_bio . - Handling results and errors in the
bio->bi_end_io
An example can be found in the dm-crypt target in crypt_alloc_buffer .