本文 首发于 🌱 煎茶转载 请注明 来源

接上文,通过跟踪 libvirt 的源码,找到 virsh domblkinfo 最终是使用 QMP 协议从 QEMU 获取到关键字为 query-block 的数据,其中带有 wr_highest_offset 字段,该字段被 libvirt 认定为 磁盘利用率中 Allocation 值的来源。

今天就尝试在 QEMU 中找到获取 wr_highest_offset 字段的方法。

环境准备

  • QEMU 4.0
  • Centos
  • 鲲鹏 ARM

首先需要编译 QEMU 加入函数表,重新编译 QEMU在其中加入该字段即可,编译方法可以参考源码目录:

./configure --enable-debug

跟踪前需要定位到 QEMU 中填充该字段的函数,首先在源码中全局搜索 wr_highest_offset ,最终确定 block/qapi.c 文件中的 bdrv_query_bds_stats 函数最有可能是填充该字段的位置,下面就来跟踪这个函数的走向吧。

跟踪记录

一个虚拟机在宿主机中表现为一个 QEMU 的进程,在这里仅保留一个虚拟机,查询该虚拟机状态时 libvirt 回使用 unix socket 的方式发往该进程监听的 unix socket 服务。因此跟踪该虚拟机所在进程即可。

# ps -aux | grep qemu
qemu     2185346  0.6  0.5 3562240 333440 ?      Sl   10:05   2:20 /usr/bin/qemu-system-aarch64 -name guest=instance-000001bb,...imestamp=on
root     2472547  0.0  0.0 110784  2496 pts/3    S+   16:03   0:00 grep --color=auto qemu

GDB 开始跟踪:

gdb qemu-system-aarch64 2185346

在之前找到的目标函数处打上断点:

(gdb) b bdrv_query_bds_stats

之后 c 继续执行,尝试查询一下磁盘状态。

$ virsh domblkinfo 25 vda --human

Breakpoint 1, bdrv_query_bds_stats (bs=0x3b549940, blk_level=true) at /root/stl/qemu-4.0.0/block/qapi.c:509
509         BlockStats *s = NULL;

会发现终端卡住了,此时 gdb 中断了进程,说明我们找对函数了,下面我们继续追踪吧。

发现这个函数是在 qmp_query_blockstats 中被调用多次,最终得出结果。

544     }
(gdb) n
qmp_query_blockstats (has_query_nodes=false, query_nodes=false, errp=0xffffe3963110) at /root/stl/qemu-4.0.0/block/qapi.c:609
609                 s->has_device = true;
(gdb) p s->stats->wr_highest_offset 
$3 = 3072

下面主要就是跟着源码来看了,本文主要是讲了如何使用 GDB 跟踪 QEMU 源码,若有疑问欢迎留言。

参考文献