Активация 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 игла в яйце, яйцо в утке, утка в зайце
:
Первое что нужно сделать, это проверить, что контроллер 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-раздела
В приведенной выше схеме, чтобы 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
систему следует перезагрузить для применения изменений.
В приведенной схеме выше для раздела диска /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
На этом всё!