分析virtio-blk+qemu+spdk场景下不用virtqueue_kick通知后端的原因

当VM向virtio-blk的vring中添加IO vector之后,代码会进入到virtqueue_kick函数,该函数的实现如下


        virtqueue_kick_prepare函数中如果vq->event不存在,则判断virtio-blk设备是否设置了【VRING_USED_F_NO_NOTIFY】feature,如果virtio-blk设备设置了此feature,则needs_kick一直为false,则virtqueue_kick_prepare函数一直返回false,从而virtqueue_kick函数不会执行virtqueue_notify函数通知virtio-blk后端来处理IO

而virtqueue_kick_prepare函数中vq->event的值是在__vring_new_virtqueue函数中赋值,赋值的代码如下
        
                vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
        
        也就是说virtio-blk设备不支持VIRTIO_RING_F_EVENT_IDX feature的话,那么vq->event就为NULL,此时我们看看spdk在进行virtio-blk设备feature协商的时候都设置了哪些feature。下面是spdk enable的feature
                #define SPDK_VHOST_FEATURES ((1ULL << VHOST_F_LOG_ALL) |
                        (1ULL << VHOST_USER_F_PROTOCOL_FEATURES) |
                        (1ULL << VIRTIO_F_VERSION_1) |
                        (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) |
                        (1ULL << VIRTIO_RING_F_EVENT_IDX) |
                        (1ULL << VIRTIO_RING_F_INDIRECT_DESC))

spdk_vhost_dev_register函数设置feature的代码如下

        
        rte_vhost_driver_set_features函数直接设置path对应的vsocket->feature

rte_vhost_driver_disable_features函数去掉vsocket->feature中想要disable的feature。

        通过跟踪rte_vhost_driver_disable_features函数中的features参数发现,此features = vhost_blk_device_backend ->disabled_features ,而vhost_blk_device_backend->disabled_features 数据结构的值如下:

static const struct spdk_vhost_dev_backend vhost_blk_device_backend =
                {
                        …
                        .disabled_features = SPDK_VHOST_DISABLED_FEATURES |
                                                (1ULL << VIRTIO_BLK_F_GEOMETRY) |
                                                (1ULL << VIRTIO_BLK_F_RO) |
                                                (1ULL << VIRTIO_BLK_F_FLUSH) |
                                                (1ULL << VIRTIO_BLK_F_CONFIG_WCE) |
                                                (1ULL << VIRTIO_BLK_F_BARRIER) |
                                                (1ULL << VIRTIO_BLK_F_SCSI),
                        …
                }

而 SPDK_VHOST_DISABLED_FEATURES 宏定义如下:
                        #define SPDK_VHOST_DISABLED_FEATURES ((1ULL << VIRTIO_RING_F_EVENT_IDX) |
(1ULL << VIRTIO_F_NOTIFY_ON_EMPTY))

这样的话virtio-blk设备就不存在feature【VIRTIO_RING_F_EVENT_IDX】。这样vm的driver代码执行到__vring_new_virtqueue函数下面代码时,vq->event为false
        
                        vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
        
        这样的话,virtqueue_kick_prepare函数将执行下图中红框部分的代码。

        下面我们看下virtio-blk设备是否支持feature【VRING_USED_F_NO_NOTIFY】,我们期望是支持的,这样need_kicks就为false,从而不用通知后端来处理IO,我们再从spdk代码中分析此feature。
        spdk在rte_vhost_enable_guest_notification函数设置VRING_USED_F_NO_NOTIFY
        
                        dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
        
        rte_vhost_enable_guest_notification函数的调用栈如下

(gdb) bt
#0 rte_vhost_enable_guest_notification (vid=vid@entry=0, queue_id=queue_id@entry=0, enable=enable@entry=0) at vhost.c:572
#1 0x0000000000442bd2 in start_device (vid=0) at vhost.c:1655
#2 0x000000000049707c in vhost_user_msg_handler (vid=, fd=fd@entry=60) at vhost_user.c:2373
#3 0x00000000004941ec in vhost_user_read_cb (connfd=60, dat=0x7ffecc0008c0, remove=0x7ffedb911f98) at socket.c:572
#4 0x000000000049a231 in fdset_event_dispatch (arg=0x80f940 <vhost_user+8192>) at fd_man.c:314
#5 0x00007ffff5ce8e25 in start_thread () from /lib64/libpthread.so.0
#6 0x00007ffff4a7835d in clone () from /lib64/libc.so.6
        
        start_device函数中调用rte_vhost_enable_guest_notification函数的代码如下

        从上图可以得出,rte_vhost_enable_guest_notification函数的第三个参数是0rte_vhost_enable_guest_notification函数实现如下,当第三个参数enable为false,则设置feature VRING_USED_F_NO_NOTIFY

        start_device是spdk对virtio-blk后端设备初始化过程中调用的,当设备开始处理IO时,feature都已经设置完毕。
        至此,当virtio-blk处理IO时,就会执行到下面的代码中,virtqueue_kick操作不会通知后端,避免vm-exit,从而提升IO处理性能。

分析virtio-blk+qemu+spdk环境中virtio-blk不用执行virtqueue_kick操作通知后端处理IO的原因相关推荐

  1. 通过三种情况深度分析,复杂的公网环境,网络穿透如何做到?丨C++后端开发丨P2P丨c/c++Linux服务器开发丨网关API

    通过三种情况深度分析,复杂的公网环境,网络穿透如何做到? 视频讲解如下,点击观看: 通过三种情况深度分析,复杂的公网环境,网络穿透如何做到?丨C++后端开发丨P2P丨c/c++Linux服务器开发丨网 ...

  2. linux 网卡virtio,浅谈linux设备中virtio组织关系

    当我们查看Linux kernel.C的Virtio代码时,我们会发现许多相关的文件.那么,verdio,我们只有Virtio\UC',Virtio\ubk.C. 美德\ubalon.C. 等等.与这 ...

  3. 在QEMU硬件环境中启动 kernel 2.6 + busybox as rootfs

    ## 环境和软件版本 ubuntu 14.04 x86_64 compiler: codesourcery 2009q1 arm-none-linux-gnueabi- i686 [1] kernel ...

  4. Webpack中的sourcemap以及如何在生产和开发环境中合理的设置sourcemap的类型

    简要介绍:在webpack的官网,给出了十几种sourcemap,那么每一种sourcemap之间有什么区别,本文在理解sourcemap的基础上,分析在生产和开发环境中,应该采用何种形式的sourc ...

  5. 经典文献阅读之--Lifelong SLAM(变化环境中Lifelong定位建图)

    0. 简介 商场.超市等大多数现实场景的环境随时都在变化.不考虑这些变化的预建地图很容易变得过时.因此,有必要拥有一个最新的环境模型,以促进机器人的长期运行.为此<A General Frame ...

  6. base环境中无法安装nb_conda_kernels问题

    因为jupyter需要配置在base环境中安装nb_conda_kernels所以执行了如下指令 conda install nb_conda_kernels 我又执行了 conda update - ...

  7. python27怎么安装thrift解压包_Python在Linux环境中安装Thrift

    1.文件下载:thrift-0.11.0.tar.gz 个人网盘下载:链接:https://pan.baidu.com/s/1MXgx8LuN4wk7ssVUD9Wzaw  提取码:xw85 2. 将 ...

  8. Hadoop集群中增加与ElasticSearch连接的操作

    在没有引入elasticsearch-hadoop-xxx.jar相应的Jar包时,的在Hive中执行ElasticSearch外部表操作,会报如下的异常: Exception in thread & ...

  9. ORA-14551: 无法在查询中执行 DML 操作

    最近在调试一个带DML操作的函数时,一直不成功,在PL/SQL中测试时没问题,通过SQL语句调用函数时就不行了,刚开始一直没找到原因,后来无意间把 函数中捕获异常的代码注释掉,终于通过SQL调试时,弹 ...

  10. 使用SQL数据库在Python中执行CRUD操作

    目录 介绍 背景 在Visual Studio中创建一个Python项目 在SQL中创建数据库和表 为数据库创建配置文件 安装Python包 "Pypyodbc" 创建连接文件 创 ...

最新文章

  1. Cordova error:npm install -g ios-deploy
  2. ifm virtual check in part 2
  3. java servicefactory_Java DirectoryServiceFactory.getDirectoryService方法代碼示例
  4. 多线程中堆和栈区别的深入解析
  5. You have new mail in /var/spool/mail/root消除提示的方法
  6. 论文浅尝 - ICLR2021 | 从信息论的角度提高语言模型的鲁棒性
  7. 首届全国信创大赛圆满收官,信创新势力载誉而归!
  8. [Guava源码日报](8)ImmutableCollection
  9. VMware知识库中文文章列表 (更新2013年6月)
  10. 【GIS导论】实验六 叠加分析
  11. 使用Microsoft Office Visio 2007 绘图
  12. python源码剖析-笔记2
  13. Vue.js尚硅谷视频学习笔记(第一章:Vue 核心)
  14. mean shift segmentation matlab,Mean Shift图像分割算法的并行化
  15. Simulink永磁同步电机控制仿真系列七:使用脉振高频注入法的位置估计
  16. Chap.16 总结《CL: An Introduction》 (Vyvyan Evans)
  17. 关于试用期的四大认知误区,千万别被渣公司坑了!
  18. java 删除本地图片_java如何删除
  19. 基于Linux系统的边界网关协议的设计与实现
  20. c语言中未定义标识符IDD,一、Windows对话框—对话框及其模板

热门文章

  1. 编程语言【JAVA】编程(4)---摇色子
  2. Crazy Mother
  3. android 9 qq登录,天天练qq登录版
  4. 海洋cms常见问题有哪些?
  5. 菊花是哪个城市的市花1_2.html,花中四君子——秋菊知多少?
  6. ReclyclerView刷新数据
  7. 三菱化学控股公司:关于代表执行董事的人事变动通知
  8. 计算机音乐超级马丽,你与你的音乐梦想,只差一台数学计算器
  9. d : 无法将“d”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
  10. appcan注册功能php,appcan是什么