Search by Tags

TRIM and ubihealthd Support (Linux)

 

Article updated at 17 Aug 2021
Subscribe for this article updates

Select the version of your OS from the tabs below. If you don't know the version you are using, run the command cat /etc/os-release or cat /etc/issue on the board.

BSP 5

Introduction

ubihealthd is a simple daemon that scans every PEB of a UBI device in random order. It helps to deal with read disturb on systems that either reboot infrequently, use UBI Fastmap or hardly read much data. This would prevent data loss for systems running unattended for quite a long time.

Modern eMMC and SSD storage devices require an ATA interface fstrim command, and for this, an OS built on the Linux kernel provides two methods of management at the file system level:

  • discard: installed as an option when mounting the filesystem. Allows the Linux kernel to immediately send a TRIM command to the device as soon as the filesystem reports it.
  • fstrim: it is a utility that is launched manually or on a schedule as an OS service that sends a list of deleted blocks from the filesystem to clean them up low-level on the device.

This article complies to the Typographic Conventions for the Toradex Documentation.

Prerequisites

ubihealthd

ubihealthd is provided as part of ubi-utils. It is only available for raw NAND-based Toradex SoMs, as they run the UBIFS filesystem. The BSP Layers and Reference Images for Yocto Project, starting from release 5.2.0, provides the ubihealthd.service daemon.

Note: ubi-utils is not deployed to any eMMC modules running VFAT/ext4 instead of UBIFS. ubihealthd must not be used on eMMC-based SKUs.

ubihealthd Service

The ubihealthd service is disabled by default and you can configure it depending on your system-level use-case.

To enable the service on the board, making it automatically start on every boot:

# systemctl enable ubihealthd.service
Created symlink /etc/systemd/system/multi-user.target.wants/ubihealthd.service -> /lib/systemd/system/ubihealthd.service.

To start the service without rebooting:

# systemctl start ubihealthd.service

To check the system health, for example if it started successfully:

# systemctl status ubihealthd.service
* ubihealthd.service - UBI health daemon
     Loaded: loaded (/lib/systemd/system/ubihealthd.service; enabled; vendor preset: disabled)
     Active: active (running) since Tue 2021-07-20 12:10:43 UTC; 17s ago
    Process: 635 ExecStart=/usr/sbin/ubihealthd -i 240 (code=exited, status=0/SUCCESS)
   Main PID: 636 (ubihealthd)
      Tasks: 1 (limit: 1023)
     Memory: 272.0K
     CGroup: /system.slice/ubihealthd.service
             `-636 /usr/sbin/ubihealthd -i 240

Jul 20 12:10:43 colibri-imx6ull-06388146 systemd[1]: Starting UBI health daemon...
Jul 20 12:10:43 colibri-imx6ull-06388146 systemd[1]: Started UBI health daemon.

To enable the service in a custom image built the with Yocto Project/OpenEmbedded, you must set SYSTEMD_AUTO_ENABLE = "enable" in the recipe meta-toradex-bsp-common/recipes-devtools/mtd/mtd-utils_%.bbappend.

ubihealthd Settings

ubihealthd provides command-line options, like the UBI device and an interval to rerun it:

# ubihealthd -help
Usage: ubihealthd [ -d UBI_DEVICE ] [-i INTERVAL_SEC ] [ -f ]

The default settings for these options are /dev/ubi0 for the UBI device and 120 seconds for the default interval. ubihealthd.service is running with default settings. These settings can be modified with appropriate changes made in the /lib/systemd/system/ubihealthd.service on the device:

ubihealthd.service
[Unit]
Description=UBI health daemon
After=multi-user.target
 
[Service]
Type=forking
ExecStart=/usr/sbin/ubihealthd
 
[Install]
WantedBy=multi-user.target

For example, to change the interval to 240 seconds, edit the line ExecStart by adding the option -i 240:

ExecStart=/usr/sbin/ubihealthd -i 240

Reload and restart the service, and check that it is running with the new parameter:

# systemctl daemon-reload
# systemctl restart ubihealthd.service
# ps aux | grep ubihealthd
root       651  0.0  0.0   1388   136 ?        Ss   11:23   0:00 /usr/sbin/ubihealthd -i 240

To customize the settings on a custom image built the with Yocto Project/OpenEmbedded, edit the file meta-toradex-bsp-common/recipes-devtools/mtd/mtd-utils/ubihealthd.service. For example, to set the interval to 240 seconds, set ExecStart=@SBINDIR@/ubihealthd -i 240.

fstrim

fstrim is often run periodically. You can configure the systemd timer fstrim.timer to execute the fstrim.service periodically. By default, it runs the service weekly, every Monday 00:00:00.

fstrim Service

Enable and start the timer:

# systemctl enable fstrim.timer                                   
Created symlink /etc/systemd/system/timers.target.wants/fstrim.timer -> /lib/systemd/system/.
# systemctl start fstrim.timer

Check that the timer is active, and when it is scheduled to run next:

# systemctl list-timers
NEXT                         LEFT        LAST                         PASSED    UNIT
Mon 2021-07-12 00:00:00 UTC  4 days left n/a                          n/a       fstrim.timer

To enable the service in a custom image built the with Yocto Project/OpenEmbedded, you must set SYSTEMD_AUTO_ENABLE = "enable" in the recipe meta-toradex-bsp-common/recipes-core/util-linux/util-linux_%.bbappend.

fstrim Settings

To adjust the frequency of the fstrim.timer, you must edit the lines OnCalendar=weekly and AccuracySec=1h on the file /lib/systemd/system/fstrim.timer:

fstrim.service
[Unit]
Description=Discard unused blocks once a week
ConditionVirtualization=!container
 
[Timer]
OnCalendar=weekly
AccuracySec=1h
Persistent=true
 
[Install]
WantedBy=timers.target

To make a proper configuration, learn more about the systemd timer options and the syntax of calendar event expressions.

To customize the settings on a custom image built the with Yocto Project/OpenEmbedded, edit the file meta-toradex-bsp-common/recipes-core/util-linux/util-linux/fstrim.timer.

Check fstrim Support

To check if TRIM is supported, run the following command:

# lsblk --discard
NAME         DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
mmcblk1             0      512B     3.5M         0
|-mmcblk1p1         0      512B     3.5M         0
`-mmcblk1p2         0      512B     3.5M         0
mmcblk1boot0        0      512B     3.5M         0
mmcblk1boot1        0      512B     3.5M         0

If you see zero values ​​in the DISC-GRAN (discard granularity) and DISC-MAX (discard max bytes) columns on the SSD device, then TRIM is not working.

With full TRIM support, the values ​​should be shown on all partitions, as in the example above. DISC-GRAN is 512B because the sector size on the storage device is 512 bytes. The operating system sends a TRIM command to the drive controller specifying the sector numbers that can be cleared.

Alternatively, you can also check with the manual TRIM command:

#  fstrim -v /
2/: 2.7 GiB (2917261312 bytes) trimmed

If you see a positive result, then TRIM is working.