Пишу target драйвер для device mapper. Столкнулся с падением при попытке освобождения bio контекста выделяемого bio_map_kern. В исходниках ядра примеров применения этой функции не обнаружил, в сети с подробной документацией туго. Пример кода:
static void dcrypt_endio(struct bio *clone, int status)
{
dc_io *io = clone->bi_private;
dc_dev *dc = io->target->private;
struct bio_vec *bv;
int i;
char *buff, *data;
unsigned long flags;
if (unlikely(!bio_flagged(clone, BIO_UPTODATE) && !status)) {
DbgMsg("EIO\n");
status = -EIO;
}
if (unlikely(status))
goto out;
if (bio_data_dir(io->base_io) == READ)
{
buff = io->data;
bio_for_each_segment(bv, io->base_io, i) {
data = bvec_kmap_irq(bv, &flags);
memcpy(data, buff, bv->bv_len); buff += bv->bv_len;
flush_dcache_page(bv->bv_page);
bvec_kunmap_irq(data, &flags);
}
}
out:
DbgMsg("dcrypt_endio-1 : %d\n", status);
// bio_put(clone);
dcrypt_complete_io(io, status);
}
static void dcrypt_do_io(dc_io *io, char *buff, u32 size)
{
dc_dev *dc = io->target->private;
struct bio *bio = io->base_io;
struct bio *clone;
sector_t sector = bio->bi_sector + io->target->begin;
struct request_queue *q = bdev_get_queue(dc->orig_dev->bdev);
clone = bio_map_kern(q, buff, size, GFP_NOIO);
if (IS_ERR(clone)) {
DbgMsg("clone is not mapped\n");
dcrypt_io_complete(io, -ENOMEM);
return;
}
clone->bi_private = io;
clone->bi_end_io = dcrypt_endio;
clone->bi_bdev = dc->orig_dev->bdev;
clone->bi_rw = bio->bi_rw;
clone->bi_sector = DC_AREA_SIZE + sector;
DbgMsg("dcrypt_do_io %x\n", clone);
generic_make_request(clone);
}