https://bugs.kde.org/show_bug.cgi?id=512635
Bug ID: 512635
Summary: Free Space Notifier keeps automount partitions mounted
forever (e.g. /boot, /efi)
Classification: Plasma
Product: plasmashell
Version First 6.5.3
Reported In:
Platform: unspecified
OS: Linux
Status: REPORTED
Severity: normal
Priority: NOR
Component: general
Assignee: [email protected]
Reporter: [email protected]
CC: [email protected]
Target Milestone: 1.0
SUMMARY
If you have an automount partition (autofs) with an idle timeout longer than 1
minute, it will never be unmounted.
It's caused by a timer in freespacenotifier that checks used space every 1
minute, which resets the kernel's timeout.
A specific example is the EFI System Partition (ESP) and Extended Boot Loader
Partition (XBOOTLDR). By default, systemd-gpt-auto-generator generates
automount units for them on /boot and/or /efi with a 2 minute idle timeout (see
LOADER_PARTITION_IDLE_USEC). Lennart's blog says this is intended to improve
data safety by limiting how long it can be in a "dirty" state. That benefit is
lost if it stays mounted.
STEPS TO REPRODUCE
1. Configure systemd with an automount unit. Options:
a) systemd-gpt-auto-generator creates boot.automount and/or efi.automount if
its conditions are met.
b) Manually edit /etc/fstab and add or change a line like this: "/dev/foo
/foobar vfat
defaults,nosuid,nodev,noexec,noatime,x-systemd.automount,x-systemd.idle-timeout=120
0 2"
c) Manually create /etc/systemd/system/foobar.automount with the required
options and "TimeoutIdleSec=120s"
2. Access the partition, e.g. "ls /foobar". At this point, "journalctl" will
print: "foobar.automount: Got automount request for /foobar, triggered by 12345
(ls)". (Side note - the ESP is usually touched by
systemd-boot-random-seed.service during bootup.)
3. Wait at least 2 minutes.
OBSERVED RESULT
Once the partition is mounted (on first access), it won't automatically
unmount.
"journalctl" won't print "Unmounted foobar.mount - /foobar.".
"findmnt" or "mount" will print two lines for /foobar, one with type "autofs"
and one with the real fs type, which means it is mounted.
EXPECTED RESULT
It should unmount after the configured idle timeout. Or some longer but finite
time.
If possible, Free Space Notifier should still notify when the ESP is getting
too full, because it can be a useful warning. Instead of outright excluding
automounts, it would be best to find a way to measure free space without
refreshing the mount's idle timer.
I included a strace snippet below. Theory: Maybe if the openat() used O_PATH
(or was avoided), and the FS_IOC_GETFSLABEL call was avoided, would that be
sufficient?
SOFTWARE/OS VERSIONS
Operating System: Arch Linux
KDE Plasma Version: 6.5.3
KDE Frameworks Version: 6.20.0
Qt Version: 6.10.0
Kernel Version: 6.17.8-arch1-1 (64-bit)
Graphics Platform: Wayland
...
kded 6.20.0-1
plasma-workspace 6.5.3-1
systemd 258.2-2
ADDITIONAL INFORMATION
https://0pointer.net/blog/linux-boot-partitions.html
https://docs.kernel.org/filesystems/autofs.html
https://www.freedesktop.org/software/systemd/man/latest/systemd.automount.html
https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html
https://www.freedesktop.org/software/systemd/man/latest/systemd-gpt-auto-generator.html
https://github.com/KDE/plasma-workspace/blob/445f6fb07091902d54276c1a233f778a8e258923/freespacenotifier/freespacenotifier.cpp#L37
https://github.com/systemd/systemd/blob/2ba910ab06e5970e9e2dc6d28a8d38a4adcd4a16/src/gpt-auto-generator/gpt-auto-generator.c#L67
I used "fatrace" to figure out which process is the culprit. (But beware,
"fatrace" itself also keeps the mount busy.)
If I disable/stop Free Space Notifier in "kcmshell6 kcm_kded", (and stop
"fatrace"), the partition unmounts.
strace:
$ sudo strace -f -p $(pidof kded6)
...
[pid 1782] ppoll([{fd=40, events=POLLIN|POLLOUT}], 1, NULL, NULL, 8) = 1
([{fd=40, revents=POLLOUT}])
[pid 50382] ppoll([{fd=39, events=POLLIN}], 1, NULL, NULL, 8 <unfinished ...>
[pid 1782] write(40, " f_5f_\0\0\0\vfile:///efi", 25 <unfinished ...>
[pid 50382] <... ppoll resumed>) = 1 ([{fd=39, revents=POLLIN}])
[pid 1782] <... write resumed>) = 25
[pid 50382] ioctl(39, FIONREAD <unfinished ...>
[pid 1782] write(5, "\1\0\0\0\0\0\0\0", 8 <unfinished ...>
[pid 50382] <... ioctl resumed>, [25]) = 0
[pid 1782] <... write resumed>) = 8
[pid 1782] ppoll([{fd=5, events=POLLIN}, {fd=19, events=POLLIN}, {fd=22,
events=POLLIN}, {fd=34, events=POLLIN}, {fd=36, events=POLLIN}, {fd=40,
events=POLLIN}, {fd=43, events=POLLIN}, {fd=62, events=POLLIN}, {fd=72,
events=POLLIN}, {fd=78, events=POLLIN}, {fd=81, events=POLLIN}, {fd=82,
events=POLLIN}], 12, {tv_sec=30, tv_nsec=993000000}, NULL, 8 <unfinished ...>
[pid 50382] read(39, " f_5f_\0\0\0\vfile:///efi", 25) = 25
[pid 1782] <... ppoll resumed>) = 1 ([{fd=5, revents=POLLIN}], left
{tv_sec=30, tv_nsec=992993736})
[pid 50382] statfs("/efi" <unfinished ...>
[pid 1782] read(5, "\4\0\0\0\0\0\0\0", 8) = 8
[pid 50382] <... statfs resumed>, {f_type=MSDOS_SUPER_MAGIC, f_bsize=4096,
f_blocks=261628, f_bfree=182207, f_bavail=182207, f_files=0, f_ffree=0,
f_fsid={val=[0x10301, 0]}, f_namelen=1530, f_frsize=4096,
f_flags=ST_VALID|ST_NOSUID|ST_NODEV|ST_NOEXEC|ST_NOATIME}) = 0
[pid 1782] ppoll([{fd=5, events=POLLIN}, {fd=19, events=POLLIN}, {fd=22,
events=POLLIN}, {fd=34, events=POLLIN}, {fd=36, events=POLLIN}, {fd=40,
events=POLLIN}, {fd=43, events=POLLIN}, {fd=62, events=POLLIN}, {fd=72,
events=POLLIN}, {fd=78, events=POLLIN}, {fd=81, events=POLLIN}, {fd=82,
events=POLLIN}], 12, {tv_sec=30, tv_nsec=993000000}, NULL, 8 <unfinished ...>
[pid 50382] readlink("/efi", 0x7f303970f030, 1023) = -1 EINVAL (Invalid
argument)
[pid 50382] openat(AT_FDCWD, "/proc/self/mountinfo", O_RDONLY|O_CLOEXEC) = 37
[pid 50382] statx(37, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH,
STATX_ALL, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, stx_attributes=0,
stx_mode=S_IFREG|0444, stx_size=0, ...}) = 0
[pid 50382] statx(37, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH,
STATX_ALL, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, stx_attributes=0,
stx_mode=S_IFREG|0444, stx_size=0, ...}) = 0
[pid 50382] statx(37, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH,
STATX_ALL, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID, stx_attributes=0,
stx_mode=S_IFREG|0444, stx_size=0, ...}) = 0
[pid 50382] read(37, "69 2 0:34 / / rw,noatime shared:"..., 16384) = 2989
[pid 50382] read(37, "", 13395) = 0
[pid 50382] read(37, "", 16384) = 0
[pid 50382] close(37) = 0
[pid 50382] openat(AT_FDCWD, "/efi", O_RDONLY|O_CLOEXEC) = 37
[pid 50382] statx(37, "", AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH,
STATX_MNT_ID, {stx_mask=STATX_BASIC_STATS|STATX_MNT_ID,
stx_attributes=STATX_ATTR_MOUNT_ROOT, stx_mode=S_IFDIR|0755, stx_size=4096,
...}) = 0
[pid 50382] ioctl(37, FS_IOC_GETFSLABEL, 0x7f30397104d0) = -1 ENOTTY
(Inappropriate ioctl for device)
[pid 50382] openat(AT_FDCWD, "/dev/disk/by-label",
O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 44
[pid 50382] fstat(44, {st_mode=S_IFDIR|0755, st_size=80, ...}) = 0
[pid 50382] getdents64(44, 0x7f3028019920 /* 4 entries */, 32768) = 104
[pid 50382] newfstatat(AT_FDCWD, "/dev/disk/by-label/ESP",
{st_mode=S_IFBLK|0660, st_rdev=makedev(0x103, 0x1), ...}, 0) = 0
[pid 50382] close(44) = 0
[pid 50382] close(37) = 0
[pid 50382] write(38, "\1\0\0\0\0\0\0\0", 8) = 8
[pid 50382] ppoll([{fd=39, events=POLLIN|POLLOUT}], 1, NULL, NULL, 8) = 1
([{fd=39, revents=POLLOUT}])
[pid 50382] write(39, " 56_1b_\0\0\0\2\0\0\0\22\0a\0v\0a\0i\0l\0a\0b"...,
96) = 96
[pid 50382] write(38, "\1\0\0\0\0\0\0\0", 8) = 8
[pid 50382] write(38, "\1\0\0\0\0\0\0\0", 8 <unfinished ...>
The heavy artillery - just in case:
sudo bpftrace -e 'kprobe:autofs_direct_busy { printf("afdb start\n"); }
kretprobe:autofs_direct_busy { printf("afdb %d\n", retval); }
fentry:vmlinux:may_umount_tree { printf("mut %p\n", args.m); }
kretprobe:may_umount_tree { printf("mut %d\n", retval); }
fentry:vmlinux:mnt_get_count { printf("mgc %p %s\n", args.mnt,
str(args.mnt->mnt_devname)); } kretprobe:mnt_get_count { printf("mgc %d\n",
retval); } fentry:vmlinux:mntget { let $smnt = (struct
mount*)(((uint64)args.mnt) - offsetof(struct mount, mnt)); if
(strncmp(str($smnt->mnt_devname), "/dev/", 5) == 0) { printf("mntget %p %s %d
%s\n", $smnt, str($smnt->mnt_devname), pid, comm); } }'
--
You are receiving this mail because:
You are watching all bug changes.