在SSD出现之后,产生了一个问题:由于SSD底层的存储实现上和传统的机械硬盘截然不同,导致两者在数据写入和删除上表现出了极大的差异,传
统机械硬盘删除数据时仅仅需要将元数据标记为删除,而真正的数据block实际上并没有立即被删除,当下一次写入数据时,只需要用新的数据覆盖掉旧的数据
即可。而SSD则不一样,新的数据只能往空白区域写入,不能像机械硬盘那样直接覆盖,因此一次覆盖写操作将变成一个
read-erase-modify-write
的循环,操作系统如果还是按照机械硬盘的覆盖写入方式来操作SSD的话,将带来性能上的大打折扣和硬盘使用寿命的缩短。因此对于SSD的操作人们提出了新
的需求——需要在数据删除的时候通知硬盘,将数据立即清理掉,在这种需求下,trim指令[1]诞生了,trim指令允许操作系统在SSD上将不再使用的
数据通知到SSD底层并在其内部将数据擦除掉。
在虚拟化技术的磁盘虚拟化中,也出现了类似问题:由于虚拟磁盘与物理机械硬盘的差异,导致操作系统如果还是按照机械硬
盘的方式来删除虚拟磁盘的数据的话,会出现一些额外的效果。通常我们都希望thin
providing的磁盘设备容量用多少算多少,但是现实往往不尽如人意,当我们往虚拟磁盘中写入100M数据,再将它删除,再写入100M数据,我们希
望看到的结果是,虚拟磁盘占用不超过100M容量大小,但是现实是虚拟磁盘占用了超过100M容量。这是因为当我们在虚拟机内部执行了删除操作时,如果还
是按照机械硬盘的删除方式,那么真正占用了磁盘空间的block部分并没有立即被释放,如果我们在虚拟机内部不断地进行write-delete
循环的话,虚拟磁盘文件将越来越大,大到甚至超过了额定预分配大小。人们开始意识到在这种虚拟化场景下类似于SSD的trim指令所提供的功能也仍然适
用,对于节省存储开销有积极意义。因此,与trim类似的指令也出现在了虚拟磁盘中,用在scsi接口虚拟磁盘上的这个指令叫unmap,通常我们把trim和unmap指令提供的功能称之为discard。
哪些版本支持discard?
内核对discard的支持早在2.6.33中就被包含进来,在RHEL6中我们可以发现在2.6.32版本的内核包就将这个功能backport进来,用户空间的程序开始支持discard要稍微晚一些,qemu在1.5版本开始支持(), libvirt从1.0.6开始支持()。这两个项目的discard功能支持都是由Red Hat提交的,其中libvirt的discard支持是由负责的,他是兰大开源社区的创始人之一。
我们可以看看当前最新的fedora20中的版本情况:
|
[root@localhost ~]$ rpm -q qemu-kvm
qemu-kvm-1.6.2-1.fc20.x86_64
[root@localhost ~]$ rpm -q libvirt-daemon
libvirt-daemon-1.1.3.4-4.fc20.x86_64
|
如何使用discard?
要启用虚拟机的discard功能我们只需要在确保当前系统版本支持的基础上,进行两方面的配置即可,一是在host
machine上通过libvirt修改虚拟机配置添加disk
driver的相关支持,注意下面的配置示例中将使用virtio-scsi作为虚拟磁盘驱动,且添加了额外的' discard="unmap" '
另一方面我们需要在虚拟机system内修改磁盘的挂载参数以增加对discard的支持:
mount -o discard
或者使用fstrim命令来一次性触发discard操作:
fstrim /mntpoint
如何验证discard是否有效?
我们可以通过下面这个简单的对比实验来观察discard的效果,首先为虚拟机分配两块磁盘,sda设置为支持discard而sdb不设置
接着启动虚拟机,将两块磁盘分区格式化文件系统后分别挂载到/sda和/sdb目录,对于两个目录均执行循环写入和删除数据的操作,
#mount -o discard /dev/sda1 /sda
#mount /dev/sdb1 /sdb
#for _ in {1..3}; do
dd if=/dev/urandom of=/sda/file.$RANDOM bs=1M count=100 && sync
dd if=/dev/urandom of=/sdb/file.$RANDOM bs=1M count=100 && sync
rm -f /sda/file.* /sdb/file.* && sync
done
现在回到host machine中,使用du命令来观察两个虚拟磁盘的占用容量大小情况:
$du -h sd{a,b}.img
34M sda.img
138M sdb.img
此时discard的好处显而易见,启用了discard功能的sda消耗的存储容量要比没有启用的sdb小得多。
libvirt/qemu 文件系统trim
目前virtio驱动无法支持trim,ide/scsi/virtio-scsi驱动可以支持trim。
qemu的trim特性:1.5版支持raw,1.6版支持qcow2。
NTFS本身支持trim命令,EXT4需要在mount时指定参数-o discard,EXT3需要手工执行fstrim。
type='file' device='disk'> name='qemu' type='qcow2' cache='none' discard='unmap'/>
virtio-scsi为例:
type='file' device='disk'> type='scsi' index='0' model='virtio-scsi'/>
./qemu-system-x86_64 --enable-kvm -m 2g -smp 2 -drive file=/data/hotplug/hotplug.qcow2,cache=none,if=ide,discard=on,format=qcow2 -drive file=/data/hotplug/vdb.qcow2,cache=none,if=ide,discard=on,format=qcow2 -vnc 186.100.8.138:-1
新格式(以virtio-scsi-pci为例):
./qemu-system-x86_64 --enable-kvm -m 2g -smp 2 -drive file=/data/hotplug/hotplug.qcow2,cache=none,if=none,id=hd2,discard=on,format=qcow2 -drive file=/data/hotplug/vdb.qcow2,cache=none,if=none,id=hd,discard=on,format=qcow2 -device virtio-scsi-pci,id=scsi -device scsi-hd,drive=hd2 -device scsi-hd,drive=hd -vnc 186.100.8.138:-1
-
确认方法
虚拟机内部(文件系统挂载需要-o discard参数):
mount -o discard /dev/sdb /mnt
在guest中/mnt下创建大文件:
[root@localhost hotplug]# du -hs vdb.qcow2
481M vdb.qcow2
在guest中/mnt下删除大文件:
[root@localhost hotplug]# du -hs vdb.qcow2
294M vdb.qcow2
阅读(7356) | 评论(2) | 转发(0) |