fstrim服务及周期TRIM

Linux固态驱动器(SSD) 上,需要激活文件系统 TRIM 来实现降低写入放大、延长SSD设备使用寿命。所谓TRIM,就是一种声明设备上没有使用的块,对于没有需要数据的块可以返回给存储池重新使用。我们有两种方式激活文件系统的TRIM功能:

  • 持久化TRIM: 挂载文件系统的时候,使用 discard 参数,例如

对于 EXT4文件系统 增加挂载参数:

mount -t ext4 -o discard /dev/sda2 /mnt

对于XFS文件系统,在 /etc/fstab 中也可以配置该参数:

UUID=3453g54-6628-2346-8123435f  /home  xfs  defaults,discard   0 0

上述 discard 参数都会激活文件系统的持续TRIM,也就是每次新数据写入磁盘都会激活TRIM。这个方式也引发了是否存在潜在性能影响的争论。

  • 周期性TRIM: 通过定时任务定时触发TRIM

传统上定时任务采用 cron 实现,不过在现代化的 Systemd进程管理器 系统,可以采用和系统更为紧密结合的 Systemd timer服务(替代cron) 来实现,下文就是采用一条简单的 fstrim.timer 服务激活实现周期性TRIM

TRIM服务 fstrim

  • 在终端执行以下命令来确定 fstrim 命令是否可以正常根据 fstab 配置调用:

    sudo /usr/sbin/fstrim --fstab --verbose --quiet
    

此时会看到类似以下输出:

/var/lib/docker: 183.4 GiB (196879622144 bytes) trimmed on /dev/disk/by-uuid/d80f2f08-3b50-4b19-a0eb-058fb47693b0
/boot/efi: 505.8 MiB (530321408 bytes) trimmed on /dev/disk/by-uuid/7E7B-5E3A
/: 6.6 GiB (7021338624 bytes) trimmed on /dev/disk/by-uuid/caa4193b-9222-49fe-a4b3-89f1cb417e6a

这表明当前挂载的文件系统可以正确实现TRIM

  • fstrim--help 提供了简洁说明:

    sudo /usr/sbin/fstrim --help
    

输出显示:

Usage:
 fstrim [options] <mount point>

Discard unused blocks on a mounted filesystem.

Options:
 -a, --all           trim all supported mounted filesystems
 -A, --fstab         trim all supported mounted filesystems from /etc/fstab
 -o, --offset <num>  the offset in bytes to start discarding from
 -l, --length <num>  the number of bytes to discard
 -m, --minimum <num> the minimum extent length to discard
 -v, --verbose       print number of discarded bytes
     --quiet         suppress error messages
 -n, --dry-run       does everything, but trim

 -h, --help          display this help
 -V, --version       display version
  • 如果只想查看一下设置是否正确,模拟TRIM(不实际执行TRIM)可以执行:

    sudo /usr/sbin/fstrim --fstab --verbose --dry-run
    
  • 可以执行TRIM显示每个文件系统的TRIM操作:

    sudo /usr/sbin/fstrim --fstab --verbose
    

激活定时TRIM

对于 Fedora 30 / RHEL 8 / CentOS 8 提供了 Systemd timer服务(替代cron) 服务,周期性执行 fstrim.timer

sudo systemctl status fstrim.timer

在 Ubuntu 20.04.3 LTS 上, fstrim.timer 默认激活,所以显示如下:

● fstrim.timer - Discard unused blocks once a week
     Loaded: loaded (/lib/systemd/system/fstrim.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Wed 2021-10-20 17:52:32 CST; 21h ago
    Trigger: Mon 2021-10-25 00:00:00 CST; 3 days left
   Triggers: ● fstrim.service
       Docs: man:fstrim

Oct 20 17:52:32 zcloud systemd[1]: Started Discard unused blocks once a week.

如果没有激活,可以通过以下命令执行激活:

sudo systemctl enable fstrim.timer

可以通过以下命令检查 Systemd timer服务(替代cron) 配置:

sudo systemctl list-timers --all

显示如下:

NEXT                        LEFT          LAST                        PASSED      UNIT                         ACTIVATES
...
Mon 2021-10-25 00:00:00 CST 3 days left   Mon 2021-10-18 00:00:24 CST 3 days ago  fstrim.timer                 fstrim.service

现在你可以放心使用 Linux固态驱动器(SSD) 设备了。

禁用fstrim的情况

以下情况下需要禁用周期性TRIM:

  • 底层设备是 thin-provisioned (精简分配)

并且

  • 文件系统内部不使用 UNMAP (trim是ata指令,对应scsi指令是unmap)

注解

thin-provisioned (精简分配) 策略是虚拟化根据虚拟环境中的实际使用情况实现存储资源的“过度分配(over-commit)”功能。“存储过度分配”是指分配给虚拟机的存储总量比存储池中所具有的物理存储总量要大。通常情况下,虚拟机不会使用分配给它们的全部存储资源。从用户的角度来看,使用精简分配功能的虚拟机完全具有了所有定义的存储空间;而实际上,只有一部分存储空间被实际分配给虚拟机。 – Red Hat Virtualization 2.11. 精简分配(THIN PROVISIONING)和存储过度分配(OVER-COMMITMENT)

fstrim (或者通常是 TRIM/DISCARD) 在 over-provisioned 过度分配的系统上操作和 thin-provisioned 精简分配系统处理方式是不同的。如果系统在每个LUN(不论是不是精简分配)都分配了足够的空间,则不需要TRIM指令。然而,在SAP HANA是不建议使用 over-provisioned 过度分配系统,而且也强烈建议 使用精简分配设备。

  • 检查文件系统是否支持 UNMAP 的方法是使用 lsblk -D 命令,如果 DISC-MAX 值是 0 就标识设备不支持 discard 功能:

    lsblk -D
    

输出类似:

NAME   DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
sda           0      512B       2G         0
├─sda1        0      512B       2G         0
├─sda2        0      512B       2G         0
└─sda3        0      512B       2G         0
sdb           0        0B       0B         0
└─sdb1        0        0B       0B         0
sdc           0        0B       0B         0
├─sdc1        0        0B       0B         0
└─sdc2        0        0B       0B         0
sdd           0        0B       0B         0
├─sdd1        0        0B       0B         0
└─sdd2        0        0B       0B         0

可以看到 sdb , sdc , sdd 存储设备不支持 UNMAP / TRIM ,实际上是传统的机械硬盘。

  • 使用 fstrim 命令也可以验证:

    sudo mount /dev/sdb1 /mnt
    sudo fstrim -v /mnt
    

可以看到信息:

fstrim: /mnt: the discard operation is not supported

虚拟机

在虚拟机内部, fstrim.service 是没有效果的,除非虚拟块设备宣告它支持 discard 。在 virt-manager 虚拟化管理器中,需要对块设备设置:

Advanced options>Performance options>Discard mode: unmap

默认情况下 virt-managerqemu-kvm 虚拟机会忽略 discard 执行,所以虽然 ftrim.service 显示执行成功,但是内核日志会显示这个执行失败:

[ 122.895923 ] localhost.localdomain kernel: blk_update_request: operation not supported error, dev vda, sector 206856170 op 0x3:(DISCARD) flags 0x0 phys_seg 2 prio class 0

如果对支持的存储设置VM使用 unmap ,此时 fstrim 指令会 pass through 透传给底层块存储;如果底层块存储是 raw 或者 qcow2 则该文件会编程一个稀疏(sparse)文件。

容器

util-linux 2.35 开始,也就是 Fedora 32开始, fstrim.service 包含了以下配置:

ConditionVirtualization=!container

Docker systemd进程管理器 通过Docker环境变量 container=docker 可以知道自己运行在容器内部,也就会停止运行 fstrim.service