我有一个正在工作的块设备驱动程序,经过一段时间。它适用于 PCIe 设备,我直接使用 make_request_fn 处理 bios,而不是使用请求队列,因为该设备没有寻道时间。但是,它仍然有事务开销。
当我从设备连续读取时,我得到包含许多段的 bios(通常我最多 32 个),每个段由 2 个硬件扇区(所以 2 * 2k)组成,然后将其作为设备的一个分散-收集事务处理,节省大量的信令开销。然而,在写入时,每个 bios 都只有一个 2 个扇区的段,因此操作总共需要更长的时间。我希望以某种方式使传入的 bios 由许多段组成,或者我自己将 bios 明智地合并在一起。这里的正确方法是什么?
的当前内容make_request_fn
大致如下:
- 确定生物的读/写
- 对于 bio 中的每个部分,在
scatterlist*
with中添加一个条目sg_set_page
- 将此散点列表映射到 PCI
pci_map_sg
- 对于 scatterlist 中的每个段,添加到定义多段 DMA scatter-gather 操作的设备特定结构
- 将该结构映射到 DMA
- 进行交易
- 取消映射结构和 SG DMA
- 如果失败和
bio_endio
成功则调用。-EIO
0
请求队列设置如下:
#define MYDEV_BLOCK_MAX_SEGS 32
#define MYDEV_SECTOR_SIZE 2048
blk_queue_make_request(mydev->queue, mydev_make_req);
set_bit(QUEUE_FLAG_NONROT, &mydev->queue->queue_flags);
blk_queue_max_segments(mydev->queue, MYDEV_BLOCK_MAX_SEGS);
blk_queue_physical_block_size(mydev->queue, MYDEV_SECTOR_SIZE);
blk_queue_logical_block_size(mydev->queue, MYDEV_SECTOR_SIZE);
blk_queue_flush(mydev->queue, 0);
blk_queue_segment_boundary(mydev->queue, -1UL);
blk_queue_max_segments(mydev->queue, MYDEV_BLOCK_MAX_SEGS);
blk_queue_dma_alignment(mydev->queue, 0x7);