diff --git a/s390utils-2.22.0-rhel.patch b/s390utils-2.22.0-rhel.patch deleted file mode 100644 index 623ce0e..0000000 --- a/s390utils-2.22.0-rhel.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 2844d07e4bba2301fef66f56574c92054bac7cac Mon Sep 17 00:00:00 2001 -From: Steffen Eiden -Date: Mon, 25 Jul 2022 12:57:53 +0200 -Subject: [PATCH] zipl: Add missing check for a nullpointer. - -Fixes a bug that leads to a segmentation fault when no parmline is -provided. - -Fixes: 11b401b5 ("zipl: move and make check for maximum command line length dynamic") -Signed-off-by: Steffen Eiden -Reviewed-by: Marc Hartmayer -Reviewed-by: Stefan Haberland ---- - zipl/src/job.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/zipl/src/job.c b/zipl/src/job.c -index ffdc297..b5bf5b2 100644 ---- a/zipl/src/job.c -+++ b/zipl/src/job.c -@@ -790,7 +790,7 @@ check_common_ipl_data(struct job_common_ipl_data *common, const char *section, - if (!max_parm_size) - max_parm_size = LEGACY_MAXIMUM_PARMLINE_SIZE; - -- len = strlen(common->parmline); -+ len = common->parmline ? strlen(common->parmline) : 0; - if (len > max_parm_size) { - error_text("The length of the parameters line " - "(%d bytes) exceeds the allowed maximum " --- -2.37.1 - diff --git a/s390utils-2.24.0-rhel.patch b/s390utils-2.24.0-rhel.patch new file mode 100644 index 0000000..c03075c --- /dev/null +++ b/s390utils-2.24.0-rhel.patch @@ -0,0 +1,1665 @@ +From 5107a7be16e4849fbda7beae0504fdbc0f2cb4b5 Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Tue, 9 Aug 2022 13:12:26 +0200 +Subject: [PATCH 1/7] zconf/lsdasd: fix Copy Pair related output +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix the default output for copy pair secondary devices to not show +a faulty blockdevice entry and major:minor combination. + +The new output looks like: + + # lsdasd + Bus-ID Status Name Device Type BlkSz Size Blocks + ================================================================================ + 0.0.9740 secondary ECKD + 0.0.9741 secondary ECKD + 0.0.9742 secondary ECKD + 0.0.e964 active dasda 94:0 ECKD 4096 21129MB 5409180 + 0.0.e967 active dasdb 94:4 ECKD 4096 21129MB 5409180 + 0.0.9330 active dasdc 94:8 ECKD 4096 782MB 200340 + 0.0.9700 active dasdd 94:12 ECKD 4096 782MB 200340 + 0.0.9701 active dasdf 94:20 ECKD 4096 782MB 200340 + 0.0.9702 active dasdh 94:28 ECKD 4096 782MB 200340 + +Also add copy_pairs to extended output: + + # lsdasd -l 9700 + 0.0.9700/dasdd/94:12 + status: active + type: ECKD + blksz: 4096 + size: 782MB + blocks: 200340 + extent_size: 1113 + logical_capacity: 1113 + space_allocated: 1113 + use_diag: 0 + readonly: 0 + eer_enabled: 0 + erplog: 0 + hpf: 1 + uid: IBM.750000000ABT31.9700.00 + fc_security: Unsupported + paths_installed: 38 39 3a 3b + paths_in_use: 38 39 3a 3b + paths_non_preferred: + paths_invalid_cabling: + paths_cuir_quiesced: + paths_invalid_hpf_characteristics: + paths_error_threshold_exceeded: + copy_pairs: 0.0.9700,0.0.9740 0.0.9700,0.0.9743 0.0.9700,0.0.9744 0.0.9700,0.0.9745 + +Signed-off-by: Stefan Haberland +Reviewed-by: Jan Hoeppner +Signed-off-by: Jan Höppner +--- + zconf/lsdasd | 113 +++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 96 insertions(+), 17 deletions(-) + +diff --git a/zconf/lsdasd b/zconf/lsdasd +index 795b33b..8b2cc0f 100755 +--- a/zconf/lsdasd ++++ b/zconf/lsdasd +@@ -146,6 +146,62 @@ function findDASDDebugfsDirectorie() { + fi + } + ++#------------------------------------------------------------------------------ ++# The blockpath can usually be found over the DEVPATH ++# In case of a swapped Copy Pair device the blockdev is likely associated ++# with one of the secondary devices ++# this function checks if the blockdev is associated with the primary device ++# and if not search for it in the secondary device list ++#------------------------------------------------------------------------------ ++function setCorrectBlockPath() { ++ local DRIVERECKD="$SYSFSDIR/bus/ccw/drivers/dasd-eckd/" ++ local DRIVERFBA="$SYSFSDIR/bus/ccw/drivers/dasd-fba/" ++ local SEARCHDIRS= ++ local SEARCHLIST= ++ ++ if [[ "$COPYROLE" == "none" ]] || [[ -d "$DEVPATH/block" ]]; then ++ BLOCKPATH="$DEVPATH"/block/dasd* ++ return ++ fi ++ ++ if [[ -d "$DRIVERECKD" ]]; then ++ SEARCHDIRS="$DRIVERECKD" ++ fi ++ if [[ -d "$DRIVERFBA" ]]; then ++ SEARCHDIRS="$SEARCHDIRS $DRIVERFBA" ++ fi ++ ++ SEARCHLIST=$(echo $SECONDARY_LIST | sed 's/,/ /g') ++ for SEARCHDEV in $SEARCHLIST ++ do ++ if [[ -n "$SEARCHDIRS" ]]; then ++ PRIM_DEVPATH=$(find $SEARCHDIRS -type l -name $SEARCHDEV \ ++ -printf "%h/%l\n" 2> /dev/null) ++ if [[ -d "$PRIM_DEVPATH/block" ]]; then ++ break ++ fi ++ else ++ # The above paths may become invalid in the future, so we keep the ++ # following query as backup: ++ PRIM_DEVPATH=$(find "$SYSFSDIR/devices" -type l -name $SEARCHDEV \ ++ "driver" -lname "*/dasd*" -printf "%h\n" \ ++ 2> /dev/null) ++ fi ++ done ++ ++ BLOCKPATH="$PRIM_DEVPATH"/block/dasd* ++} ++ ++#------------------------------------------------------------------------------ ++# gather Copy Pair related data ++#------------------------------------------------------------------------------ ++function gatherCopyPairData() { ++ read COPYPAIR 2> /dev/null < $DEVPATH/copy_pair ++ PRIMARY_UID=`echo $COPYPAIR | cut -d " " -f1 | cut -d "," -f1` ++ COPYPAIR=`echo "$COPYPAIR" | sed 's/ /,/g' | sed 's/^,//' ` ++ SECONDARY_LIST=`echo ${COPYPAIR//$PRIMARY_UID","/} ` ++} ++ + #------------------------------------------------------------------------------ + # gather device data and call appropriate output function + #------------------------------------------------------------------------------ +@@ -165,16 +221,18 @@ function gatherDeviceData() { + read READONLY 2> /dev/null < $DEVPATH/readonly || continue + read DISCIPLINE 2> /dev/null < $DEVPATH/discipline || continue + read ESE 2> /dev/null < $DEVPATH/ese ++ read COPYROLE 2> /dev/null < $DEVPATH/copy_role + ++ if [[ "$COPYROLE" != "none" ]]; then ++ gatherCopyPairData ++ fi + # Block device specific information is only available for + # devices that are online and not a PAV alias +- if [[ ! "$ONLINE" == 0 ]] && [[ ! "$ALIAS" == 1 ]]; then +- #find device Path to the block device +- if [[ -d "$DEVPATH/block" ]]; then +- set - "$DEVPATH"/block/dasd* +- else +- set - "$DEVPATH"/block:dasd* +- fi ++ if [[ ! "$ONLINE" == 0 ]] && [[ ! "$ALIAS" == 1 ]] && ++ [[ ! "$COPYROLE" == "secondary" ]]; then ++ #find device Path to the block device ++ setCorrectBlockPath ++ set - $BLOCKPATH + MAJMIN= + MAJOR= + MINOR= +@@ -194,10 +252,12 @@ function gatherDeviceData() { + fi + fi + else +- # BLOCKNAME for offline and alias devices will not be +- # printed, it's just a key for sorting ++ # BLOCKNAME for offline, alias and secondary devices ++ # will not be printed, it's just a key for sorting + if [[ "$ONLINE" == 0 ]]; then + BLOCKNAME="" ++ elif [[ "$COPYROLE" == "secondary" ]]; then ++ BLOCKNAME="b" + else + BLOCKNAME="a" + fi +@@ -261,6 +321,15 @@ function newoutput() + return + fi + ++ if [[ "$COPYROLE" == "secondary" ]]; then ++ printf "%s:%s:%-8s secondary %-8s %13s\n" \ ++ "$SORTKEYLEN" "$SORTKEY" \ ++ "$BUSID" \ ++ "$PRIMARY_BLOCKNAME" \ ++ "$DISCIPLINE" ++ return ++ fi ++ + if [[ "$READONLY" == 0 ]]; then + ROSTRING="" + else +@@ -519,10 +588,14 @@ function extended() + "${HPF_PATHS[@]}" \ + "${IFCC_PATHS[@]}" ; + return +- elif [[ "$ALIAS" == 1 ]]; then +- if [[ "$BASEONLY" == "false" ]]; then +- ACTIVE="alias" +- printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \ ++ elif [[ "$ALIAS" == 1 ]] || [[ "$COPYROLE" == "secondary" ]]; then ++ if [[ "$BASEONLY" == "false" ]] || [[ "$COPYROLE" == "secondary" ]]; then ++ if [[ "$COPYROLE" == "secondary" ]]; then ++ ACTIVE="secondary" ++ else ++ ACTIVE="alias" ++ fi ++ printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s# copy_pairs:\t\t\t\t%s#\n" \ + "$SORTKEYLEN" "$SORTKEY" \ + "$BUSID" \ + "$ACTIVE" \ +@@ -540,7 +613,8 @@ function extended() + "${CABLE_PATHS[@]}" \ + "${CUIR_PATHS[@]}" \ + "${HPF_PATHS[@]}" \ +- "${IFCC_PATHS[@]}" ; ++ "${IFCC_PATHS[@]}" \ ++ "${COPYPAIR}" ; + fi + return + elif [[ -z "$BLOCKNAME" ]] || [[ -z "$SIZE" ]]; then +@@ -565,7 +639,7 @@ function extended() + DISCIPLINE="${DISCIPLINE} (ESE)" + fi + +- printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \ ++ printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s# copy_pairs:\t\t\t\t%s#\n" \ + "$SORTKEYLEN" "$SORTKEY" \ + "$BUSID" \ + "$BLOCKNAME" \ +@@ -593,7 +667,8 @@ function extended() + "${CABLE_PATHS[@]}" \ + "${CUIR_PATHS[@]}" \ + "${HPF_PATHS[@]}" \ +- "${IFCC_PATHS[@]}" ; ++ "${IFCC_PATHS[@]}" \ ++ "${COPYPAIR}" ; + } + + function host() +@@ -710,7 +785,11 @@ function uid() + fi + fi + +- printf "%s:%s:%-8s %-8s %s\n" \ ++ if [[ "$COPYROLE" == "secondary" ]]; then ++ BLOCKNAME="secondary" ++ fi ++ ++ printf "%s:%s:%-8s %-10s %s\n" \ + "$SORTKEYLEN" "$SORTKEY" \ + "$BUSID" \ + "$BLOCKNAME" \ +-- +2.38.1 + + +From 803b87e324d704036c5bef1d1daba6cf5b69b668 Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Wed, 12 Oct 2022 15:55:43 +0200 +Subject: [PATCH 2/7] zconf/lsdasd: add Copy Pair output option +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add an option -P|--copy-pairs to show all DASD devices with copy +relations set up in the system and their roles. + +The output looks like: + + # ./s390-tools/zconf/lsdasd -h + [...] + -P|--copy-pairs + Print information about copy pairs. + + # ./s390-tools/zconf/lsdasd -P + Bus-ID Role Name Paired devices + ================================================================================ + 0.0.9700 primary dasdd 0.0.9740,0.0.9743,0.0.9744,0.0.9745 + 0.0.9740 secondary 0.0.9700 + 0.0.9701 primary dasdf 0.0.9741 + 0.0.9741 secondary 0.0.9701 + 0.0.9702 primary dasdh 0.0.9742 + 0.0.9742 secondary 0.0.9702 + +Signed-off-by: Stefan Haberland +Reviewed-by: Jan Hoeppner +Signed-off-by: Jan Höppner +--- + zconf/lsdasd | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/zconf/lsdasd b/zconf/lsdasd +index 8b2cc0f..59720b6 100755 +--- a/zconf/lsdasd ++++ b/zconf/lsdasd +@@ -35,6 +35,8 @@ function PrintUsage() { + Print extended information about DASDs. + -H|--host-access-list + Print information about hosts accessing DASDs. ++ -P|--copy-pairs ++ Print information about copy pairs. + -v|--verbose + For compatibility/future use. Currently ignored. + --version +@@ -292,6 +294,8 @@ function gatherDeviceData() { + uid + elif [[ "$OUTPUT" == "host" ]]; then + host ++ elif [[ "$OUTPUT" == "copy" ]]; then ++ copy + else + newoutput + fi +@@ -769,6 +773,41 @@ printf "\n"; + rm -f $temp + } + ++# pad sortkey with given number zeroes ++function padSortKey() ++{ ++ local LEN=$1 ++ for (( i=0; i<$LEN; i++ )) ++ do ++ printf -v SORTKEY "%s0" $SORTKEY ++ done ++} ++ ++function copy() ++{ ++ if [[ "$COPYROLE" == "none" ]]; then ++ return ++ fi ++ ++ SORTKEYLEN=$((${#PRIMARY_UID}+${#DEV_UID})) ++ if [[ "$COPYROLE" == "secondary" ]]; then ++ SORTKEY=$PRIMARY_UID$DEV_UID ++ PAIREDDEVICES=$PRIMARY_UID ++ BLOCKNAME="" ++ else ++ SORTKEY=$PRIMARY_UID ++ padSortKey ${#DEV_UID} ++ PAIREDDEVICES=$SECONDARY_LIST ++ fi ++ ++ printf "%s:%s:%-8s %-10s %-8s %-8s %s \n" \ ++ "$SORTKEYLEN" "$SORTKEY" \ ++ "$BUSID" \ ++ "$COPYROLE" \ ++ "$BLOCKNAME" \ ++ "$PAIREDDEVICES"; ++} ++ + function uid() + { + #-------------------------------------------# +@@ -835,6 +874,9 @@ while [ $# -gt 0 ]; do + --host-access-list|-H) + OUTPUT="host" + ;; ++ --copy-pairs|-P) ++ OUTPUT="copy" ++ ;; + --version) + PrintVersion + exit 0 +@@ -889,6 +931,9 @@ if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then + elif [[ "$OUTPUT" == "new" ]]; then + printf "Bus-ID Status Name Device Type BlkSz Size Blocks\n" + printf "================================================================================\n" ++elif [[ "$OUTPUT" == "copy" ]]; then ++ printf "Bus-ID Role Name Paired devices\n"; ++ printf "================================================================================\n"; + elif [[ "$OUTPUT" == "extended" ]]; then + PROCESSING=" $PROCESSING | sed 's/#/\n/g' " + fi +-- +2.38.1 + + +From e742d1c9ae5103c9f88d3fde085e0694efaeeb5a Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Thu, 11 Aug 2022 13:52:30 +0200 +Subject: [PATCH 3/7] zdev: correctly handle multiple values for CCW devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Correctly create multiple lines in the udev rule for CCW device attributes +with multi bit set that contain multiple values. + +Suggested-by: Peter Oberparleiter +Signed-off-by: Stefan Haberland +Reviewed-by: Jan Hoeppner +Reviewed-by: Peter Oberparleiter +Signed-off-by: Jan Höppner +--- + zdev/src/udev_ccw.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/zdev/src/udev_ccw.c b/zdev/src/udev_ccw.c +index 7c0a703..3375a5e 100644 +--- a/zdev/src/udev_ccw.c ++++ b/zdev/src/udev_ccw.c +@@ -221,6 +221,7 @@ static void write_attr_to_file(FILE *fd, struct device_state *state, const char + struct ptrlist_node *p; + struct setting *s; + struct util_list *list = NULL; ++ struct strlist_node *str; + + /* Apply attributes in correct order. */ + list = setting_list_get_sorted(state->settings); +@@ -229,8 +230,13 @@ static void write_attr_to_file(FILE *fd, struct device_state *state, const char + s = p->ptr; + if (s->removed) + continue; +- if ((s->attrib && s->attrib->internal) || +- internal_by_name(s->name)) { ++ if (s->values) { ++ util_list_iterate(s->values, str) { ++ fprintf(fd, "ATTR{[ccw/%s]%s}=\"%s\"\n", ++ id, s->name, str->str); ++ } ++ } else if ((s->attrib && s->attrib->internal) || ++ internal_by_name(s->name)) { + fprintf(fd, "ENV{zdev_%s}=\"%s\"\n", + internal_get_name(s->name), s->value); + } else { +-- +2.38.1 + + +From f654b971d0e78a139c7ed8c0df821af2f4356a8b Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Tue, 9 Aug 2022 16:17:23 +0200 +Subject: [PATCH 4/7] zdev: add copy_pair attribute for DASD devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The DASD device driver has a new attribute copy_pair to make storage +server copy pairs known to the driver. +Add this attribute to zdev. + +Usage example: + +Add two copy pairs 1000,2000 and 1000,3000 to a DASD device 1000 +$ chzdev dasd 1000 copy_pairs=1000,2000 copy_pairs=1000,3000 + +or + +$ chzdev dasd 1000 copy_pairs="1000,2000 1000,3000" + +To add a third copy pair later on: +$ chzdev dasd 1000 copy_pairs=1000,4000 + +To remove all copy pairs from the device 1000: +$ chzdev dasd 1000 -r copy_pairs + +Signed-off-by: Stefan Haberland +Reviewed-by: Peter Oberparleiter +Signed-off-by: Jan Höppner +--- + zdev/src/dasd.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 93 insertions(+) + +diff --git a/zdev/src/dasd.c b/zdev/src/dasd.c +index daec916..f9fd231 100644 +--- a/zdev/src/dasd.c ++++ b/zdev/src/dasd.c +@@ -137,6 +137,21 @@ static struct attrib dasd_attr_readonly = { + .accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)), + }; + ++static struct attrib dasd_attr_copy_pair = { ++ .name = "copy_pair", ++ .title = "Modify copy-pair relations", ++ .desc = "Make a copy-pair relation for this device known to the DASD " ++ "driver.\n" ++ "A copy-pair is a comma-separated pair of device bus-IDs\n" ++ ",.\n" ++ "Example: 0.0.1000,0.0.2000\n" ++ "Up to 4 copy-pairs are accepted by the DASD driver for each " ++ "device.\n", ++ .unstable = 1, ++ .multi = 1, ++ .activerem = 1, ++}; ++ + static struct attrib dasd_attr_erplog = { + .name = "erplog", + .title = "Enable logging of Error Recovery Processing", +@@ -600,6 +615,81 @@ persistent: + return rc; + } + ++/* Remove all entries from the copy_pair attribute by writing 'clear' to it. */ ++static void dasd_clear_copy_pair(struct setting *s) ++{ ++ free(s->value); ++ s->value = misc_strdup("clear"); ++ strlist_free(s->values); ++ s->values = strlist_new(); ++ strlist_add(s->values, "clear"); ++ s->removed = 0; ++ s->modified = 1; ++} ++ ++/* ++ * Copy-pair values may contain multiple values in one line ++ * those need to be split up and put in multiple values entries ++ * delimiter is " " and "\n" depending on the source ++ * values read from sysfs have " " as delimiter and values from ++ * zdev have "\n" ++ */ ++static void dasd_split_copy_pair(struct setting *s) ++{ ++ struct util_list *new = NULL; ++ struct strlist_node *node; ++ ++ new = strlist_new(); ++ util_list_iterate(s->values, node) ++ strlist_add_multi(new, node->str, "\n ", 0); ++ ++ strlist_free(s->values); ++ s->values = new; ++} ++ ++/* ++ * For persistent configurations one value per values[] entry is required ++ * to achieve a correct multi-line copy-pair statement in the resulting ++ * udev-rule. ++ */ ++static exit_code_t dasd_st_configure_persistent(struct subtype *st, ++ struct device *dev) ++{ ++ struct setting *s; ++ ++ util_list_iterate(&dev->persistent.settings->list, s) { ++ if (strcmp(s->name, "copy_pair") == 0) ++ dasd_split_copy_pair(s); ++ } ++ ++ return st->super->configure_persistent(st, dev); ++} ++ ++/* ++ * For active configurations one value per values[] entry is required to ++ * correctly operate the sysfs attribute. ++ * ++ * In case of removal the string "clear" has to be written to the ++ * value and values[] entry. ++ */ ++static exit_code_t dasd_st_configure_active(struct subtype *st, ++ struct device *dev) ++{ ++ struct setting *s; ++ ++ util_list_iterate(&dev->active.settings->list, s) { ++ if (strcmp(s->name, "copy_pair") != 0) ++ continue; ++ ++ if (s->removed) ++ dasd_clear_copy_pair(s); ++ else ++ dasd_split_copy_pair(s); ++ } ++ ++ return st->super->configure_active(st, dev); ++} ++ + /* + * DASD device sub-types. + */ +@@ -634,10 +724,13 @@ struct subtype dasd_subtype_eckd = { + &dasd_attr_last_known_reservation_state, + &dasd_attr_safe_offline, + &dasd_attr_fc_security, ++ &dasd_attr_copy_pair, + &internal_attr_early, + ), + .unknown_dev_attribs = 1, + ++ .configure_active = &dasd_st_configure_active, ++ .configure_persistent = &dasd_st_configure_persistent, + .check_pre_configure = &dasd_st_check_pre_configure, + .add_modules = &dasd_st_add_modules, + }; +-- +2.38.1 + + +From 4e28047eb4cacc7b7208018a8c095102517517e8 Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Thu, 10 Nov 2022 16:11:09 +0100 +Subject: [PATCH 5/7] tunedasd: move tunedasd ioctls to libdasd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move all DASD IOCTLs to libdasd and adapt all affected +users accordingly. + +Signed-off-by: Stefan Haberland +Reviewed-by: Jan Hoeppner +Signed-off-by: Jan Höppner +--- + include/lib/dasd_base.h | 73 +++++++++++ + libdasd/dasd_ioctl.c | 129 +++++++++++++++++++ + tunedasd/src/disk.c | 268 ++++++++-------------------------------- + 3 files changed, 252 insertions(+), 218 deletions(-) + +diff --git a/include/lib/dasd_base.h b/include/lib/dasd_base.h +index b12e1f9..11ec94b 100644 +--- a/include/lib/dasd_base.h ++++ b/include/lib/dasd_base.h +@@ -187,6 +187,61 @@ typedef struct format_check_t { + #define DASD_FMT_ERR_RECORD_ID 4 + #define DASD_FMT_ERR_KEY_LENGTH 5 + ++/* ++ * struct profile_info_t ++ * holds the profiling information ++ */ ++typedef struct dasd_profile_info_t { ++ unsigned int dasd_io_reqs; /* # of requests processed at all */ ++ unsigned int dasd_io_sects; /* # of sectors processed at all */ ++ unsigned int dasd_io_secs[32]; /* request's sizes */ ++ unsigned int dasd_io_times[32]; /* requests's times */ ++ unsigned int dasd_io_timps[32]; /* requests's times per sector */ ++ unsigned int dasd_io_time1[32]; /* time from build to start */ ++ unsigned int dasd_io_time2[32]; /* time from start to irq */ ++ unsigned int dasd_io_time2ps[32]; /* time from start to irq */ ++ unsigned int dasd_io_time3[32]; /* time from irq to end */ ++ unsigned int dasd_io_nr_req[32]; /* # of requests in chanq */ ++} dasd_profile_info_t; ++ ++/* ++ * struct attrib_data_t ++ * represents the operation (cache) bits for the device. ++ * Used in DE to influence caching of the DASD. ++ */ ++typedef struct attrib_data_t { ++ unsigned char operation : 3; /* cache operation mode */ ++ unsigned char reserved : 5; ++ unsigned short nr_cyl; /* no of cyliners for read ahaed */ ++ unsigned char reserved2[29]; /* for future use */ ++} __attribute__((packed)) attrib_data_t; ++ ++/* definition of operation (cache) bits within attributes of DE */ ++#define DASD_NORMAL_CACHE 0x0 ++#define DASD_BYPASS_CACHE 0x1 ++#define DASD_INHIBIT_LOAD 0x2 ++#define DASD_SEQ_ACCESS 0x3 ++#define DASD_SEQ_PRESTAGE 0x4 ++#define DASD_REC_ACCESS 0x5 ++ ++/* ++ * Data returned by Sense Path Group ID (SNID) ++ */ ++struct dasd_snid_data { ++ struct { ++ __u8 group : 2; ++ __u8 reserve : 2; ++ __u8 mode : 1; ++ __u8 res : 3; ++ } __attribute__((packed)) path_state; ++ __u8 pgid[11]; ++} __attribute__((packed)); ++ ++struct dasd_snid_ioctl_data { ++ struct dasd_snid_data data; ++ __u8 path_mask; ++} __attribute__((packed)); ++ + #ifndef __linux__ + /* definition from hdreg.h */ + struct hd_geometry { +@@ -207,12 +262,24 @@ struct hd_geometry { + #define BIODASDRSRV _IO(DASD_IOCTL_LETTER, 2) + /* Release the device for the current LPAR */ + #define BIODASDRLSE _IO(DASD_IOCTL_LETTER, 3) ++/* Unconditional reserve the device for the current LPAR */ ++#define BIODASDSLCK _IO(DASD_IOCTL_LETTER, 4) ++/* reset profiling information of a device */ ++#define BIODASDPRRST _IO(DASD_IOCTL_LETTER, 5) ++/* retrieve profiling information of a device */ ++#define BIODASDPRRD _IOR(DASD_IOCTL_LETTER, 2, dasd_profile_info_t) + /* Get information on a dasd device (enhanced) */ + #define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t) ++/* Get Attributes (cache operations) */ ++#define BIODASDGATTR _IOR(DASD_IOCTL_LETTER, 5, attrib_data_t) + /* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */ + #define BIODASDFMT _IOW(DASD_IOCTL_LETTER, 1, format_data_t) ++/* Set Attributes (cache operations) */ ++#define BIODASDSATTR _IOW(DASD_IOCTL_LETTER, 2, attrib_data_t) + /* Release Allocated Space */ + #define BIODASDRAS _IOW(DASD_IOCTL_LETTER, 3, format_data_t) ++/* Get Sense Path Group ID (SNID) data */ ++#define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data) + /* Check device format according to format_data_t */ + #define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t) + +@@ -245,5 +312,11 @@ int dasd_is_ro(const char *device, bool *ro); + int dasd_reread_partition_table(const char *device, int ntries); + int dasd_disk_reserve(const char *device); + int dasd_disk_release(const char *device); ++int dasd_slock(const char *device); ++int dasd_get_cache(const char *device, attrib_data_t *attrib_data); ++int dasd_set_cache(const char *device, attrib_data_t *attrib_data); ++int dasd_query_reserve(const char *device); ++int dasd_profile(const char *device, dasd_profile_info_t *dasd_profile_info); ++int dasd_reset_profile(const char *device); + + #endif /* LIB_DASD_BASE_H */ +diff --git a/libdasd/dasd_ioctl.c b/libdasd/dasd_ioctl.c +index f954961..40e726c 100644 +--- a/libdasd/dasd_ioctl.c ++++ b/libdasd/dasd_ioctl.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + #include "lib/dasd_base.h" + +@@ -321,3 +322,131 @@ int dasd_disk_release(const char *device) + + return 0; + } ++ ++/* ++ * Unconditionally reserve DASD disk ++ * ++ * An existing reserve lock is lifted (steal lock) and the device ++ * is reserved. ++ * ++ * @param[in] device node device node's name ++ * ++ * @retval 0 in case of success ++ * @retval errno in case of failure ++ */ ++int dasd_slock(const char *device) ++{ ++ int fd; ++ ++ fd = dasd_open_device(device, O_RDONLY); ++ RUN_IOCTL(fd, BIODASDSLCK, NULL); ++ dasd_close_device(fd); ++ ++ return 0; ++} ++ ++/* ++ * Get the caching algorithm used for the channel programs of this device. ++ * ++ * @param[in] device node device node's name ++ * @param[out] attrib_data pointer to dasd attrib data with: ++ * 'cache' is the caching mode ++ * 'no_cyl' the number of cylinders to be cached. ++ * ++ * @retval 0 in case of success ++ * @retval errno in case of failure ++ */ ++int dasd_get_cache(const char *device, attrib_data_t *attrib_data) ++{ ++ int fd; ++ ++ fd = dasd_open_device(device, O_RDONLY); ++ RUN_IOCTL(fd, BIODASDGATTR, attrib_data); ++ dasd_close_device(fd); ++ ++ return 0; ++} ++ ++/* ++ * Set the caching algorithm used for the channel programs of this device. ++ * ++ * @param[in] device node device node's name ++ * @param[in] attrib_data pointer to dasd attrib data with: ++ * 'cache' is the caching mode ++ * 'no_cyl' the number of cylinders to be cached. ++ * ++ * @retval 0 in case of success ++ * @retval errno in case of failure ++ */ ++int dasd_set_cache(const char *device, attrib_data_t *attrib_data) ++{ ++ int fd; ++ ++ fd = dasd_open_device(device, O_RDONLY); ++ RUN_IOCTL(fd, BIODASDSATTR, attrib_data); ++ dasd_close_device(fd); ++ ++ return 0; ++} ++ ++/* ++ * Get reserve status of device. ++ * ++ * @param[in] device node device node's name ++ * ++ * @retval errno in case of failure ++ * @retval 0 unreserved ++ * @retval 1 implicit reserved ++ * @retval 2 other reservation ++ * @retval 3 reserved ++ */ ++int dasd_query_reserve(const char *device) ++{ ++ struct dasd_snid_ioctl_data snid = { 0 }; ++ int fd; ++ ++ fd = dasd_open_device(device, O_RDONLY); ++ RUN_IOCTL(fd, BIODASDSNID, &snid); ++ dasd_close_device(fd); ++ ++ return snid.data.path_state.reserve; ++} ++ ++/* ++ * Get and print the profiling info of the device. ++ * ++ * @param[in] device node device node's name ++ * @param[in] dasd_profile_info pointer to dasd profile info ++ * ++ * @retval 0 in case of success ++ * @retval errno in case of failure ++ */ ++int dasd_profile(const char *device, dasd_profile_info_t *dasd_profile_info) ++{ ++ int fd; ++ ++ fd = dasd_open_device(device, O_RDONLY); ++ RUN_IOCTL(fd, BIODASDPRRD, dasd_profile_info); ++ dasd_close_device(fd); ++ ++ return 0; ++} ++ ++/* ++ * Reset the profiling counters of the device. ++ * ++ * @param[in] device node device node's name ++ * ++ * @retval 0 in case of success ++ * @retval errno in case of failure ++ */ ++int dasd_reset_profile(const char *device) ++{ ++ int fd; ++ ++ fd = dasd_open_device(device, O_RDONLY); ++ RUN_IOCTL(fd, BIODASDPRRST, NULL); ++ dasd_close_device(fd); ++ ++ return 0; ++} +diff --git a/tunedasd/src/disk.c b/tunedasd/src/disk.c +index f240651..1e8de16 100644 +--- a/tunedasd/src/disk.c ++++ b/tunedasd/src/disk.c +@@ -19,6 +19,7 @@ + #include + #include + ++#include "lib/dasd_base.h" + #include "lib/dasd_sys.h" + + #include "disk.h" +@@ -26,91 +27,6 @@ + + #define BUS_ID_SIZE 30 + +-/* +- * DASD DEFINITIONS (copied from dasd.h) +- */ +- +-#define DASD_IOCTL_LETTER 'D' +- +-/* +- * struct profile_info_t +- * holds the profiling information +- */ +-typedef struct dasd_profile_info_t { +- unsigned int dasd_io_reqs; /* # of requests processed at all */ +- unsigned int dasd_io_sects; /* # of sectors processed at all */ +- unsigned int dasd_io_secs[32]; /* request's sizes */ +- unsigned int dasd_io_times[32]; /* requests's times */ +- unsigned int dasd_io_timps[32]; /* requests's times per sector */ +- unsigned int dasd_io_time1[32]; /* time from build to start */ +- unsigned int dasd_io_time2[32]; /* time from start to irq */ +- unsigned int dasd_io_time2ps[32]; /*time from start to irq */ +- unsigned int dasd_io_time3[32]; /* time from irq to end */ +- unsigned int dasd_io_nr_req[32]; /* # of requests in chanq */ +-} dasd_profile_info_t; +- +- +-/* +- * struct attrib_data_t +- * represents the operation (cache) bits for the device. +- * Used in DE to influence caching of the DASD. +- */ +-typedef struct attrib_data_t { +- unsigned char operation:3; /* cache operation mode */ +- unsigned char reserved:5; +- unsigned short nr_cyl; /* no of cyliners for read ahaed */ +- unsigned char reserved2[29]; /* for future use */ +-} __attribute__ ((packed)) attrib_data_t; +- +-/* definition of operation (cache) bits within attributes of DE */ +-#define DASD_NORMAL_CACHE 0x0 +-#define DASD_BYPASS_CACHE 0x1 +-#define DASD_INHIBIT_LOAD 0x2 +-#define DASD_SEQ_ACCESS 0x3 +-#define DASD_SEQ_PRESTAGE 0x4 +-#define DASD_REC_ACCESS 0x5 +- +-/* +- * Data returned by Sense Path Group ID (SNID) +- */ +-struct dasd_snid_data { +- struct { +- __u8 group:2; +- __u8 reserve:2; +- __u8 mode:1; +- __u8 res:3; +- } __attribute__ ((packed)) path_state; +- __u8 pgid[11]; +-} __attribute__ ((packed)); +- +-struct dasd_snid_ioctl_data { +- struct dasd_snid_data data; +- __u8 path_mask; +-} __attribute__ ((packed)); +- +- +-/* +- * DASD-IOCTLs (copied from dasd.h) +- */ +-/* Issue a reserve/release command, rsp. */ +-#define BIODASDRSRV _IO (DASD_IOCTL_LETTER,2) /* reserve */ +-#define BIODASDRLSE _IO (DASD_IOCTL_LETTER,3) /* release */ +-#define BIODASDSLCK _IO (DASD_IOCTL_LETTER,4) /* steal lock */ +-/* reset profiling information of a device */ +-#define BIODASDPRRST _IO (DASD_IOCTL_LETTER,5) +- +-/* retrieve profiling information of a device */ +-#define BIODASDPRRD _IOR (DASD_IOCTL_LETTER,2,dasd_profile_info_t) +-/* Get Attributes (cache operations) */ +-#define BIODASDGATTR _IOR(DASD_IOCTL_LETTER,5,attrib_data_t) +- +-/* Set Attributes (cache operations) */ +-#define BIODASDSATTR _IOW (DASD_IOCTL_LETTER,2,attrib_data_t) +- +-/* Get Sense Path Group ID (SNID) data */ +-#define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data) +- +- + /* id definition for profile items */ + enum prof_id { + prof_reqs = 0, +@@ -241,48 +157,33 @@ check_prof_item (char* prof_item) + * 'cache' is the caching mode (see ESS docu for more info) and 'no_cyl' + * the number of cylinders to be cached. + */ +-int +-disk_get_cache (char* device) ++int disk_get_cache(char *device) + { +- int fd; + attrib_data_t attrib_data; +- +- /* Open device file */ +- fd = open (device, O_RDONLY); +- if (fd == -1) { +- error_print ("<%s> - %s", device, strerror (errno)); +- return -1; +- } ++ int rc; + +- /* Get the given caching attributes */ +- if (ioctl (fd, BIODASDGATTR, &attrib_data)) { +- error_print ("Could not get cache attributes for device <%s>", +- device); +- close (fd); +- return -1; +- } ++ rc = dasd_get_cache(device, &attrib_data); ++ if (rc) ++ return rc; + + printf ("%s (%i cyl)\n", + get_cache_name(attrib_data.operation), + attrib_data.nr_cyl); + +- close (fd); + return 0; + } + +- + /* + * Set the caching algorithm used for the channel programs of this device. + * 'cache' is the caching mode (see ESS docu for more info) and 'no_cyl' + * the number of cylinders to be cached. + */ +-int +-disk_set_cache (char* device, char* cache, char* no_cyl) ++int disk_set_cache(char *device, char *cache, char *no_cyl) + { +- int fd; + attrib_data_t attrib_data; +- +- /* get caching mode and # cylinders */ ++ int rc; ++ ++ /* get caching mode and # cylinders */ + attrib_data.operation = check_cache (cache); + attrib_data.nr_cyl = check_no_cyl (no_cyl); + +@@ -292,52 +193,34 @@ disk_set_cache (char* device, char* cache, char* no_cyl) + attrib_data.nr_cyl); + } + +- /* Open device file */ +- fd = open (device, O_RDONLY); +- if (fd == -1) { +- error_print ("<%s> - %s", device, strerror (errno)); +- return -1; +- } +- + /* Set the given caching attributes */ + printf ("Setting cache mode for device <%s>...\n", device); +- if (ioctl (fd, BIODASDSATTR, &attrib_data)) { +- error_print ("Could not set caching for device <%s>", device); +- close (fd); ++ rc = dasd_set_cache(device, &attrib_data); ++ if (rc) { ++ error_print("Could not set caching for device <%s>", device); + return -1; + } +- + printf ("Done.\n"); +- close (fd); ++ + return 0; + } + +- + /* + * Reserve the device. + */ +-int +-disk_reserve (char* device) ++int disk_reserve(char *device) + { +- int fd; +- +- /* Open device file */ +- fd = open (device, O_RDONLY); +- if (fd == -1) { +- error_print ("<%s> - %s", device, strerror (errno)); +- return -1; +- } ++ int rc; + + /* Reserve device */ + printf ("Reserving device <%s>...\n", device); +- if (ioctl (fd, BIODASDRSRV)) { +- error_print ("Could not reserve device <%s>", device); +- close (fd); ++ rc = dasd_disk_reserve(device); ++ if (rc) { ++ error_print("Could not reserve device <%s>", device); + return -1; + } + +- printf ("Done.\n"); +- close (fd); ++ printf("Done.\n"); + return 0; + } + +@@ -345,28 +228,18 @@ disk_reserve (char* device) + /* + * Release the device. + */ +-int +-disk_release (char* device) ++int disk_release(char *device) + { +- int fd; +- +- /* Open device file */ +- fd = open (device, O_RDONLY); +- if (fd == -1) { +- error_print ("<%s> - %s", device, strerror (errno)); +- return -1; +- } ++ int rc; + +- /* Release device */ + printf ("Releasing device <%s>...\n", device); +- if (ioctl (fd, BIODASDRLSE)) { +- error_print ("Could not release device <%s>", device); +- close (fd); ++ rc = dasd_disk_release(device); ++ if (rc) { ++ error_print("Could not release device <%s>", device); + return -1; + } + +- printf ("Done.\n"); +- close (fd); ++ printf("Done.\n"); + return 0; + } + +@@ -376,29 +249,19 @@ disk_release (char* device) + * This means to reserve the device even if it was already reserved. + * The current reserve is broken (steal lock). + */ +-int +-disk_slock (char* device) ++int disk_slock(char *device) + { +- int fd; +- +- /* Open device file */ +- fd = open (device, O_RDONLY); +- if (fd == -1) { +- error_print ("<%s> - %s", device, strerror (errno)); +- return -1; +- } ++ int rc; + + /* Unconditional reserve device */ + printf ("Unconditional reserving device <%s>...\n", device); +- if (ioctl (fd, BIODASDSLCK)) { +- error_print ("Could not unconditional reserve device <%s>", +- device); +- close (fd); ++ rc = dasd_slock(device); ++ if (rc) { ++ error_print("Could not unconditional reserve device <%s>", device); + return -1; + } +- + printf ("Done.\n"); +- close (fd); ++ + return 0; + } + +@@ -407,27 +270,16 @@ disk_slock (char* device) + * Uses the Sense Path Group ID (SNID) ioctl to find out if + * a device is reserved to it's path group. + */ +-int +-disk_query_reserve_status(char* device) ++int disk_query_reserve_status(char *device) + { +- int fd; +- struct dasd_snid_ioctl_data snid; ++ int rc; + +- /* Open device file */ +- fd = open (device, O_RDONLY); +- if (fd == -1) { +- error_print ("<%s> - %s", device, strerror (errno)); ++ rc = dasd_query_reserve(device); ++ if (rc < 0) { ++ error_print("Could not read reserve status for device <%s>", device); + return -1; + } +- snid.path_mask = 0; +- /* Release device */ +- if (ioctl(fd, BIODASDSNID, &snid)) { +- error_print("Could not read reserve status" +- " for device <%s>", device); +- close (fd); +- return -1; +- } +- switch (snid.data.path_state.reserve) { ++ switch (rc) { + case 0: + printf("none\n"); + break; +@@ -441,7 +293,7 @@ disk_query_reserve_status(char* device) + printf("reserved\n"); + break; + } +- close (fd); ++ + return 0; + } + +@@ -615,21 +467,14 @@ static int disk_profile_item(dasd_profile_info_t dasd_profile_info, + /* + * Get and print the profiling info of the device. + */ +-int +-disk_profile (char* device, char* prof_item) ++int disk_profile(char *device, char *prof_item) + { +- int fd, rc; + dasd_profile_info_t dasd_profile_info; +- +- /* Open device file */ +- fd = open (device, O_RDONLY); +- if (fd == -1) { +- error_print ("<%s> - %s", device, strerror (errno)); +- return -1; +- } ++ int rc; + + /* Get the profile info */ +- if (ioctl (fd, BIODASDPRRD, &dasd_profile_info)) { ++ rc = dasd_profile(device, &dasd_profile_info); ++ if (rc) { + switch (errno) { + case EIO: /* profiling is not active */ + error_print ("Profiling (on device <%s>) is not " +@@ -639,7 +484,6 @@ disk_profile (char* device, char* prof_item) + error_print ("Could not get profile info for device " + "<%s>.", device); + } +- close (fd); + return -1; + } + /* Check for profile item or summary */ +@@ -648,38 +492,26 @@ disk_profile (char* device, char* prof_item) + } else { + rc = disk_profile_item (dasd_profile_info, prof_item); + } +- +- close (fd); ++ + return rc; + } + +- + /* + * Reset the profiling counters of the device. + */ +-int +-disk_reset_prof (char* device) ++int disk_reset_prof(char *device) + { +- int fd; +- +- /* Open device file */ +- fd = open (device, O_RDONLY); +- if (fd == -1) { +- error_print ("<%s> - %s", device, strerror (errno)); +- return -1; +- } ++ int rc; + + /* reset profile info */ + printf ("Resetting profile info for device <%s>...\n", device); +- if (ioctl (fd, BIODASDPRRST)) { +- error_print ("Could not reset profile info for device <%s>", +- device); +- close (fd); ++ rc = dasd_reset_profile(device); ++ if (rc) { ++ error_print("Could not reset profile info for device <%s>", device); + return -1; + } +- + printf ("Done.\n"); +- close (fd); ++ + return 0; + } + +-- +2.38.1 + + +From 3aa7f6e29871c06537ab95bf2a14b5eb3ca6e847 Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Thu, 27 Oct 2022 15:51:00 +0200 +Subject: [PATCH 6/7] libdasd: fix ioctl macro to return also positive return + codes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In case of an error the ioctl macro only returns errno to the calling +function. +This misses positive returncodes from ioctls. +Change the macro to also return positive return codes. + +Signed-off-by: Stefan Haberland +Reviewed-by: Jan Hoeppner +Signed-off-by: Jan Höppner +--- + libdasd/dasd_ioctl.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/libdasd/dasd_ioctl.c b/libdasd/dasd_ioctl.c +index 40e726c..3a36375 100644 +--- a/libdasd/dasd_ioctl.c ++++ b/libdasd/dasd_ioctl.c +@@ -28,11 +28,13 @@ + + #define RUN_IOCTL(fd, req, argp) \ + do { \ +- if (ioctl(fd, req, argp) != 0) { \ +- int err = errno; \ +- if (err != EBADF) \ ++ int rc = ioctl(fd, req, argp); \ ++ if (rc != 0) { \ ++ if (rc == -1) \ ++ rc = errno; \ ++ if (rc != EBADF) \ + dasd_close_device(fd); \ +- return err; \ ++ return rc; \ + } \ + } while (0) + +-- +2.38.1 + + +From 3f12bdf4c728caeaeaa64158efb26f917d905b08 Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Fri, 11 Nov 2022 13:17:32 +0100 +Subject: [PATCH 7/7] tunedasd: add copy_pair swap capability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add an option to tunedasd to trigger a copy pair swap using the appropriate +ioctl for DASD devices. + + -s, --copy-pair-swap COPY_PAIR + +This command requires a comma separated pair of primary,secondary to be +specified. In case of success the old secondary will become the new primary +device and the old primary will become a secondary device. + +Example: + +tunedasd /dev/dasda -s 0.0.9700,0.0.9740 + +This will set the old secondary device 0.0.9740 as the new primary. +The old primary device 0.0.9700 will automatically become a secondary +device. + +Signed-off-by: Stefan Haberland +Reviewed-by: Jan Hoeppner +Signed-off-by: Jan Höppner +--- + include/lib/dasd_base.h | 14 ++++++++-- + libdasd/dasd_ioctl.c | 28 ++++++++++++++++++++ + tunedasd/include/disk.h | 1 + + tunedasd/man/tunedasd.8 | 14 ++++++++++ + tunedasd/src/disk.c | 50 ++++++++++++++++++++++++++++++++++-- + tunedasd/src/tunedasd.c | 57 +++++++++++++++++++++++++---------------- + 6 files changed, 138 insertions(+), 26 deletions(-) + +diff --git a/include/lib/dasd_base.h b/include/lib/dasd_base.h +index 11ec94b..400e374 100644 +--- a/include/lib/dasd_base.h ++++ b/include/lib/dasd_base.h +@@ -20,8 +20,8 @@ + #include + #include + +-/* A bus id of a DASD is 8 characters long. E.g. 0.0.4711 */ +-#define DASD_BUS_ID_SIZE 9 ++/* the definition of a BUSID in the DASD driver is 20 */ ++#define DASD_BUS_ID_SIZE 20 + + typedef struct dasd_information2_t { + unsigned int devno; /* S/390 devno */ +@@ -242,6 +242,13 @@ struct dasd_snid_ioctl_data { + __u8 path_mask; + } __attribute__((packed)); + ++struct dasd_copypair_swap_data { ++ char primary[DASD_BUS_ID_SIZE]; /* BUSID of primary */ ++ char secondary[DASD_BUS_ID_SIZE]; /* BUSID of secondary */ ++ /* Reserved for future updates. */ ++ char reserved[64]; ++}; ++ + #ifndef __linux__ + /* definition from hdreg.h */ + struct hd_geometry { +@@ -278,6 +285,8 @@ struct hd_geometry { + #define BIODASDSATTR _IOW(DASD_IOCTL_LETTER, 2, attrib_data_t) + /* Release Allocated Space */ + #define BIODASDRAS _IOW(DASD_IOCTL_LETTER, 3, format_data_t) ++/* Swap copy pair */ ++#define BIODASDPPRCSWAP _IOW(DASD_IOCTL_LETTER, 4, struct dasd_copypair_swap_data) + /* Get Sense Path Group ID (SNID) data */ + #define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data) + /* Check device format according to format_data_t */ +@@ -318,5 +327,6 @@ int dasd_set_cache(const char *device, attrib_data_t *attrib_data); + int dasd_query_reserve(const char *device); + int dasd_profile(const char *device, dasd_profile_info_t *dasd_profile_info); + int dasd_reset_profile(const char *device); ++int dasd_copy_swap(const char *device, struct dasd_copypair_swap_data *data); + + #endif /* LIB_DASD_BASE_H */ +diff --git a/libdasd/dasd_ioctl.c b/libdasd/dasd_ioctl.c +index 3a36375..f684761 100644 +--- a/libdasd/dasd_ioctl.c ++++ b/libdasd/dasd_ioctl.c +@@ -452,3 +452,31 @@ int dasd_reset_profile(const char *device) + + return 0; + } ++ ++/* ++ * Initiate the swap of a copy pairs primary,secondary relation. ++ * The old secondary will become the new primary and vice versa. ++ * ++ * @param[in] device node device node's name ++ * @param[in] copy_pair data pointer to dasd copypair data with: ++ * 'primary' old primary, becoming secondary ++ * 'secondary' old secondary, becoming primary. ++ * ++ * @retval errno in case of failure ++ * @retval 0 in case of success ++ * @retval 1 swap data invalid ++ * @retval 2 no active device found ++ * @retval 3 wrong primary specified ++ * @retval 4 secondary device not found ++ * @retval 5 swap already running ++ */ ++int dasd_copy_swap(const char *device, struct dasd_copypair_swap_data *data) ++{ ++ int fd; ++ ++ fd = dasd_open_device(device, O_RDONLY); ++ RUN_IOCTL(fd, BIODASDPPRCSWAP, data); ++ dasd_close_device(fd); ++ ++ return 0; ++} +diff --git a/tunedasd/include/disk.h b/tunedasd/include/disk.h +index ea35f6f..55a32d0 100644 +--- a/tunedasd/include/disk.h ++++ b/tunedasd/include/disk.h +@@ -31,6 +31,7 @@ int disk_query_reserve_status(char* device); + int disk_profile (char* device, char* prof_item); + int disk_reset_prof(char *device); + int disk_reset_chpid(char *device, char *chpid); ++int disk_copy_swap(char *device, char *copy_pair); + + #endif /* not DISK_H */ + +diff --git a/tunedasd/man/tunedasd.8 b/tunedasd/man/tunedasd.8 +index 94c3608..ae41b97 100644 +--- a/tunedasd/man/tunedasd.8 ++++ b/tunedasd/man/tunedasd.8 +@@ -174,6 +174,14 @@ Reset all channel paths of the selected device. The channel paths + might be suspended due to high IFCC error rates or a High Performance + FICON failure. Use this option to resume considering all defined + channel paths for I/O. ++.TP ++.BR "\-s" " or " "\-\-copy\-pair\-swap " ++Swap the copy roles of the specified copy pair. The has to ++be a comma separated pair of \fBPRIMARY,SECONDARY\fR where ++\fBPRIMARY\fR is the old primary device that will become a secondary ++automatically. The old \fBSECONDARY\fR device will become the new ++primary device. Both devices have to be online for this operation to ++succeed. + .\" + .\".TP + .\".BR "\-o" " or " "\-\-online" +@@ -197,6 +205,12 @@ channel paths for I/O. + .br + + tunedasd -p 45 /dev/dasdc ++ ++.br ++4. Scenario: Swap copy pair 0.0.9700 and 0.0.9740 ++.br ++ ++ tunedasd -s 0.0.9700,0.0.9740 /dev/dasdc + .br + .SH "SEE ALSO" + .BR dasdview (8), +diff --git a/tunedasd/src/disk.c b/tunedasd/src/disk.c +index 1e8de16..490c1c5 100644 +--- a/tunedasd/src/disk.c ++++ b/tunedasd/src/disk.c +@@ -21,12 +21,11 @@ + + #include "lib/dasd_base.h" + #include "lib/dasd_sys.h" ++#include "lib/util_libc.h" + + #include "disk.h" + #include "tunedasd.h" + +-#define BUS_ID_SIZE 30 +- + /* id definition for profile items */ + enum prof_id { + prof_reqs = 0, +@@ -549,3 +548,50 @@ int disk_reset_chpid(char *device, char *chpid) + + return -1; + } ++ ++int disk_copy_swap(char *device, char *copy_pair) ++{ ++ struct dasd_copypair_swap_data data = { 0 }; ++ char *primary, *secondary; ++ int rc = 0; ++ ++ primary = strtok(copy_pair, ","); ++ secondary = strtok(NULL, ","); ++ ++ if (!primary || !secondary) { ++ error_print("%s: Error parsing Copy Pair %s", device, copy_pair); ++ return -1; ++ } ++ ++ util_strlcpy(data.primary, primary, DASD_BUS_ID_SIZE); ++ util_strlcpy(data.secondary, secondary, DASD_BUS_ID_SIZE); ++ ++ printf("Swapping copy pair %s %s on device <%s>...\n", primary, secondary, device); ++ rc = dasd_copy_swap(device, &data); ++ ++ switch (rc) { ++ case 0: ++ printf("Done.\n"); ++ return 0; ++ case 1: ++ error_print("Swap data invalid"); ++ break; ++ case 2: ++ error_print("No active device found"); ++ break; ++ case 3: ++ error_print("Wrong primary device specified"); ++ break; ++ case 4: ++ error_print("Secondary device not found"); ++ break; ++ case 5: ++ error_print("Swap already running"); ++ break; ++ default: ++ error_print("Swap not successful rc %d", rc); ++ break; ++ } ++ ++ return -1; ++} +diff --git a/tunedasd/src/tunedasd.c b/tunedasd/src/tunedasd.c +index 3c14eb8..691841c 100644 +--- a/tunedasd/src/tunedasd.c ++++ b/tunedasd/src/tunedasd.c +@@ -119,12 +119,17 @@ static struct util_opt opt_vec[] = { + .desc = "Reset all channel paths of a device", + .flags = UTIL_OPT_FLAG_NOSHORT, + }, ++ { ++ .option = { "copy-pair-swap", required_argument, NULL, 's' }, ++ .argument = "COPY_PAIR", ++ .desc = "Swap a specified, comma separated copy pair.", ++ }, + UTIL_OPT_HELP, + UTIL_OPT_VERSION, + UTIL_OPT_END + }; + +-#define CMD_KEYWORD_NUM 16 ++#define CMD_KEYWORD_NUM 17 + #define DEVICES_NUM 256 + + enum cmd_keyword_id { +@@ -144,6 +149,7 @@ enum cmd_keyword_id { + cmd_keyword_path_all, + cmd_keyword_enable_stats, + cmd_keyword_disable_stats, ++ cmd_keyword_copy_swap, + }; + + +@@ -167,7 +173,8 @@ static const struct { + { "path_reset", cmd_keyword_path }, + { "path_reset_all", cmd_keyword_path_all }, + { "enable-stats", cmd_keyword_enable_stats }, +- { "disable-stats", cmd_keyword_disable_stats } ++ { "disable-stats", cmd_keyword_disable_stats }, ++ { "copy-swap", cmd_keyword_copy_swap }, + }; + + +@@ -180,26 +187,27 @@ enum cmd_key_state { + + /* Determines which combination of keywords are valid */ + static enum cmd_key_state cmd_key_table[CMD_KEYWORD_NUM][CMD_KEYWORD_NUM] = { +- /* help vers get_ cach no_c rese rele sloc prof prof rese quer path path +- * ion cach e yl rve ase k ile _ite t_pr y_re _all +- * e m of serv ++ /* help vers get_ cach no_c rese rele sloc prof prof rese quer path path enab disa copy ++ * ion cach e yl rve ase k ile _ite t_pr y_re _all le-s ble- -swa ++ * e m of serv tats stat p + */ +- /* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv, inv, inv, inv, inv }, +- /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, +- /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, +- /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, +- /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, +- /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, +- /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv }, +- /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv }, +- /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv, inv, inv, inv, inv }, +- /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv, inv, inv }, +- /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv }, +- /* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv }, +- /* path */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv }, +- /* path_all */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv }, +- /* enable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv }, +- /* disable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req }, ++ /* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv, inv, inv, inv, inv, inv }, ++ /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, ++ /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, ++ /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, ++ /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, ++ /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, ++ /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, ++ /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv }, ++ /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv, inv, inv, inv, inv, inv }, ++ /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv, inv, inv, inv }, ++ /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv }, ++ /* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv }, ++ /* path */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv }, ++ /* path_all */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv }, ++ /* enable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv }, ++ /* disable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv }, ++ /* copy-swap */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req }, + }; + + struct parameter { +@@ -439,7 +447,9 @@ static int get_command_line(int argc, char *argv[], struct command_line *line) + rc = store_option (&cmdline, cmd_keyword_query_reserve, + optarg); + break; +- ++ case 's': ++ rc = store_option(&cmdline, cmd_keyword_copy_swap, optarg); ++ break; + case -1: + /* End of options string - start of devices list */ + cmdline.device_id = optind; +@@ -508,6 +518,9 @@ static int do_command(char *device, struct command_line cmdline) + case cmd_keyword_path_all: + rc = disk_reset_chpid(device, NULL); + break; ++ case cmd_keyword_copy_swap: ++ rc = disk_copy_swap(device, cmdline.parm[cmd_keyword_copy_swap].data); ++ break; + default: + error_print ("Unknown command '%s' specified", + get_keyword_name (i)); +-- +2.38.1 + diff --git a/s390utils.spec b/s390utils.spec index 21f1c36..46e2a3a 100644 --- a/s390utils.spec +++ b/s390utils.spec @@ -9,8 +9,8 @@ Name: s390utils Summary: Utilities and daemons for IBM z Systems -Version: 2.22.0 -Release: 2%{?dist} +Version: 2.24.0 +Release: 1%{?dist} Epoch: 2 License: MIT ExclusiveArch: s390 s390x @@ -84,7 +84,6 @@ make \ %endif NO_PIE_LDFLAGS="" \ BINDIR=/usr/sbin \ - UDEVRUNDIR=/run/udev \ DISTRELEASE=%{release} \ V=1 @@ -98,7 +97,6 @@ make install \ DESTDIR=%{buildroot} \ BINDIR=/usr/sbin \ SYSTEMDSYSTEMUNITDIR=%{_unitdir} \ - UDEVRUNDIR=/run/udev \ DISTRELEASE=%{release} \ V=1 @@ -277,7 +275,6 @@ BuildRequires: json-c-devel BuildRequires: rpm-devel BuildRequires: glib2-devel BuildRequires: libxml2-devel -BuildRequires: liblockfile-devel %description base @@ -816,6 +813,7 @@ Requires(preun): systemd Requires(postun): systemd Requires(pre): shadow-utils BuildRequires: systemd +BuildRequires: systemd-devel %description cpacfstatsd The cpacfstats tools provide a client/server application set to monitor @@ -903,6 +901,15 @@ User-space development files for the s390/s390x architecture. %changelog +* Thu Nov 24 2022 Dan Horák - 2:2.24.0-1 +- rebased to 2.24.0 (#2110310) +- KVM: Tool to process encrypted Secure Execution guest dumps (#2044198) +- zdev: Site-aware device configuration (#2044202) +- Support IBM z16 Processor-Activity-Instrumentation Facility (#2110298) +- Transparent DASD PPRC (Peer-to-Peer Remote Copy) handling (#2126617) +- Support IBM z16 Processor Activity Instrumentation Extension 1 (#2127435) +- Resolves: #2110310 #2044198 #2044202 #2110298 #2126617 #2127435 + * Thu Aug 04 2022 Dan Horák - 2:2.22.0-2 - zipl: Add missing check for a nullpointer (#2113884) - Resolves: #2113884 diff --git a/sources b/sources index 0d0a345..0c54d2e 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (s390-tools-2.22.0.tar.gz) = ac613cddd6d85191f874d8d9eb014b9edc00868f7432a7ac057db0f7011d3ab3371b58a3881d78726e17c8e416d486e6fffb64264d5500abcaabcd56d9f181f6 +SHA512 (s390-tools-2.24.0.tar.gz) = 5c681a031c2bab0ab167623ad08da67bfd236e4892f8a5de813ebfbbc1c60a842f0954bcbca6d2f6ab125ee089b2b5dcbfbb24152bcdde3401810232e21460f4