支持非对称命名空间访问的SPDK多路径验证
这是一个有点绕口的标题。我们先来拆分一下,里面包含了三个概念:命名空间,非对称访问,以及多路径。多路径(multipath),可以针对单点故障提供容错能力,还可以为I/O流量提供负载平衡。当多路径驱动程序检测到活动路径的I/O错误时,它会将流量从故障路径转移到设备指定的辅助路径。当首选路径恢复正常时,可以将控制权返回到首选路径。本文主要围绕一个测试用例来介绍这些功能在SPDK中的支持和实现。
一
先看几个名词
1►
非对称命名空间访问 (ANA)
共享命名空间(namespace)可以借助于多PCIe端口或NVMe over Fabrics等网络端口,通过NVMe存储控制器(controller)被访问。如果,controller的namespace访问特征受到NVM subsystem内部配置的影响,那么就会发生非对称访问(Asymmetric Namespace Access , 简称ANA),反之称为对称访问。
ANA的状态,有Optimized(最优访问)和Non-Optimized(非最优访问),还有Inaccessible(不可访问)等,SPDK暂不支持Persistent Loss(持久消失)。
图1.1展示了一个非对称访问的例子,这是一个包含双端口NVMe SSD的subsystem,呈现了两个独立的域。NVMe namespace B (图中NS B)和namespace C (图中NS C)都包含在controller2所在的域里。也就是说,controller 2提供对namespace B和namespace C的最优访问,而controller 1不能。
图1.1 controller 2提供对namespace B的最优访问
为了让controller 1提供对namespace B最优访问,NVM subsystem可以重新配置或可以自动执行内部配置动作来改变,如图1.2所示。controller 2提供对namespace C的最优访问,而controller 1提供对namespace B的最优访问。
图1.2 controller 1提供对namespace B的最优访问
2►
多路径I / O和命名空间共享
根据NVMe协议,多路径I/O指的是主机和命名空间之间,两个或多个完全独立的PCIe路径。命名空间共享,是指两个或多个主机使用不同的NVMe控制器,访问公共共享命名空间的能力,如图1.3所示。(注:多路径I/O和命名空间共享都需要NVM系统包含两个或多个控制器。)
图1.3:具有两个控制器和两个端口的NVM子系统
3►
bpftrace脚本
bpftrace.sh 是一个帮助脚本,有助于针对正在运行的SPDK 应用程序,运行 bpftrace 脚本。它使用了数据包筛选器(Berkeley Packet Filter,简称BPF),所以要求SPDK在配置编译选项时使能userspace DTrace探针,./configure --with-usdt。
这是一个典型的用法:
scripts/bpftrace.sh `pid of spdk_tgt` scripts/bpf/nvmf.bt
通过nvmf.bt的筛选,SPDK 应用程序将打印出有关 NVMF子系统和轮询组信息状态转换的信息,如下所示:
2110.935735: nvmf_tgt reached state NONE
2110.954316: nvmf_tgt reached state CREATE_TARGET
2110.967905: nvmf_tgt reached state CREATE_POLL_GROUPS
2111.235982: nvmf_tgt reached state START_SUBSYSTEMS
2189.921492: nqn.2016-06.io.spdk:cnode1 change state from INACTIVE to ACTIVE start
2189.952508: nqn.2016-06.io.spdk:cnode1 on thread 2 state to ACTIVE start
2189.959125: nqn.2016-06.io.spdk:cnode1 on thread 2 state to ACTIVE done
2190.005832: nqn.2016-06.io.spdk:cnode1 change state from INACTIVE to ACTIVE done
关于SPDK BPF的详细使用方法,请参考之前的微信文章:SPDK的BPF Tracing
二
ANA multipath的验证
SPDK新增了支持ANA multipath验证的实例。在这个例子中,我们首先在target和host之间建立两条I/O路径(含两个端口),然后改变其中一个端口的ANA state。通过bpfrace脚本产生实时的与NVMF相关的I/O路径直方图,进而验证当前port是否是active port,确定活动的I/O路径。
图2.1显示了I/O路径的基本框架,本例的单网卡双端口环境比较简单,仅作为验证需要。如果用户环境允许的话可以用两个物理网卡测试。需要说明的是,测试脚本是建立在RPC交互命令之上,涉及到subsystem、transport等与NVMF相关的一些名词,关于这些名词的说明请参考附录。接下来看下具体的步骤。
图2.1:ANA multipath框架示例
1►
启动target server
我们在target端运行nvmf_tgt,然后创建nvmf tcp传输、侦听tcp端口的nvmf子系统,以及作为命名空间添加到nvmf子系统的malloc bdev。
build/bin/nvmf_tgt -i 0 -e 0xFFFF -m 0x3 &
rpc.py nvmf_create_transport -t tcp -o -u 8192
rpc.py bdev_malloc_create 64 512 -b Malloc0
rpc.py nvmf_create_subsystem nqn.2016-06.io.spdk:cnode1 -a -s SPDK1 -r -m 2
rpc.py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 Malloc0
还是在target端,添加两个listener,
rpc.py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t tcp -a 10.0.0.2 -s 4420
rpc.py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t tcp -a 10.0.0.2 -s 4421
并设置ANA state,选择4421端口所在的路径为最优路径,并打印。
rpc.py nvmf_subsystem_listener_set_ana_state nqn.2016-06.io.spdk:cnode1 -t tcp -a 10.0.0.2 -s 4420 -n non_optimized
rpc.py nvmf_subsystem_listener_set_ana_state nqn.2016-06.io.spdk:cnode1 -t tcp -a 10.0.0.2 -s 4421 -n optimized
rpc.py nvmf_subsystem_get_listeners nqn.2016-06.io.spdk:cnode1 | jq '.[] | .ana_states[0]'
配置好的ana_states数组显示如下:
{"ana_group": 1,"ana_state": "optimized"}{"ana_group": 1,"ana_state": "non_optimized"}
2►
启动host端
这时我们在host端启动一个app(比如bdevperf)来接收RPC 命令,
test/bdev/bdevperf/bdevperf -m 0x4 -z -q 128 -o 4096 -w verify -t 60 &
同样在host端创建NVMe控制器,设置multipath行为类型(failover或multipath)。回看图2.1,host端看到的Nvme0就是target端的Malloc0。
rpc.py bdev_nvme_attach_controller -b Nvme0 -t tcp -a 10.0.0.2 -s 4420 -f ipv4 -n nqn.2016-06.io.spdk:cnode1 -l -1 -o 10
rpc.py bdev_nvme_attach_controller -b Nvme0 -t tcp -a 10.0.0.2 -s 4421 -f ipv4 -n nqn.2016-06.io.spdk:cnode1 -x multipath -l -1 -o 10
回到target端,尝试改变4421端口listener的ANA state。
rpc.py nvmf_subsystem_listener_set_ana_state nqn.2016-06.io.spdk:cnode1 -t tcp -a 10.0.0.2-s 4420 -n non_optimized
rpc.py nvmf_subsystem_listener_set_ana_state nqn.2016-06.io.spdk:cnode1 -t tcp -a 10.0.0.2 -s 4421 -n inaccessible
再在host端运行bdevperf脚本,设置时长2分钟。
test/bdev/bdevperf/bdevperf.py -t 120 perform_tests
在target端使用bpftrace.sh脚本产生NVMF路径相关的trace日志文件。
scripts/bpftrace.sh “nvmf_tgt的进程号” scripts/bpf/nvmf_path.bt &> trace.txt
打印trace.txt获得I/O路径直方图。
Attaching 4 probes...
@path[10.0.0.2, 4421]: 20764
@path[10.0.0.2, 4421]: 21053
@path[10.0.0.2, 4421]: 21008
在target端查看当前活动的端口,是不是trace文件里记录的端口,这里应是4421。
rpc.py nvmf_subsystem_get_listeners nqn.2016-06.io.spdk:cnode1 |
jq -r '.[] | select (.ana_states[0].ana_state=="optimized")'
图2.2:两个端口ANA state的变化过程
当断开port2的listener,我们会看到SPDK会选择仅存的non_optimized 状态的端口作为I/O路径。
rpc.py nvmf_subsystem_remove_listener nqn.2016-06.io.spdk:cnode1 -t tcp -a 10.0.0.2 -s 4421
再重连port2的listener,并恢复端口的optimized 状态,active I/O路径为又会回到port2 。
rpc.py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t tcp -a 10.0.0.2 -s 4421
rpc.py nvmf_subsystem_listener_set_ana_state nqn.2016-06.io.spdk:cnode1 -t tcp -a 10.0.0.2 -s 4421 -n optimized
到这里,这个实例算是演示结束了。以上命令和步骤会整理到<spdk dir>/test/nvmf/host/multipath.sh,并随新版本发布。
3►
multipath和failover
为了弄明白multipath和failover的区别,我们来看下SPDK代码里RPC命令bdev_nvme_attach_controller是怎么处理这两个参数的。先看这3个参数,
-x 设置多路径行为 (disable关闭, failover故障切换, multipath多路径)
-l 删除ctrlr之前,等待ctrlr重新连接的时间,-1表示无限次重试。0表示没有重新连接重试。
-o 延迟重新连接重试的时间。
rpc.py bdev_nvme_attach_controller -b Nvme0 -t tcp -a 10.0.0.2 -s 4420 -f ipv4 -n nqn.2016-06.io.spdk:cnode1 -l -1 -o 10 -----①
rpc.py bdev_nvme_attach_controller -b Nvme0 -t tcp -a 10.0.0.2 -s 4421 -f ipv4 -n nqn.2016-06.io.spdk:cnode1 -x multipath -l -1 -o 10 -----②
再回看上面示例里的命令,首先由rpc_bdev_nvme_attach_controller( ) 函数解析multipath参数,然后由bdev_nvme_create( )函数创建这个控制器。
1. int bdev_nvme_create(…) 2. /* 处理multipath和failover参数的回调函数不一样 */ 3. if (nvme_bdev_ctrlr_get_by_name(base_name) == NULL || multipath) 4. attach_cb = connect_attach_cb; 5. else6. attach_cb = connect_set_failover_cb;
connect_attach_cb( )会调用nvme_bdev_ctrlr_create( ),
1. static int nvme_bdev_ctrlr_create(…) 2. nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name(name); /* 获得Nvme0控制器指针*/3. if (nbdev_ctrlr != NULL) 4. /* 如果已经存在,检查是否支持multipath,对应上面第②条命令 */ 5. bdev_nvme_check_multipath(nbdev_ctrlr, ctrlr); 6. else 7. /* 如果是新的NVMe控制器,则将该控制器入队,对应上面第①命令 */ 8. TAILQ_INSERT_TAIL(&g_nvme_bdev_ctrlrs, nbdev_ctrlr, tailq); 9. /* 把指定的控制器添加到现有控制器队列 */ 10. nvme_ctrlr->nbdev_ctrlr = nbdev_ctrlr; 11. TAILQ_INSERT_TAIL(&nbdev_ctrlr->ctrlrs, nvme_ctrlr, tailq);
而在failover的情况下,connect_set_failover_cb则会调用bdev_nvme_add_secondary_trid( ),将辅助路径添加到现有nvme_ctrlr路径队列用以进行故障切换,也就是一次入队操作。
1. static int bdev_nvme_add_secondary_trid(…) 2. TAILQ_FOREACH(tmp_trid, &nvme_ctrlr->trids, link) 3. if (tmp_trid->is_failed && tmp_trid != nvme_ctrlr->active_path_id) 4. TAILQ_INSERT_BEFORE(tmp_trid, new_trid, link);
在检查它是否可以访问与主路径相同的命名空间后,它将断开连接,直到发生故障转移。值得注意的是,SPDK目前不支持transport类型为PCIe的故障切换,只支持同一transport类型,和同一NQN的故障切换。
4►
listener和ANA
关于添加、删除listener和更改ANA状态的RPC命令,都是通过操作码来分配到不同分支来处理的。
1. static void nvmf_rpc_listen_paused() 2. if (ctx->op == NVMF_RPC_LISTEN_ADD)3. spdk_nvmf_subsystem_add_listener(ctx->subsystem, &ctx->trid, nvmf_rpc_subsystem_listen, ctx); 4. else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) 5. spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid); 6. else if (ctx->op == NVMF_RPC_LISTEN_SET_ANA_STATE) 7. nvmf_subsystem_set_ana_state(subsystem, &ctx->trid, ctx->ana_state, ctx->anagrpid, nvmf_rpc_set_ana_state_done, ctx);
RPC命令nvmf_subsystem_add_listener:首先找到对应的target和subsystem,初始化ana_state,默认为OPTIMIZED,接下来更新发现日志,继续侦听。
1. void spdk_nvmf_subsystem_add_listener(…) 2. for (i = 0; i < subsystem->max_nsid; i++) 3. listener->ana_state[i] = SPDK_NVME_ANA_OPTIMIZED_STATE; 4. TAILQ_INSERT_HEAD(&listener->subsystem->listeners, listener, link); 5. nvmf_update_discovery_log(listener->subsystem->tgt, NULL); 6. nvmf_rpc_listen_resumed(…);
RPC命令nvmf_subsystem_remove_listener:找到相对应的控制器,把它的listener指针置空,然后删除subsystem的这个listener结点,最后在每一个I/O 通道上通知更新poll group(附录表A)。
RPC命令nvmf_subsystem_listener_set_ana_state:通过nvmf_subsystem_set_ana_state( )函数,先找到指定的listener,改完ANA state以后,再在每一个I/O 通道上通知更新poll group。实际上是先断开listener,设置好再重连的过程。
►
附录
SPDK NVMe-oF名词 |
解释 |
target |
具有关联命名空间的子系统的集合,以及传输集和关联的网络连接。 |
subsystem |
NVMe-oF 子系统,包含命名空间和控制器,并执行访问控制。 |
namespace(ns) |
NVMe-oF 命名空间,是指块设备层。 |
transport |
网络结构传输方式,有RDMA,TCP等。 |
poll group |
作为一个单元轮询的网络连接集合的抽象。 |
listener |
侦听器,被target接受的新连接网络地址。 |
NQN |
代表主机系统(启动器)。 |
ANA state |
ANA 状态是每个侦听器和每个子系统的,并存储在子系统listener中。 |
表A:SPDK NVMe-oF名称解释
原文链接:https://mp.weixin.qq.com/s/WOH6Lo8yfn-LiexWA77AYQ
学习更多dpdk视频
DPDK 学习资料、教学视频和学习路线图 :https://space.bilibili.com/1600631218
Dpdk/网络协议栈/ vpp /OvS/DDos/NFV/虚拟化/高性能专家 上课地址: https://ke.qq.com/course/5066203?flowToken=1043799
DPDK开发学习资料、教学视频和学习路线图分享有需要的可以自行添加学习交流q 君羊909332607备注(XMG) 获取
支持非对称命名空间访问的SPDK多路径验证相关推荐
- arm服务器获取文件路径中文,ssh 访问远程服务器文件路径
ssh 访问远程服务器文件路径 内容精选 换一换 在IntelliJ上选择"项目",找到".idea"文件夹,单击右键选择"新建>文件" ...
- 2005服务器文件夹网页设设置,设置VSS2005使支持通过Internet访问
Re:设置VSS2005使支持通过Internet访问 (2006/7/25 15:15:27) by 我的邮箱:zhang.wei34@zte.com.cn请问,我按上面的要求做到了" ...
- ssh查看服务器上的文件,ssh 访问远程服务器文件路径
ssh 访问远程服务器文件路径 内容精选 换一换 在IntelliJ上选择"项目",找到".idea"文件夹,单击右键选择"新建>文件" ...
- 设置VSS2005使支持通过Internet访问
转自:http://www.web3.cn/Content,2006,6,18,151.aspx 最近需要通过Internet来访问源代码,以前一直是使用VSS6.0D,但没有支持Internet访问 ...
- CentOS 7虚拟机支持virsh console访问
CentOS 7虚拟机支持virsh console访问方法: 1. 在KVM(客户机)下开机启动并启动服务 systemctl enable serial-getty@ttyS0.service s ...
- win10添加打印机--无法访问指定设备,路径或文件。。
win10添加打印机无法访问指定设备,路径或文件..后来发现很多按钮点击多说无法访问指定设备,路径或文件.. 解决添加打印机问题: 在搜索栏中搜索:print (从这里添加) 彻底解决: 添加环境变量 ...
- 解决springmvc中添加了静态资源访问路径之后就访问不到Controller路径的问题
访问不到Controller,也访问不到controller路径. Controller代码: /*** Created by 李柏霖* 2020/10/19 17:35*/package com.l ...
- python不支持下标访问元素吗_Python 集合不支持使用下标访问其中的元素
Python 集合不支持使用下标访问其中的元素 答:对 下列对于新创企业的优势的描述中,错误的是(). 答:开拓新市场投资多,但潜在的回报少 与欧洲近代科学革命相比,18世纪美国科学发展的优势是() ...
- win10系统无法访问指定设备或路径怎么解决?
win10系统无法访问指定设备或路径怎么解决? 1 尝试选择打开方式能不能打开 2 如果能打开,那么只要将此打开方式设置为默认方式即可 win10系统中如何设置文件的默认打开方式? 1右键文件 2点击 ...
- 安装虚拟光驱时提示windows无法访问指定设备、路径或文件。可能没有权限访问该项目
安装虚拟光驱时提示windows无法访问指定设备.路径或文件.可能没有权限访问该项目 解决方式:win10有自带的虚拟光驱,右键镜像文件装载即可...
最新文章
- Keras快速上手:基于Python的深度学习
- Ubuntu 14.04 安装小企鹅输入法 Fcitx
- T级的备份兄弟们都怎么做
- Intel Realsense 图像投影(Projection)翻译
- C算法编程题(一)扑克牌发牌
- 今日arXiv精选 | 15篇EMNLP 2021最新论文
- C语言数组类型、数组指针类型、数组指针类型变量
- 移动开发框架,第【一】弹:QuoJs 官方文档(汉化版)
- linux字符雨,linux周记
- Sublime Text3常用基本操作
- oracle cogs 科目,请问R12中,Mtl_material_transaction中的 COGS Recognition记录是干啥的?
- 【版本发布】JEECG 3.6.2 移动能力版发布,快速开发平台
- ubuntu同时装有MXNet和Caffe框架
- 每日一句(2014-9-11)
- Python新手需要掌握的知识点
- python 分数等级转换_一文读懂,新高考“3+1+2”模式中等级赋分如何换算?
- java 实现pdf 转图片_java实现pdf转图片pdf
- Java Spider介绍
- JPA与Hibernate的区别
- Android锁屏状态下点亮屏幕并弹窗提醒