From 537045ec2f4bd31167e2fd6beb27ee57058f1e77 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 23:09:09 +0100 Subject: [PATCH 01/17] recurse-dir: remove stale comment Follow-up for 6393b847f459dba14d2b615ee93babb143168b57 --- src/basic/recurse-dir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/basic/recurse-dir.c b/src/basic/recurse-dir.c index f7f8e4a7ab..0efa731868 100644 --- a/src/basic/recurse-dir.c +++ b/src/basic/recurse-dir.c @@ -36,8 +36,7 @@ int readdir_all(int dir_fd, RecurseDirFlags flags, DirectoryEntries **ret) { assert(dir_fd >= 0); - /* Returns an array with pointers to "struct dirent" directory entries, optionally sorted. Free the - * array with readdir_all_freep(). + /* Returns an array with pointers to "struct dirent" directory entries, optionally sorted. * * Start with space for up to 8 directory entries. We expect at least 2 ("." + ".."), hence hopefully * 8 will cover most cases comprehensively. (Note that most likely a lot more entries will actually From a3507f6628b4c5409bc7562f4ea291b1c0b36f34 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Mon, 19 Jan 2026 00:46:01 +0100 Subject: [PATCH 02/17] mkosi/opensuse: remove resolved TODO Follow-up for ff9c4ace709a1274b8f7e2569161da559c43fbd5 --- .../build/mkosi.conf.d/opensuse/mkosi.build.chroot | 3 --- 1 file changed, 3 deletions(-) diff --git a/mkosi/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot b/mkosi/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot index 15001ff9fc..5a05a34717 100755 --- a/mkosi/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot +++ b/mkosi/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot @@ -18,9 +18,6 @@ TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" # The openSUSE filelists hardcode the manpage compression extension. This causes rpmbuild errors since we # disable manpage compression as the files cannot be found. Fix the issue by removing the compression # extension. -# -# TODO: remove patches for removal of cgroups-agent, renaming pubring file, and removal of sysv files -# when the upstream spec is updated while read -r filelist; do sed -E \ -e 's/\.gz$//' \ From 77b4a411ac9c468704ea5568e7739d34c7ddb456 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 22:31:25 +0100 Subject: [PATCH 03/17] README: CONFIG_DEVPTS_MULTIPLE_INSTANCES has been dropped in v4.7 --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index f591f65114..c442db08c7 100644 --- a/README +++ b/README @@ -192,7 +192,7 @@ REQUIREMENTS: This is shipped by default, see modprobe.d/systemd.conf. Required for systemd-nspawn: - CONFIG_DEVPTS_MULTIPLE_INSTANCES or Linux kernel >= 4.7 + CONFIG_DEVPTS_MULTIPLE_INSTANCES (removed and unneeded since 4.7) Required for systemd-oomd: CONFIG_PSI From 254445e9271bbf5721573982b31945ea80e5b620 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Mon, 19 Jan 2026 12:49:02 +0100 Subject: [PATCH 04/17] README: kcmp() is unnecessary if we have F_DUPFD_QUERY (v6.10) --- README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README b/README index c442db08c7..2b19d2f21b 100644 --- a/README +++ b/README @@ -124,7 +124,8 @@ REQUIREMENTS: CONFIG_SECCOMP CONFIG_SECCOMP_FILTER (required for seccomp support) CONFIG_KCMP (for the kcmp() syscall, used to be under - CONFIG_CHECKPOINT_RESTORE before ~5.12) + CONFIG_CHECKPOINT_RESTORE before ~5.12; + not needed after 6.10) CONFIG_NET_SCHED CONFIG_NET_SCH_FQ_CODEL From 742308cabaed143dc397dfd886020847948ec0df Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 22:32:20 +0100 Subject: [PATCH 05/17] nspawn: drop compat glue for kernel < 3.14 --- README | 13 ------------- src/nspawn/nspawn.c | 12 ++---------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/README b/README index 2b19d2f21b..56361f5eef 100644 --- a/README +++ b/README @@ -199,19 +199,6 @@ REQUIREMENTS: CONFIG_PSI CONFIG_MEMCG - Note that kernel auditing is broken when used with systemd's container - code. When using systemd in conjunction with containers, please make - sure to either turn off auditing at runtime using the kernel command - line option "audit=0", or turn it off at kernel compile time using: - CONFIG_AUDIT=n - - If systemd is compiled with libseccomp support on architectures which do - not use socketcall() and where seccomp is supported (this effectively - means x86-64 and ARM, but excludes 32-bit x86!), then nspawn will now - install a work-around seccomp filter that makes containers boot even - with audit being enabled. This works correctly only on kernels 3.14 and - newer though. TL;DR: turn audit off, still. - glibc >= 2.31 libxcrypt >= 4.4.0 (optional) libmount >= 2.30 (from util-linux) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index a7b43cba91..851454dafa 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2767,16 +2767,8 @@ static int reset_audit_loginuid(void) { return 0; r = write_string_file("/proc/self/loginuid", "4294967295", WRITE_STRING_FILE_DISABLE_BUFFER); - if (r < 0) { - log_error_errno(r, - "Failed to reset audit login UID. This probably means that your kernel is too\n" - "old and you have audit enabled. Note that the auditing subsystem is known to\n" - "be incompatible with containers on old kernels. Please make sure to upgrade\n" - "your kernel or to off auditing with 'audit=0' on the kernel command line before\n" - "using systemd-nspawn. Sleeping for 5s... (%m)"); - - sleep(5); - } + if (r < 0) + return log_error_errno(r, "Failed to reset audit login UID: %m"); return 0; } From 42b09813f45842526ab9e7f458d5930663328d59 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 22:34:16 +0100 Subject: [PATCH 06/17] netlink-util: remove support for kernel < 5.5 --- src/libsystemd/sd-netlink/netlink-util.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c index 3cb5820ff6..4c1baafcb6 100644 --- a/src/libsystemd/sd-netlink/netlink-util.c +++ b/src/libsystemd/sd-netlink/netlink-util.c @@ -117,8 +117,7 @@ int rtnl_resolve_ifname_full( r = sd_netlink_call(*rtnl, message, 0, &reply); if (r >= 0) return parse_newlink_message(reply, ret_name, ret_altnames); - /* The kernels older than 76c9ac0ee878f6693d398d3a95ccaf85e1f597a6 (v5.5) return -EINVAL. */ - if (!IN_SET(r, -ENODEV, -EINVAL)) + if (r != -ENODEV) return r; } From 58fb46ecd5f2e1bcdca2f51c27a1512b37af525b Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 22:58:45 +0100 Subject: [PATCH 07/17] firewall-util: drop fallback for kernel < 5.8 --- src/shared/firewall-util.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/shared/firewall-util.c b/src/shared/firewall-util.c index 8032e131f7..93eef4eecf 100644 --- a/src/shared/firewall-util.c +++ b/src/shared/firewall-util.c @@ -1060,7 +1060,6 @@ static int fw_nftables_add_local_dnat_internal( sd_netlink_message *messages[3] = {}; _unused_ _cleanup_(netlink_message_unref_manyp) sd_netlink_message **unref = messages; - static bool ipv6_supported = true; uint32_t data[5], key[2], dlen; size_t msgcnt = 0; int r; @@ -1069,9 +1068,6 @@ static int fw_nftables_add_local_dnat_internal( assert(add || !previous_remote); assert(IN_SET(af, AF_INET, AF_INET6)); - if (!ipv6_supported && af == AF_INET6) - return -EOPNOTSUPP; - if (!IN_SET(protocol, IPPROTO_TCP, IPPROTO_UDP)) return -EPROTONOSUPPORT; @@ -1125,14 +1121,6 @@ static int fw_nftables_add_local_dnat_internal( assert(msgcnt < ELEMENTSOF(messages)); r = sd_nfnl_call_batch(nfnl, messages, msgcnt, NFNL_DEFAULT_TIMEOUT_USECS); - if (r == -EOVERFLOW && af == AF_INET6) { - /* The current implementation of DNAT in systemd requires kernel's - * fdb9c405e35bdc6e305b9b4e20ebc141ed14fc81 (v5.8), and the older kernel returns - * -EOVERFLOW. Let's treat the error as -EOPNOTSUPP. */ - log_debug_errno(r, "The current implementation of IPv6 DNAT in systemd requires kernel 5.8 or newer, ignoring: %m"); - ipv6_supported = false; - return -EOPNOTSUPP; - } if (r < 0) return r; From 6753bd8a2f38bd77a4c8b973174db6ec8bcaf3ab Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 22:44:56 +0100 Subject: [PATCH 08/17] mountpoint-util: assume MS_NOSYMFOLLOW is available Since our kernel baseline is v5.10 now. --- README | 2 +- TODO | 2 -- src/basic/mountpoint-util.c | 60 --------------------------------- src/basic/mountpoint-util.h | 1 - src/nspawn/nspawn.c | 6 ++-- src/shared/dissect-image.c | 2 +- src/shared/mount-util.c | 2 +- src/shared/mount-util.h | 2 +- src/test/test-mountpoint-util.c | 4 --- 9 files changed, 7 insertions(+), 74 deletions(-) diff --git a/README b/README index 56361f5eef..2410174138 100644 --- a/README +++ b/README @@ -52,7 +52,7 @@ REQUIREMENTS: BPF links and the BPF LSM hook ≥ 5.8 for LOOP_CONFIGURE and STATX_ATTR_MOUNT_ROOT ≥ 5.9 for close_range() - ≥ 5.10 for STATX_MNT_ID + ≥ 5.10 for STATX_MNT_ID and MS_NOSYMFOLLOW mount option ⛔ Kernel versions below 5.10 ("minimum baseline") are not supported at all, and are missing required functionality as listed above. diff --git a/TODO b/TODO index 6fb1d6597b..e24eade381 100644 --- a/TODO +++ b/TODO @@ -107,8 +107,6 @@ Deprecations and removals: * drop support for LOOP_CONFIGURE-less loopback block devices, once kernel baseline is 5.8. -* Once baseline is 5.10, remove support or MS_NOSYMFOLLOW-less kernels - * Remove /dev/mem ACPI FPDT parsing when /sys/firmware/acpi/fpdt is ubiquitous. That requires distros to enable CONFIG_ACPI_FPDT, and have kernels v5.12 for x86 and v6.2 for arm. diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c index 35bf3bdfcc..9c04d381f3 100644 --- a/src/basic/mountpoint-util.c +++ b/src/basic/mountpoint-util.c @@ -529,66 +529,6 @@ bool mount_new_api_supported(void) { return (cache = true); } -unsigned long ms_nosymfollow_supported(void) { - _cleanup_close_ int fsfd = -EBADF, mntfd = -EBADF; - static int cache = -1; - - /* Returns MS_NOSYMFOLLOW if it is supported, zero otherwise. */ - - if (cache >= 0) - return cache ? MS_NOSYMFOLLOW : 0; - - if (!mount_new_api_supported()) - goto not_supported; - - /* Checks if MS_NOSYMFOLLOW is supported (which was added in 5.10). We use the new mount API's - * mount_setattr() call for that, which was added in 5.12, which is close enough. */ - - fsfd = fsopen("tmpfs", FSOPEN_CLOEXEC); - if (fsfd < 0) { - if (ERRNO_IS_NOT_SUPPORTED(errno)) - goto not_supported; - - log_debug_errno(errno, "Failed to open superblock context for tmpfs: %m"); - return 0; - } - - if (fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0) < 0) { - if (ERRNO_IS_NOT_SUPPORTED(errno)) - goto not_supported; - - log_debug_errno(errno, "Failed to create tmpfs superblock: %m"); - return 0; - } - - mntfd = fsmount(fsfd, FSMOUNT_CLOEXEC, 0); - if (mntfd < 0) { - if (ERRNO_IS_NOT_SUPPORTED(errno)) - goto not_supported; - - log_debug_errno(errno, "Failed to turn superblock fd into mount fd: %m"); - return 0; - } - - if (mount_setattr(mntfd, "", AT_EMPTY_PATH|AT_RECURSIVE, - &(struct mount_attr) { - .attr_set = MOUNT_ATTR_NOSYMFOLLOW, - }, sizeof(struct mount_attr)) < 0) { - if (ERRNO_IS_NOT_SUPPORTED(errno)) - goto not_supported; - - log_debug_errno(errno, "Failed to set MOUNT_ATTR_NOSYMFOLLOW mount attribute: %m"); - return 0; - } - - cache = true; - return MS_NOSYMFOLLOW; - -not_supported: - cache = false; - return 0; -} - int mount_option_supported(const char *fstype, const char *key, const char *value) { _cleanup_close_ int fd = -EBADF; int r; diff --git a/src/basic/mountpoint-util.h b/src/basic/mountpoint-util.h index 899e9635d1..659f038556 100644 --- a/src/basic/mountpoint-util.h +++ b/src/basic/mountpoint-util.h @@ -75,7 +75,6 @@ int mount_propagation_flag_from_string(const char *name, unsigned long *ret); bool mount_propagation_flag_is_valid(unsigned long flag); bool mount_new_api_supported(void); -unsigned long ms_nosymfollow_supported(void); int mount_option_supported(const char *fstype, const char *key, const char *value); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 851454dafa..6cfc0e7395 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3767,7 +3767,7 @@ static int setup_unix_export_dir_outside(char **ret) { "tmpfs", q, "tmpfs", - MS_NODEV|MS_NOEXEC|MS_NOSUID|ms_nosymfollow_supported(), + MS_NODEV|MS_NOEXEC|MS_NOSUID|MS_NOSYMFOLLOW, "size=4M,nr_inodes=64,mode=0755"); if (r < 0) return r; @@ -3781,7 +3781,7 @@ static int setup_unix_export_dir_outside(char **ret) { /* what= */ NULL, w, /* fstype= */ NULL, - MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NODEV|MS_NOEXEC|MS_NOSUID|ms_nosymfollow_supported(), + MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NODEV|MS_NOEXEC|MS_NOSUID|MS_NOSYMFOLLOW, /* options= */ NULL); if (r < 0) return r; @@ -3826,7 +3826,7 @@ static int setup_unix_export_host_inside(const char *directory, const char *unix /* what= */ NULL, p, /* fstype= */ NULL, - MS_BIND|MS_REMOUNT|MS_NODEV|MS_NOEXEC|MS_NOSUID|ms_nosymfollow_supported(), + MS_BIND|MS_REMOUNT|MS_NODEV|MS_NOEXEC|MS_NOSUID|MS_NOSYMFOLLOW, /* options= */ NULL); if (r < 0) return r; diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 14120f2d57..97dc89e5a4 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -2383,7 +2383,7 @@ int partition_pick_mount_options( case PARTITION_ESP: case PARTITION_XBOOTLDR: - flags |= MS_NOSUID|MS_NOEXEC|ms_nosymfollow_supported(); + flags |= MS_NOSUID|MS_NOEXEC|MS_NOSYMFOLLOW; /* The ESP might contain a pre-boot random seed. Let's make this unaccessible to regular * userspace. ESP/XBOOTLDR is almost certainly VFAT, hence if we don't know assume it is. */ diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index 31b1ca2b36..f3eaa7ba97 100644 --- a/src/shared/mount-util.c +++ b/src/shared/mount-util.c @@ -1951,7 +1951,7 @@ int trigger_automount_at(int dir_fd, const char *path) { unsigned long credentials_fs_mount_flags(bool ro) { /* A tight set of mount flags for credentials mounts */ - return MS_NODEV|MS_NOEXEC|MS_NOSUID|ms_nosymfollow_supported()|(ro ? MS_RDONLY : 0); + return MS_NODEV|MS_NOEXEC|MS_NOSUID|MS_NOSYMFOLLOW|(ro ? MS_RDONLY : 0); } int fsmount_credentials_fs(int *ret_fsfd) { diff --git a/src/shared/mount-util.h b/src/shared/mount-util.h index 8d907988eb..768aacf09c 100644 --- a/src/shared/mount-util.h +++ b/src/shared/mount-util.h @@ -166,7 +166,7 @@ int make_mount_point_inode_from_path(const char *source, const char *dest, mode_ int trigger_automount_at(int dir_fd, const char *path); -unsigned long credentials_fs_mount_flags(bool ro); +unsigned long credentials_fs_mount_flags(bool ro) _const_; int fsmount_credentials_fs(int *ret_fsfd); int mount_credentials_fs(const char *path); diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c index ba2ed3b347..7381357336 100644 --- a/src/test/test-mountpoint-util.c +++ b/src/test/test-mountpoint-util.c @@ -359,10 +359,6 @@ TEST(is_mount_point_at) { ASSERT_OK(is_mount_point_at(fd, "regular", 0)); } -TEST(ms_nosymfollow_supported) { - log_info("MS_NOSYMFOLLOW supported: %s", yes_no(ms_nosymfollow_supported())); -} - TEST(mount_option_supported) { int r; From 52bf232e82d22a8c1443c40bfadcded2d65ea07a Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 23:02:19 +0100 Subject: [PATCH 09/17] fs-util: drop fallback for kernels without AT_EMPTY_PATH support (< 5.8) --- src/basic/fs-util.c | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index d3712622f1..4ca01c7444 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -321,22 +321,7 @@ int futimens_opath(int fd, const struct timespec ts[2]) { assert(fd >= 0); - if (utimensat(fd, "", ts, AT_EMPTY_PATH) >= 0) - return 0; - if (errno != EINVAL) - return -errno; - - /* Support for AT_EMPTY_PATH is added rather late (kernel 5.8), so fall back to going through /proc/ - * if unavailable. */ - - if (utimensat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), ts, /* flags= */ 0) < 0) { - if (errno != ENOENT) - return -errno; - - return proc_fd_enoent_errno(); - } - - return 0; + return RET_NERRNO(utimensat(fd, "", ts, AT_EMPTY_PATH)); } int stat_warn_permissions(const char *path, const struct stat *st) { @@ -722,22 +707,7 @@ int access_fd(int fd, int mode) { assert(fd >= 0); - if (faccessat(fd, "", mode, AT_EMPTY_PATH) >= 0) - return 0; - if (errno != EINVAL) - return -errno; - - /* Support for AT_EMPTY_PATH is added rather late (kernel 5.8), so fall back to going through /proc/ - * if unavailable. */ - - if (access(FORMAT_PROC_FD_PATH(fd), mode) < 0) { - if (errno != ENOENT) - return -errno; - - return proc_fd_enoent_errno(); - } - - return 0; + return RET_NERRNO(faccessat(fd, "", mode, AT_EMPTY_PATH)); } int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) { From 9b906ae48ee658ac4aa425b25933efe87c2477e8 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 23:04:39 +0100 Subject: [PATCH 10/17] fs-util: group access_fd() with access_nofollow() --- src/basic/fs-util.c | 26 +++++++++++++------------- src/basic/fs-util.h | 3 +-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 4ca01c7444..0159934ddb 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -360,6 +360,19 @@ int access_nofollow(const char *path, int mode) { return RET_NERRNO(faccessat(AT_FDCWD, path, mode, AT_SYMLINK_NOFOLLOW)); } +int access_fd(int fd, int mode) { + /* Like access() but operates on an already open fd */ + + if (fd == AT_FDCWD) + return RET_NERRNO(access(".", mode)); + if (fd == XAT_FDROOT) + return RET_NERRNO(access("/", mode)); + + assert(fd >= 0); + + return RET_NERRNO(faccessat(fd, "", mode, AT_EMPTY_PATH)); +} + int touch_fd(int fd, usec_t stamp) { assert(fd >= 0); @@ -697,19 +710,6 @@ char* unlink_and_free(char *p) { return mfree(p); } -int access_fd(int fd, int mode) { - /* Like access() but operates on an already open fd */ - - if (fd == AT_FDCWD) - return RET_NERRNO(access(".", mode)); - if (fd == XAT_FDROOT) - return RET_NERRNO(access("/", mode)); - - assert(fd >= 0); - - return RET_NERRNO(faccessat(fd, "", mode, AT_EMPTY_PATH)); -} - int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) { _cleanup_close_ int truncate_fd = -EBADF; struct stat st; diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index b26674d139..d75c253dbb 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -42,6 +42,7 @@ int fd_warn_permissions(const char *path, int fd); int stat_warn_permissions(const char *path, const struct stat *st); int access_nofollow(const char *path, int mode); +int access_fd(int fd, int mode); int touch_fd(int fd, usec_t stamp); int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode); @@ -86,8 +87,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rmdir_and_free); char* unlink_and_free(char *p); DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free); -int access_fd(int fd, int mode); - typedef enum UnlinkDeallocateFlags { UNLINK_REMOVEDIR = 1 << 0, UNLINK_ERASE = 1 << 1, From 02bf2b7cdfb26af99e13dded572b1ff44f04049a Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Mon, 19 Jan 2026 00:53:48 +0100 Subject: [PATCH 11/17] fs-util: optimize xopenat(XAT_FDROOT, ...) a bit Follow-up for ef582ab201c2942813960ad3c451df3642d85558 * Open / with O_PATH * Shortcut to fd_reopen() directly if path is empty --- src/basic/fs-util.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 0159934ddb..f790ca4e13 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1158,19 +1158,6 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_ * • The dir fd can be passed as XAT_FDROOT, in which case any relative paths will be taken relative to the root fs. */ - _cleanup_close_ int _dir_fd = -EBADF; - if (dir_fd == XAT_FDROOT) { - if (path_is_absolute(path)) - dir_fd = AT_FDCWD; - else { - _dir_fd = open("/", O_CLOEXEC|O_DIRECTORY|O_RDONLY); - if (_dir_fd < 0) - return -errno; - - dir_fd = _dir_fd; - } - } - if (mode == MODE_INVALID) mode = (open_flags & O_DIRECTORY) ? 0755 : 0644; @@ -1186,6 +1173,19 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_ return fd_reopen(dir_fd, open_flags & ~O_NOFOLLOW); } + _cleanup_close_ int _dir_fd = -EBADF; + if (dir_fd == XAT_FDROOT) { + if (path_is_absolute(path)) + dir_fd = AT_FDCWD; + else { + _dir_fd = open("/", O_CLOEXEC|O_DIRECTORY|O_PATH); + if (_dir_fd < 0) + return -errno; + + dir_fd = _dir_fd; + } + } + bool call_label_ops_post = false; if (FLAGS_SET(open_flags, O_CREAT) && FLAGS_SET(xopen_flags, XO_LABEL)) { From b0906b12168dd82cd5ffca3913dcda7d75e58a53 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Mon, 19 Jan 2026 01:13:01 +0100 Subject: [PATCH 12/17] stat-util: do not use RET_NERRNO for our own function Follow-up for 95abe4beff08636681069623ffdf16cfa34c7cf8 --- src/basic/stat-util.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index d1c5d7aa37..5113d0459b 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -257,6 +257,22 @@ static int xfstatfs(int fd, struct statfs *ret) { return RET_NERRNO(fstatfs(fd, ret)); } +int xstatfsat(int dir_fd, const char *path, struct statfs *ret) { + _cleanup_close_ int fd = -EBADF; + + assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT)); + assert(ret); + + if (!isempty(path)) { + fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return fd; + dir_fd = fd; + } + + return xfstatfs(dir_fd, ret); +} + int fd_is_read_only_fs(int fd) { int r; @@ -522,22 +538,6 @@ bool statx_mount_same(const struct statx *a, const struct statx *b) { return a->stx_mnt_id == b->stx_mnt_id; } -int xstatfsat(int dir_fd, const char *path, struct statfs *ret) { - _cleanup_close_ int fd = -EBADF; - - assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT)); - assert(ret); - - if (!isempty(path)) { - fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY); - if (fd < 0) - return fd; - dir_fd = fd; - } - - return RET_NERRNO(xfstatfs(dir_fd, ret)); -} - usec_t statx_timestamp_load(const struct statx_timestamp *ts) { return timespec_load(&(const struct timespec) { .tv_sec = ts->tv_sec, .tv_nsec = ts->tv_nsec }); } From 5f90e4e4bc23982c9f06f85fc278245560b7a622 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Mon, 19 Jan 2026 01:15:18 +0100 Subject: [PATCH 13/17] stat-util: O_NOCTTY is nop with O_PATH --- src/basic/stat-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 5113d0459b..628d99ac5a 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -264,7 +264,7 @@ int xstatfsat(int dir_fd, const char *path, struct statfs *ret) { assert(ret); if (!isempty(path)) { - fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY); + fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC); if (fd < 0) return fd; dir_fd = fd; From 6fd7c5ecdfd569d8c491b9583510a16c1e87290b Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 22:54:17 +0100 Subject: [PATCH 14/17] core/namespace: remove availability checks for procfs hidepid=/subset= opts --- README | 3 ++- src/core/namespace.c | 33 +++++++++------------------------ 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/README b/README index 2410174138..3f4bce5c92 100644 --- a/README +++ b/README @@ -50,7 +50,8 @@ REQUIREMENTS: ≥ 5.6 for getrandom() GRND_INSECURE ≥ 5.7 for CLONE_INTO_CGROUP, cgroup2fs memory_recursiveprot option, BPF links and the BPF LSM hook - ≥ 5.8 for LOOP_CONFIGURE and STATX_ATTR_MOUNT_ROOT + ≥ 5.8 for LOOP_CONFIGURE, STATX_ATTR_MOUNT_ROOT, and procfs + per-instance hidepid=/subset= options ≥ 5.9 for close_range() ≥ 5.10 for STATX_MNT_ID and MS_NOSYMFOLLOW mount option diff --git a/src/core/namespace.c b/src/core/namespace.c index 87d93a4fe7..065e291ccb 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1515,6 +1515,7 @@ static int mount_private_cgroup2fs(const MountEntry *m, const NamespaceParameter static int mount_procfs(const MountEntry *m, const NamespaceParameters *p) { _cleanup_free_ char *opts = NULL; + int r; assert(m); assert(p); @@ -1522,32 +1523,16 @@ static int mount_procfs(const MountEntry *m, const NamespaceParameters *p) { if (p->protect_proc != PROTECT_PROC_DEFAULT || p->proc_subset != PROC_SUBSET_ALL) { - /* Starting with kernel 5.8 procfs' hidepid= logic is truly per-instance (previously it - * pretended to be per-instance but actually was per-namespace), hence let's make use of it - * if requested. To make sure this logic succeeds only on kernels where hidepid= is - * per-instance, we'll exclusively use the textual value for hidepid=, since support was - * added in the same commit: if it's supported it is thus also per-instance. */ + opts = strjoin("hidepid=", + p->protect_proc == PROTECT_PROC_DEFAULT ? "off" : protect_proc_to_string(p->protect_proc)); + if (!opts) + return -ENOMEM; - const char *hpv = p->protect_proc == PROTECT_PROC_DEFAULT ? - "off" : - protect_proc_to_string(p->protect_proc); - - /* hidepid= support was added in 5.8, so we can use fsconfig()/fsopen() (which were added in - * 5.2) to check if hidepid= is supported. This avoids a noisy dmesg log by the kernel when - * trying to use hidepid= on systems where it isn't supported. The same applies for subset=. - * fsopen()/fsconfig() was also backported on some distros which allows us to detect - * hidepid=/subset= support in even more scenarios. */ - - if (mount_option_supported("proc", "hidepid", hpv) > 0) { - opts = strjoin("hidepid=", hpv); - if (!opts) - return -ENOMEM; + if (p->proc_subset != PROC_SUBSET_ALL) { + r = strextendf_with_separator(&opts, ",", "subset=%s", proc_subset_to_string(p->proc_subset)); + if (r < 0) + return r; } - - if (p->proc_subset == PROC_SUBSET_PID && - mount_option_supported("proc", "subset", "pid") > 0) - if (!strextend_with_separator(&opts, ",", "subset=pid")) - return -ENOMEM; } /* Mount a new instance, so that we get the one that matches our user namespace, if we are running in From 8292b859f39bfcb14a1687242b20cb8645b6ea15 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sun, 18 Jan 2026 22:40:30 +0100 Subject: [PATCH 15/17] core/cgroup: drop trusted.survive_final_kill_signal fallback for kernel < 5.7 --- src/core/cgroup.c | 33 +++------------------------------ src/shared/killall.c | 3 --- 2 files changed, 3 insertions(+), 33 deletions(-) diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 9a218ff058..c4336cd80e 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -944,39 +944,12 @@ static void cgroup_delegate_xattr_apply(Unit *u) { } static void cgroup_survive_xattr_apply(Unit *u) { - int r; - assert(u); - CGroupRuntime *crt = unit_get_cgroup_runtime(u); - if (!crt) - return; - - if (u->survive_final_kill_signal) { - r = cg_set_xattr( - crt->cgroup_path, - "user.survive_final_kill_signal", - "1", - 1, - /* flags= */ 0); - /* user xattr support was added in kernel v5.7 */ - if (ERRNO_IS_NEG_NOT_SUPPORTED(r)) - r = cg_set_xattr( - crt->cgroup_path, - "trusted.survive_final_kill_signal", - "1", - 1, - /* flags= */ 0); - if (r < 0) - log_unit_debug_errno(u, - r, - "Failed to set 'survive_final_kill_signal' xattr on control " - "group %s, ignoring: %m", - empty_to_root(crt->cgroup_path)); - } else { + if (u->survive_final_kill_signal) + unit_set_xattr_graceful(u, "user.survive_final_kill_signal", "1", 1); + else unit_remove_xattr_graceful(u, "user.survive_final_kill_signal"); - unit_remove_xattr_graceful(u, "trusted.survive_final_kill_signal"); - } } static void cgroup_xattr_apply(Unit *u) { diff --git a/src/shared/killall.c b/src/shared/killall.c index 729e0e2480..d81f385634 100644 --- a/src/shared/killall.c +++ b/src/shared/killall.c @@ -64,9 +64,6 @@ static bool is_in_survivor_cgroup(const PidRef *pid) { } r = cg_get_xattr_bool(cgroup_path, "user.survive_final_kill_signal"); - /* user xattr support was added to kernel v5.7, try with the trusted namespace as a fallback */ - if (ERRNO_IS_NEG_XATTR_ABSENT(r)) - r = cg_get_xattr_bool(cgroup_path, "trusted.survive_final_kill_signal"); if (r < 0 && !ERRNO_IS_NEG_XATTR_ABSENT(r)) log_debug_errno(r, "Failed to get survive_final_kill_signal xattr of %s, ignoring: %m", From d57fdbb5e29dbec320eb755e5512ba57033ddbc7 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Mon, 19 Jan 2026 02:05:33 +0100 Subject: [PATCH 16/17] core/cgroup: do not consider cgroup_context_has_io_config() if only IOAccounting=yes This makes things in line with unit_has_memory_config(), and suppresses pointless application of IO configs. --- src/core/cgroup.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/cgroup.c b/src/core/cgroup.c index c4336cd80e..6519440e45 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -1150,8 +1150,9 @@ static void cgroup_apply_cpuset(Unit *u, const CPUSet *cpus, const char *name) { } static bool cgroup_context_has_io_config(CGroupContext *c) { - return c->io_accounting || - c->io_weight != CGROUP_WEIGHT_INVALID || + assert(c); + + return c->io_weight != CGROUP_WEIGHT_INVALID || c->startup_io_weight != CGROUP_WEIGHT_INVALID || c->io_device_weights || c->io_device_latencies || @@ -1691,7 +1692,8 @@ static CGroupMask unit_get_cgroup_mask(Unit *u) { if (cgroup_context_has_allowed_cpus(c) || cgroup_context_has_allowed_mems(c)) mask |= CGROUP_MASK_CPUSET; - if (cgroup_context_has_io_config(c)) + if (c->io_accounting || + cgroup_context_has_io_config(c)) mask |= CGROUP_MASK_IO; if (c->memory_accounting || From 1a0df07843cd5803a0858dd0b646e12992e7561a Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sat, 17 Jan 2026 01:21:34 +0100 Subject: [PATCH 17/17] core/cgroup: obsolete DefaultMemoryMin/Low= Now that our kernel baseline is v5.7 and memory_recursiveprot is universally enabled, remove userspace workarounds. --- TODO | 4 - man/org.freedesktop.systemd1.xml | 108 -------------- man/systemd.resource-control.xml | 12 +- src/core/cgroup.c | 63 ++------ src/core/cgroup.h | 12 -- src/core/dbus-cgroup.c | 84 +++-------- src/core/execute-serialize.c | 65 --------- src/core/load-fragment-gperf.gperf.in | 6 +- src/core/load-fragment.c | 26 +--- src/core/varlink-cgroup.c | 7 +- src/shared/bus-get-properties.c | 1 + src/shared/bus-get-properties.h | 1 + src/shared/bus-unit-util.c | 6 +- src/shared/varlink-io.systemd.Unit.c | 6 - src/systemctl/systemctl-show.c | 7 - src/test/meson.build | 3 - src/test/test-cgroup-unit-default.c | 136 ------------------ test/meson.build | 1 - .../dml-discard-empty.service | 8 -- .../dml-discard-set-ml.service | 9 -- .../dml-discard.slice | 6 - .../dml-override-empty.service | 8 -- .../dml-override.slice | 6 - .../dml-passthrough-empty.service | 8 -- .../dml-passthrough-set-dml.service | 9 -- .../dml-passthrough-set-ml.service | 9 -- .../dml-passthrough.slice | 6 - test/test-cgroup-unit-default/dml.slice | 6 - 28 files changed, 48 insertions(+), 575 deletions(-) delete mode 100644 src/test/test-cgroup-unit-default.c delete mode 100644 test/test-cgroup-unit-default/dml-discard-empty.service delete mode 100644 test/test-cgroup-unit-default/dml-discard-set-ml.service delete mode 100644 test/test-cgroup-unit-default/dml-discard.slice delete mode 100644 test/test-cgroup-unit-default/dml-override-empty.service delete mode 100644 test/test-cgroup-unit-default/dml-override.slice delete mode 100644 test/test-cgroup-unit-default/dml-passthrough-empty.service delete mode 100644 test/test-cgroup-unit-default/dml-passthrough-set-dml.service delete mode 100644 test/test-cgroup-unit-default/dml-passthrough-set-ml.service delete mode 100644 test/test-cgroup-unit-default/dml-passthrough.slice delete mode 100644 test/test-cgroup-unit-default/dml.slice diff --git a/TODO b/TODO index e24eade381..d45ee30dc9 100644 --- a/TODO +++ b/TODO @@ -120,10 +120,6 @@ Deprecations and removals: https://github.com/util-linux/util-linux/commit/508fb0e7ac103b68531a59db2a4473897853ab52 has hit the prominent distributions, revert --issue-file= hack in units/*getty*service.in -* Once kernel baseline is 5.7, obsolete DefaultMemoryMin/Low= and DefaultStartupMemoryLow= - since we can systematically enable memory_recursiveprot on cgroupfs and have those - enforced by the kernel - Features: * systemd-sysupdate: add support a "best before" in manifests (ie. SHA256SUMS) diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 7a65bfa809..e6c2c6fdab 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -2969,12 +2969,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b MemoryAccounting = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultStartupMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryMin = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryMin = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryLow = ...; @@ -3642,12 +3636,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - - - - @@ -4336,12 +4324,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - - - - @@ -5238,12 +5220,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b MemoryAccounting = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultStartupMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryMin = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryMin = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryLow = ...; @@ -5929,12 +5905,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - - - - @@ -6599,12 +6569,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - - - - @@ -7325,12 +7289,6 @@ node /org/freedesktop/systemd1/unit/home_2emount { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b MemoryAccounting = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultStartupMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryMin = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryMin = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryLow = ...; @@ -7940,12 +7898,6 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - - - - @@ -8518,12 +8470,6 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - - - - @@ -9377,12 +9323,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b MemoryAccounting = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultStartupMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryMin = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryMin = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryLow = ...; @@ -9974,12 +9914,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - - - - - @@ -10534,12 +10468,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - - - - - @@ -11246,12 +11174,6 @@ node /org/freedesktop/systemd1/unit/system_2eslice { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b MemoryAccounting = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultStartupMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryMin = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryMin = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryLow = ...; @@ -11427,12 +11349,6 @@ node /org/freedesktop/systemd1/unit/system_2eslice { - - - - - - @@ -11619,12 +11535,6 @@ node /org/freedesktop/systemd1/unit/system_2eslice { - - - - - - @@ -11836,12 +11746,6 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b MemoryAccounting = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultStartupMemoryLow = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t DefaultMemoryMin = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryMin = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t MemoryLow = ...; @@ -12031,12 +11935,6 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { - - - - - - @@ -12247,12 +12145,6 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { - - - - - - diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index cabadb74f7..12a3c0e644 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -326,7 +326,7 @@ CPUWeight=20 DisableControllers=cpu / \ MemoryMin=bytes, MemoryLow=bytes - StartupMemoryLow=bytes, DefaultStartupMemoryLow=bytes + StartupMemoryLow=bytes These settings control the controller in the unified hierarchy. @@ -353,16 +353,6 @@ CPUWeight=20 DisableControllers=cpu / \ For details about this control group attribute, see Memory Interface Files. - Units may have their children use a default memory.min or - memory.low value by specifying DefaultMemoryMin= or - DefaultMemoryLow=, which has the same semantics as - MemoryMin= and MemoryLow=, or DefaultStartupMemoryLow= - which has the same semantics as StartupMemoryLow=. - This setting does not affect memory.min or memory.low - in the unit itself. - Using it to set a default child allocation is only useful on kernels older than 5.7, - which do not support the memory_recursiveprot cgroup2 mount option. - While StartupMemoryLow= applies to the startup and shutdown phases of the system, MemoryMin= applies to normal runtime of the system, and if the former is not set also to the startup and shutdown phases. Using StartupMemoryLow= allows prioritizing specific services at diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 6519440e45..6a434eba84 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -330,13 +330,13 @@ static int unit_compare_memory_limit(Unit *u, const char *property_name, uint64_ bool startup = u->manager && IN_SET(manager_state(u->manager), MANAGER_STARTING, MANAGER_INITIALIZING, MANAGER_STOPPING); if (streq(property_name, "MemoryLow")) { - unit_value = unit_get_ancestor_memory_low(u); + unit_value = c->memory_low; file = "memory.low"; } else if (startup && streq(property_name, "StartupMemoryLow")) { - unit_value = unit_get_ancestor_startup_memory_low(u); + unit_value = c->startup_memory_low; file = "memory.low"; } else if (streq(property_name, "MemoryMin")) { - unit_value = unit_get_ancestor_memory_min(u); + unit_value = c->memory_min; file = "memory.min"; } else if (streq(property_name, "MemoryHigh")) { unit_value = c->memory_high; @@ -504,8 +504,6 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { "%sStartupAllowedMemoryNodes: %s\n" "%sIOWeight: %" PRIu64 "\n" "%sStartupIOWeight: %" PRIu64 "\n" - "%sDefaultMemoryMin: %" PRIu64 "\n" - "%sDefaultMemoryLow: %" PRIu64 "\n" "%sMemoryMin: %" PRIu64 "%s\n" "%sMemoryLow: %" PRIu64 "%s\n" "%sStartupMemoryLow: %" PRIu64 "%s\n" @@ -542,8 +540,6 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { prefix, strempty(startup_cpuset_mems), prefix, c->io_weight, prefix, c->startup_io_weight, - prefix, c->default_memory_min, - prefix, c->default_memory_low, prefix, c->memory_min, format_cgroup_memory_limit_comparison(u, "MemoryMin", cda, sizeof(cda)), prefix, c->memory_low, format_cgroup_memory_limit_comparison(u, "MemoryLow", cdb, sizeof(cdb)), prefix, c->startup_memory_low, format_cgroup_memory_limit_comparison(u, "StartupMemoryLow", cdc, sizeof(cdc)), @@ -764,36 +760,6 @@ int cgroup_context_add_bpf_foreign_program(CGroupContext *c, uint32_t attach_typ return 0; } -#define UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(entry) \ - uint64_t unit_get_ancestor_##entry(Unit *u) { \ - CGroupContext *c; \ - \ - /* 1. Is entry set in this unit? If so, use that. \ - * 2. Is the default for this entry set in any \ - * ancestor? If so, use that. \ - * 3. Otherwise, return CGROUP_LIMIT_MIN. */ \ - \ - assert(u); \ - \ - c = unit_get_cgroup_context(u); \ - if (c && c->entry##_set) \ - return c->entry; \ - \ - while ((u = UNIT_GET_SLICE(u))) { \ - c = unit_get_cgroup_context(u); \ - if (c && c->default_##entry##_set) \ - return c->default_##entry; \ - } \ - \ - /* We've reached the root, but nobody had default for \ - * this entry set, so set it to the kernel default. */ \ - return CGROUP_LIMIT_MIN; \ -} - -UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_low); -UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(startup_memory_low); -UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_min); - static void unit_set_xattr_graceful(Unit *u, const char *name, const void *data, size_t size) { int r; @@ -1263,15 +1229,11 @@ static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t (void) set_attribute_and_warn(u, "io.max", buf); } -static bool unit_has_memory_config(Unit *u) { - CGroupContext *c; +static bool cgroup_context_has_memory_config(CGroupContext *c) { + assert(c); - assert(u); - - assert_se(c = unit_get_cgroup_context(u)); - - return unit_get_ancestor_memory_min(u) > 0 || - unit_get_ancestor_memory_low(u) > 0 || unit_get_ancestor_startup_memory_low(u) > 0 || + return c->memory_min > 0 || + c->memory_low > 0 || c->startup_memory_low_set || c->memory_high != CGROUP_LIMIT_MAX || c->startup_memory_high_set || c->memory_max != CGROUP_LIMIT_MAX || c->startup_memory_max_set || c->memory_swap_max != CGROUP_LIMIT_MAX || c->startup_memory_swap_max_set || @@ -1517,19 +1479,20 @@ static void cgroup_context_apply( /* 'memory' attributes do not exist on the root cgroup. */ if ((apply_mask & CGROUP_MASK_MEMORY) && !is_local_root) { - uint64_t max = CGROUP_LIMIT_MAX, swap_max = CGROUP_LIMIT_MAX, zswap_max = CGROUP_LIMIT_MAX, high = CGROUP_LIMIT_MAX; + uint64_t low = CGROUP_LIMIT_MIN, max = CGROUP_LIMIT_MAX, swap_max = CGROUP_LIMIT_MAX, zswap_max = CGROUP_LIMIT_MAX, high = CGROUP_LIMIT_MAX; - if (unit_has_memory_config(u)) { + if (cgroup_context_has_memory_config(c)) { bool startup = IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING, MANAGER_STOPPING); + low = startup && c->startup_memory_low_set ? c->startup_memory_low : c->memory_low; high = startup && c->startup_memory_high_set ? c->startup_memory_high : c->memory_high; max = startup && c->startup_memory_max_set ? c->startup_memory_max : c->memory_max; swap_max = startup && c->startup_memory_swap_max_set ? c->startup_memory_swap_max : c->memory_swap_max; zswap_max = startup && c->startup_memory_zswap_max_set ? c->startup_memory_zswap_max : c->memory_zswap_max; } - cgroup_apply_memory_limit(u, "memory.min", unit_get_ancestor_memory_min(u)); - cgroup_apply_memory_limit(u, "memory.low", unit_get_ancestor_memory_low(u)); + cgroup_apply_memory_limit(u, "memory.min", c->memory_min); + cgroup_apply_memory_limit(u, "memory.low", low); cgroup_apply_memory_limit(u, "memory.high", high); cgroup_apply_memory_limit(u, "memory.max", max); cgroup_apply_memory_limit(u, "memory.swap.max", swap_max); @@ -1697,7 +1660,7 @@ static CGroupMask unit_get_cgroup_mask(Unit *u) { mask |= CGROUP_MASK_IO; if (c->memory_accounting || - unit_has_memory_config(u)) + cgroup_context_has_memory_config(c)) mask |= CGROUP_MASK_MEMORY; if (cgroup_context_has_device_policy(c)) diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 5d450bd608..0cd290e92f 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -137,9 +137,6 @@ typedef struct CGroupContext { LIST_HEAD(CGroupIODeviceLimit, io_device_limits); LIST_HEAD(CGroupIODeviceLatency, io_device_latencies); - uint64_t default_memory_min; - uint64_t default_memory_low; - uint64_t default_startup_memory_low; uint64_t memory_min; uint64_t memory_low; uint64_t startup_memory_low; @@ -152,11 +149,6 @@ typedef struct CGroupContext { uint64_t memory_zswap_max; uint64_t startup_memory_zswap_max; - bool default_memory_min_set:1; - bool default_memory_low_set:1; - bool default_startup_memory_low_set:1; - bool memory_min_set:1; - bool memory_low_set:1; bool startup_memory_low_set:1; bool startup_memory_high_set:1; bool startup_memory_max_set:1; @@ -416,10 +408,6 @@ Unit* manager_get_unit_by_pidref_cgroup(Manager *m, const PidRef *pid); Unit* manager_get_unit_by_pidref_watching(Manager *m, const PidRef *pid); Unit* manager_get_unit_by_pidref(Manager *m, PidRef *pid); -uint64_t unit_get_ancestor_memory_min(Unit *u); -uint64_t unit_get_ancestor_memory_low(Unit *u); -uint64_t unit_get_ancestor_startup_memory_low(Unit *u); - int unit_search_main_pid(Unit *u, PidRef *ret); int unit_get_memory_available(Unit *u, uint64_t *ret); diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 92c59cd4ec..dcb27f80f8 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -395,9 +395,6 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0), SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency, 0, 0), SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0), - SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL, offsetof(CGroupContext, default_memory_low), 0), - SD_BUS_PROPERTY("DefaultStartupMemoryLow", "t", NULL, offsetof(CGroupContext, default_startup_memory_low), 0), - SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL, offsetof(CGroupContext, default_memory_min), 0), SD_BUS_PROPERTY("MemoryMin", "t", NULL, offsetof(CGroupContext, memory_min), 0), SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0), SD_BUS_PROPERTY("StartupMemoryLow", "t", NULL, offsetof(CGroupContext, startup_memory_low), 0), @@ -447,6 +444,10 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_ast, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN), /* since kernel v4.15 CPU accounting requires no controller, i.e. is available everywhere */ SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool_true, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN), + /* since kernel v5.7 kernel would take care of these when cgroup is mounted with memory_recursiveprot */ + SD_BUS_PROPERTY("DefaultMemoryMin", "t", bus_property_get_uint64_0, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("DefaultMemoryLow", "t", bus_property_get_uint64_0, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("DefaultStartupMemoryLow", "t", bus_property_get_uint64_0, 0, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_HIDDEN), SD_BUS_VTABLE_END }; @@ -1053,19 +1054,11 @@ int bus_cgroup_set_property( if (streq(name, "MemoryAccounting")) return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, reterr_error); - if (streq(name, "MemoryMin")) { - r = bus_cgroup_set_memory_protection(u, name, &c->memory_min, message, flags, reterr_error); - if (r > 0) - c->memory_min_set = true; - return r; - } + if (streq(name, "MemoryMin")) + return bus_cgroup_set_memory_protection(u, name, &c->memory_min, message, flags, reterr_error); - if (streq(name, "MemoryLow")) { - r = bus_cgroup_set_memory_protection(u, name, &c->memory_low, message, flags, reterr_error); - if (r > 0) - c->memory_low_set = true; - return r; - } + if (streq(name, "MemoryLow")) + return bus_cgroup_set_memory_protection(u, name, &c->memory_low, message, flags, reterr_error); if (streq(name, "StartupMemoryLow")) { r = bus_cgroup_set_memory_protection(u, name, &c->startup_memory_low, message, flags, reterr_error); @@ -1074,27 +1067,6 @@ int bus_cgroup_set_property( return r; } - if (streq(name, "DefaultMemoryMin")) { - r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_min, message, flags, reterr_error); - if (r > 0) - c->default_memory_min_set = true; - return r; - } - - if (streq(name, "DefaultMemoryLow")) { - r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_low, message, flags, reterr_error); - if (r > 0) - c->default_memory_low_set = true; - return r; - } - - if (streq(name, "DefaultStartupMemoryLow")) { - r = bus_cgroup_set_memory_protection(u, name, &c->default_startup_memory_low, message, flags, reterr_error); - if (r > 0) - c->default_startup_memory_low_set = true; - return r; - } - if (streq(name, "MemoryHigh")) return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, reterr_error); @@ -1135,33 +1107,11 @@ int bus_cgroup_set_property( return r; } - if (streq(name, "MemoryMinScale")) { - r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_min, message, flags, reterr_error); - if (r > 0) - c->memory_min_set = true; - return r; - } + if (streq(name, "MemoryMinScale")) + return bus_cgroup_set_memory_protection_scale(u, name, &c->memory_min, message, flags, reterr_error); - if (streq(name, "MemoryLowScale")) { - r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_low, message, flags, reterr_error); - if (r > 0) - c->memory_low_set = true; - return r; - } - - if (streq(name, "DefaultMemoryMinScale")) { - r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_min, message, flags, reterr_error); - if (r > 0) - c->default_memory_min_set = true; - return r; - } - - if (streq(name, "DefaultMemoryLowScale")) { - r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_low, message, flags, reterr_error); - if (r > 0) - c->default_memory_low_set = true; - return r; - } + if (streq(name, "MemoryLowScale")) + return bus_cgroup_set_memory_protection_scale(u, name, &c->memory_low, message, flags, reterr_error); if (streq(name, "MemoryHighScale")) return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, reterr_error); @@ -2041,8 +1991,8 @@ int bus_cgroup_set_property( return 1; } - /* deprecated CGroup v1 properties */ if (STR_IN_SET(name, + /* deprecated CGroup v1 properties */ "MemoryLimit", "MemoryLimitScale", "CPUShares", @@ -2053,7 +2003,13 @@ int bus_cgroup_set_property( "BlockIODeviceWeight", "BlockIOReadBandwidth", "BlockIOWriteBandwidth", - "CPUAccounting")) { /* see comment in bus_cgroup_vtable */ + /* see comments in bus_cgroup_vtable */ + "CPUAccounting", + "DefaultMemoryMin", + "DefaultMemoryMinScale", + "DefaultMemoryLow", + "DefaultMemoryLowScale", + "DefaultStartupMemoryLow")) { r = sd_bus_message_skip(message, NULL); if (r < 0) diff --git a/src/core/execute-serialize.c b/src/core/execute-serialize.c index 955fa1937c..3ffedf58db 100644 --- a/src/core/execute-serialize.c +++ b/src/core/execute-serialize.c @@ -132,18 +132,6 @@ static int exec_cgroup_context_serialize(const CGroupContext *c, FILE *f) { return r; } - if (c->default_memory_min > 0) { - r = serialize_item_format(f, "exec-cgroup-context-default-memory-min", "%" PRIu64, c->default_memory_min); - if (r < 0) - return r; - } - - if (c->default_memory_low > 0) { - r = serialize_item_format(f, "exec-cgroup-context-default-memory-low", "%" PRIu64, c->default_memory_low); - if (r < 0) - return r; - } - if (c->memory_min > 0) { r = serialize_item_format(f, "exec-cgroup-context-memory-min", "%" PRIu64, c->memory_min); if (r < 0) @@ -226,26 +214,6 @@ static int exec_cgroup_context_serialize(const CGroupContext *c, FILE *f) { return r; } - r = serialize_bool_elide(f, "exec-cgroup-context-default-memory-min-set", c->default_memory_min_set); - if (r < 0) - return r; - - r = serialize_bool_elide(f, "exec-cgroup-context-default-memory-low-set", c->default_memory_low_set); - if (r < 0) - return r; - - r = serialize_bool_elide(f, "exec-cgroup-context-default-startup-memory-low-set", c->default_startup_memory_low_set); - if (r < 0) - return r; - - r = serialize_bool_elide(f, "exec-cgroup-context-memory-min-set", c->memory_min_set); - if (r < 0) - return r; - - r = serialize_bool_elide(f, "exec-cgroup-context-memory-low-set", c->memory_low_set); - if (r < 0) - return r; - r = serialize_bool_elide(f, "exec-cgroup-context-startup-memory-low-set", c->startup_memory_low_set); if (r < 0) return r; @@ -532,14 +500,6 @@ static int exec_cgroup_context_deserialize(CGroupContext *c, FILE *f) { r = safe_atou64(val, &c->startup_io_weight); if (r < 0) return r; - } else if ((val = startswith(l, "exec-cgroup-context-default-memory-min="))) { - r = safe_atou64(val, &c->default_memory_min); - if (r < 0) - return r; - } else if ((val = startswith(l, "exec-cgroup-context-default-memory-low="))) { - r = safe_atou64(val, &c->default_memory_low); - if (r < 0) - return r; } else if ((val = startswith(l, "exec-cgroup-context-memory-min="))) { r = safe_atou64(val, &c->memory_min); if (r < 0) @@ -597,31 +557,6 @@ static int exec_cgroup_context_deserialize(CGroupContext *c, FILE *f) { r = safe_atou64(val, &c->tasks_max.scale); if (r < 0) return r; - } else if ((val = startswith(l, "exec-cgroup-context-default-memory-min-set="))) { - r = parse_boolean(val); - if (r < 0) - return r; - c->default_memory_min_set = r; - } else if ((val = startswith(l, "exec-cgroup-context-default-memory-low-set="))) { - r = parse_boolean(val); - if (r < 0) - return r; - c->default_memory_low_set = r; - } else if ((val = startswith(l, "exec-cgroup-context-default-startup-memory-low-set="))) { - r = parse_boolean(val); - if (r < 0) - return r; - c->default_startup_memory_low_set = r; - } else if ((val = startswith(l, "exec-cgroup-context-memory-min-set="))) { - r = parse_boolean(val); - if (r < 0) - return r; - c->memory_min_set = r; - } else if ((val = startswith(l, "exec-cgroup-context-memory-low-set="))) { - r = parse_boolean(val); - if (r < 0) - return r; - c->memory_low_set = r; } else if ((val = startswith(l, "exec-cgroup-context-startup-memory-low-set="))) { r = parse_boolean(val); if (r < 0) diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in index 69e39ed0dc..7f8198ff48 100644 --- a/src/core/load-fragment-gperf.gperf.in +++ b/src/core/load-fragment-gperf.gperf.in @@ -223,11 +223,11 @@ {{type}}.CPUQuotaPeriodSec, config_parse_sec_def_infinity, 0, offsetof({{type}}, cgroup_context.cpu_quota_period_usec) {{type}}.MemoryAccounting, config_parse_bool, 0, offsetof({{type}}, cgroup_context.memory_accounting) {{type}}.MemoryMin, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) -{{type}}.DefaultMemoryMin, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) -{{type}}.DefaultMemoryLow, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) -{{type}}.DefaultStartupMemoryLow, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) {{type}}.MemoryLow, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) {{type}}.StartupMemoryLow, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) +{{type}}.DefaultMemoryMin, config_parse_warn_compat, DISABLED_LEGACY, 0 +{{type}}.DefaultMemoryLow, config_parse_warn_compat, DISABLED_LEGACY, 0 +{{type}}.DefaultStartupMemoryLow, config_parse_warn_compat, DISABLED_LEGACY, 0 {{type}}.MemoryHigh, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) {{type}}.StartupMemoryHigh, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) {{type}}.MemoryMax, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index baee9b56c9..decdd2eae3 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -3790,9 +3790,7 @@ int config_parse_memory_limit( uint64_t bytes = CGROUP_LIMIT_MAX; int r; - if (isempty(rvalue) && STR_IN_SET(lvalue, "DefaultMemoryLow", - "DefaultMemoryMin", - "MemoryLow", + if (isempty(rvalue) && STR_IN_SET(lvalue, "MemoryLow", "StartupMemoryLow", "MemoryMin")) bytes = CGROUP_LIMIT_MIN; @@ -3816,31 +3814,17 @@ int config_parse_memory_limit( "StartupMemoryZSwapMax", "MemoryLow", "StartupMemoryLow", - "MemoryMin", - "DefaultMemoryLow", - "DefaultstartupMemoryLow", - "DefaultMemoryMin"))) { + "MemoryMin"))) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue); return 0; } } - if (streq(lvalue, "DefaultMemoryLow")) { - c->default_memory_low = bytes; - c->default_memory_low_set = true; - } else if (streq(lvalue, "DefaultStartupMemoryLow")) { - c->default_startup_memory_low = bytes; - c->default_startup_memory_low_set = true; - } else if (streq(lvalue, "DefaultMemoryMin")) { - c->default_memory_min = bytes; - c->default_memory_min_set = true; - } else if (streq(lvalue, "MemoryMin")) { + if (streq(lvalue, "MemoryMin")) c->memory_min = bytes; - c->memory_min_set = true; - } else if (streq(lvalue, "MemoryLow")) { + else if (streq(lvalue, "MemoryLow")) c->memory_low = bytes; - c->memory_low_set = true; - } else if (streq(lvalue, "StartupMemoryLow")) { + else if (streq(lvalue, "StartupMemoryLow")) { c->startup_memory_low = bytes; c->startup_memory_low_set = true; } else if (streq(lvalue, "MemoryHigh")) diff --git a/src/core/varlink-cgroup.c b/src/core/varlink-cgroup.c index d26542f032..ffa3b7ca6d 100644 --- a/src/core/varlink-cgroup.c +++ b/src/core/varlink-cgroup.c @@ -259,12 +259,9 @@ int unit_cgroup_context_build_json(sd_json_variant **ret, const char *name, void /* Memory Accounting and Control */ SD_JSON_BUILD_PAIR_BOOLEAN("MemoryAccounting", c->memory_accounting), - JSON_BUILD_PAIR_CONDITION_UNSIGNED(c->memory_min_set, "MemoryMin", c->memory_min), - JSON_BUILD_PAIR_CONDITION_UNSIGNED(c->default_memory_min_set, "DefaultMemoryMin", c->default_memory_min), - JSON_BUILD_PAIR_CONDITION_UNSIGNED(c->memory_low_set, "MemoryLow", c->memory_low), - JSON_BUILD_PAIR_CONDITION_UNSIGNED(c->default_memory_low_set, "DefaultMemoryLow", c->default_memory_low), + JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("MemoryMin", c->memory_min, CGROUP_LIMIT_MIN), + JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("MemoryLow", c->memory_low, CGROUP_LIMIT_MIN), JSON_BUILD_PAIR_CONDITION_UNSIGNED(c->startup_memory_low_set, "StartupMemoryLow", c->startup_memory_low), - JSON_BUILD_PAIR_CONDITION_UNSIGNED(c->default_startup_memory_low_set, "DefaultStartupMemoryLow", c->default_startup_memory_low), JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("MemoryHigh", c->memory_high, CGROUP_LIMIT_MAX), JSON_BUILD_PAIR_CONDITION_UNSIGNED(c->startup_memory_high_set, "StartupMemoryHigh", c->startup_memory_high), JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("MemoryMax", c->memory_max, CGROUP_LIMIT_MAX), diff --git a/src/shared/bus-get-properties.c b/src/shared/bus-get-properties.c index ffbe2b7930..c977df66d0 100644 --- a/src/shared/bus-get-properties.c +++ b/src/shared/bus-get-properties.c @@ -10,6 +10,7 @@ BUS_DEFINE_PROPERTY_GET_GLOBAL(bus_property_get_bool_false, "b", 0); BUS_DEFINE_PROPERTY_GET_GLOBAL(bus_property_get_bool_true, "b", 1); +BUS_DEFINE_PROPERTY_GET_GLOBAL(bus_property_get_uint64_0, "t", UINT64_C(0)); BUS_DEFINE_PROPERTY_GET_GLOBAL(bus_property_get_uint64_max, "t", UINT64_MAX); int bus_property_get_bool( diff --git a/src/shared/bus-get-properties.h b/src/shared/bus-get-properties.h index 23d68bd635..219c8195b7 100644 --- a/src/shared/bus-get-properties.h +++ b/src/shared/bus-get-properties.h @@ -107,4 +107,5 @@ int bus_property_get_pidfdid(sd_bus *bus, const char *path, const char *interfac /* For deprecated properties. */ int bus_property_get_bool_false(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *reterr_error); int bus_property_get_bool_true(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *reterr_error); +int bus_property_get_uint64_0(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *reterr_error); int bus_property_get_uint64_max(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *reterr_error); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 894a2639cd..ad718ea0f0 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -342,8 +342,6 @@ static int bus_append_parse_resource_limit(sd_bus_message *m, const char *field, if (isempty(eq) || streq(eq, "infinity")) { uint64_t x = streq(eq, "infinity") ? CGROUP_LIMIT_MAX : STR_IN_SET(field, - "DefaultMemoryLow", - "DefaultMemoryMin", "MemoryLow", "MemoryMin") ? CGROUP_LIMIT_MIN : CGROUP_LIMIT_MAX; @@ -2348,8 +2346,6 @@ static const BusProperty cgroup_properties[] = { { "DisableControllers", bus_append_strv }, { "Delegate", bus_append_parse_delegate }, { "MemoryMin", bus_append_parse_resource_limit }, - { "DefaultMemoryLow", bus_append_parse_resource_limit }, - { "DefaultMemoryMin", bus_append_parse_resource_limit }, { "MemoryLow", bus_append_parse_resource_limit }, { "MemoryHigh", bus_append_parse_resource_limit }, { "MemoryMax", bus_append_parse_resource_limit }, @@ -2386,6 +2382,8 @@ static const BusProperty cgroup_properties[] = { { "BlockIOReadBandwidth", warn_deprecated }, { "BlockIOWriteBandwidth", warn_deprecated }, { "CPUAccounting", warn_deprecated }, + { "DefaultMemoryMin", warn_deprecated }, + { "DefaultMemoryLow", warn_deprecated }, { NULL, bus_try_append_parse_cgroup_io_limit, cgroup_io_limits_list }, {} diff --git a/src/shared/varlink-io.systemd.Unit.c b/src/shared/varlink-io.systemd.Unit.c index 1cdb52de14..f8e255dd5b 100644 --- a/src/shared/varlink-io.systemd.Unit.c +++ b/src/shared/varlink-io.systemd.Unit.c @@ -111,15 +111,9 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#MemoryMin=bytes,%20MemoryLow=bytes"), SD_VARLINK_DEFINE_FIELD(MemoryMin, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#MemoryMin=bytes,%20MemoryLow=bytes"), - SD_VARLINK_DEFINE_FIELD(DefaultMemoryMin, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#MemoryMin=bytes,%20MemoryLow=bytes"), SD_VARLINK_DEFINE_FIELD(MemoryLow, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#MemoryMin=bytes,%20MemoryLow=bytes"), - SD_VARLINK_DEFINE_FIELD(DefaultMemoryLow, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#MemorySwapMax=bytes"), SD_VARLINK_DEFINE_FIELD(StartupMemoryLow, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#MemoryMin=bytes,%20MemoryLow=bytes"), - SD_VARLINK_DEFINE_FIELD(DefaultStartupMemoryLow, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#MemoryHigh=bytes"), SD_VARLINK_DEFINE_FIELD(MemoryHigh, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#MemoryHigh=bytes"), diff --git a/src/systemctl/systemctl-show.c b/src/systemctl/systemctl-show.c index 08319602c0..c35db87c45 100644 --- a/src/systemctl/systemctl-show.c +++ b/src/systemctl/systemctl-show.c @@ -302,10 +302,6 @@ typedef struct UnitStatusInfo { uint64_t io_read_bytes; uint64_t io_write_bytes; - uint64_t default_memory_min; - uint64_t default_memory_low; - uint64_t default_startup_memory_low; - /* Exec Quotas */ QuotaInfo exec_directories_quota[_EXEC_DIRECTORY_TYPE_MAX]; @@ -2248,9 +2244,6 @@ static int show_one( { "MemorySwapPeak", "t", NULL, offsetof(UnitStatusInfo, memory_swap_peak) }, { "MemoryZSwapCurrent", "t", NULL, offsetof(UnitStatusInfo, memory_zswap_current) }, { "MemoryAvailable", "t", NULL, offsetof(UnitStatusInfo, memory_available) }, - { "DefaultMemoryMin", "t", NULL, offsetof(UnitStatusInfo, default_memory_min) }, - { "DefaultMemoryLow", "t", NULL, offsetof(UnitStatusInfo, default_memory_low) }, - { "DefaultStartupMemoryLow", "t", NULL, offsetof(UnitStatusInfo, default_startup_memory_low) }, { "MemoryMin", "t", NULL, offsetof(UnitStatusInfo, memory_min) }, { "MemoryLow", "t", NULL, offsetof(UnitStatusInfo, memory_low) }, { "StartupMemoryLow", "t", NULL, offsetof(UnitStatusInfo, startup_memory_low) }, diff --git a/src/test/meson.build b/src/test/meson.build index 44b6d5e4bd..c68477dc60 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -540,9 +540,6 @@ executables += [ 'sources' : files('test-cgroup-mask.c'), 'dependencies' : common_test_dependencies, }, - core_test_template + { - 'sources' : files('test-cgroup-unit-default.c'), - }, core_test_template + { 'sources' : files('test-chown-rec.c'), }, diff --git a/src/test/test-cgroup-unit-default.c b/src/test/test-cgroup-unit-default.c deleted file mode 100644 index a841524134..0000000000 --- a/src/test/test-cgroup-unit-default.c +++ /dev/null @@ -1,136 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "cgroup.h" -#include "manager.h" -#include "rm-rf.h" -#include "tests.h" -#include "unit.h" - -TEST_RET(default_memory_low, .sd_booted = true) { - _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; - _cleanup_(manager_freep) Manager *m = NULL; - Unit *root, *dml, - *dml_passthrough, *dml_passthrough_empty, *dml_passthrough_set_dml, *dml_passthrough_set_ml, - *dml_override, *dml_override_empty, - *dml_discard, *dml_discard_empty, *dml_discard_set_ml; - uint64_t dml_tree_default; - int r; - - r = enter_cgroup_subroot(NULL); - if (r == -ENOMEDIUM) - return log_tests_skipped("cgroupfs not available"); - - _cleanup_free_ char *unit_dir = NULL; - ASSERT_OK(get_testdata_dir("test-cgroup-unit-default", &unit_dir)); - ASSERT_OK(setenv_unit_path(unit_dir)); - assert_se(runtime_dir = setup_fake_runtime_dir()); - r = manager_new(RUNTIME_SCOPE_USER, MANAGER_TEST_RUN_BASIC, &m); - if (IN_SET(r, -EPERM, -EACCES)) { - log_error_errno(r, "manager_new: %m"); - return log_tests_skipped("cannot create manager"); - } - - ASSERT_OK(r); - ASSERT_OK(manager_startup(m, NULL, NULL, NULL)); - - /* dml.slice has DefaultMemoryLow=50. Beyond that, individual subhierarchies look like this: - * - * 1. dml-passthrough.slice sets MemoryLow=100. This should not affect its children, as only - * DefaultMemoryLow is propagated, not MemoryLow. As such, all leaf services should end up with - * memory.low as 50, inherited from dml.slice, *except* for dml-passthrough-set-ml.service, which - * should have the value of 0, as it has MemoryLow explicitly set. - * - * ┌───────────┐ - * │ dml.slice │ - * └─────┬─────┘ - * MemoryLow=100 - * ┌───────────┴───────────┐ - * │ dml-passthrough.slice │ - * └───────────┬───────────┘ - * ┌───────────────────────────────────┼───────────────────────────────────┐ - * no new settings DefaultMemoryLow=15 MemoryLow=0 - * ┌───────────────┴───────────────┐ ┌────────────────┴────────────────┐ ┌───────────────┴────────────────┐ - * │ dml-passthrough-empty.service │ │ dml-passthrough-set-dml.service │ │ dml-passthrough-set-ml.service │ - * └───────────────────────────────┘ └─────────────────────────────────┘ └────────────────────────────────┘ - * - * 2. dml-override.slice sets DefaultMemoryLow=10. As such, dml-override-empty.service should also - * end up with a memory.low of 10. dml-override.slice should still have a memory.low of 50. - * - * ┌───────────┐ - * │ dml.slice │ - * └─────┬─────┘ - * DefaultMemoryLow=10 - * ┌─────────┴──────────┐ - * │ dml-override.slice │ - * └─────────┬──────────┘ - * no new settings - * ┌─────────────┴──────────────┐ - * │ dml-override-empty.service │ - * └────────────────────────────┘ - * - * 3. dml-discard.slice sets DefaultMemoryLow= with no rvalue. As such, - * dml-discard-empty.service should end up with a value of 0. - * dml-discard-set-ml.service sets MemoryLow=15, and as such should have that override the - * reset DefaultMemoryLow value. dml-discard.slice should still have an eventual memory.low of 50. - * - * ┌───────────┐ - * │ dml.slice │ - * └─────┬─────┘ - * DefaultMemoryLow= - * ┌─────────┴─────────┐ - * │ dml-discard.slice │ - * └─────────┬─────────┘ - * ┌──────────────┴───────────────┐ - * no new settings MemoryLow=15 - * ┌─────────────┴─────────────┐ ┌─────────────┴──────────────┐ - * │ dml-discard-empty.service │ │ dml-discard-set-ml.service │ - * └───────────────────────────┘ └────────────────────────────┘ - */ - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml.slice", NULL, &dml)); - - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml-passthrough.slice", NULL, &dml_passthrough)); - assert_se(UNIT_GET_SLICE(dml_passthrough) == dml); - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml-passthrough-empty.service", NULL, &dml_passthrough_empty)); - assert_se(UNIT_GET_SLICE(dml_passthrough_empty) == dml_passthrough); - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-dml.service", NULL, &dml_passthrough_set_dml)); - assert_se(UNIT_GET_SLICE(dml_passthrough_set_dml) == dml_passthrough); - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-ml.service", NULL, &dml_passthrough_set_ml)); - assert_se(UNIT_GET_SLICE(dml_passthrough_set_ml) == dml_passthrough); - - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml-override.slice", NULL, &dml_override)); - assert_se(UNIT_GET_SLICE(dml_override) == dml); - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml-override-empty.service", NULL, &dml_override_empty)); - assert_se(UNIT_GET_SLICE(dml_override_empty) == dml_override); - - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml-discard.slice", NULL, &dml_discard)); - assert_se(UNIT_GET_SLICE(dml_discard) == dml); - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml-discard-empty.service", NULL, &dml_discard_empty)); - assert_se(UNIT_GET_SLICE(dml_discard_empty) == dml_discard); - ASSERT_OK(manager_load_startable_unit_or_warn(m, "dml-discard-set-ml.service", NULL, &dml_discard_set_ml)); - assert_se(UNIT_GET_SLICE(dml_discard_set_ml) == dml_discard); - - assert_se(root = UNIT_GET_SLICE(dml)); - assert_se(!UNIT_GET_SLICE(root)); - - assert_se(unit_get_ancestor_memory_low(root) == CGROUP_LIMIT_MIN); - - assert_se(unit_get_ancestor_memory_low(dml) == CGROUP_LIMIT_MIN); - dml_tree_default = unit_get_cgroup_context(dml)->default_memory_low; - assert_se(dml_tree_default == 50); - - assert_se(unit_get_ancestor_memory_low(dml_passthrough) == 100); - assert_se(unit_get_ancestor_memory_low(dml_passthrough_empty) == dml_tree_default); - assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_dml) == 50); - assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_ml) == 0); - - assert_se(unit_get_ancestor_memory_low(dml_override) == dml_tree_default); - assert_se(unit_get_ancestor_memory_low(dml_override_empty) == 10); - - assert_se(unit_get_ancestor_memory_low(dml_discard) == dml_tree_default); - assert_se(unit_get_ancestor_memory_low(dml_discard_empty) == CGROUP_LIMIT_MIN); - assert_se(unit_get_ancestor_memory_low(dml_discard_set_ml) == 15); - - return 0; -} - -DEFINE_TEST_MAIN(LOG_DEBUG); diff --git a/test/meson.build b/test/meson.build index b1d5421f67..6c7fd666a0 100644 --- a/test/meson.build +++ b/test/meson.build @@ -332,7 +332,6 @@ if install_tests 'journal-data', 'knot-data', 'test-cgroup-mask', - 'test-cgroup-unit-default', 'test-engine', 'test-execute', 'test-fstab-generator', diff --git a/test/test-cgroup-unit-default/dml-discard-empty.service b/test/test-cgroup-unit-default/dml-discard-empty.service deleted file mode 100644 index c17698999a..0000000000 --- a/test/test-cgroup-unit-default/dml-discard-empty.service +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML discard empty service - -[Service] -Slice=dml-discard.slice -Type=oneshot -ExecStart=true diff --git a/test/test-cgroup-unit-default/dml-discard-set-ml.service b/test/test-cgroup-unit-default/dml-discard-set-ml.service deleted file mode 100644 index 0fba2acdaf..0000000000 --- a/test/test-cgroup-unit-default/dml-discard-set-ml.service +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML discard set ml service - -[Service] -Slice=dml-discard.slice -Type=oneshot -ExecStart=true -MemoryLow=15 diff --git a/test/test-cgroup-unit-default/dml-discard.slice b/test/test-cgroup-unit-default/dml-discard.slice deleted file mode 100644 index dc8a39747f..0000000000 --- a/test/test-cgroup-unit-default/dml-discard.slice +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML discard slice - -[Slice] -DefaultMemoryLow= diff --git a/test/test-cgroup-unit-default/dml-override-empty.service b/test/test-cgroup-unit-default/dml-override-empty.service deleted file mode 100644 index 5f0c143d66..0000000000 --- a/test/test-cgroup-unit-default/dml-override-empty.service +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML override empty service - -[Service] -Slice=dml-override.slice -Type=oneshot -ExecStart=true diff --git a/test/test-cgroup-unit-default/dml-override.slice b/test/test-cgroup-unit-default/dml-override.slice deleted file mode 100644 index ac664d1f6b..0000000000 --- a/test/test-cgroup-unit-default/dml-override.slice +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML override slice - -[Slice] -DefaultMemoryLow=10 diff --git a/test/test-cgroup-unit-default/dml-passthrough-empty.service b/test/test-cgroup-unit-default/dml-passthrough-empty.service deleted file mode 100644 index 896622689f..0000000000 --- a/test/test-cgroup-unit-default/dml-passthrough-empty.service +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML passthrough empty service - -[Service] -Slice=dml-passthrough.slice -Type=oneshot -ExecStart=true diff --git a/test/test-cgroup-unit-default/dml-passthrough-set-dml.service b/test/test-cgroup-unit-default/dml-passthrough-set-dml.service deleted file mode 100644 index ec82174e69..0000000000 --- a/test/test-cgroup-unit-default/dml-passthrough-set-dml.service +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML passthrough set DML service - -[Service] -Slice=dml-passthrough.slice -Type=oneshot -ExecStart=true -DefaultMemoryLow=15 diff --git a/test/test-cgroup-unit-default/dml-passthrough-set-ml.service b/test/test-cgroup-unit-default/dml-passthrough-set-ml.service deleted file mode 100644 index 63ec3058cf..0000000000 --- a/test/test-cgroup-unit-default/dml-passthrough-set-ml.service +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML passthrough set ML service - -[Service] -Slice=dml-passthrough.slice -Type=oneshot -ExecStart=true -MemoryLow=0 diff --git a/test/test-cgroup-unit-default/dml-passthrough.slice b/test/test-cgroup-unit-default/dml-passthrough.slice deleted file mode 100644 index 1c8769d2d8..0000000000 --- a/test/test-cgroup-unit-default/dml-passthrough.slice +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML passthrough slice - -[Slice] -MemoryLow=100 diff --git a/test/test-cgroup-unit-default/dml.slice b/test/test-cgroup-unit-default/dml.slice deleted file mode 100644 index 8e00e7fbf6..0000000000 --- a/test/test-cgroup-unit-default/dml.slice +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Unit] -Description=DML slice - -[Slice] -DefaultMemoryLow=50