Qemu TRIM 并丢弃在物理 SSD 设备上

noh*_*per 6 linux virtual-machines ssd qemu kvm-virtualization

我在 Qemu/KVM 中运行 Windows 7,通过 GPU 用于与工作相关的东西。我最近厌倦了它前所未有的缓慢,因为它运行在机械驱动器上,所以我在我的盒子里添加了一个 SSD 来“给”我的 Windows-KVM。我正在为“通过”磁盘使用以下 qemu 命令行选项: -drive file=/dev/disk/by-id/wwn-0x5002538d4002d61f,if=none,id=drive-scsi0-0-0-0,format=raw,discard=on" \ -device virtio-scsi-pci,id=scsi0" \ -device scsi-hd,bus=scsi0.0,drive=drive-scsi0-0-0-0"

我希望来宾 OS TRIM 命令实际上会传递到主机上的物理驱动器,但事实并非如此。

"discard=on" 是否只影响由图像文件支持的驱动器,而不影响实际物理 SSD 的驱动器?如果是这样,我如何能够完成对来宾操作系统上的设备的 TRIM 命令以传递给主机上的物理设备?在主机上使用图像文件是唯一的解决方案吗?我希望有更好的东西,因为在那个磁盘上有一个文件系统只会产生开销,我不需要它来做其他任何事情。

小智 10

研究

Qemu 的处理方式discard=unmapdiscard=on您在其源代码中看到的相同:

block.c (L 1102): if (!strcmp(mode, "on") || !strcmp(mode, "unmap"))

它似乎还支持多个 Linux ioctl,如此处所述 用于在块级别写入或丢弃零:

block/file-posix.c (L 744): if (ioctl(s->fd, BLKDISCARDZEROES, &arg) == 0 && arg)

block/file-posix.c (L L1621): if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0)

block/file-posix.c (L 1788): if (ioctl(aiocb->aio_fildes, BLKDISCARD, range) == 0)

因此,基于此,使用 options 使用 SCSI 仿真阻止直通discard=unmap,detect-zeroes=unmap,除非您使用的是旧的 Qemu 机器类型或有问题的 Qemu 版本,否则两者都应该有效。

例子

在这里找到了一个很棒的演示文稿。

从演讲中吸取的教训:

  1. 您必须以 root 或具有 CAP_SYS_RAWIO 权限的用户身份运行 Qemu/KVM 才能让 Linux 不会忽略丢弃。
  2. 如果你的透传设备确实是SCSI盘,那么要注意真正的SCSI UNMAP和WRITE SAME命令,可以使用scsi-block透传。
  3. 如果没有,则必须使用 scsi-hd 模拟 SCSI 磁盘,它将通过 Qemu 将丢弃命令发送到 Linux 块层

对我来说,虽然使用 scsi-block 传递允许访问真实设备的统计信息和 SMART 信息,并且常规 IO 工作正常,但不支持丢弃命令。

由于我的后备设备确实是 SATA,所以是 IDE,而不是 SCSI LUN,我猜这就是不支持这种方式的原因。

从 scsi-block 切换到 scsi-hd,您将丢失统计数据和 SMART 信息,但会获得丢弃...所以需要权衡。

就我个人而言,我没有遇到任何明显的性能下降,从“真正的直通”到“模拟直通”以满足我的需求。

以下是具有模拟 SCSI 和后备块设备的 Virtio SCSI 示例:

    -device virtio-scsi-pci,id=scsi \
    -blockdev driver=raw,node-name=disk.0,cache.direct=on,discard=unmap,file.driver=host_device,file.aio=native,file.filename=/dev/disk/by-id/ata-Samsung_SSD_840_PRO_Series_S12PNEAD233247L \
    -device scsi-hd,drive=disk.0,bus=scsi.0
Run Code Online (Sandbox Code Playgroud)

您在 Qemu 文档中找不到的file.driver=host_device部分是 .. 它是 scsi-block 工作所必需的,而且似乎也不会伤害 scsi-hd,当我们使用真正的块设备而不是主机上的文件时文件系统。

测试

我用来测试 Linux 块级函数调用的 blktrace 工具记录在此处

您可以同时运行 blktrace 和 blkparse 程序来拦截丢弃调用:

blktrace -a discard -d /dev/disk/by-id/ata-Samsung_SSD_840_PRO_Series_S12PNEAD233247L -o - | blkparse -i -

现在,当您运行defrag /L c:fstrim -v /在您的 VM 中时,您会看到主机上打印了很多丢弃的内容……来自输出的示例片段:

    8,0    1      493     0.641661863  3118  Q  DS 45458024 + 728 [qemu-system-x86]
    8,0    1      494     0.641664662  3118  G  DS 45458024 + 728 [qemu-system-x86]
    8,0    1      495     0.641665920  3118  I  DS 45458024 + 728 [qemu-system-x86]
    8,0    1      496     0.641669312  3118  D  DS 45458024 + 728 [qemu-system-x86]
Run Code Online (Sandbox Code Playgroud)

所以这对我来说足以证明丢弃是有效的。


Mic*_*ton 0

discard=unmap所有的 qemu 命令行都有。这就是我在互联网上找到的所有内容都说可以使用的。这也是 libvirt 配置的。

我使用 ZFS zvols 作为后备存储。因此,我可以很容易地看到运行时使用的空间减少,例如 Windows 中的“优化”驱动器。