git: 0661f93892a2 - main - rc: add support for cpuset(1)

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Thu, 11 May 2023 04:40:31 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=0661f93892a2564a64c5650ffffa3d73417172a9

commit 0661f93892a2564a64c5650ffffa3d73417172a9
Author:     Miroslav Lachman <000.fbsd_quip.cz>
AuthorDate: 2023-05-11 04:38:23 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2023-05-11 04:40:18 +0000

    rc: add support for cpuset(1)
    
    If ${name}_cpuset is specified (and /usr is mounted), cpuset(1) will be
    run to limit the service to the configured cpuset.
    
    PR:             142434
    Reviewed by:    kevans
---
 libexec/rc/rc.subr | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/libexec/rc/rc.subr b/libexec/rc/rc.subr
index 1c01f1cfd071..9b5b3d8b37e7 100644
--- a/libexec/rc/rc.subr
+++ b/libexec/rc/rc.subr
@@ -52,6 +52,8 @@ ID="/usr/bin/id"
 IDCMD="if [ -x $ID ]; then $ID -un; fi"
 PS="/bin/ps -ww"
 JID=0
+CPUSET="/usr/bin/cpuset"
+
 # rc_service provides the path to the service script that we are executing.
 # This is not being set here in an execution context, necessarily, so it's
 # really just a reasonable guess, and it will get overwritten later if
@@ -777,6 +779,9 @@ startmsg()
 #	${name}_chdir	n	Directory to cd to before running ${command}
 #				(if not using ${name}_chroot).
 #
+#	${name}_cpuset	n	A list of CPUs to run ${command} on.
+#				Requires /usr to be mounted.
+#
 #	${name}_flags	n	Arguments to call ${command} with.
 #				NOTE:	$flags from the parent environment
 #					can be used to override this.
@@ -963,6 +968,23 @@ run_rc_command()
 	_pidcmd=
 	_procname=${procname:-${command}}
 
+	eval _cpuset=\$${name}_cpuset
+
+	# Loose validation of the configured cpuset; just make sure it starts
+	# with a number.  There have also been cases in the past where a hyphen
+	# in a service name has caused eval errors, which trickle down into
+	# various variables; don't let a situation like that break a bunch of
+	# services just because of cpuset(1).
+	case "$_cpuset" in
+	[0-9]*)	;;
+	*)	_cpuset="" ;;
+	esac
+
+	_cpusetcmd=
+	if [ -n "$_cpuset" -a -x $CPUSET ]; then
+		_cpusetcmd="$CPUSET -l $_cpuset"
+	fi
+
 					# setup pid check command
 	if [ -n "$_procname" ]; then
 		if [ -n "$pidfile" ]; then
@@ -1059,7 +1081,7 @@ run_rc_command()
 				eval "export -- $_env"
 			fi
 			_run_rc_precmd || return 1
-			_run_rc_doit "$_cmd $rc_extra_args" || return 1
+			_run_rc_doit "$_cpusetcmd $_cmd $rc_extra_args" || return 1
 			_run_rc_postcmd
 			return $_return
 		fi
@@ -1105,6 +1127,11 @@ run_rc_command()
 			_run_rc_precmd || return 1
 			if [ -n "$rc_pid" ]; then
 				echo "${name} is running as pid $rc_pid."
+				# for cpuset debug only, not committable (cut)
+				if [ -n "$_cpuset" -a -x $CPUSET ]; then
+					echo -n "on CPU(s)"
+					$CPUSET -g -p "$rc_pid" | cut -s -d: -f 2
+				fi
 			else
 				echo "${name} is not running."
 				return 1
@@ -1130,6 +1157,7 @@ run_rc_command()
 				_cd=
 				_doit="\
 ${_nice:+nice -n $_nice }\
+$_cpusetcmd \
 ${_fib:+setfib -F $_fib }\
 ${_env:+env $_env }\
 chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
@@ -1139,7 +1167,7 @@ $_chroot $command $rc_flags $command_args"
 				_doit="\
 ${_fib:+setfib -F $_fib }\
 ${_env:+env $_env }\
-$command $rc_flags $command_args"
+$_cpusetcmd $command $rc_flags $command_args"
 				if [ -n "$_user" ]; then
 				    _doit="su -m $_user -c 'sh -c \"$_doit\"'"
 				fi