FS#69887 - [btrfs-progs] systemd scrub service does not verify that the mount point is available

Attached to Project: Arch Linux
Opened by Jordan Williams (jwillikers) - Friday, 05 March 2021, 17:47 GMT
Last edited by Sébastien Luttringer (seblu) - Wednesday, 07 April 2021, 17:58 GMT
Task Type Bug Report
Category Packages: Core
Status Closed
Assigned To Sébastien Luttringer (seblu)
Architecture All
Severity Very Low
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 0
Private No

Details

Description:

The btrfs-progs package ships an instantiable systemd unit to run Btrfs scrubs.
The instantiable systemd unit verifies that the instantiated path is a mount point and that it exists.
This is helpful but doesn't verify that the mounted filesystem is actually present and mounted.
If the filesystem is not mounted, btrfs-scrub may unintentially scrub the filesystem with the mount point directory instead.
Additionally, when the mount point is not mounted, an unhelpful error is output from btrfs-scrub in systemd's logs which isn't very insightful.

Making the relationship explicit between the systemd service and the mount it depends upon ensures that the mount point is present and mounted by systemd.
The BindsTo and After directives are the best way to define this dependency relationship as far as I know.
The btrfs-scrub@.service file I would propose would look like the following.

[Unit]
Description=Btrfs scrub on %f
ConditionPathIsMountPoint=%f
BindsTo=%i.mount
After=%i.mount

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


This produces a much more helpful error message in systemd and doesn't bother launching the btrfs-scrub command until the mount point is available.
This works nicely with systemd's mount and automount functionality, which is exactly what I would like to take advantage of.
I want to schedule scrubs for my external backup drive.
This task depends upon

Closed by  Sébastien Luttringer (seblu)
Wednesday, 07 April 2021, 17:58 GMT
Reason for closing:  Fixed
Comment by Sébastien Luttringer (seblu) - Saturday, 06 March 2021, 11:19 GMT
btrfs-progs 5.10.1-3 already use ConditionPathIsMountPoint to prevent scrub to start when the path is not a mountpoint.
So, you are suggesting to add BindsTo=%i.mount and After=%i.mount.

I agree with After=, it will properly order scrub to run after the filesystem mount if there is a race between the 2 units.
But BindsTo= will mount the filesystem to starts scrubing. The original design of this service is to be used with the timer to provide a monthly scrubbing of a btrfs. When a filesystem is not started explicitly or has been unmounted, I don't think it's a safe idea to mount it again because a scrub timer remain.
Maybe it's over protective, but I currently think Requisite= is more appropriate.

Comment by Jordan Williams (jwillikers) - Saturday, 06 March 2021, 13:50 GMT
I'm not against using Requisite= instead.
That sounds like a good idea in order to avoid overstepping by automatically mounting filesystems.
If an automount unit exists for the mount point, should the behavior be the same?
I'm curious about this since my use case for the timer in addition to srubbing my internal disk is to scrub my external HDD backup drive when it's available.
I have a systemd automount setup for the external disk, but I'm wondering if I would need to mount the filesystem manually in that case for the service to run.

I noticed there's also RequiresMountsFor= but this uses Requires= instead of Requisite= which would still automatically mount the drive, but I figured it was worth mentioning for completeness in the discussion

I'm not sure what you mean about a scrub timer remaining, though.
Could you a elaborate on that a little bit for me?
I might be missing something.
Thanks!
Comment by Sébastien Luttringer (seblu) - Sunday, 07 March 2021, 11:09 GMT
Automount means the filesystem will be mounted when a VFS access to it.

I made few tests and when automount is enabled, even without Requires=, the filesystem is mounted when the scrub unit is started. I guess because the ConditionPathIsMountPoint is doing a VFS access.
Without, automount, systemd returns "Condition check resulted in Btrfs scrub on /mnt being skipped."

In mean, in a situation you have configured a scrub timer and the filesytem is broken. At that moment, you don't want your timer elapse and mount the filesystem read/write and scrub. While disabling the filesystem in fstab (with or without automount) is a reflex, the scrub timer can catch you from behind. We may conclude that it's the root user fault after all.

On the other end, when you configure your fs with noauto flag, the scrub timer will do nothing silently.
I pushed the 5.11 version with RequiresMountsFor= to give it a try.
Comment by Jordan Williams (jwillikers) - Monday, 08 March 2021, 13:27 GMT
I didn't know that ConditionPathIsMountPoint would mount automounts, that's really helpful to know.
I really appreciate you taking the time to test that out, thanks!

I understand what you mean now.
The timer mounts a damaged filesystem unless the user explicitly disables the timer.
Thanks for the clarification.

Thanks for the update and I'll make sure to test that out.

Loading...