mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
cpi: Introduce new udev rule and integrate with systemd unit
Add a new udev rule that is triggered when a KVM VM is started on the system the very first time. This rule reports over the sysfs CPI kernel interface that the system is a KVM host. Currently the cpi.service systemd unit already works with the CPI sysfs interface. Introduce a new internal utility script "cpictl" that is used by both the udev rule and the systemd unit to guarantee coordinated access to the kernel CPU interface. Signed-off-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com> Reviewed-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
This commit is contained in:
committed by
Michael Holzheu
parent
8ff6af3a4b
commit
ca50924acb
@@ -35,6 +35,8 @@ Package contents
|
||||
- 57-osasnmpd.rules: udev rules for osasnmpd.
|
||||
- 60-readahead.rules: udev rules to set increased "default max readahead".
|
||||
- 40-z90crypt.rules: udev rules for z90crypt driver
|
||||
- 90-cpi.rules: udev rule to update Control-Program-Information when KVM is
|
||||
used.
|
||||
|
||||
* systemd units:
|
||||
- cpi.service: Unit to apply CPI settings
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
# The system and sysplex names consist of up to eight characters of
|
||||
# the following set: A-Z, 0-9, $, @, #, and blank.
|
||||
|
||||
#
|
||||
# CPI system type
|
||||
#
|
||||
CPI_SYSTEM_TYPE="LINUX"
|
||||
|
||||
#
|
||||
# CPI system name
|
||||
#
|
||||
|
||||
6
etc/udev/rules.d/90-cpi.rules
Normal file
6
etc/udev/rules.d/90-cpi.rules
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Rules to trigger cpictl when KVM is used
|
||||
# This file should be installed in /etc/udev/rules.d
|
||||
#
|
||||
|
||||
SUBSYSTEM=="misc", KERNEL=="kvm", ENV{CREATED}=="1", ENV{EVENT}=="create", RUN+="/lib/s390-tools/cpictl -b kvm"
|
||||
@@ -15,7 +15,12 @@ install:
|
||||
chown $(OWNER):$(GROUP) $(DESTDIR)$(BINDIR)/$$i; \
|
||||
chmod 755 $(DESTDIR)$(BINDIR)/$$i; \
|
||||
done
|
||||
|
||||
|
||||
sed -e 's+%S390_TOOLS_VERSION%+$(S390_TOOLS_RELEASE)+' cpictl > \
|
||||
$(DESTDIR)$(TOOLS_LIBDIR)/cpictl
|
||||
chown $(OWNER):$(GROUP) $(DESTDIR)$(TOOLS_LIBDIR)/cpictl
|
||||
chmod 775 $(DESTDIR)$(TOOLS_LIBDIR)/cpictl
|
||||
|
||||
@for i in $(MAN_PAGES); \
|
||||
do \
|
||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 $$i \
|
||||
|
||||
274
scripts/cpictl
Executable file
274
scripts/cpictl
Executable file
@@ -0,0 +1,274 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# cpictl - Configure the Control-Program-Information (CPI) settings
|
||||
#
|
||||
# This is an internal helper script that is used by the "cpi.service"
|
||||
# systemd unit and the "90-cpi.rules" udev rule.
|
||||
#
|
||||
# The bash shell is really needed. Other shells have different ideas of how
|
||||
# bitwise operators work.
|
||||
#
|
||||
# Copyright 2017 IBM Corp.
|
||||
#
|
||||
# s390-tools is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the MIT license. See LICENSE for details.
|
||||
#
|
||||
|
||||
readonly CPI_LOCK="/var/lock/cpictl.lock"
|
||||
|
||||
readonly PRG="${0##*/}"
|
||||
|
||||
readonly SYSTEM_LEVEL_PATH="/sys/firmware/cpi/system_level"
|
||||
readonly SYSTEM_TYPE_PATH="/sys/firmware/cpi/system_type"
|
||||
readonly SYSTEM_NAME_PATH="/sys/firmware/cpi/system_name"
|
||||
readonly SYSPLEX_NAME_PATH="/sys/firmware/cpi/sysplex_name"
|
||||
readonly CPI_SET="/sys/firmware/cpi/set"
|
||||
|
||||
declare LEVEL
|
||||
declare TYPE
|
||||
declare NAME
|
||||
declare SYSPLEX
|
||||
|
||||
declare -i DRYRUN=0
|
||||
|
||||
# Exit codes
|
||||
readonly EXIT_SUCCESS=0
|
||||
readonly EXIT_FAILURE=1
|
||||
readonly EXIT_ARG_TOO_LONG=3
|
||||
readonly EXIT_INVALID_CHARS=4
|
||||
|
||||
print_help_and_exit()
|
||||
{
|
||||
cat <<EndHelp
|
||||
Usage: $PRG [OPTIONS]
|
||||
|
||||
Configure the Control-Program-Information (CPI) settings.
|
||||
|
||||
-b, --set-bit BIT Set and commit the bit BIT in the flags
|
||||
-e, --environment Set and commit the system type, level, name and
|
||||
sysplex name with values taken from environment
|
||||
variables
|
||||
-h, --help Ignore all other options and print this help
|
||||
-L, --level LEVEL Set and commit OS level to LEVEL (format xx.yy.zzABCD)
|
||||
-N, --name SYSTEM Set and commit the system name to SYSTEM
|
||||
-S, --sysplex SYSPLEX Set and commit the sysplex name to SYSPLEX
|
||||
-T, --type TYPE Set and commit OS type to TYPE
|
||||
--commit Ignore all other options and commit any uncommitted
|
||||
values
|
||||
--dry-run Do not actually set or commit anything, but show what
|
||||
would be done
|
||||
--show Ignore all other options and show current (possibly
|
||||
uncommitted) values
|
||||
|
||||
Environment variables used for the --defaults option:
|
||||
CPI_SYSTEM_TYPE, CPI_SYSTEM_LEVEL, CPI_SYSTEM_NAME, CPI_SYSPLEX_NAME
|
||||
|
||||
Available bits for the --set-bit option:
|
||||
kvm: Indicate that system is a KVM host
|
||||
|
||||
The maximum length for system type, system name, and sysplex name is 8
|
||||
characters. The allowed characters are: [A-Z0-9 @#$]
|
||||
|
||||
This tool should be called as root.
|
||||
EndHelp
|
||||
exit $EXIT_SUCCESS
|
||||
}
|
||||
|
||||
print_version_and_exit()
|
||||
{
|
||||
cat <<EndVersion
|
||||
$PRG: Configure the CPI settings version %S390_TOOLS_VERSION%
|
||||
Copyright IBM Corp. 2017
|
||||
EndVersion
|
||||
exit $EXIT_SUCCESS
|
||||
}
|
||||
|
||||
cpi_show()
|
||||
{
|
||||
cat <<-EndShow
|
||||
System type: $(cat "$SYSTEM_TYPE_PATH")
|
||||
System level: $(cat "$SYSTEM_LEVEL_PATH")
|
||||
System name: $(cat "$SYSTEM_NAME_PATH")
|
||||
Sysplex name: $(cat "$SYSPLEX_NAME_PATH")
|
||||
EndShow
|
||||
}
|
||||
|
||||
print_parse_error_and_exit()
|
||||
{
|
||||
echo "Try '$PRG --help' for more information." >&2
|
||||
exit $EXIT_FAILURE
|
||||
}
|
||||
|
||||
fail_with()
|
||||
{
|
||||
echo "$1" >&2
|
||||
echo "Try '$PRG --help' for more information." >&2
|
||||
exit ${2:-$EXIT_FAILURE}
|
||||
}
|
||||
|
||||
cpi_commit()
|
||||
{
|
||||
echo 1 > "$CPI_SET"
|
||||
}
|
||||
|
||||
do_length_check()
|
||||
{
|
||||
[ ${#1} -gt 8 ] &&
|
||||
fail_with "$PRG: Specified $2 too long. The maximum length is 8 characters." $EXIT_ARG_TOO_LONG
|
||||
}
|
||||
|
||||
do_character_check()
|
||||
{
|
||||
echo "$1" | grep -q -E '^[a-zA-Z0-9@#$ ]*$' ||
|
||||
fail_with "$PRG: Invalid characters in $2. Valid characters are: A-Z0-9 @#$" $EXIT_INVALID_CHARS
|
||||
}
|
||||
|
||||
cpi_set_bit()
|
||||
{
|
||||
LEVEL=$(printf '0x%x' $((LEVEL | (1 << (63 - $1)) )) )
|
||||
}
|
||||
|
||||
cpi_set_oslevel()
|
||||
{
|
||||
local kver=$(echo "${1:-$(uname -r)}" | grep -E -o '^[0-9]+[.][0-9]+[.][0-9]+')
|
||||
local maj=$((${kver%%.*} % 256))
|
||||
local min=${kver#*.}
|
||||
min=$((${min%.*} % 256))
|
||||
local rev=$((${kver##*.} % 256))
|
||||
local hexlevel=$(printf '0x%02x%02x%02x' $maj $min $rev)
|
||||
LEVEL=$(printf '0x%016x' $(((LEVEL & 0xFFFFFFFFFF000000) | hexlevel)))
|
||||
}
|
||||
|
||||
cpi_set_type()
|
||||
{
|
||||
TYPE="$1"
|
||||
do_length_check "$TYPE" "system type"
|
||||
do_character_check "$TYPE" "system type"
|
||||
}
|
||||
|
||||
cpi_set_sysplex()
|
||||
{
|
||||
SYSPLEX="$1"
|
||||
do_length_check "$SYSPLEX" "sysplex name"
|
||||
do_character_check "$SYSPLEX" "sysplex name"
|
||||
}
|
||||
|
||||
cpi_set_name()
|
||||
{
|
||||
NAME="$1"
|
||||
do_length_check "$NAME" "system name"
|
||||
do_character_check "$NAME" "system name"
|
||||
}
|
||||
|
||||
# cpictl starts here
|
||||
|
||||
if [ $# -le 0 ]; then
|
||||
echo "$PRG: No parameters specified"
|
||||
print_parse_error_and_exit
|
||||
fi
|
||||
|
||||
opts=$(getopt -o b:ehL:N:S:T:v -l set-bit:,environment,help,level:,name:,sysplex:,type:,commit,dry-run,show,version -n $PRG -- "$@")
|
||||
if [ $? -ne 0 ]; then
|
||||
print_parse_error_and_exit
|
||||
fi
|
||||
|
||||
# This guarantees that only one instance will be running, and will serialize
|
||||
# the execution of multiple instances
|
||||
[ -e "$CPI_LOCK" -a ! -w "$CPI_LOCK" ] &&
|
||||
fail_with "$PRG: Cannot access lock file: $CPI_LOCK"
|
||||
[ ! -w "${CPI_LOCK%/*}" ] &&
|
||||
fail_with "$PRG: Cannot access lock file: $CPI_LOCK"
|
||||
|
||||
exec 9<> "$CPI_LOCK"
|
||||
flock -x 9
|
||||
|
||||
# Get current values from sys/firmware
|
||||
read LEVEL < "$SYSTEM_LEVEL_PATH"
|
||||
read TYPE < "$SYSTEM_TYPE_PATH"
|
||||
read NAME < "$SYSTEM_NAME_PATH"
|
||||
read SYSPLEX < "$SYSPLEX_NAME_PATH"
|
||||
|
||||
# Parse command line options: Use eval to remove getopt quotes
|
||||
eval set -- $opts
|
||||
while [ -n $1 ]; do
|
||||
case "$1" in
|
||||
--help|-h)
|
||||
print_help_and_exit
|
||||
;;
|
||||
--version|-v)
|
||||
print_version_and_exit
|
||||
;;
|
||||
-b|--set-bit)
|
||||
case "$2" in
|
||||
kvm)
|
||||
cpi_set_bit 0
|
||||
;;
|
||||
*)
|
||||
fail_with "$PRG: Unknown bit \"$2\" for the $1 option"
|
||||
;;
|
||||
esac
|
||||
shift 2
|
||||
;;
|
||||
-L|--level)
|
||||
cpi_set_oslevel "$2"
|
||||
shift 2
|
||||
;;
|
||||
-e|--environment)
|
||||
cpi_set_type "$CPI_SYSTEM_TYPE"
|
||||
cpi_set_name "$CPI_SYSTEM_NAME"
|
||||
cpi_set_oslevel "$CPI_SYSTEM_LEVEL"
|
||||
cpi_set_sysplex "$CPI_SYSPLEX_NAME"
|
||||
shift
|
||||
;;
|
||||
-T|--type)
|
||||
cpi_set_type "$2"
|
||||
shift 2
|
||||
;;
|
||||
-S|--sysplex)
|
||||
cpi_set_sysplex "$2"
|
||||
shift 2
|
||||
;;
|
||||
-N|--name)
|
||||
cpi_set_name "$2"
|
||||
shift 2
|
||||
;;
|
||||
--show)
|
||||
cpi_show
|
||||
exit $EXIT_SUCCESS
|
||||
;;
|
||||
--commit)
|
||||
cpi_commit
|
||||
exit $EXIT_SUCCESS
|
||||
;;
|
||||
--dry-run)
|
||||
DRYRUN=1
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break;
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Print settings for --dry-run or commit them to sysfs otherwise
|
||||
|
||||
if [ $DRYRUN -eq 1 ]; then
|
||||
cat <<-EndDryrun
|
||||
System type: $TYPE
|
||||
System level: $LEVEL
|
||||
System name: $NAME
|
||||
Sysplex name: $SYSPLEX
|
||||
EndDryrun
|
||||
else
|
||||
echo "$LEVEL" > "$SYSTEM_LEVEL_PATH"
|
||||
echo "$TYPE" > "$SYSTEM_TYPE_PATH"
|
||||
echo "$NAME" > "$SYSTEM_NAME_PATH"
|
||||
echo "$SYSPLEX" > "$SYSPLEX_NAME_PATH"
|
||||
cpi_commit
|
||||
fi
|
||||
|
||||
exit $EXIT_SUCCESS
|
||||
@@ -35,12 +35,6 @@ EnvironmentFile=/etc/sysconfig/cpi
|
||||
# Environment=CPI_SYSTEM_LEVEL=
|
||||
# Environment=CPI_SYSTEM_TYPE=LINUX
|
||||
|
||||
#
|
||||
# Apply settings
|
||||
ExecStartPre=/bin/sh -c 'if test -n "$CPI_SYSTEM_TYPE"; then echo $CPI_SYSTEM_TYPE |tr a-z A-Z > /sys/firmware/cpi/system_type; fi'
|
||||
ExecStartPre=/bin/sh -c 'if test -n "$CPI_SYSTEM_NAME"; then echo $CPI_SYSTEM_NAME |tr a-z A-Z > /sys/firmware/cpi/system_name; fi'
|
||||
ExecStartPre=/bin/sh -c 'if test -n "$CPI_SYSPLEX_NAME"; then echo $CPI_SYSPLEX_NAME |tr a-z A-Z > /sys/firmware/cpi/sysplex_name; fi'
|
||||
ExecStartPre=/bin/sh -c 'test -n "$CPI_SYSTEM_LEVEL" || CPI_SYSTEM_LEVEL="$(uname -r)" ; echo $CPI_SYSTEM_LEVEL |cut -d- -f1 | tr . " " |xargs printf "0x0000000000%02x%02x%02x\n" > /sys/firmware/cpi/system_level'
|
||||
#
|
||||
# Sending data to the HMC/SE
|
||||
ExecStart=/bin/sh -c 'echo 1 > /sys/firmware/cpi/set'
|
||||
ExecStart=@toolslib_path@/cpictl -e
|
||||
|
||||
Reference in New Issue
Block a user