不适用请求队列
使用请求队列对于一个机械磁盘设备而言的确有助于提高系统的性能,但是对于RAMDISK
、ZRAM(Compressed RAM Block Device)等
完全可真正随机访问的设备而言,无法从高级的请求队列逻辑中获益。对于这些设备,块层支持“无队列”的操作模式,为使用这个模式,驱动必须提供一个“
制造请求”函数,而不是一个请求处理函数,“
制造请求`”函数的原型:
static void xxx_make_request(struct request_queue *queue,struct bio *bio);
块设备驱动初始化的时候不再调用blk_init_queue()
,而是调用blk_alloc_queue()
和blk_queue_make_request()
,xxx_make_request
则会成为blk_queue_make_request
()的第二个参数。
xxx_make_request()
函数的第一个参数仍然是“请求队列”,但是这个请求队列不包含任何请求,因为快层没有必要将bio
调整为请求。因此"制造请求"函数的的主要参数是bio结构体。代码清单13.12所示为一个“制造请求”函数的例子,它取材于drivers/block/zram/zram_drv.c
。
static void zarm_make_request(struct request_queue *queue,struct bio *bio)
{
......
__zram_make_request(zram,bio);
......
}
static void __zram_make_request(struct zram *zram,struct bio *bio)
{
int offset;
u32 index;
struct bio_vec bvec;
struct bvec_iter iter;
index = bio->bio_iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
offset = (bio->bi_iter.bi_sector &(SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
if(unlikely(bio->bi_rw & REQ_DISCARD))
{
zram_bio_discard(zram,index,offset,bio);
bio_endio(bio,0);
return;
}
bio_for_each_segment(bvec,bio,iter)
{
struct bio_vec bv = bvec;
unsigned int unwritten = bvec.bv_len;
do
{
bv.bv_len = min_t(unsigned int,PAGE_SIZE - offset,unwritten);
if(zram_bvec_rw(zram,&bv,index,offset,bio_op(bio),bio)<0)
{
goto out;
}
bv.bv_offset += bv.bv_len;
unwritten -= bv.bv_len;
update_position(&index,&offset,&bv);
}while(unwritten);
}
bio_endio(bio);
return;
out:
bio_io_error(bio);
}
上述代码通过bio_for_each_segment()
;迭代bio中的每个segment
,最终调用zram_bvec_rw()
完成内存的压缩,解压,读取和写入。
zram是Linux的一种内存优化技术,他划定一片内存区域作为swap的交换分区,但是它本身具备自动压缩功能,从而可以达到辅助Linux匿名页
的交换效果,变相增大了内存。