Включение TRIM на (внешнем) SSD: различия между версиями

Материал из ALT Linux Wiki
м (→‎Ссылки: +mdraid trim)
 
(не показаны 34 промежуточные версии 3 участников)
Строка 1: Строка 1:
[[Категория:Hardware]]
[[Категория:HOWTO]]
{{w|Trim_(команда_для_накопителей)}}
== Введение ==
== Введение ==
Статья является адаптацией к реалиям  ALT Linux статьи [https://www.jeffgeerling.com/blog/2020/enabling-trim-on-external-ssd-on-raspberry-pi Включение TRIM на внешнем SSD на Raspberry Pi (eng) ]
Статья является адаптацией к реалиям  ALT Linux статьи [https://www.jeffgeerling.com/blog/2020/enabling-trim-on-external-ssd-on-raspberry-pi Включение TRIM на внешнем SSD на Raspberry Pi (eng) ].


Теория взята из [http://blog.neutrino.es/2013/howto-properly-activate-trim-for-your-ssd-on-linux-fstrim-lvm-and-dmcrypt/ Как правильно активировать TRIM для вашего SSD в Linux  (eng)]
Теория взята из [http://blog.neutrino.es/2013/howto-properly-activate-trim-for-your-ssd-on-linux-fstrim-lvm-and-dmcrypt/ Как правильно активировать TRIM для вашего SSD в Linux  (eng)].


В отличие от жестких дисков (HDD), флэш-память NAND, которая лежит в основе SSD дисков, не может перезаписывать существующие данные. Это означает, что вы должны сначала удалить старые данные, прежде чем записывать новые. Флэш-память разделена на блоки, которые далее делятся на страницы. Минимальная единица записи — это страница, а наименьшая единица стирания — блок.
В отличие от жестких дисков (HDD), флэш-память NAND, которая лежит в основе SSD дисков, не может перезаписывать существующие данные. Это означает, что вы должны сначала удалить старые данные, прежде чем записывать новые. Флэш-память разделена на блоки, которые далее делятся на страницы. Минимальная единица записи — это страница, а наименьшая единица стирания — блок.


Данные можно записывать прямо на пустую страницу, но стирать можно только целые блоки. Поэтому, для того, чтобы освободить пространство, занятое удалёнными данными, все имеющиеся данные из одного блока должны быть сначала скопированы и записаны на пустые страницы нового блока. Только после этого  данные в исходном блоке могут быть окончательно стерты, что делает блок готовым для записи новых данных.
Данные можно записывать прямо на пустую страницу, но стирать можно только целые блоки. Поэтому, для того, чтобы освободить пространство, занятое удалёнными данными, все имеющиеся данные из одного блока должны быть сначала скопированы и записаны на пустые страницы нового блока. Только после этого  данные в исходном блоке могут быть окончательно стерты, что делает блок готовым для записи новых данных.


Проблема в том, что со временем возникнет "куча" не полностью занятых страниц и быстродействие диска сильно упадёт. Это связано с тем, что при удалении файла операционная система просто помечает данные блоки как свободные, но не сообщает об этом контроллеру диска. И вне зависимости от оставшегося места, контроллер диска не сможет найти куда записать новые данные. Для решения этой проблемы и используется TRIM
Проблема в том, что со временем возникнет "куча" не полностью занятых страниц и быстродействие диска сильно упадёт. Это связано с тем, что при удалении файла операционная система просто помечает данные блоки как свободные, но не сообщает об этом контроллеру диска. И вне зависимости от оставшегося места, контроллер диска не сможет найти куда записать новые данные. Для решения этой проблемы и используется TRIM.


=== Что такое ТРИМ? ===
=== Что такое ТРИМ? ===
Строка 17: Строка 20:
|+  Поддержка ТРИМ файловыми системами  [https://wiki.archlinux.org/title/Solid_state_drive_(Русский)#Использование Источник]
|+  Поддержка ТРИМ файловыми системами  [https://wiki.archlinux.org/title/Solid_state_drive_(Русский)#Использование Источник]
|-
|-
! Файллвая система !! Опция discard !! Поддержка fstrim !!  Замечания
! Файловая система !! Опция discard !! Поддержка fstrim !!  Замечания
|-
|-
| ext4 || Yes || Yes || "discard, nodiscard(*)" [https://docs.kernel.org/admin-guide/ext4.html?highlight=discard,%20nodiscard(*)#options]
| ext4 || Yes || Yes || "discard, nodiscard(*)" [https://docs.kernel.org/admin-guide/ext4.html?highlight=discard,%20nodiscard(*)#options]
Строка 41: Строка 44:




{{Note|Пользователи должны быть уверены, что их SSD поддерживает TRIM, прежде чем пытаться использовать его. В противном случае возможна потеря данных}}
{{Note|Пользователи должны быть уверены, что их SSD поддерживает TRIM, прежде чем пытаться использовать его. В противном случае возможна потеря данных.}}


Классический способ включения TRIM в Linux , это прописать в /etc/fstab опцию discard, например так (если корень находится на SSD диске):
Классический способ включения TRIM в Linux , это прописать в {{path|/etc/fstab}} опцию discard, например так (если корень находится на SSD диске):


<source lang=txt>
<syntaxhighlight lang="ini">
UUID="6ff0461b-4796-4s0f-a8c0-1fs5f884a593    /  ext4    discard,noatime 1  1
UUID="6ff0461b-4796-4s0f-a8c0-1fs5f884a593    /  ext4    discard,noatime 1  1
</source>
</syntaxhighlight>


{{Note| Определение опции монтирования discard в /etc/fstab не работает с разделом XFS на /. Опция должна быть установлена с помощью параметра ядра rootflags}}
{{Note|Определение опции монтирования discard в {{path|/etc/fstab}} не работает с разделом XFS на {{path|/}}. Опция должна быть установлена с помощью параметра ядра rootflags:
'''rootflags=discard'''
<syntaxhighlight lang="ini">rootflags=discard</syntaxhighlight> }}


В файловой системе ext4 флаг discard также может быть установлен как опция монтирования по умолчанию с помощью tune2fs (например):
В файловой системе ext4 флаг discard также может быть установлен как опция монтирования по умолчанию для "внутренних дисков" с помощью {{cmd|tune2fs}}, например<ref> Мне не удалось так включить TRIM на внешнем диске</ref>:
<syntaxhighlight lang="bash">
# tune2fs -o discard /dev/sda1
</syntaxhighlight>


# tune2fs -o discard /dev/sda1
== Очистка ТРИМ ==
Использование опций монтирования по умолчанию вместо записи в {{path|/etc/fstab}} особенно полезно для внешних дисков, поскольку такой раздел будет монтироваться с опциями по умолчанию и на других машинах. Таким образом, нет необходимости редактировать {{path|/etc/fstab}} на каждой машине.


Использование опций монтирования по умолчанию вместо записи в /etc/fstab особенно полезно для внешних дисков, поскольку такой раздел будет монтироваться с опциями по умолчанию и на других машинах. Таким образом, нет необходимости редактировать /etc/fstab на каждой машине.
Пакет {{pkg|util-linux}} предоставляет fstrim.service и fstrim.timer файлы модулей systemd. Enabling таймера активирует службу еженедельно. Служба выполняет fstrim(8) на всех смонтированных файловых системах на устройствах, поддерживающих операцию discard.


Пакет util-linux предоставляет fstrim.service и fstrim.timer файлы модулей systemd. Enabling таймера активирует службу еженедельно. Служба выполняет fstrim(8) на всех смонтированных файловых системах на устройствах, поддерживающих операцию discard.
Таймер полагается на метку времени {{path|/var/lib/systemd/timers/stamp-fstrim.timer}} (которую он создаст при первом вызове), чтобы узнать, прошла ли неделя с момента его последнего запуска. Поэтому нет необходимости беспокоиться о слишком частых вызовах, в стиле anacron.


Таймер полагается на метку времени /var/lib/systemd/timers/stamp-fstrim.timer (который он создаст при первом вызове), чтобы узнать, прошла ли неделя с момента его последнего запуска. Поэтому нет необходимости беспокоиться о слишком частых вызовах, в стиле anacron.
Чтобы запросить активность и состояние блоков, смотрите journalctl. Чтобы изменить периодичность таймера или выполнените команду {{cmd|systemctl edit fstrim.timer}} или создайте файл {{path|/etc/systemd/system/timers.target.wants/fstrim.timer}} с заданной периодичностью (по умолчанию раз в неделю). fstrim.timer запускает {{cmd|fstrim}}, беря пути для разделов из {{path|/etc/fstab}}.  


Чтобы запросить активность и состояние блоков, смотрите journalctl. Чтобы изменить периодичность таймера или выполнения команд, systemctrl edit fstrim.timer или создайте файл /etc/systemd/system/timers.target.wants/fstrim.timer с заданной периодичностью (по-умолчанию раз в неделю). fstrim.timer запускает fstrim, беря пути для разделов из /etc/fstab.  
Альтернативный способ периодичной проверки, это установить пакет {{pkg|auto-fstrim}} и запустить anacron. Особенностью auto-fstrim  является то, что он проверяет все смонтированные разделы, не обращая внимание есть ли они в {{path|/etc/fstab}} или нет, и запуск {{cmd|fstrim}} проходит ежедневно.


Альтернативный способ периодичной проверки, это установить пакет auto-fstrim и запустить anacron. Особенностью auto-fstrim  является то, что он проверяет все смонтированные разделы, не обращая внимание есть-ли они в /etc/fstab или нет, и запуск fstrim проходит ежедневно.
{{Note|Нет необходимости включать непрерывный TRIM, если вы периодически запускаете {{cmd|fstrim}}. Если вы хотите использовать TRIM, используйте либо периодический TRIM, либо непрерывный TRIM.}}


{{Note|Нет необходимости включать непрерывный TRIM, если вы периодически запускаете fstrim. Если вы хотите использовать TRIM, используйте либо периодический TRIM, либо непрерывный TRIM.}}
Непрерывный TRIM ведёт к некоторому замедлению файловых операций, так как после каждой из них выполняются операции по по очистке неиспользуемых блоков. Поэтому в большинстве дистрибутивах Linux советуют настроить периодический запуск {{cmd|fstrim}}.


Непрерывный TRIM ведёт к некоторому замедлению файловых операций, так как после каждой из них выполняются операции по по очистке неиспользуемых блоков. Поэтому в большинстве дистрибутивах Linux советуют настроить периодический запуск fstrim.
Можно также самому очищать TRIM вручную с помощью команды {{cmd|fstrim}} время от времени, или после больших операций с диском.


=== Поддерживает ли мой SSD TRIM ===
Конкретный раздел:
Для проверки, поддерживает-ли ваш SSD диск TRIM, надо выполнить команду:
<syntaxhighlight lang="bash">
fstrim -v /mnt/disk
</syntaxhighlight>
 
Все смонтированные разделы:
<syntaxhighlight lang="bash">
fstrim -av
</syntaxhighlight>
 
== Поддерживает ли мой SSD TRIM ==
Для проверки, поддерживает ли ваш SSD диск TRIM, надо выполнить команду:


  # fstrim  -v путь_до_точки_монтирования_раздела
  # fstrim  -v путь_до_точки_монтирования_раздела


Например, если у вас раздел c SSD диска смонтирован в /mnt/arhiv. То вы при поддерживаемом TRIM вы увидите  
Например, если у вас раздел c SSD диска смонтирован в {{path|/mnt/arhiv}}, то при поддерживаемом TRIM вы увидите:
<source lang=bash>
 
fstrim -v /mnt/arhiv/
<syntaxhighlight lang="bash">
/media/arhiv/: 0 B (0 bytes) trimmed
# fstrim -v /mnt/arhiv/
</source>
/mnt/arhiv/: 0 B (0 bytes) trimmed
</syntaxhighlight>


Если диск не поддерживает TRIM, то вы увидите что-то подобное:
Если диск не поддерживает TRIM, то вы увидите что-то подобное:
<source lang=bash>
<syntaxhighlight lang="bash">
fstrim -v /mnt/arhiv/
# fstrim -v /mnt/arhiv/
mnt/arhiv: the discard operation is not supported
/mnt/arhiv: the discard operation is not supported
</source>
</syntaxhighlight>
 
Ещё одним вариантом является запуск команды:
<syntaxhighlight lang="bash">$ lsblk -Df</syntaxhighlight>
 
Если столбец DISC-GRAN или DISC-MAX имеют ненулевые значения, то раздел поддерживается TRIM.
 
=== Проверка поддержки TRIM прошивкой (firmware) диска ===
 
Для того чтобы проверить это, установите {{pkg|sg3_utils}} (обязательно) и  {{pkg|lsscsi}} (не обязательно, но желательно):
<syntaxhighlight lang="bash">
# apt-get install sg3_utils lsscsi
</syntaxhighlight>
 
Запустите следующие команды для проверки параметра '''Maximum unmap LBA count''' и  '''Unmap command supported (LBPU)''':
 
<syntaxhighlight lang="bash">
# sg_vpd -p bl /dev/sdc | grep -i unmap
  Maximum unmap LBA count: 4194240
  Maximum unmap block descriptor count: 1
....
 
# sg_vpd -p lbpv /dev/sdc | grep LBPU
  Unmap command supported (LBPU): 1
 
</syntaxhighlight>
 
 
Если '''Maximum unmap LBA count''' и '''Unmap command supported (LBPU)''' имеют ненулевые значения,  значит устройство умеет работать с TRIM.
 
{{Note|Автор [https://www.jeffgeerling.com/blog/2020/enabling-trim-on-external-ssd-on-raspberry-pi] имел печальный опыт с некоторыми устройствами, показывавшими поддержку TRIM в прошивке (например, флэш-накопитель Arcanite USB 3.1), но при включении TRIM он получил несколько ошибок, а попытавшись запустить fstrim -v / насильно, испортил прошивку диска до такой степени, что диск теперь ни смонтировать, ни отформатировать. Так что убедитесь, что у вас есть резервная копия любых важных данных, прежде чем пытаться использовать диск, который на самом деле может не поддерживать TRIM!}}
 
=== Пробное включение TRIM ===
 
Если ядро не обнаружило способность вашего устройства к разметке данных, то, скорее всего, будет возвращено значение "full". Кроме "full", драйвер SCSI-накопителя ядра в настоящее время знает следующие значения для provisioning_mode:
 
<syntaxhighlight lang="ini">
unmap
writesame_16
writesame_10
writesame_zero
disabled
</syntaxhighlight>
 
==== Проверим все значения '''provisioning_mode''' ====
у всех устройств подключенных к компьютеру, например имеем такую картину:
 
<syntaxhighlight lang="bash">
# find /sys/ -name provisioning_mode -exec grep -H . {} + | sort
/sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb4/4-1/4-1.1/4-1.1:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb5/5-2/5-2:1.0/host5/target5:0:0/5:0:0:0/scsi_disk/5:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb5/5-4/5-4:1.0/host4/target4:0:0/4:0:0:0/scsi_disk/4:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:11.0/ata1/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/provisioning_mode:writesame_16
/sys/devices/pci0000:00/0000:00:11.0/ata2/host1/target1:0:0/1:0:0:0/scsi_disk/1:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:12.2/usb1/1-4/1-4:1.3/host11/target11:0:0/11:0:0:0/scsi_disk/11:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-4/2-4:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-4/2-4:1.0/host7/target7:0:0/7:0:0:1/scsi_disk/7:0:0:1/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-4/2-4:1.0/host7/target7:0:0/7:0:0:2/scsi_disk/7:0:0:2/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-4/2-4:1.0/host7/target7:0:0/7:0:0:3/scsi_disk/7:0:0:3/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-6/2-6:1.0/host8/target8:0:0/8:0:0:0/scsi_disk/8:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:14.1/ata6/host10/target10:0:0/10:0:0:0/scsi_disk/10:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:14.1/ata6/host10/target10:0:1/10:0:1:0/scsi_disk/10:0:1:0/provisioning_mode:full
</syntaxhighlight>
 
<syntaxhighlight lang="bash">
# lsscsi
[0:0:0:0]    disk    ATA      HS-SSD-E100 512G 002  /dev/sda
[1:0:0:0]    disk    ATA      WDC WD5000AACS-0 1B01  /dev/sdb
[2:0:0:0]    cd/dvd  ATAPI    iHAS124  D      8L07  /dev/sr0
[4:0:0:0]    disk    StoreJet Transcend        0    /dev/sde
[5:0:0:0]    disk    Samsung  SSD 870 EVO 1TB  0    /dev/sdc
[6:0:0:0]    disk    USSD    USSD            5.00  /dev/sdd
[7:0:0:0]    disk    Generic- SD/MMC          1.00  /dev/sdg
[7:0:0:1]    disk    Generic- Compact Flash    1.01  /dev/sdh
[7:0:0:2]    disk    Generic- SM/xD-Picture    1.02  /dev/sdi
[7:0:0:3]    disk    Generic- MS/MS-Pro        1.03  /dev/sdj
[8:0:0:0]    disk    ASMT    2235            0    /dev/sdf
[10:0:0:0]  disk    ATA      SAMSUNG HM250JI  0-08  /dev/sdk
[10:0:1:0]  disk    ATA      ST31000524AS    JC4B  /dev/sdl
[11:0:0:0]  disk            TF CARD Storage  2.31  /dev/sdm
</syntaxhighlight>
 
Мы раньше узнали, что прошивка диска {{path|/dev/sdc}} поддерживает TRIM. Запускаем команду:
 
<syntaxhighlight lang="bash">
# find /sys/ -name provisioning_mode -exec grep -H . {} + | grep 5:0:0:0
/sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb5/5-2/5-2:1.0/host5/target5:0:0/5:0:0:0/scsi_disk/5:0:0:0/provisioning_mode:full
</syntaxhighlight>
 
И завершающий "укол":
 
<syntaxhighlight lang="bash">
echo unmap > /sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb5/5-2/5-2:1.0/host5/target5:0:0/5:0:0:0/scsi_disk/5:0:0:0/provisioning_mode
</syntaxhighlight>
 
Теперь '''provisioning_mode''' имеет значение unmap.


Ещё одним вариантом является запуск команды
Следующий шаг


$ lsblk -Df
==== Правильно установим переменную discard_max_bytes ====


Если столбец DISC-GRAN или DISC-MAX имеют ненулевые значения, то раздел поддерживается TRIM
Получаем значение '''Мaximum unmap LBA count''':
<syntaxhighlight lang="bash">
# sg_vpd -p bl /dev/sdc | grep "unmap LBA"
  Maximum unmap LBA count: 4194240
</syntaxhighlight>


Получаем значение '''logical block length''':
<syntaxhighlight lang="bash">
# sg_readcap -l /dev/sdc | grep length
  Logical block length=512 bytes
</syntaxhighlight>


=== Проверка поддерживает-ли прошивка диска TRIM ===
Расчитываем discard_max_bytes умножая '''Мaximum unmap LBA count''' на '''logical block length''':
 
 
<syntaxhighlight lang="bash">
# echo $((4194240*512))
2147450880
</syntaxhighlight>
 
Устанавливаем значение '''discard_max_bytes''':
<syntaxhighlight lang="bash">
# echo 2147450880 > /sys/block/sdс/queue/discard_max_bytes
</syntaxhighlight>
 
==== Запускаем fstrim ====
<syntaxhighlight lang="bash">
# fstrim -v /mnt/arhiv/
/mmnt/arhiv/: 0 B (0 bytes) trimmed
</syntaxhighlight>
Всё заработало.
{{Note|{{cmd|fstrim}} не должен выдавать ошибок, и в зависимости от того, сколько блоков ему нужно очистить, это может занять некоторое время. В случае ошибок выданных {{cmd|fstrim}}, лучше не использовать на этом диске TRIM.}}
 
== Создание правила UDEV ==
По умолчанию на внешних носителях TRIM отключен, а при попытке запустить {{cmd|fstrim}} путь до внешнего носителя, мы получаем сообщение '''the discard operation is not supported''',  если мы проведём вышеуказанные операции, то можно запустить {{cmd|fstrim}}, но это будет работать только до перезагузки компьютера. Для того, чтобы внешний диск работал всегда надо создать правило udev.
 
Первым делом узнаём значение idVendor и idProduct жесткого диска:
 
1 Вариант (работает только для USB устройств):
 
<syntaxhighlight lang="bash">
$ cat /sys/block/sdc/../../../../../../idVendor
174c
$ cat /sys/block/sdc/../../../../../../idProduct
55aa
</syntaxhighlight>
 
 
2 Вариант — использовать lsusb:
 
<syntaxhighlight lang="bash">
# lsusb
Bus 004 Device 003: ID 174c:55aa ASMedia Technology Inc. ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s bridge, ASM1153 SATA 3Gb/s bridge, ASM1153E SATA 6Gb/s bridge
</syntaxhighlight>
 
Создаём правило udev:
 
<syntaxhighlight lang="bash">
# echo 'ACTION=="add|change", ATTRS{idVendor}=="174c", ATTRS{idProduct}=="55aa", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"' >>/etc/udev/rules.d/10-uas-discard.rules
</syntaxhighlight>
 
Или открываем в редакторе и вписываем строку:
 
<syntaxhighlight lang="ini">
ACTION=="add|change", ATTRS{idVendor}=="174c", ATTRS{idProduct}=="55aa", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"
</syntaxhighlight>
<syntaxhighlight lang="bash">
# mcedit /etc/udev/rules.d/10-uas-discard.rules
</syntaxhighlight>
 
Перезагружаю правила udev:
<syntaxhighlight lang="bash"># udevadm control -R -S</syntaxhighlight>
 
Монтирую устройство:
<syntaxhighlight lang="bash">$ udisksctl mount -b /dev/sdd1</syntaxhighlight>


Проверяю работу ftrim:
<syntaxhighlight lang="bash">
# lsblk -Df
...
─sdd1        0      512B      4G        0 ext4  1.0  Arhiv2      be4327fe-6153-4698-ad46-03a4b74abce6
...               
</syntaxhighlight>


{{stub}}
Для точки монтирования {{path|/media/Arhiv/}}:
<syntaxhighlight lang="bash">
# fstrim -v /media/Arhiv/
/media/Arhiv/: 0 B (0 bytes) trimmed
</syntaxhighlight>


== Ссылки : ==
== Ссылки ==


# [https://wiki.archlinux.org/title/Solid_state_drive_(Русский)]
* [https://wiki.archlinux.org/title/Solid_state_drive_(Русский) Solid_state_drive_(Русский)]
# [https://www.jeffgeerling.com/blog/2020/enabling-trim-on-external-ssd-on-raspberry-pi Включение TRIM на внешнем SSD на Raspberry Pi (eng) ]
* [https://www.jeffgeerling.com/blog/2020/enabling-trim-on-external-ssd-on-raspberry-pi Включение TRIM на внешнем SSD на Raspberry Pi (eng) ]
# [http://blog.neutrino.es/2013/howto-properly-activate-trim-for-your-ssd-on-linux-fstrim-lvm-and-dmcrypt/ Как правильно активировать TRIM для вашего SSD в Linux  (eng)]
* [http://blog.neutrino.es/2013/howto-properly-activate-trim-for-your-ssd-on-linux-fstrim-lvm-and-dmcrypt/ Как правильно активировать TRIM для вашего SSD в Linux  (eng)]
* [http://bbs.archlinux.org/viewtopic.php?pid=2014231#p2014231 Fstrim (periodic trim) and SSD raid (raid5)]

Текущая версия от 17:53, 8 февраля 2024


Логотип Википедии
В Википедии есть обзорная статья по теме «Trim_(команда_для_накопителей)».

Введение

Статья является адаптацией к реалиям ALT Linux статьи Включение TRIM на внешнем SSD на Raspberry Pi (eng) .

Теория взята из Как правильно активировать TRIM для вашего SSD в Linux (eng).

В отличие от жестких дисков (HDD), флэш-память NAND, которая лежит в основе SSD дисков, не может перезаписывать существующие данные. Это означает, что вы должны сначала удалить старые данные, прежде чем записывать новые. Флэш-память разделена на блоки, которые далее делятся на страницы. Минимальная единица записи — это страница, а наименьшая единица стирания — блок.

Данные можно записывать прямо на пустую страницу, но стирать можно только целые блоки. Поэтому, для того, чтобы освободить пространство, занятое удалёнными данными, все имеющиеся данные из одного блока должны быть сначала скопированы и записаны на пустые страницы нового блока. Только после этого данные в исходном блоке могут быть окончательно стерты, что делает блок готовым для записи новых данных.

Проблема в том, что со временем возникнет "куча" не полностью занятых страниц и быстродействие диска сильно упадёт. Это связано с тем, что при удалении файла операционная система просто помечает данные блоки как свободные, но не сообщает об этом контроллеру диска. И вне зависимости от оставшегося места, контроллер диска не сможет найти куда записать новые данные. Для решения этой проблемы и используется TRIM.

Что такое ТРИМ?

TRIM был придуман для решения этой проблемы. TRIM — это имя команды, которую операционная система может отправить, чтобы сообщить SSD, какие блоки в файловой системе свободны. SSD использует эту информацию для внутренней дефрагментации блоков и сохранения свободных страниц для быстрой и эффективной записи.

Поддержка ТРИМ файловыми системами Источник
Файловая система Опция discard Поддержка fstrim Замечания
ext4 Yes Yes "discard, nodiscard(*)" [1]
ext3 Yes Yes
Btfs Yes Yes
F2F2FS Yes Yes
JFS Yes Yes [2]
XFS Yes Yes [3]
NILFS2 Yes Yes [4]
NTFS-3G No Yes начиная с версии 2015.3.14 [5]
VFAT Yes Yes fstrim поддерживается начиная с ядра 4.19 [6]
ExFAT Yes Yes fstrim поддерживается начиная с ядра 5.13, [7]


Примечание: Пользователи должны быть уверены, что их SSD поддерживает TRIM, прежде чем пытаться использовать его. В противном случае возможна потеря данных.


Классический способ включения TRIM в Linux , это прописать в /etc/fstab опцию discard, например так (если корень находится на SSD диске):

UUID="6ff0461b-4796-4s0f-a8c0-1fs5f884a593    /  ext4    discard,noatime 1  1
Примечание: Определение опции монтирования discard в /etc/fstab не работает с разделом XFS на /. Опция должна быть установлена с помощью параметра ядра rootflags:
rootflags=discard


В файловой системе ext4 флаг discard также может быть установлен как опция монтирования по умолчанию для "внутренних дисков" с помощью tune2fs, например[1]:

# tune2fs -o discard /dev/sda1

Очистка ТРИМ

Использование опций монтирования по умолчанию вместо записи в /etc/fstab особенно полезно для внешних дисков, поскольку такой раздел будет монтироваться с опциями по умолчанию и на других машинах. Таким образом, нет необходимости редактировать /etc/fstab на каждой машине.

Пакет util-linux предоставляет fstrim.service и fstrim.timer файлы модулей systemd. Enabling таймера активирует службу еженедельно. Служба выполняет fstrim(8) на всех смонтированных файловых системах на устройствах, поддерживающих операцию discard.

Таймер полагается на метку времени /var/lib/systemd/timers/stamp-fstrim.timer (которую он создаст при первом вызове), чтобы узнать, прошла ли неделя с момента его последнего запуска. Поэтому нет необходимости беспокоиться о слишком частых вызовах, в стиле anacron.

Чтобы запросить активность и состояние блоков, смотрите journalctl. Чтобы изменить периодичность таймера или выполнените команду systemctl edit fstrim.timer или создайте файл /etc/systemd/system/timers.target.wants/fstrim.timer с заданной периодичностью (по умолчанию раз в неделю). fstrim.timer запускает fstrim, беря пути для разделов из /etc/fstab.

Альтернативный способ периодичной проверки, это установить пакет auto-fstrim и запустить anacron. Особенностью auto-fstrim является то, что он проверяет все смонтированные разделы, не обращая внимание есть ли они в /etc/fstab или нет, и запуск fstrim проходит ежедневно.

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


Непрерывный TRIM ведёт к некоторому замедлению файловых операций, так как после каждой из них выполняются операции по по очистке неиспользуемых блоков. Поэтому в большинстве дистрибутивах Linux советуют настроить периодический запуск fstrim.

Можно также самому очищать TRIM вручную с помощью команды fstrim время от времени, или после больших операций с диском.

Конкретный раздел:

fstrim -v /mnt/disk

Все смонтированные разделы:

fstrim -av

Поддерживает ли мой SSD TRIM

Для проверки, поддерживает ли ваш SSD диск TRIM, надо выполнить команду:

# fstrim  -v путь_до_точки_монтирования_раздела

Например, если у вас раздел c SSD диска смонтирован в /mnt/arhiv, то при поддерживаемом TRIM вы увидите:

# fstrim -v /mnt/arhiv/
/mnt/arhiv/: 0 B (0 bytes) trimmed

Если диск не поддерживает TRIM, то вы увидите что-то подобное:

# fstrim -v /mnt/arhiv/
/mnt/arhiv: the discard operation is not supported

Ещё одним вариантом является запуск команды:

$ lsblk -Df

Если столбец DISC-GRAN или DISC-MAX имеют ненулевые значения, то раздел поддерживается TRIM.

Проверка поддержки TRIM прошивкой (firmware) диска

Для того чтобы проверить это, установите sg3_utils (обязательно) и lsscsi (не обязательно, но желательно):

# apt-get install sg3_utils lsscsi

Запустите следующие команды для проверки параметра Maximum unmap LBA count и Unmap command supported (LBPU):

# sg_vpd -p bl /dev/sdc | grep -i unmap 
  Maximum unmap LBA count: 4194240
  Maximum unmap block descriptor count: 1
.... 

# sg_vpd -p lbpv /dev/sdc | grep LBPU
  Unmap command supported (LBPU): 1


Если Maximum unmap LBA count и Unmap command supported (LBPU) имеют ненулевые значения, значит устройство умеет работать с TRIM.

Примечание: Автор [8] имел печальный опыт с некоторыми устройствами, показывавшими поддержку TRIM в прошивке (например, флэш-накопитель Arcanite USB 3.1), но при включении TRIM он получил несколько ошибок, а попытавшись запустить fstrim -v / насильно, испортил прошивку диска до такой степени, что диск теперь ни смонтировать, ни отформатировать. Так что убедитесь, что у вас есть резервная копия любых важных данных, прежде чем пытаться использовать диск, который на самом деле может не поддерживать TRIM!


Пробное включение TRIM

Если ядро не обнаружило способность вашего устройства к разметке данных, то, скорее всего, будет возвращено значение "full". Кроме "full", драйвер SCSI-накопителя ядра в настоящее время знает следующие значения для provisioning_mode:

unmap
writesame_16
writesame_10
writesame_zero
disabled

Проверим все значения provisioning_mode

у всех устройств подключенных к компьютеру, например имеем такую картину:

# find /sys/ -name provisioning_mode -exec grep -H . {} + | sort
/sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb4/4-1/4-1.1/4-1.1:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb5/5-2/5-2:1.0/host5/target5:0:0/5:0:0:0/scsi_disk/5:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb5/5-4/5-4:1.0/host4/target4:0:0/4:0:0:0/scsi_disk/4:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:11.0/ata1/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/provisioning_mode:writesame_16
/sys/devices/pci0000:00/0000:00:11.0/ata2/host1/target1:0:0/1:0:0:0/scsi_disk/1:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:12.2/usb1/1-4/1-4:1.3/host11/target11:0:0/11:0:0:0/scsi_disk/11:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-4/2-4:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-4/2-4:1.0/host7/target7:0:0/7:0:0:1/scsi_disk/7:0:0:1/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-4/2-4:1.0/host7/target7:0:0/7:0:0:2/scsi_disk/7:0:0:2/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-4/2-4:1.0/host7/target7:0:0/7:0:0:3/scsi_disk/7:0:0:3/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:13.2/usb2/2-6/2-6:1.0/host8/target8:0:0/8:0:0:0/scsi_disk/8:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:14.1/ata6/host10/target10:0:0/10:0:0:0/scsi_disk/10:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:14.1/ata6/host10/target10:0:1/10:0:1:0/scsi_disk/10:0:1:0/provisioning_mode:full
# lsscsi
[0:0:0:0]    disk    ATA      HS-SSD-E100 512G 002   /dev/sda 
[1:0:0:0]    disk    ATA      WDC WD5000AACS-0 1B01  /dev/sdb 
[2:0:0:0]    cd/dvd  ATAPI    iHAS124   D      8L07  /dev/sr0 
[4:0:0:0]    disk    StoreJet Transcend        0     /dev/sde 
[5:0:0:0]    disk    Samsung  SSD 870 EVO 1TB  0     /dev/sdc 
[6:0:0:0]    disk    USSD     USSD             5.00  /dev/sdd 
[7:0:0:0]    disk    Generic- SD/MMC           1.00  /dev/sdg 
[7:0:0:1]    disk    Generic- Compact Flash    1.01  /dev/sdh 
[7:0:0:2]    disk    Generic- SM/xD-Picture    1.02  /dev/sdi 
[7:0:0:3]    disk    Generic- MS/MS-Pro        1.03  /dev/sdj 
[8:0:0:0]    disk    ASMT     2235             0     /dev/sdf 
[10:0:0:0]   disk    ATA      SAMSUNG HM250JI  0-08  /dev/sdk 
[10:0:1:0]   disk    ATA      ST31000524AS     JC4B  /dev/sdl 
[11:0:0:0]   disk             TF CARD Storage  2.31  /dev/sdm

Мы раньше узнали, что прошивка диска /dev/sdc поддерживает TRIM. Запускаем команду:

# find /sys/ -name provisioning_mode -exec grep -H . {} + | grep 5:0:0:0
/sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb5/5-2/5-2:1.0/host5/target5:0:0/5:0:0:0/scsi_disk/5:0:0:0/provisioning_mode:full

И завершающий "укол":

echo unmap > /sys/devices/pci0000:00/0000:00:07.0/0000:02:00.0/usb5/5-2/5-2:1.0/host5/target5:0:0/5:0:0:0/scsi_disk/5:0:0:0/provisioning_mode

Теперь provisioning_mode имеет значение unmap.

Следующий шаг

Правильно установим переменную discard_max_bytes

Получаем значение Мaximum unmap LBA count:

# sg_vpd -p bl /dev/sdc | grep "unmap LBA"
  Maximum unmap LBA count: 4194240

Получаем значение logical block length:

# sg_readcap -l /dev/sdc | grep length
   Logical block length=512 bytes

Расчитываем discard_max_bytes умножая Мaximum unmap LBA count на logical block length:

# echo $((4194240*512))
2147450880

Устанавливаем значение discard_max_bytes:

# echo 2147450880 > /sys/block/sdс/queue/discard_max_bytes

Запускаем fstrim

# fstrim -v /mnt/arhiv/
/mmnt/arhiv/: 0 B (0 bytes) trimmed

Всё заработало.

Примечание: fstrim не должен выдавать ошибок, и в зависимости от того, сколько блоков ему нужно очистить, это может занять некоторое время. В случае ошибок выданных fstrim, лучше не использовать на этом диске TRIM.


Создание правила UDEV

По умолчанию на внешних носителях TRIM отключен, а при попытке запустить fstrim путь до внешнего носителя, мы получаем сообщение the discard operation is not supported, если мы проведём вышеуказанные операции, то можно запустить fstrim, но это будет работать только до перезагузки компьютера. Для того, чтобы внешний диск работал всегда надо создать правило udev.

Первым делом узнаём значение idVendor и idProduct жесткого диска:

1 Вариант (работает только для USB устройств):

$ cat /sys/block/sdc/../../../../../../idVendor
174c
$ cat /sys/block/sdc/../../../../../../idProduct
55aa


2 Вариант — использовать lsusb:

# lsusb
Bus 004 Device 003: ID 174c:55aa ASMedia Technology Inc. ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s bridge, ASM1153 SATA 3Gb/s bridge, ASM1153E SATA 6Gb/s bridge

Создаём правило udev:

# echo 'ACTION=="add|change", ATTRS{idVendor}=="174c", ATTRS{idProduct}=="55aa", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"' >>/etc/udev/rules.d/10-uas-discard.rules

Или открываем в редакторе и вписываем строку:

ACTION=="add|change", ATTRS{idVendor}=="174c", ATTRS{idProduct}=="55aa", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"
# mcedit /etc/udev/rules.d/10-uas-discard.rules

Перезагружаю правила udev:

# udevadm control -R -S

Монтирую устройство:

$ udisksctl mount -b /dev/sdd1

Проверяю работу ftrim:

# lsblk -Df
...
─sdd1        0      512B       4G         0 ext4   1.0   Arhiv2       be4327fe-6153-4698-ad46-03a4b74abce6
...

Для точки монтирования /media/Arhiv/:

# fstrim -v /media/Arhiv/
/media/Arhiv/: 0 B (0 bytes) trimmed

Ссылки

  1. Мне не удалось так включить TRIM на внешнем диске