Активация discard (TRIM) на Linux для SSD диска

Современные SSD диски нуждаются в команде TRIM интерфейса ATA и для этого в ОС построенных на базе ядра Linux предусмотрено два метода управления на уровне файловых систем:


  • discard — устанавливается как опция монтировании файловой системы. Позволяет ядру Linux сразу отправлять команду TRIM на устройство, как только об этом сообщит файловая система.
  • fstrim — утилита которая запускается вручную или по расписанию как сервис ОС, отправляет список удаленных блоков с ФС для зачистки их на устройстве.

Для включения fstrim достаточно активировать сервис fstrim.service в systemd, но лучше вместо сервиса, который будет висеть в памяти, использовать таймер fstrim.timer который будет запускать еженедельный TRIM.

Пример включения сервиса:

# Включение, старт и вывод статуса сервиса:
systemctl enable fstrim.service && \
systemctl start fstrim.service && \
systemctl status fstrim.service

Но этих мер недостаточно, если у вас файловые системы располагаются на томах LVM, а LVM в LUKS игла в яйце, яйцо в утке, утка в зайце:


gisbqw8ahpkyogun4q-ylkagczs.png

Первое что нужно сделать, это проверить, что контроллер SATA работает в режиме AHCI, а не IDE, иначе TRIM работать не будет:

sudo hdparm -I /dev/sda | grep TRIM
    *    Data Set Management TRIM supported (limit 8 blocks)
    *    Deterministic read ZEROs after TRIM

Ключевое слово здесь это TRIM supported, значит контроллер SATA работает в режиме AHCI и вам не нужно ничего менять в BIOS или UEFI.

Итак, опция discard может устанавливаться:


  • в суперблоке ФС (как опция монтирования по умолчанию)
  • в конфигурации монтирования ФС — /etc/fstab
  • в конфигурации cryptsetup — /etc/crypttab
  • в конфигурации LVM — /etc/lvm/lvm.conf
  • в конфигурации загрузчика — /boot/grub/grub.cfg

Мы рассмотрим все эти варианты. Примеры будут даны для дистрибутива Arch Linux и его производных, но я думаю вас не затруднит адаптировать тему к любому другому дистрибутиву Linux.

Если в /etc/fstab для файловой системы опция discard не указана или в опциях монтирования указана опция defaults, то система будет использовать опции монтирования прописанные в суперблоке файловой системы. Это актуально для файловой системы EXT4. Запись опций монтирования в суперблоке ФС может быть выгодна тем, что если у вас съёмное устройство которое подключается по SATA к разным машинам в которых вы не можете по каким-то причинам вносить изменения в /etc/fstab.

Добавляем опцию монтирования discard по умолчанию в суперблок файловой системы EXT4. У меня это три раздела:

sudo tune2fs -o discard /dev/mapper/vg1-lvroot
sudo tune2fs -o discard /dev/mapper/vg1-lvhome
sudo tune2fs -o discard /dev/mapper/vg1-lvvar

Убедиться в установленной опции можно через tune2fs. Здесь /dev/mapper/vg1-lvroot это устройство, раздел с файловой системой EXT4 в томе LVM:

sudo tune2fs -l /dev/mapper/vg1-lvroot | grep options

Если это единственная система куда разделы SSD диска будут монтироваться, то мы можем прописать опцию discard явно в /etc/fstab для автомонтирования разделов, но устанавливать опцию необязательно для EXT4, если она уже была ранее задана в суперблоке.

Также, опцию discard следует добавить для swap раздела:

# /dev/mapper/vg1-lvroot
UUID=e86ab458-341d-4f59-8344-0271d2c363e8    /            ext4    rw,noatime,discard   0 0
# /dev/mapper/vg1-lvvar
UUID=44b31816-1193-4dc1-9f58-f70df2250e1a    /var         ext4    rw,noatime,discard   0 0
# /dev/mapper/vg1-lvhome
UUID=372bc9ae-b581-49a4-abed-ca9f3b67edb6    /home        ext4    rw,noatime,discard   0 0
# /dev/sda1
UUID=0BE5-60FB                               /boot/efi    vfat    rw,relatime,discard,...,errors=remount-ro   0 0
# /dev/mapper/vg1-lvswap
UUID=cf67ae1e-3a17-4e5e-ac58-ef23725d2359    none         swap    defaults,discard,pri=-2   0 0

В конфигурационном файле /etc/lvm/lvm.conf устанавливаем значение опции issue_discards в значение равное 1:

devices {
  issue_discards = 1
}

Важно отметить, что включение этой опции не пересылает команду TRIM с файловых систем когда на них производятся команды удаления файлов, эта опция посылает команду TRIM только когда производятся манипуляции изменения логического тома, например, через такие команды как lvremove, lvreduce и т.д.


discard для зашифрованного root-раздела


gisbqw8ahpkyogun4q-ylkagczs.png

В приведенной выше схеме, чтобы TRIM включился для разделов диска которые находятся в LUKS, корневой раздел должен быть открыт cryptsetup'ом с аргументом --allow-discards или опция должна быть прописана в /etc/crypttab для нужного раздела, но проблема заключается в том, что мы не можем прописать опцию в /etc/crypttab, так как root-раздел в нашей схеме изначально зашифрован и система не может прочитать его до того как откроет криптоконтейнер.

Решением этой проблемы является указать опцию при открытии криптоконтейнера на раннем этапе загрузки в initramfs, а передать эту опцию в initramfs поможет опция в конфигурации загрузчика grub для ядра Linux.

Добавляем значение allow-discards в конфигурационный файл /etc/default/grub для параметра cryptdevice в параметре для ядра GRUB_CMDLINE_LINUX.

Меняем эту строчку:

GRUB_CMDLINE_LINUX="cryptdevice=UUID=3c121aac-ead9-4d57-88be-c1199acf72f0:cryptlvm"

на эту:

GRUB_CMDLINE_LINUX="cryptdevice=UUID=3c121aac-ead9-4d57-88be-c1199acf72f0:cryptlvm:allow-discards"

Затем необходимо сгенерировать «правильный» конфиг grub’а:

sudo grub-mkconfig -o /boot/grub/grub.cfg

Также проверьте, что у вас образ initramfs скомпилирован с хуком encrypt который позволяет открывать криптоконтейнеры с помощью cryptsetup и он расположен до хука lvm2:

cat /etc/mkinitcpio.conf | grep ^HOOKS

HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt lvm2 resume filesystems)

После внесения изменений в grub систему следует перезагрузить для применения изменений.


qrixsaiqprvbsaeieqtn29n-p_u.png

В приведенной схеме выше для раздела диска /home который не является корневым и находится в контейнере LUKS, можно прописать опцию монтирования discard в конфигурационном файле /etc/crypttab который зачитывается и выполняется системой со смонтированным корневым разделом и до зачитывания и выполнения fstab.

Как прописать опцию в конфигурационном файле вы найдете в мануале: man crypttab

Выполните следующую команду:

lsblk --discard

NAME             DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
sda                     0      512B       2G         0
├─sda1                  0      512B       2G         0
└─sda2                  0      512B       2G         0
  └─cryptlvm            0        0B       0B         0
      ├─vg1-lvroot      0        0B       0B         0
      ├─vg1-lvvar       0        0B       0B         0
      ├─vg1-lvswap      0        0B       0B         0
      └─vg1-lvhome      0        0B       0B         0

Если вы видите нулевые значения в колонках DISC-GRAN (discard granularity) и DISC-MAX (discard max bytes), значит TRIM не работает.

Проверить еще можно командой ручного вызова TRIM:

sudo fstrim -v /

/: 7,4 GiB (7906193408 bytes) trimmed

Если вы видите положительный результат, значит TRIM работает. При полной поддержке TRIM значения должны быть на всех разделах:

lsblk --discard

NAME             DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
sda                     0      512B       2G         0
├─sda1                  0      512B       2G         0
└─sda2                  0      512B       2G         0
  └─cryptlvm            0      512B       2G         0
    ├─vg1-lvroot        0      512B       2G         0
    ├─vg1-lvvar         0      512B       2G         0
    ├─vg1-lvswap        0      512B       2G         0
    └─vg1-lvhome        0      512B       2G         0

Здесь DISC-GRAN равен 512B потому что размер сектора на моём SSD диске равен 512 bytes. Операционная система посылает команду TRIM контроллеру диска с указанием номеров секторов, которые могут быть очищены на диске. Размер вашего сектора можно узнать из следующих команд:

sudo cryptsetup status cryptlvm

/dev/mapper/cryptlvm is active and is in use.
type:    LUKS1
cipher:  aes-xts-plain64
keysize: 512 bits
key location: dm-crypt
device:  /dev/sda2
sector size:  512
offset:  4096 sectors
size:    487806976 sectors
mode:    read/write
sudo hdparm -I /dev/sda | grep -i "sector size"

      Logical  Sector size:                   512 bytes
      Physical Sector size:                   512 bytes
sudo smartctl -a /dev/sda | grep -i "sector size"

Sector Size:      512 bytes logical/physical

На этом всё!

© Habrahabr.ru