第九篇讨论了 virtio 迁移状态。本篇作为系列收束回到实践当 virtio 设备不工作、I/O 卡住、性能异常或迁移后出问题时如何从 guest、QEMU、vhost 和 backend 多层联合观察1. 调试 virtio 不能只看一层virtio 路径跨越多层Guest driver | v virtqueue in guest RAM | v QEMU virtio device model | v QEMU backend / vhost backend | v host storage or network如果只看 guest可能只看到 I/O hang。如果只看 QEMU可能看不到 guest driver 为什么没有提交 buffer。如果只看 backend可能不知道 virtqueue 是否已经通知过来。所以 virtio 调试需要把几类信息串起来guest 是否发现设备feature negotiation 是否成功virtqueue 是否配置完成guest 是否提交 descriptorQEMU 或 vhost 是否收到 kickbackend 是否完成请求used ring 是否写回interrupt 是否到达 guest2. 先确认 guest 是否看到设备第一步是确认 guest driver 是否绑定成功。在 guest 中可以看dmesg|grep-ivirtiols/sys/bus/virtio/devices/cat/proc/interrupts对于块设备lsblkdmesg|grep-ivirtio_blk对于网络设备iplinkdmesg|grep-ivirtio_netethtool-ieth0如果 guest 根本没有看到设备问题通常在 transport 或平台描述层virtio-mmio DTB 节点缺失或地址错误virtio-pci 没有被枚举QEMU 命令行没有创建设备guest kernel 没有对应 driver中断控制器或 bus 配置错误3. 确认 transport 是否正确virtio-mmio 场景下重点看 Device Tree。可以 dump DTBqemu-system-riscv64\-machinevirt,dumpdtbvirt.dtb\...然后反编译dtc-Idtb-Odts virt.dtbvirt.dts检查 virtio-mmio 节点compatible 是否正确reg 地址是否正确interrupt 是否正确节点数量是否符合 QEMU 配置virtio-pci 场景下重点看 guest PCI 枚举lspci lspci-vv如果设备发现阶段就失败不要急着看 virtqueue。先把 transport 问题排除。4. 使用 QEMU traceQEMU trace 是观察 virtio 路径的重要工具。QEMU 源码中有trace-events文件很多 virtio、vhost、block、net 路径都有 trace point。运行时可以使用-trace打开部分事件。示意qemu-system-...\-tracevirtio_*\...不同 QEMU 版本支持的 trace event 名称不同需要结合源码里的trace-events查看。建议按主题开 tracevirtio common: 观察 queue、status、notify virtio-blk: 观察 block request virtio-net: 观察 TX/RX packet vhost: 观察 backend setup 和 vring migration: 观察设备状态保存和恢复trace 的价值是把“是否走到某个代码路径”变成可观测事实。5. 观察 KVM ioctl 和 eventfd有些问题和通知路径有关。可以用strace观察 QEMU 的 ioctl、eventfd、poll/epoll 行为。示意strace-f-eioctl,eventfd2,epoll_wait,poll qemu-system-...需要注意QEMU 输出会很多。更实用的方式是结合具体问题过滤。例如想判断是否启用了 KVM irqfd/ioeventfd、vhost ioctl可以观察相关 ioctl 是否出现。这对理解“请求有没有回到 QEMU 主循环”或“是否已经交给 vhost”很有帮助。6. 区分 QEMU 路径和 vhost 路径性能排查时先确认数据面到底在哪里。基础 QEMU 路径Guest virtqueue | v QEMU device model | v backendvhost 路径Guest virtqueue | v vhost backend | v backend QEMU remains control plane可以从几个方向判断QEMU 命令行是否启用 vhostQEMU trace 是否显示 vhost setupstrace 是否看到 vhost ioctlhost 上是否有 vhost kernel threadbackend 是否是 vhost-user socketQEMU CPU usage 是否随吞吐明显升高如果预期走 vhost但实际仍由 QEMU 处理吞吐和 CPU 使用都会不同。7. virtio-blk 卡住如何看virtio-blk I/O hang 可以按路径排查Guest block layer 是否提交请求 | v virtio-blk driver 是否 kick queue | v QEMU 是否收到 queue notify | v QEMU 是否解析 descriptor | v QEMU block backend 是否完成 | v used ring 是否写回 | v guest 是否收到 interruptGuest 侧可以看dmesglsblk iostatcat/proc/interruptsQEMU 侧可以看virtio-blk traceblock layer traceQEMU monitor 中 block device 状态backend 文件或存储服务状态常见问题包括backend 卡住image 文件权限问题descriptor 格式异常interrupt 没送到 guestqueue index 不一致migration 后 pending request 状态错误8. virtio-net 性能低如何看virtio-net 性能问题要同时看 guest 和 host。Guest 侧ip-slinkethtool-Seth0cat/proc/interrupts mpstat sar-nDEVHost 侧top-H-p$(pidof qemu-system-...)perftopip-slinkethtool-StapX需要确认是否启用 vhost-net是否启用 multiqueueguest vCPU 是否足够interrupt 是否集中在一个 CPUtap 或 bridge 是否成为瓶颈host CPU 是否过载packet size 和 offload 配置是否合理QEMU main loop 是否过忙网络性能不是单个 virtio 参数决定的它受到 guest driver、vhost、host 网络栈、CPU 调度和中断分布共同影响。9. vhost-user 问题如何看vhost-user 多了一个 backend process。排查时要看三方Guest QEMU vhost-user backend重点检查QEMU 是否成功连接 Unix socketbackend 是否收到 memory tablevring 是否设置完成kick/call fd 是否传递成功feature negotiation 是否一致backend 是否能访问 guest memorybackend 是否支持迁移所需 protocol feature常见问题socket path 错误 backend 未启动 feature 不匹配 hugepage/memory backend 配置错误 NUMA placement 不合理 backend crash migration state 不支持vhost-user 调试不能只看 QEMU 日志backend 日志同样关键。10. 迁移后 virtio 异常如何看迁移后 virtio 异常通常和状态不一致有关。排查方向source 和 target QEMU 版本 / machine type 是否兼容 feature bits 是否一致 queue state 是否恢复 pending interrupt 是否丢失 in-flight request 是否处理 vhost backend 是否正确暂停和恢复 target backend 是否配置一致症状可能包括磁盘 I/O 卡住网络断流guest driver reset devicevirtqueue errormigration downtime 异常变长target resume 后设备不可用调试迁移问题时建议同时打开QEMU migration tracevirtio tracevhost traceguest dmesgbackend log11. 看源码时如何定位路径源码定位可以按事件驱动设备发现失败: 看 transport 和 machine model queue 配置失败: 看 VirtIODevice / VirtQueue setup 请求不处理: 看 notify 和 queue handler 请求不完成: 看 backend completion 和 used ring guest 收不到完成: 看 interrupt / irqfd / eventfd 性能低: 看 vhost、batching、multiqueue、backend 迁移失败: 看 migration state 和 backend coordination这样比从文件头硬读到底更有效。virtio 是事件驱动系统调试也应该围绕事件流。12. 常用观察清单可以把排查清单压缩成Guest: dmesg /sys/bus/virtio/devices /proc/interrupts lsblk / ip link / ethtool QEMU: command line trace events monitor strace ioctl/eventfd QEMU logs Host: top -H perf tap / bridge / block backend stats vhost threads Backend: vhost-user logs storage/network service logs migration support state先判断设备是否存在再判断 queue 是否工作最后判断性能和迁移。13. 系列回顾这一组文章从hw/virtio/总览开始依次走过VirtIODevice与设备生命周期virtqueue、descriptor、avail ring、used ringnotification、eventfd、irqfdvirtio-mmio 与 virtio-pci transportvirtio-blk 请求路径virtio-net 与 vhost-netvhost-uservirtio 迁移状态trace 和故障定位这条线覆盖了 virtio 从协议骨架到生产排障的主要路径。14. 本篇小结调试 virtio 的关键是把路径拆开。先确认 guest 是否发现设备再确认 transport 和 queue setup然后看 descriptor 是否提交、backend 是否处理、used ring 是否写回、中断是否到达 guest。如果启用了 vhost 或 vhost-user还要确认数据面是否真的下沉以及 backend 是否正确接管 memory、vring 和 eventfd。可以把本篇压缩成一句话virtio 故障定位不是在 guest 或 QEMU 单点找答案而是沿着 guest driver、virtqueue、QEMU/vhost、backend、interrupt 和 migration state 这条链路逐段验证。15. 后续深入方向这个系列只是第一阶段。后续可以继续深入packed virtqueuevirtio-net offloadvhost-user protocol 细节virtio-fsvDPAlive migration inflight descriptorvirtio-iommuconfidential VM 下的 virtioQEMU block layer 与 virtio-blk 深度联动DPDK/vhost-user 性能调优如果把整个系列压缩成一句话virtio 的本质是一套围绕共享队列建立的虚拟 I/O 协议QEMU 负责设备语义和控制面vhost 负责快路径而可观测性和迁移能力决定它能否在真实系统里稳定运行。