为什么 NBD 要嵌套 NBD?qcow2 镜像链解析原理

创建 NBD 镜像时,为什么要把 backing 的所有镜像全部设置为 NBD? 因为镜像链的解析是 qemu driver 负责的,NBD 和本地 file 都只是独立的块设备,没有解析能力。 现象 创建 NBD 镜像时报错: cmd [qemu-img create -f qcow2 -b nbd://10.0.0.10:54195 -F qcow2 /dev/qbd/vol/vol-example.img] on [local] failed: ret[1] out[] err[qemu-img: /dev/qbd/vol/vol-example.img: Could not open backing file: Could not open '/data/image/centos79x64a': No such file or directory Could not open backing image.]. exec_time is [0.093]s 怪不得创建 NBD 镜像的时候,会把 backing 的所有镜像全部设置为 NBD。之前很费解。 有一个误区 以为通过 NBD 找到 nbd://10.0.0.10:54195 head 镜像,那么 NBD 镜像的 backing 镜像,自然通过 NBD head 链接一起使用了。 ...

July 18, 2026 · 2 min · 223 words · 文叨叨

qemu64 CPU 模型为什么有 svm?兼容性模型的指令集设计

qemu64 是 qemu 的默认兼容性 CPU 模型,指令集很基础。但查看它的定义,居然包含 svm 这类虚拟化指令,这背后是 TCG 与 KVM 两种支持场景的差异。 现象 查看 qemu64 CPU 模型定义: cat /usr/share/libvirt/cpu_map/x86_qemu64.xml <cpus> <model name='qemu64'> <decode host='on' guest='on'/> <!-- These are supported only by TCG. KVM supports them only if the host does. So we leave them out: <feature name='abm'/> <feature name='lahf_lm'/> <feature name='popcnt'/> <feature name='sse4a'/> --> <feature name='apic'/> <feature name='clflush'/> <feature name='cmov'/> <feature name='cx16'/> <feature name='cx8'/> <feature name='de'/> <feature name='fpu'/> <feature name='fxsr'/> <feature name='lm'/> <feature name='mca'/> <feature name='mce'/> <feature name='mmx'/> <feature name='msr'/> <feature name='mtrr'/> <feature name='nx'/> <feature name='pae'/> <feature name='pat'/> <feature name='pge'/> <feature name='pni'/> <feature name='pse'/> <feature name='pse36'/> <feature name='sep'/> <feature name='sse'/> <feature name='sse2'/> <feature name='svm'/> <feature name='syscall'/> <feature name='tsc'/> </model> </cpus> 分析 qemu64 是 qemu 为了兼容性提供的默认 CPU 模型,指令集非常基础。 但有意思的是,它居然包含了 svm(AMD 的虚拟化扩展指令)。 ...

July 12, 2026 · 1 min · 158 words · 文叨叨

libvirt CPU feature 的 disable 和 forbid 有什么区别?

libvirt CPU feature 的 policy 有 force、require、optional、disable、forbid 五种。disable 是虚拟 CPU 不支持该特性,forbid 是宿主机支持该特性时创建会失败。 现象 在 libvirt XML 中配置 CPU feature: <cpu> <model>EPYC</model> <feature name="pclmuldq" policy="disable"/> <feature name="aes" policy="disable"/> <feature name="sha-ni" policy="disable"/> <feature name="monitor" policy="disable"/> <feature name="svm" policy="disable"/> <feature name="npt" policy="disable"/> 【物理机支撑 npt 的】 <topology cores="1" sockets="1" threads="1"/> </cpu> 物理 CPU 是有 npt 的,virsh create 的时候就报错,而且这是 disable 也报错。 足以说明,不是 CPU 问题,而是 libvirt 不支持问题: 2025-06-24 12:50:13,539 WARNING -140207347541760- cmd [virsh create /data/vmxml/vm-example.xml] on [local] failed: ret[1] out[] err[error: Failed to create domain from /data/vmxml/vm-example.xml error: unsupported configuration: unknown CPU feature: npt]. exec_time is [0.089]s 排查 在 commandline 中禁用 npt 是可以创建虚拟机的 <qemu:commandline> <qemu:arg value="-cpu"/> <qemu:arg value="EPYC,vendor=AuthenticAMD,model_id=Example CPU 7380 32-core Processor,-x2apic,-hypervisor,-topoext,-npt,-nrip-save,-monitor,-svm"/> </qemu:commandline> 说明什么? ...

January 31, 2026 · 2 min · 267 words · 文叨叨

qemu 为什么只支持一个 IDE controller?

qemu 只支持一个 IDE controller,一个 IDE controller 只支持 4 个设备(hda 到 hdd)。定义两个 IDE controller 或使用 hde 都会报错。 现象 在 libvirt XML 中定义两个 IDE controller: <controller type='ide' index='0'/> <controller type='ide' index='1'/> 直接会报如下错误: error: Failed to create domain from vm-example.xml error: unsupported configuration: Only a single IDE controller is supported for this machine type 排查 默认有一个 IDE controller 默认有一个 IDE controller。 所以不定义 <controller type='ide' index='0'/>,也是有一个 IDE controller 的。 直接定义 IDE disk 的情况 <disk type="network" device="cdrom"> <driver name="qemu" type="raw"></driver> <source protocol="http" name="/yy/img-example.iso"> <host name="qa1b01" port="8021"></host> </source> <target dev="hdd" bus="ide"></target> 【注意 hdd】 <readonly></readonly> <shareable></shareable> </disk> 直接定义了 IDE 的 disk,没有定义 IDE 的 controller。 ...

January 24, 2026 · 1 min · 174 words · 文叨叨

qemu-img commit 的链为什么必须完整?-d 参数又是什么

qemu-img commit 的链必须是完整的,虽然 commit 的是 head,看起来和底层几级镜像没关系,但实际还是需要。commit 链的关系还可以是临时的,-d 参数决定 commit 后是否清空文件。 现象 qemu-img commit 的链,必须是完整的。 虽然你 commit 的是 head,看起来和底层几级的镜像没有关系,但实际还是需要的: root@host:~/tmp# qemu-img commit -f qcow2 /root/tmp/vm-example_tmp.img qemu-img: Could not open '/root/tmp/vm-example_tmp.img': Could not open backing file: Could not open backing file: Could not open '/root/tmp/focal1x64a': No such file or directory 排查 commit 链的关系还可以是临时的 下面命令不会改变 /dev/vg2/vm-example_lss-sjjgi703 的 backing file,但是确可以提交数据到其他链上,非常方便: qemu-img commit --image-opts file.filename=/dev/vg2/vm-example_lss-sjjgi703,backing.file.filename=/root/tmp/vm-example.img 底层链有 nbd 镜像也会失败 如果底层的链中有 nbd 镜像,那么即便 commit 没到 nbd img,也会失败: 2024-12-09 18:08:26,809 INFO -139636383823616- commit_snap command is [qemu-img commit -f qcow2 -d /data/container/vm-example/vm-example.resize_tmp.img] ret is [(1, '', u"qemu-img: Block format 'nbd' used by node '#block817' does not support reopening files")] 如果底层的链中有 nbd 镜像,那么即便 commit 没到 nbd img,也会失败。 ...

January 18, 2026 · 2 min · 224 words · 文叨叨

sanlock 的 wdmd 为什么在多 vg 场景下要禁用?

sanlock 的 wdmd 看门狗在多 vg 场景下不适合启用:只要一个锁空间续约失败,wdmd 就不喂狗,导致宿主机被强制重启。上层的事应该上层做,双写并发控制应该用业务全局锁,而不是依赖底层存储机制。 现象 sanlock 这里,还是应该把 wdmd 给禁用了。尤其是在多 vg 场景下,不太适合。 根因 wdmd 是什么 wdmd 是 Watchdog Multiplexing Daemon(看门狗多路复用守护进程)。 为什么多 vg 场景下不适合 一个锁空间,sanlock 会和 wdmd 建立一个连接。一个 vg 一个锁空间。 只要有一个锁空间续约失败,wdmd 就不会喂狗。 所以,如果一个 vg 断联了,其他 vg 正常,客户其实不希望关闭宿主机。 哪些情况会触发 reset 存储 IO 压力大,也会导致 sanlock 续约失败,但是上面的虚拟机是正常的; 如果 wdmd 自身异常了,也会触发 watchdog reset; 如果 sanlock 服务异常了,也会触发 watchdog reset; 有些慢存储,sanlock 容易锁过期、失效,也会触发 reset。 这些都不是用户想看到的。 设计思考 sanlock 是个底层存储锁,但是上层应用有自己的场景和控制逻辑。 底层做,只能一刀切: 要么很严格,动不动就关宿主机了; 要么很宽松,那可能还是会造成双写数据不安全。 上层的事上层做。 双写,终究是因为有两个虚拟机。 所以,要在创建虚拟机那里使用业务的全局锁,来做并发控制,而不是依赖底层存储机制。 小结 wdmd 看门狗在多 vg 场景下不适合启用; 只要一个锁空间续约失败,wdmd 就不喂狗,导致宿主机被强制重启; 存储 IO 压力大、wdmd 异常、sanlock 异常、慢存储锁过期,都可能触发 reset; 底层锁只能一刀切,双写并发控制应该用业务全局锁,上层的事上层做。

January 10, 2026 · 1 min · 82 words · 文叨叨

ARM 架构下 CPU 模型设置为什么失效?只有 passthrough

在 ARM(aarch64)架构下,libvirt/QEMU 的 CPU 模型与特性禁用设置不生效,虚拟机看到的 CPU 依然是透传的物理 CPU。所以 ARM 架构下,别探索什么指令集、热迁移了,全部用 passthrough。 现象 将虚拟机 CPU 设置为 custom 模式,指定 Kunpeng-920 指令集,并通过 <feature policy="disable"> 禁用 asimddp、asimdfhm 两个 CPU 特性。 对比宿主机与虚拟机内的 lscpu / /proc/cpuinfo 输出,发现设置未生效。 尽管 QEMU 进程命令行已携带 -cpu Kunpeng-920,asimddp=off,asimdfhm=off,虚拟机内部看到的 CPU 依然是透传的物理 CPU(特性、implementer、part 号与宿主机完全一致)。 排查 测试环境 项目 值 宿主机架构 aarch64 (ARM64) 宿主机 CPU HUAWEI Kunpeng 920 3210 (HiSilicon) 虚拟机架构 aarch64, machine virt-4.1 QEMU qemu-system-aarch64 (4.1.0.2) 虚拟化 KVM (accel=kvm) 虚拟机内存/CPU 1024 MiB / 1 vCPU 虚拟机 XML 的 CPU 部分 <cpu mode="custom" match="exact"> <model>Kunpeng-920</model> <feature policy="disable" name="asimddp"/> <feature policy="disable" name="asimdfhm"/> <topology sockets="1" cores="1" threads="1"></topology> <numa> <cell id="0" cpus="0" memory="1048576" unit="KiB" discard="yes"></cell> </numa> </cpu> QEMU 进程的 -cpu 参数 虚拟机启动后,QEMU 进程实际命令行中的 CPU 相关参数: ...

January 4, 2026 · 2 min · 414 words · 文叨叨