Linux nvme驱动分析之块设备层

参考

Product Documentation Red Hat Enterprise Linux7 7.2 发行注记 第 14 章 存储

blk_mq

数据缓冲区转换成prp或者sg列表

用户态分配的内存使用blk_rq_map_user,内核态分配的内存使用blk_rq_map_kern

//xilinx petalinux-v2018.2
blk_rq_map_user

对比来看,

//xilinx petalinux-v2018.2
blk_rq_map_kern
  bio_copy_kern //数据buf地址不对齐,硬件能力不支持,该分支应该很少进入,copy会带来性能降低
                //类似于bounce buffer回弹缓冲区
  bio_map_kern
    bio_kmalloc //分配一个bio
    bio_add_pc_page //把page循环加入bio

通过上面的操作把request的内存记录到bio中,通过blk_rq_map_sg,形成struct scatterlist *sg,prp或者sg列表是通过nvme_setup_prps基于struct scatterlist *sg构造的。

IO请求如何下发到SSD

创建队列的时候注册blk_mq_ops

static const struct blk_mq_ops nvme_mq_admin_ops = {
	.queue_rq	= nvme_queue_rq,
	.complete	= nvme_pci_complete_rq,
	.init_hctx	= nvme_admin_init_hctx,
	.exit_hctx      = nvme_admin_exit_hctx,
	.init_request	= nvme_init_request,
	.timeout	= nvme_timeout,
};

static const struct blk_mq_ops nvme_mq_ops = {
	.queue_rq	= nvme_queue_rq,
	.complete	= nvme_pci_complete_rq,
	.init_hctx	= nvme_init_hctx,
	.init_request	= nvme_init_request,
	.map_queues	= nvme_pci_map_queues,
	.timeout	= nvme_timeout,
	.poll		= nvme_poll,
};

块设备层通过blk_execute_rqblk_execute_rq_nowait把请求加入队列,然后下发到硬件,

//xilinx petalinux-v2018.2
nvme_queue_rq
  nvme_setup_cmd
  nvme_init_iod
  nvme_map_data
    blk_rq_map_sg
    dma_map_sg_attrs
    nvme_setup_prps
  blk_mq_start_request
  __nvme_submit_cmd
  nvme_process_cq

legacy blk

传统的块设备只有一个队列,通过make_request分发io,内核在bio这块变动太多了,

#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,4,0)
#define bio_op(bio) ((bio)->bi_rw & REQ_OP_MASK)
#define bio_opf(bio) ((bio)->bi_rw)
#else
#define REQ_FLUSH REQ_PREFLUSH
#define bio_opf(bio) ((bio)->bi_opf)
#endif

验证

写一个测试脚本,

root@t2080rdb:~# cat test.sh 
#!/bin/sh
echo "test read"
nvmeqe_benchmark -r /dev/nvme0n1 -p 0xe2000000 -s 0 -l 0x100000 -c 128 &
nvmeqe_benchmark -r /dev/nvme0n1 -p 0xe2100000 -s 0 -l 0x100000 -c 128 &
nvmeqe_benchmark -r /dev/nvme0n1 -p 0xe2200000 -s 0 -l 0x100000 -c 128 &
nvmeqe_benchmark -r /dev/nvme0n1 -p 0xe2300000 -s 0 -l 0x100000 -c 128

测试结果,对比测试前后的中断统计,内核把任务平均分给了各个CPU,

root@t2080rdb:~# cat /proc/interrupts | grep nvme0
 58:          0          0        403          0          0          0          0          0  fsl-msi-263  15 Edge      nvme0q0, nvme0q1
 59:          0          0          0        109          0          0          0          0  fsl-msi-224  16 Edge      nvme0q2
 60:          0          0          0          0        118          0          0          0  fsl-msi-225  17 Edge      nvme0q3
 61:          0          0          0          0          0        755          0          0  fsl-msi-226  18 Edge      nvme0q4
 62:          0          0          0          0          0          0        206          0  fsl-msi-227  19 Edge      nvme0q5
 63:          0          0          0          0          0          0          0        439  fsl-msi-228  20 Edge      nvme0q6
 64:       1038          0          0          0          0          0          0          0  fsl-msi-229  21 Edge      nvme0q7
 65:          0        353          0          0          0          0          0          0  fsl-msi-230  22 Edge      nvme0q8
root@t2080rdb:~# ./test.sh 
test read
speed: 306.95MB/s, cost times: 417ms
speed: 306.22MB/s, cost times: 418ms
speed: 305.49MB/s, cost times: 419ms
speed: 305.49MB/s, cost times: 419ms
root@t2080rdb:~# cat /proc/interrupts | grep nvme0
 58:          0          0        461          0          0          0          0          0  fsl-msi-263  15 Edge      nvme0q0, nvme0q1
 59:          0          0          0        142          0          0          0          0  fsl-msi-224  16 Edge      nvme0q2
 60:          0          0          0          0        243          0          0          0  fsl-msi-225  17 Edge      nvme0q3
 61:          0          0          0          0          0        938          0          0  fsl-msi-226  18 Edge      nvme0q4
 62:          0          0          0          0          0          0        260          0  fsl-msi-227  19 Edge      nvme0q5
 63:          0          0          0          0          0          0          0        471  fsl-msi-228  20 Edge      nvme0q6
 64:       1092          0          0          0          0          0          0          0  fsl-msi-229  21 Edge      nvme0q7
 65:          0        385          0          0          0          0          0          0  fsl-msi-230  22 Edge      nvme0q8

你可能感兴趣的:(存储)