LINUX.ORG.RU

подводные камни в функции bio_map_kern


1

0

Пишу 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); 
}
Если раскомментировать bio_put(clone), то система падает. Кто-нибудь с этим сталкивался? Ядро 2.6.27, Ubuntu.


Ответ на: комментарий от tailgunner

Ничего не говорит, просто молча виснет или ребутится.

ntldr
() автор топика

// bio_put(clone);

dcrypt_complete_io(io, status);

Ты уверен, что вызовы должны идти именно в таком порядке? Если учесть, что io - это clone->bi_private?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Уверен, поскольку структура io выделяется отдельно, и не зависит от clone. Впрочем, обратный порядок ничего не меняет.

ntldr
() автор топика
Ответ на: комментарий от ntldr

Тогда обычная рутина - логи, printk, отладчик, крэшдамп. Похоже, ты нарушаешь какое-то lifetime rule.

tailgunner ★★★★★
()

Так естественно, память уже освобождена. Добавь bio_get(clone) перед вызовом generic_make_request.

anonymous
()
Ответ на: комментарий от anonymous

А вернее, валится просто потому, что счётчик ссылок в этот момент равен нулю, что и приводит к срабатыванию макроса BUG_ON. Но bio_get надо обязательно добавить, потому что эта структура используется другими подсистемами, которые тоже пытаются её освободить.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.