Perform ressource heavy tasks without slowing down other processes

While researching the best strategy to scrub my BTRFS filesystem I found a nice little trick to prevent a slow down or fight about ressources. Have a look at this systemd service file from the big boy Linux distribution Archlinux for scrubbing a filesystem:

[root@homeserver ~]# cat /usr/lib/systemd/system/btrfs-scrub@.service
[Unit]
Description=Btrfs scrub on %f
ConditionPathIsMountPoint=%f
RequiresMountsFor=%f

[Service]
Nice=19
IOSchedulingClass=idle
KillSignal=SIGINT
ExecStart=/usr/bin/btrfs scrub start -B %f

By setting IOSchedulingClass to idle and setting the niceness to 19 (lowest priority) every other operation will take precedence. Of course this comes with a cost: Your scrub process will take longer. I scrubbed my BTRFS RAID 5 like this and it took over 90 hours for three 15 TB drives scrubbing with round about 20 MByte/s. Note: Scrubbing a RAID 5 is always slow but not that slow. But my containers and virtual machines provided their services without interruption or noticeable slowdowns.

With systemd-run you can pass in the same properties to other long running, potentially heavy load generating tasks like cp, rsync, dd or even a btrfs convert. systemd-run spawns a so called transient unit which will be deleted automatically after the next reboot. No need for screen anymore and you also get the log output captured in the journal. Here is how I copy Linux ISOs I downloaded via BitTorrent out of the container into my NAS subvolume:

:~$ systemd-run -p “IOSchedulingClass=idle” -p “Nice=19” cp -rv /path/to/linux-isos/* /path/to/their/destinations/
Running as unit: run-u2496.service

The task is now running in the background. With systemctl status run-u2496.service you can see when this tasks is finished (or pass –wait to systemd-run to stay in foreground). View the complete output in the journal with journalctl -u run-u2496.service.

Another example: Convert a BTRFS RAID 5 to RAID 1 without slowdown (a conversion is pretty IO intensive):

:~$ systemd-run -p “IOSchedulingClass=idle” –unit btrfsbalance -p “Nice=19” btrfs balance -dconvert=raid1,soft /mnt
Running as unit: btrfsbalance.service

And that’s it. This is running for a couple of hours now on my machine and nothing slowed down. I love when stuff like this just works. Note: Yes, systemd thinks this unit failed because it exited with code 1 but that’s okay. The balance is still running.

Want to take it even a step further? Create a transient timer to save the output of btrfs fi us /mnt to the journal every 5 minutes to save the progress in case something fails:

:~$ systemd-run –on-calendar “*:0/5” btrfs balance status /mnt
Running as unit: run-rb40f003fd31d4be3baee0267ee1032a6.service

And then a new transient timer is created:

[root@homeserver ~]# systemctl list-timers   
NEXT                           LEFT LAST                              PASSED UNIT                                        ACTIVATES   
Sun 2024-01-21 11:10:00 CET 1min 7s Sun 2024-01-21 11:05:08 CET 3min 44s ago run-rb40f003fd31d4be3baee0267ee1032a6.timer run-rb40f003fd31d4be3baee0267ee1032a6.service

No more crontab with output redirection and $(date +%someformatstring).txt hacks you found on stackoverflow in a post from 2005 breaking the day after you went on vacation. I love systemd! Systemd rulez.


Du hast einen Kommentar, einen Wunsch oder eine Verbesserung? Schreib mir doch eine E-Mail! Die Infos dazu stehen hier.

🖇️ = Link zu anderer Webseite
🔐 = Webseite nutzt HTTPS (verschlüsselter Transportweg)
Zurück