在Qemu中虚拟化固态硬盘

Qemu虚拟机中的磁盘通常都是以文件形式存储在宿主机上,如qcow2,理论上虚拟磁盘的类型并不重要。但有时,虚拟机中的程序会主动检测当前使用的磁盘类型,如trim,于是就需要我们明确指定虚拟磁盘是机械硬盘,还是固态硬盘,本文将介绍如何在Qemu中完成配置。

目前主流的固态硬盘有两种,使用PCIe总线的NVMe固态,和使用SATA/SCSI总线的固态,下面将分别针对不同场景对两种模拟固态的配置方法进行介绍。

模拟NVMe固态

在Qemu中,NVMe是一个独立的设备类型,所以只需要将硬盘的设备类型指定为NVMe即可。

1
2
-drive file=/path/to/nvme1.img,if=none,id=NVME1 \
-device nvme,drive=NVME1,serial=nvme-1
1
2
3
4
5
6
<qemu:commandline>
<qemu:arg value='-drive'/>
<qemu:arg value='file=/path/to/nvme1.img,format=raw,if=none,id=NVME1'/>
<qemu:arg value='-device'/>
<qemu:arg value='nvme,drive=NVME1,serial=nvme-1'/>
</qemu:commandline>
1
2
--qemu-commandline='-drive file=/path/to/nvme1.img,format=raw,if=none,id=NVME1'
--qemu-commandline='-device nvme,drive=NVME1,serial=nvme-1'

模拟SATA固态

由于SATA/SCSI总线既可以连接机械硬盘,也可以连接固态硬盘,所以我们需要设置总线上设备的属性rotation speed来进行区分。当设置其为1时,表示该设备为固态硬盘。

要设置SATA/SCSI总线上的设备属性,我们必须要找到其ID,比如sata0-0-0或者scsi0-0-0-0,可以使用以下命令查询。

1
virsh qemu-monitor-command --hmp 1 "info qtree"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
dev: scsi-hd, id "scsi0-0-0-0"
drive = "drive-scsi0-0-0-0"
logical_block_size = 512 (0x200)
physical_block_size = 512 (0x200)
min_io_size = 0 (0x0)
opt_io_size = 0 (0x0)
discard_granularity = 4096 (0x1000)
write-cache = "on"
share-rw = false
rerror = "auto"
werror = "auto"
ver = "2.5+"
serial = ""
vendor = "QEMU"
product = "QEMU HARDDISK"
device_id = "drive-scsi0-0-0-0"
removable = false
dpofua = false
wwn = 0 (0x0)
port_wwn = 0 (0x0)
port_index = 0 (0x0)
max_unmap_size = 1073741824 (0x40000000)
max_io_size = 2147483647 (0x7fffffff)
rotation_rate = 1 (0x1)
scsi_version = 5 (0x5)
cyls = 16383 (0x3fff)
heads = 16 (0x10)
secs = 63 (0x3f)
channel = 0 (0x0)
scsi-id = 0 (0x0)
lun = 0 (0x0)

得到ID之后就可以进行设置了。

1
-set device.scsi0-0-0-0.rotation_rate=1
1
2
3
4
<qemu:commandline>
<qemu:arg value='-set'/>
<qemu:arg value='device.scsi0-0-0-0.rotation_rate=1'/>
</qemu:commandline>
1
--qemu-commandline='-set device.scsi0-0-0-0.rotation_rate=1'

参考

KVM guests with emulated SSD and NVMe drives
QEMU command-line passthrough