nvme命令中prp_Linux nvme驱动分析之块设备层

本文深入探讨了Linux NVMe驱动中PRP(Physical Region Pointer)列表的使用,特别是在块设备层的实现。介绍了如何通过blk_mq_ops将IO请求映射到PRP列表,并通过nvme_queue_rq等函数将请求提交到SSD。通过测试验证了多队列的性能提升,观察了中断分布的变化。
摘要由CSDN通过智能技术生成

参考

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_rq或blk_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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值