From: Darrick J. Wong <djwong@xxxxxxxxxx> Currently, the xfs_scrub background service is configured to use -b, which means that the program runs completely serially. However, even using all of one CPU core with idle priority may be enough to cause thermal throttling and unwanted fan noise on smaller systems (e.g. laptops) with fast IO systems. Let's try to avoid this (at least on systemd) by using cgroups to limit the program's usage to slghtly more than half of one CPU and lowering the nice priority in the scheduler. What we /really/ want is to run steadily on an efficiency core, but there doesn't seem to be a means to ask the scheduler not to ramp up the CPU frequency for a particular task. While we're at it, group the resource limit directives together. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> --- scrub/Makefile | 7 ++++++- scrub/system-xfs_scrub.slice | 30 ++++++++++++++++++++++++++++++ scrub/xfs_scrub@xxxxxxxxxxx | 12 ++++++++++-- scrub/xfs_scrub_all.service.in | 4 ++++ scrub/xfs_scrub_fail@xxxxxxxxxxx | 4 ++++ 5 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 scrub/system-xfs_scrub.slice diff --git a/scrub/Makefile b/scrub/Makefile index 8ccc67d01..2a257e080 100644 --- a/scrub/Makefile +++ b/scrub/Makefile @@ -18,7 +18,12 @@ XFS_SCRUB_FAIL_PROG = xfs_scrub_fail XFS_SCRUB_ARGS = -b -n ifeq ($(HAVE_SYSTEMD),yes) INSTALL_SCRUB += install-systemd -SYSTEMD_SERVICES = $(scrub_svcname) xfs_scrub_all.service xfs_scrub_all.timer xfs_scrub_fail@.service +SYSTEMD_SERVICES=\ + $(scrub_svcname) \ + xfs_scrub_fail@.service \ + xfs_scrub_all.service \ + xfs_scrub_all.timer \ + system-xfs_scrub.slice OPTIONAL_TARGETS += $(SYSTEMD_SERVICES) endif ifeq ($(HAVE_CROND),yes) diff --git a/scrub/system-xfs_scrub.slice b/scrub/system-xfs_scrub.slice new file mode 100644 index 000000000..95cd4f745 --- /dev/null +++ b/scrub/system-xfs_scrub.slice @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2022-2024 Oracle. All Rights Reserved. +# Author: Darrick J. Wong <djwong@xxxxxxxxxx> + +[Unit] +Description=xfs_scrub background service slice +Before=slices.target + +[Slice] + +# If the CPU usage cgroup controller is available, don't use more than 60% of a +# single core for all background processes. +CPUQuota=60% +CPUAccounting=true + +[Install] +# As of systemd 249, the systemd cgroupv2 configuration code will drop resource +# controllers from the root and system.slice cgroups at startup if it doesn't +# find any direct dependencies that require a given controller. Newly +# activated units with resource control directives are created under the system +# slice but do not cause a reconfiguration of the slice's resource controllers. +# Hence we cannot put CPUQuota= into the xfs_scrub service units directly. +# +# For the CPUQuota directive to have any effect, we must therefore create an +# explicit definition file for the slice that systemd creates to contain the +# xfs_scrub instance units (e.g. xfs_scrub@.service) and we must configure this +# slice as a dependency of the system slice to establish the direct dependency +# relation. +WantedBy=system.slice diff --git a/scrub/xfs_scrub@xxxxxxxxxxx b/scrub/xfs_scrub@xxxxxxxxxxx index 05e5293ee..855fe4de4 100644 --- a/scrub/xfs_scrub@xxxxxxxxxxx +++ b/scrub/xfs_scrub@xxxxxxxxxxx @@ -18,8 +18,16 @@ PrivateTmp=no AmbientCapabilities=CAP_SYS_ADMIN CAP_FOWNER CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_SYS_RAWIO NoNewPrivileges=yes User=nobody -IOSchedulingClass=idle -CPUSchedulingPolicy=idle Environment=SERVICE_MODE=1 ExecStart=@sbindir@/xfs_scrub @scrub_args@ %f SyslogIdentifier=%N + +# Run scrub with minimal CPU and IO priority so that nothing else will starve. +IOSchedulingClass=idle +CPUSchedulingPolicy=idle +CPUAccounting=true +Nice=19 + +# Create the service underneath the scrub background service slice so that we +# can control resource usage. +Slice=system-xfs_scrub.slice diff --git a/scrub/xfs_scrub_all.service.in b/scrub/xfs_scrub_all.service.in index 347cd6e66..96be90e74 100644 --- a/scrub/xfs_scrub_all.service.in +++ b/scrub/xfs_scrub_all.service.in @@ -14,3 +14,7 @@ Type=oneshot Environment=SERVICE_MODE=1 ExecStart=@sbindir@/xfs_scrub_all SyslogIdentifier=xfs_scrub_all + +# Create the service underneath the scrub background service slice so that we +# can control resource usage. +Slice=system-xfs_scrub.slice diff --git a/scrub/xfs_scrub_fail@xxxxxxxxxxx b/scrub/xfs_scrub_fail@xxxxxxxxxxx index 96a2ed5da..32012ec35 100644 --- a/scrub/xfs_scrub_fail@xxxxxxxxxxx +++ b/scrub/xfs_scrub_fail@xxxxxxxxxxx @@ -14,3 +14,7 @@ ExecStart=@pkg_libexec_dir@/xfs_scrub_fail "${EMAIL_ADDR}" %f User=mail Group=mail SupplementaryGroups=systemd-journal + +# Create the service underneath the scrub background service slice so that we +# can control resource usage. +Slice=system-xfs_scrub.slice