1. Inflight机制存在的原因

QEMU/KVM/SPDK/DPDK这种架构下,vhost相关进程会因为各种异常概率crash的,在DPDK这种网络架构下,最多是产生丢包效应,一旦vhost进程拉起重连后,DPDK网络架构仍可以正常工作,而对于SPDK则不可行,因为存储系统中丢失的任一块请求在文件系统中都可能表意元数据,导致文件系统异常,对于用户而言,QEMU VM正常运行,而SPDK vhost crash后再恢复,文件系统出现了异常尚可接受,用户数据发生无感知丢失则不可忍受了。而QEMU/SPDK inflights则用于解决这个问题。

2. 代码版本

QEMU代码:https://github.com/qemu/qemu.git v5.1.0

SPDK代码:https://github.com/spdk/spdk v20.07.x

3. 核心原理

SPDK创建一个本地文件,作为位图标记vhost正在处理的virtio io reqs,如果vhost异常crash后拉起,则读取这个本地文件处理未完成的io reqs。

4. 创建INFLIGHT文件

4.1. QEMU INFLIGHT API

VhostUserRequest有两个API负责处理INFLIGHT_FD

在QEMU侧,VHostUserBlk结构体下有vhost_inflight,SPDK本地文件就挂在vhost_inflight.fd下

vhost_inflight在vhost_user_blk_start函数下进行初始化操作

即如果当前vhost blk inflight->addr为NULL,就通过vhost_dev_get_inflight通知SPDK建立文件,并将相关信息传递给QEMU。如果inflight->addr不为NULL,则说明当前的SPDK是crash后再拉起的,需要将之前的本地文件fd传递SPDK,让其处理未完成的IO reqs。

以上就可以知道,inflight文件是SPDK创建,用fd的方式存储在QEMU的,当新vhost拉起时,再将fd信息传递给vhost。

具体再说vhost_dev_get_inflight和vhost_dev_set_inflight,在vhost_user_get_inflight_fd中

一般QMEU只需要保存inflight->fd即可,但涉及到QEMU迁移等一系列问题,故vhost_inflight其他元素有作用如上所写。
vhost_dev_set_inflight大致代码和vhost_dev_get_inflight类似,不再赘叙。

4.2. SPDK inflight 文件创建

在vhost_message_handlers有对应API的回调函数

从QEMU的vhost_dev_get_inflight和vhost_dev_set_inflight vhost_user_write下来就到了这两个函数,单说vhost_user_get_inflight_fd

在QEMU VHOST_USER_GET_INFLIGHT_FD后就进行set操作,在vhost_user_set_inflight_fd下

5. SPDK中inflight记录reqs

接着上面,回到vq->inflight_split即struct rte_vhost_inflight_info_split *inflight_split,在process_vq函数下,每准备处理一个vring desc就执行rte_vhost_set_inflight_desc_split标记该index,如下,即可看出inflight_split本质是vring desc是否正被处理的位图。

而清除位图则使用的是rte_vhost_clr_inflight_desc_split

从process_blk_request -> blk_request_complete_cb -> blk_request_finish -> blk_task_enqueue -> vhost_vq_used_ring_enqueue -> rte_vhost_clr_inflight_desc_split可以看出,当vhost完成io更新virtio vring used_inex之后才清理位图。

6. SPDK中inflight恢复reqs

从vhost日志得知

VHOST_CONFIG: read message VHOST_USER_SET_VRING_NUM
VHOST_CONFIG: read message VHOST_USER_SET_VRING_BASE
VHOST_CONFIG: read message VHOST_USER_SET_VRING_ADDR
VHOST_CONFIG: read message VHOST_USER_SET_VRING_KICK
VHOST_CONFIG: vring kick idx:3 file:79
VHOST_CONFIG: reallocate vq from 0 to 1 node
VHOST_CONFIG: virtio is now ready for processing.

VHOST_USER_SET_VRING_KICK是vhost vritio ready前的最后一个请求,reqs恢复则做到了vhost_user_set_vring_kick中,其执行了vhost_check_queue_inflights_split函数

而在vhost_start_device_cb中,rte_vhost_get_vhost_ring_inflight将vq->resubmit_inflight赋值给vring->resubmit_inflight,那么回到process_vq,一开始就有submit_inflight_desc(bvsession, vq)

submit_inflight_desc就是获取到index,提交给process_blk_task处理,处理完成之后会调用rte_vhost_clr_inflight_desc_split清除位图。

7. 其他应用场景

除了解决SPDK vhost crash问题,还可以应用于解决DPDK/SPDK VHOST热升级过程中virtio req丢失的问题。

---end---


QEMU SPDK/DPDK inflight机制来自于OenHan

链接为:http://oenhan.com/qemu-spdk-dpdk-inflight

发表评论