这是一个有点绕口的标题。我们先来拆分一下,里面包含了三个概念:命名空间非对称访问,以及多路径。多路径(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多路径验证相关推荐

  1. arm服务器获取文件路径中文,ssh 访问远程服务器文件路径

    ssh 访问远程服务器文件路径 内容精选 换一换 在IntelliJ上选择"项目",找到".idea"文件夹,单击右键选择"新建>文件" ...

  2. 2005服务器文件夹网页设设置,设置VSS2005使支持通过Internet访问

    Re:设置VSS2005使支持通过Internet访问   (2006/7/25 15:15:27) by 我的邮箱:zhang.wei34@zte.com.cn请问,我按上面的要求做到了" ...

  3. ssh查看服务器上的文件,ssh 访问远程服务器文件路径

    ssh 访问远程服务器文件路径 内容精选 换一换 在IntelliJ上选择"项目",找到".idea"文件夹,单击右键选择"新建>文件" ...

  4. 设置VSS2005使支持通过Internet访问

    转自:http://www.web3.cn/Content,2006,6,18,151.aspx 最近需要通过Internet来访问源代码,以前一直是使用VSS6.0D,但没有支持Internet访问 ...

  5. CentOS 7虚拟机支持virsh console访问

    CentOS 7虚拟机支持virsh console访问方法: 1. 在KVM(客户机)下开机启动并启动服务 systemctl enable serial-getty@ttyS0.service s ...

  6. win10添加打印机--无法访问指定设备,路径或文件。。

    win10添加打印机无法访问指定设备,路径或文件..后来发现很多按钮点击多说无法访问指定设备,路径或文件.. 解决添加打印机问题: 在搜索栏中搜索:print (从这里添加) 彻底解决: 添加环境变量 ...

  7. 解决springmvc中添加了静态资源访问路径之后就访问不到Controller路径的问题

    访问不到Controller,也访问不到controller路径. Controller代码: /*** Created by 李柏霖* 2020/10/19 17:35*/package com.l ...

  8. python不支持下标访问元素吗_Python 集合不支持使用下标访问其中的元素

    Python 集合不支持使用下标访问其中的元素 答:对 下列对于新创企业的优势的描述中,错误的是(). 答:开拓新市场投资多,但潜在的回报少 与欧洲近代科学革命相比,18世纪美国科学发展的优势是() ...

  9. win10系统无法访问指定设备或路径怎么解决?

    win10系统无法访问指定设备或路径怎么解决? 1 尝试选择打开方式能不能打开 2 如果能打开,那么只要将此打开方式设置为默认方式即可 win10系统中如何设置文件的默认打开方式? 1右键文件 2点击 ...

  10. 安装虚拟光驱时提示windows无法访问指定设备、路径或文件。可能没有权限访问该项目

    安装虚拟光驱时提示windows无法访问指定设备.路径或文件.可能没有权限访问该项目 解决方式:win10有自带的虚拟光驱,右键镜像文件装载即可...

最新文章

  1. Keras快速上手:基于Python的深度学习
  2. Ubuntu 14.04 安装小企鹅输入法 Fcitx
  3. T级的备份兄弟们都怎么做
  4. Intel Realsense 图像投影(Projection)翻译
  5. C算法编程题(一)扑克牌发牌
  6. 今日arXiv精选 | 15篇EMNLP 2021最新论文
  7. C语言数组类型、数组指针类型、数组指针类型变量
  8. 移动开发框架,第【一】弹:QuoJs 官方文档(汉化版)
  9. linux字符雨,linux周记
  10. Sublime Text3常用基本操作
  11. oracle cogs 科目,请问R12中,Mtl_material_transaction中的 COGS Recognition记录是干啥的?
  12. 【版本发布】JEECG 3.6.2 移动能力版发布,快速开发平台
  13. ubuntu同时装有MXNet和Caffe框架
  14. 每日一句(2014-9-11)
  15. Python新手需要掌握的知识点
  16. python 分数等级转换_一文读懂,新高考“3+1+2”模式中等级赋分如何换算?
  17. java 实现pdf 转图片_java实现pdf转图片pdf
  18. Java Spider介绍
  19. JPA与Hibernate的区别
  20. Android锁屏状态下点亮屏幕并弹窗提醒

热门文章

  1. 《我爱我的祖国》受捧 再现专线另类舌尖上中国
  2. k8s常见问题大收集
  3. 当我们谈注册中心时我们谈什么
  4. 如何利用 composer 替换第三方包里的某个类(color-thief-php为例)
  5. FPGA设计之门控时钟
  6. 《风暴英雄》游戏体验
  7. GTC '19 经典回顾 | 如何编排和创造二次元中的舞蹈?
  8. 小程序---宿主环境(常用组件、api)---02
  9. [4G5G专题-38]:物理层- LTE/NR下行公共控制信道PDCCH与其承载的内容下行控制信息格式DCI
  10. 5G NR 下行同步SSB(1)-- SSB时频资源