diff --git a/59-dasd.rules-wait_for.patch b/59-dasd.rules-wait_for.patch index 03d86e9..98a032e 100644 --- a/59-dasd.rules-wait_for.patch +++ b/59-dasd.rules-wait_for.patch @@ -8,7 +8,7 @@ -# on device add set request queue scheduler to deadline -SUBSYSTEM!="block", GOTO="sched_end" - --ACTION!="add", GOTO="sched_end" --KERNEL=="dasd*[!0-9]", WAIT_FOR="queue/scheduler", ATTR{queue/scheduler}="deadline" +-ACTION!="change", GOTO="sched_end" +-KERNEL=="dasd*[!0-9]", TEST=="queue/scheduler", ATTR{queue/scheduler}="deadline" - -LABEL="sched_end" diff --git a/boot.cpi b/boot.cpi deleted file mode 100644 index 8a18fcc..0000000 --- a/boot.cpi +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2001-2002 SuSE Linux AG, Nuernberg, Germany. -# Copyright (c) 2008 SuSE LINUX Products GmbH, Nuernberg, Germany. -# All rights reserved. -# -# /etc/init.d/boot.cpi -# -### BEGIN INIT INFO -# Provides: boot.cpi -# Required-Start: boot.rootfsck -# Required-Stop: $null -# Should-Start: -# X-Start-Before: -# Default-Start: B S -# Default-Stop: -# Description: Set Control Program Identification data -# Short-Description: Set Control Program Identification data -### END INIT INFO - -. /etc/rc.status -. /etc/sysconfig/cpi - -rc_reset - -case "$1" in - start|restart|reload) - if test "$CPI_SET" == "yes"; then - if test ! -e /sys/firmware/cpi; then - echo -n "sclp_cpi interface not found" - rc_status -s - rc_exit - fi - echo "$CPI_SYSTEM_NAME" >/sys/firmware/cpi/system_name - echo "$CPI_SYSPLEX_NAME" >/sys/firmware/cpi/sysplex_name - echo "LINUX " >/sys/firmware/cpi/system_type - awk "BEGIN { split(\"`uname -r`\",x,\".\"); printf(\"0x0000000000%02x%02x%02x\", x[1],x[2],x[3]) }" >/sys/firmware/cpi/system_level - echo 1 >/sys/firmware/cpi/set 2>/dev/null - rc_status -v -r - else - rc_status -u - fi - ;; - stop) - rc_status -s - ;; - status) - rc_status -s - ;; - *) - echo "Usage: $0 {start|stop|status|restart|reload}" - exit 1 - ;; -esac - -rc_exit diff --git a/dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch b/dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch index 11cd2b0..2fdc4e2 100644 --- a/dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch +++ b/dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch @@ -23,49 +23,44 @@ diff --git a/dasdfmt/dasdfmt.c b/dasdfmt/dasdfmt.c index e1877ac..f03cbad 100644 --- a/dasdfmt/dasdfmt.c +++ b/dasdfmt/dasdfmt.c -@@ -270,7 +270,7 @@ static void init_info(dasdfmt_info_t *info) +@@ -588,7 +616,7 @@ + */ static void check_disk(dasdfmt_info_t *info) { - dasd_information_t dasd_info; - int ro, errno_save; + int ro, errno_save, i = 0; if (ioctl(filedes, BLKROGET, &ro) != 0) { errno_save = errno; -@@ -283,7 +283,7 @@ static void check_disk(dasdfmt_info_t *info) - if (ro) { +@@ -602,9 +630,27 @@ + if (ro) ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n"); - } -- -+retry: - if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) { - errno_save = errno; - close(filedes); -@@ -294,8 +294,23 @@ static void check_disk(dasdfmt_info_t *info) - } - if (!info->force) -- if (dasd_info.open_count > 1) +- if (!info->force) ++ if (!info->force) { + /* + * udev strikes again. + * Modern udev will issue a 'change' event whenever + * a device opened with O_RDWR is closed again. -+ * On the ground that program _might_ have changed ++ * On the grounds that program _might_ have changed + * the partition table. + * And confusing the hell out ouf anyone else. + * Bah. -+ */ -+ if (dasd_info.open_count > 1) { -+ if (i < 5) { -+ ++i; ++ */ ++ for ( i = 0 ; i < 6 ; i++ ) { ++ if (info->dasd_info.open_count > 1) { ++ get_device_info(info); + sleep(1); -+ goto retry; + } - ERRMSG_EXIT(EXIT_BUSY, "Disk in use!\n"); ++ else break; ++ + } + if (info->dasd_info.open_count > 1) + ERRMSG_EXIT(EXIT_BUSY, "Disk in use!\n"); ++ } - info->usage_count = dasd_info.open_count; - info->devno = dasd_info.devno; + if (strncmp(info->dasd_info.type, "ECKD", 4) != 0) { + ERRMSG_EXIT(EXIT_FAILURE, -- 1.8.4.5 diff --git a/mkdump.8 b/mkdump.8 index a1335af..b80e543 100644 --- a/mkdump.8 +++ b/mkdump.8 @@ -6,7 +6,7 @@ mkdump \- Preparing disks for use as S/390 dump device. .B mkdump [\fIOPTIONS\fR] [\fIDEVICE\fR]... .SH DESCRIPTION -mkdump 2.0.2 +mkdump 2.0.3 .PP Prepare one or more volumes for use as S/390 dump device. Supported devices are ECKD DASD and SCSI over zFCP disks, while multi\-volumes are limited to DASD. diff --git a/mkdump.pl b/mkdump.pl index b69a4ac..f354f57 100644 --- a/mkdump.pl +++ b/mkdump.pl @@ -4,7 +4,8 @@ # mkdump.pl - Preparing disks for use as S/390 dump device # # Copyright (c) 2011 Tim Hardeck, SUSE LINUX Products GmbH -# bases on mkdump.sh (c) 2004 Hannes Reinecke, SuSE AG +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Based on mkdump.sh (c) 2004 Hannes Reinecke, SuSE AG # # License: # @@ -30,7 +31,7 @@ use warnings; use Fcntl; use Getopt::Long; -my $VERSION = "2.0.2"; +my $VERSION = "2.0.3"; my $BLKID = "/sbin/blkid"; my $PARTED = "/usr/sbin/parted"; @@ -41,7 +42,6 @@ my $ZIPL = "/sbin/zipl"; my $UDEVADM = "/sbin/udevadm"; my $ZGETDUMP = "/sbin/zgetdump"; -my $MNTPOINT = "/var/run/mkdump." . getppid(); # temporary DASD device configuration file for Zipl my $MDPATH = "/tmp/mvdump.conf"; # zFCP dump dir, without a leading '/' @@ -57,11 +57,6 @@ sub cleanup if (-e $MDPATH) { system("rm -f $MDPATH"); } - # zFCP - if (-d $MNTPOINT) { - system("umount $MNTPOINT"); - system("rmdir $MNTPOINT"); - } } sub exit_with @@ -230,15 +225,10 @@ sub print_device $output .= "\t$adapter\t$wwpn\t$lun"; # check for dump record - system("mkdir -p $MNTPOINT"); - if (get_partition_num($device) == 1 and system("mount -o ro ${device}1 $MNTPOINT 2>/dev/null") == 0) { - if ( -r "$MNTPOINT/bootmap" and -d "$MNTPOINT/$ZFCP_DUMP_DIR") { - $dump_device = 1; - $output .= "\tdumpdevice"; - } - system("umount $MNTPOINT"); + if (system("$ZGETDUMP -d ${device} >/dev/null 2>&1") == 0) { + $dump_device = 1; + $output .= "\tdumpdevice"; } - system("rmdir $MNTPOINT"); } if ($only_dump_disks) { if ($dump_device) { @@ -324,7 +314,7 @@ sub prepare_dasd # check formatting for my $device (@devices) { # determine disk layout - my ($fmtstr) = `$DASDVIEW -x -f $device` =~ /(\w\w\w) formatted/; + my ($fmtstr) = `$DASDVIEW -x $device` =~ /(\w\w\w) formatted/; SWITCH: for($fmtstr) { diff --git a/s390-tools-1.34.0.tar.bz2 b/s390-tools-1.34.0.tar.bz2 deleted file mode 100644 index 9092dfa..0000000 --- a/s390-tools-1.34.0.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6f4e9d6f27cfad77ff84ac7a332a7fb2e17b620b3c2da4fc2ba47d2c77c94287 -size 814967 diff --git a/s390-tools-2.1.0.tar.gz b/s390-tools-2.1.0.tar.gz new file mode 100644 index 0000000..aada5a0 --- /dev/null +++ b/s390-tools-2.1.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5ce3fa0de074dfe7d16c74771fcb5092c4a6f575168bf4e13f88275a6370122 +size 1046910 diff --git a/s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch b/s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch index 72c85e2..60237ca 100644 --- a/s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch +++ b/s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch @@ -19,27 +19,9 @@ diff --git a/fdasd/fdasd.c b/fdasd/fdasd.c index 4503d3e..f04dc3d 100644 --- a/fdasd/fdasd.c +++ b/fdasd/fdasd.c -@@ -826,7 +826,7 @@ fdasd_check_conffile_input (fdasd_anchor_t *anc, - * Verifies the specified block device. - */ - static void --fdasd_verify_device (fdasd_anchor_t *anc, char *name) -+fdasd_verify_device (fdasd_anchor_t *anc, char *name) - { - struct stat dst; - char err_str[ERROR_STRING_SIZE]; -@@ -847,7 +847,7 @@ fdasd_verify_device (fdasd_anchor_t *anc, char *name) - fdasd_error(anc, device_verification_failed, err_str); +@@ -1247,9 +1247,12 @@ } -- if (minor (dst.st_rdev) & PARTN_MASK) { -+ if (!anc->force_virtual && minor (dst.st_rdev) & PARTN_MASK) { - snprintf(err_str, ERROR_STRING_SIZE, - "Partition '%s' (%d/%d) detected where device is " - "required\n", name, -@@ -1156,9 +1156,12 @@ fdasd_reread_partition_table (fdasd_anchor_t *anc) - } - if (ioctl(fd, BLKRRPART, NULL) != 0) { - close(fd); - fdasd_error(anc, unable_to_ioctl, "Error while rereading " @@ -52,6 +34,4 @@ index 4503d3e..f04dc3d 100644 + } } close(fd); - } --- -1.8.5.2 + } diff --git a/s390-tools-sles12-pardasdfmt.patch b/s390-tools-sles12-pardasdfmt.patch index c0a4b14..e8d077d 100644 --- a/s390-tools-sles12-pardasdfmt.patch +++ b/s390-tools-sles12-pardasdfmt.patch @@ -10,12 +10,12 @@ - [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR] + [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR] [-P maxpar] .br -- [-L] [-V] [-F] [-k] [-C] \fIdevice\fR -+ [-L] [-V] [-F] [-k] [-C] \fIdevice\fR ... +- [-L] [-V] [-F] [-k] [-C] [-M \fImode\fR] \fIdevice\fR ++ [-L] [-V] [-F] [-k] [-C] [-M \fImode\fR] \fIdevice\fR ... .SH DESCRIPTION \fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it -@@ -91,7 +91,7 @@ +@@ -95,7 +95,7 @@ running in background or redirecting the output to a file. .TP @@ -24,7 +24,7 @@ Print one line for each formatted cylinder showing the number of the cylinder and percentage of formatting process. Intended to be used by higher level interfaces. -@@ -123,6 +123,20 @@ +@@ -152,6 +152,20 @@ and always be a power of two. The recommended blocksize is 4096 bytes. .TP @@ -47,7 +47,7 @@ to disk after formatting. If no label is specified, a sensible default --- s390-tools-1.34.0/dasdfmt/dasdfmt.h 2016-04-14 16:43:51.000000000 -0400 +++ s390-tools-1.34.0/dasdfmt/dasdfmt.h 2016-04-14 16:35:01.000000000 -0400 -@@ -195,6 +195,7 @@ +@@ -260,6 +260,7 @@ #define LABEL_LENGTH 14 #define VLABEL_CHARS 84 #define LINE_LENGTH 80 diff --git a/s390-tools-sles12-zipl_boot_msg.patch b/s390-tools-sles12-zipl_boot_msg.patch index b933842..1a84cb2 100644 --- a/s390-tools-sles12-zipl_boot_msg.patch +++ b/s390-tools-sles12-zipl_boot_msg.patch @@ -1,13 +1,16 @@ --- s390-tools-1.24.1/zipl/boot/menu.c 2013-12-18 11:11:45.000000000 -0500 +++ s390-tools-1.24.1/zipl/boot/menu.c 2013-12-18 11:59:18.000000000 -0500 -@@ -166,7 +166,9 @@ +@@ -167,8 +167,11 @@ + /* print config list */ menu_list(); - if (is_zvm()) +- if (is_zvm()) - printf("Note: VM users please use '#cp vi vmsg '\n"); ++ if (is_zvm()) { + printf(" \n"); + printf("Note: VM users please use '#cp vi vmsg '\n"); + printf(" \n"); ++ } value = menu_read(); diff --git a/s390-tools-sles12sp2-chiucvallow-verify.patch b/s390-tools-sles12sp2-chiucvallow-verify.patch deleted file mode 100644 index 4cb9479..0000000 --- a/s390-tools-sles12sp2-chiucvallow-verify.patch +++ /dev/null @@ -1,35 +0,0 @@ -Subject: [PATCH] [BZ 141695] chiucvallow: correct verification return code -From: Hendrik Brueckner - -Description: chiucvallow: correct verification return code -Symptom: When running test_chiucvallow.sh, the script is - failing to validate filter files with special - characters. - because the chiucvallow.in -V is -Problem: The chiucvallow -V is returning code 2 and for - this reason, the script gives an error message, - but the filter file is validated successfully - manually. -Solution: Correct the return code of chiucvallow to handle - verification failures correctly. -Reproduction: See Symptom. -Upstream-ID: - -Problem-ID: 141695 - -Signed-off-by: Hendrik Brueckner ---- - iucvterm/bin/chiucvallow.in | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/iucvterm/bin/chiucvallow.in -+++ b/iucvterm/bin/chiucvallow.in -@@ -115,7 +115,8 @@ verify_filter(){ - - printf "\n$PRG: Verification summary: verified=%d failed=%d size=%d bytes\n" \ - $count $failed $fsize -- return 2 -+ -+ test $failed -eq 0 || return 2 - } - - # diff --git a/s390-tools-sles12sp2-chreipl-virtio.patch b/s390-tools-sles12sp2-chreipl-virtio.patch deleted file mode 100644 index 6684311..0000000 --- a/s390-tools-sles12sp2-chreipl-virtio.patch +++ /dev/null @@ -1,49 +0,0 @@ -Subject: [PATCH] [BZ 143839] chreipl/virtio: fix chreipl node for virtio-blk disks -From: Christian Borntraeger - -Description: chreipl/virtio: fix chreipl node for virtio-blk disks -Symptom: chreipl node for a virtio-blk disk fails: - Could not find DASD CCW device "virtio1" -Problem: The sysfs walking code to resolve the device is not - handling virtio devices correctly. -Solution: Use the realpath of the device to get the busid for all - supported devices. -Reproduction: Run chreipl node with virtio-blk devices as - backing for mount point. -Upstream-ID: - -Problem-ID: 143839 - -Signed-off-by: Christian Borntraeger ---- - ipl_tools/ccw.c | 12 +++++------- - 1 file changed, 5 insertions(+), 7 deletions(-) - ---- a/ipl_tools/ccw.c -+++ b/ipl_tools/ccw.c -@@ -76,21 +76,19 @@ out_fclose: - static int ccw_busid_get_sysfs_new(const char *device, char *busid) - { - char path[PATH_MAX], buf[4096]; -- char *ptr; - - memset(buf, 0, sizeof(buf)); - snprintf(path, sizeof(path), "/sys/block/%s/device", device); -- if (readlink(path, buf, sizeof(buf) - 1) == -1) -+ if (realpath(path, buf) == NULL) - return -1; - - /* - * The output has the following format: -- * ../../../0.0.4e13 -+ * /sys/devices/css0/0.0.0119/0.0.3f19/block/dasda -+ * /sys/devices/css0/0.0.0000/0.0.0000/virtio0/block/vda - */ -- ptr = strrchr(buf, '/'); -- if (!ptr) -- ERR_EXIT("Could not read \"%s\"", path); -- strncpy(busid, ptr + 1, 9); -+ if (sscanf(buf, "/sys/devices/css0/%*[0-9a-f.]/%[0-9a-f.]", busid) != 1) -+ return -1; - return 0; - } - diff --git a/s390-tools-sles12sp2-chzdev-disable-root-update.patch b/s390-tools-sles12sp2-chzdev-disable-root-update.patch deleted file mode 100644 index 405e9be..0000000 --- a/s390-tools-sles12sp2-chzdev-disable-root-update.patch +++ /dev/null @@ -1,32 +0,0 @@ -Subject: [PATCH] [BZ 147113] chzdev: Disable root device update mechanism -From: Peter Oberparleiter - -Description: chzdev: Disable root device update mechanism -Symptom: chzdev reports problems updating /etc/zipl.conf and running - zipl. -Problem: When chzdev changes the root device persistent configuration, - it performs additional steps to ensure that these changes are - correctly applied. Example for such steps are: updating the - initial RAM disk, modifying the zipl.conf configuration file - and running zipl. As these steps are incompatible with the target - distribution, they fail. -Solution: Suppress chzdev's root device update mechanism. -Reproduction: chzdev --enable --persistent --by-path / -Upstream-ID: - -Problem-ID: 147113 - -Signed-off-by: Peter Oberparleiter ---- - zdev/src/chzdev.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/zdev/src/chzdev.c -+++ b/zdev/src/chzdev.c -@@ -233,6 +233,7 @@ static void init_options(struct options - opts->settings = strlist_new(); - opts->remove = strlist_new(); - opts->base = strlist_new(); -+ opts->no_root_check = 1; - } - - /* Release memory used in options data structure. */ diff --git a/s390-tools-sles12sp2-feat-01-dasd-query-host.patch b/s390-tools-sles12sp2-feat-01-dasd-query-host.patch deleted file mode 100644 index b9bc686..0000000 --- a/s390-tools-sles12sp2-feat-01-dasd-query-host.patch +++ /dev/null @@ -1,744 +0,0 @@ -Subject: [PATCH] [FEAT LS1213] dasd: add query host access to volume support -From: Stefan Haberland - -Summary: dasd: add query host access to volume support -Description: With this feature, applications can query if a DASD volume is - online to another operating system instances by checking the - online status of all attached hosts from the storage server. -Upstream-ID: - -Problem-ID: LS1213 - -Signed-off-by: Stefan Haberland ---- - dasdfmt/dasdfmt.8 | 7 ++ - dasdfmt/dasdfmt.c | 38 ++++++++++++-- - dasdfmt/dasdfmt.h | 4 + - fdasd/fdasd.8 | 9 ++- - fdasd/fdasd.c | 32 ++++++++++++ - fdasd/fdasd.h | 28 +++++----- - include/libzds.h | 1 - include/u2s.h | 5 + - libu2s/u2s.c | 43 ++++++++++++++++ - libzds/Makefile | 2 - libzds/libzds.c | 46 +++++++++++++++-- - zconf/lsdasd | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++- - zconf/lsdasd.8 | 5 + - zdsfs/zdsfs.1 | 4 + - zdsfs/zdsfs.c | 18 ++++++ - 15 files changed, 345 insertions(+), 36 deletions(-) - ---- a/dasdfmt/dasdfmt.8 -+++ b/dasdfmt/dasdfmt.8 -@@ -7,7 +7,7 @@ dasdfmt \- formatting of DASD (ECKD) dis - .br - [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR] - .br -- [-L] [-V] [-F] [-k] \fIdevice\fR -+ [-L] [-V] [-F] [-k] [-C] \fIdevice\fR - - .SH DESCRIPTION - \fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it -@@ -70,6 +70,11 @@ Print version number and exit. - Formats the device without checking, if the device is in use. - - .TP -+\fB-C\fR or \fB--check_host_count\fR -+Force dasdfmt to check the host access open count to ensure the device -+is not online on another operating system instance -+ -+.TP - \fB-d\fR \fIlayout\fR or \fB--disk_layout\fR=\fIlayout\fR - Formats the device with compatible disk layout or linux disk layout. - \fIlayout\fR is either \fIcdl\fR for the compatible disk layout ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -18,6 +18,8 @@ - #include "util_proc.h" - #include "dasd_sys.h" - -+#define BUSIDSIZE 8 -+ - /* Full tool name */ - static const char tool_name[] = "dasdfmt: zSeries DASD format program"; - -@@ -46,7 +48,7 @@ print_version (void) - */ - static void exit_usage(int exitcode) - { -- printf("Usage: %s [-htvypPLVFk]\n" -+ printf("Usage: %s [-htvypPLVFkC]\n" - " [-l | --label=]\n" - " [-b | --blocksize=]\n" - " [-d | --disk_layout=]\n" -@@ -65,6 +67,9 @@ static void exit_usage(int exitcode) - " -v means verbose mode\n" - " -F means don't check if the device is in use\n" - " -k means keep volume serial\n" -+ " -C or --check_host_count means force dasdfmt to check\n" -+ " the host access open count to ensure the device\n" -+ " is not online on another operating system instance\n" - " --norecordzero prevent storage server from modifying" - " record 0\n\n" - " is the volume identifier, which is converted\n" -@@ -190,7 +195,6 @@ static void get_device_name(dasdfmt_info - } - } - -- - /* - * initialize the dasdfmt info structure - */ -@@ -214,6 +218,7 @@ static void init_info(dasdfmt_info_t *in - info->node_specified = 0; - info->device_id = 0; - info->keep_volser = 0; -+ info->force_host = 0; - } - - -@@ -776,6 +781,7 @@ static void do_format_dasd(dasdfmt_info_ - dasd_information_t dasd_info; - struct dasd_eckd_characteristics *characteristics; - unsigned int cylinders, heads; -+ int count; - - if (info->verbosity > 0) printf("Retrieving disk geometry...\n"); - -@@ -835,6 +841,27 @@ static void do_format_dasd(dasdfmt_info_ - if ((info->verbosity > 0) || (!info->withoutprompt)) - dasdfmt_print_info(info, vlabel, cylinders, heads, p); - -+ count = u2s_get_host_access_count(info->devname); -+ if (info->force_host) { -+ if (count > 1) { -+ ERRMSG_EXIT(EXIT_FAILURE, -+ "\n%s: Disk %s is online on OS instances in %d different LPARs.\n" -+ "Note: Your installation might include z/VM systems that are configured to\n" -+ "automatically vary on disks, regardless of whether they are subsequently used.\n\n", -+ prog_name, info->devname, count); -+ } else if (count < 0) { -+ ERRMSG("\nHosts access information not available for disk %s.\n\n", -+ info->devname); -+ return; -+ } -+ } else if (count > 1) -+ ERRMSG("\nWARNING:\n" -+ "Disk %s is online on operating system instances in %d different LPARs.\n" -+ "Ensure that the disk is not being used by a system outside your LPAR.\n" -+ "Note: Your installation might include z/VM systems that are configured to\n" -+ "automatically vary on disks, regardless of whether they are subsequently used.\n", -+ info->devname, count); -+ - if (!info->testmode) { - if (!info->withoutprompt) { - printf("\n--->> ATTENTION! <<---\n"); -@@ -916,10 +943,6 @@ int main(int argc,char *argv[]) - info.force=1; - break; - -- case 'C': -- format_params.intensity |= DASD_FMT_INT_COMPAT; -- break; -- - case 'd' : - if (strncmp(optarg,"cdl",3)==0) - { -@@ -1017,6 +1040,9 @@ int main(int argc,char *argv[]) - case 'k' : - info.keep_volser=1; - break; -+ case 'C': -+ info.force_host = 1; -+ break; - case -1: - /* End of options string - start of devices list */ - info.device_id = optind; ---- a/dasdfmt/dasdfmt.h -+++ b/dasdfmt/dasdfmt.h -@@ -214,7 +214,7 @@ typedef struct format_data_t { - if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ - "is in invalid format\n",prog_name);} - --#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFk" -+#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFkC" - - static struct option dasdfmt_getopt_long_options[]= - { -@@ -233,6 +233,7 @@ static struct option dasdfmt_getopt_long - { "help", 0, 0, 'h'}, - { "keep_volser", 0, 0, 'k'}, - { "norecordzero", 0, 0, 'z'}, -+ { "check_host_count", 0, 0, 'C'}, - {0, 0, 0, 0} - }; - -@@ -265,6 +266,7 @@ typedef struct dasdfmt_info { - int node_specified; - int device_id; - int keep_volser; -+ int force_host; - } dasdfmt_info_t; - - ---- a/fdasd/fdasd.8 -+++ b/fdasd/fdasd.8 -@@ -4,11 +4,11 @@ fdasd \- partitioning tool. - .SH SYNOPSIS - interactive mode: - .br -- \fBfdasd\fR [-s] [-r] \fIdevice\fR -+ \fBfdasd\fR [-s] [-r] [-C] \fIdevice\fR - .br - command line mode: - .br -- \fBfdasd\fR [-s] [-r] {-a[-k|-l \fIvolser\fR]|-i|-p|-c \fIconf_file\fR} -+ \fBfdasd\fR [-s] [-r] [-C] {-a[-k|-l \fIvolser\fR]|-i|-p|-c \fIconf_file\fR} - [-f \fI[type,blocksize]\fR] \fIdevice\fR - .br - help: -@@ -131,6 +131,11 @@ In combination with the -s option fdasd - partition table. - - .TP -+\fB-C\fR or \fB--check_host_count\fR -+Force fdasd to check the host access open count to ensure the device -+is not online on another operating system instance -+ -+.TP - \fB-f\fR \fI[type,blocksize]\fR or \fB--force\fR \fI[type,blocksize]\fR - Force fdasd to work on non DASD devices. - .br ---- a/fdasd/fdasd.c -+++ b/fdasd/fdasd.c -@@ -369,7 +369,10 @@ fdasd_usage (void) - " found in CONFIGFILE\n" - "-i, --volser Print volume serial\n" - "-p, --table Print partition table\n" -- "-f, --force Force fdasd to work on non DASD devices\n"); -+ "-f, --force Force fdasd to work on non DASD devices\n" -+ "-C, --check_host_count Force fdasd to check the host access\n" -+ " open count to ensure the device is not\n" -+ " online on another operating system instance\n"); - } - - -@@ -572,6 +575,9 @@ fdasd_parse_options (fdasd_anchor_t *anc - anc->force_virtual++; - fdasd_parse_force_options(anc, optarg); - break; -+ case 'C': -+ anc->force_host++; -+ break; - case -1: - /* End of options string - start of devices list */ - break; -@@ -824,6 +830,7 @@ fdasd_verify_device (fdasd_anchor_t *anc - { - struct stat dst; - char err_str[ERROR_STRING_SIZE]; -+ int count; - - if ((stat(name, &dst)) < 0 ) { - snprintf(err_str, ERROR_STRING_SIZE, -@@ -856,6 +863,29 @@ fdasd_verify_device (fdasd_anchor_t *anc - fdasd_error(anc, device_verification_failed, err_str); - } - -+ count = u2s_get_host_access_count(name); -+ if (anc->force_host) { -+ if (count > 1) { -+ snprintf(err_str, ERROR_STRING_SIZE, -+ "Disk %s is online on operating system instances in %d different LPARs.\n" -+ "Note: Your installation might include z/VM systems that are configured to\n" -+ "automatically vary on disks, regardless of whether they are subsequently used.\n", -+ name, count); -+ fdasd_error(anc, device_verification_failed, err_str); -+ } else if (count < 0) { -+ snprintf(err_str, ERROR_STRING_SIZE, -+ "Hosts access information not available for disk %s.\n", -+ name); -+ fdasd_error(anc, device_verification_failed, err_str); -+ } -+ } else if (count > 1) -+ printf("\nWARNING:\n" -+ "Disk %s is online on operating system instances in %d different LPARs.\n" -+ "Ensure that the disk is not being used by a system outside your LPAR.\n" -+ "Note: Your installation might include z/VM systems that are configured to\n" -+ "automatically vary on disks, regardless of whether they are subsequently used.\n\n", -+ name, count); -+ - if (anc->verbose) - printf("Verification successful for '%s' (%d/%d)\n", name, - (unsigned short) major(dst.st_rdev), ---- a/fdasd/fdasd.h -+++ b/fdasd/fdasd.h -@@ -157,22 +157,23 @@ struct dasd_eckd_characteristics { - #define PARTITION_GPFS 5 - - static struct option fdasd_long_options[] = { -- { "version", no_argument, NULL, 'v'}, -- { "auto", no_argument, NULL, 'a'}, -- { "silent", no_argument, NULL, 's'}, -- { "verbose", no_argument, NULL, 'r'}, -- { "label", required_argument, NULL, 'l'}, -- { "config", required_argument, NULL, 'c'}, -- { "help", no_argument, NULL, 'h'}, -- { "table", no_argument, NULL, 'p'}, -- { "volser", no_argument, NULL, 'i'}, -- { "keep_volser", no_argument, NULL, 'k'}, -- { "force", optional_argument, NULL, 'f'}, -- { 0, 0, 0, 0 } -+ { "version", no_argument, NULL, 'v'}, -+ { "auto", no_argument, NULL, 'a'}, -+ { "silent", no_argument, NULL, 's'}, -+ { "verbose", no_argument, NULL, 'r'}, -+ { "label", required_argument, NULL, 'l'}, -+ { "config", required_argument, NULL, 'c'}, -+ { "help", no_argument, NULL, 'h'}, -+ { "table", no_argument, NULL, 'p'}, -+ { "volser", no_argument, NULL, 'i'}, -+ { "keep_volser", no_argument, NULL, 'k'}, -+ { "force", optional_argument, NULL, 'f'}, -+ { "check_host_count", no_argument, NULL, 'C'}, -+ { 0, 0, 0, 0 } - }; - - /* Command line option abbreviations */ --static const char option_string[] = "vasrl:c:hpikf::"; -+static const char option_string[] = "vasrl:c:hpikf::C"; - - struct fdasd_options { - char *device; -@@ -214,6 +215,7 @@ typedef struct fdasd_anchor { - int print_volser; - int keep_volser; - int force_virtual; -+ int force_host; - int big_disk; - int silent; - int verbose; ---- a/include/libzds.h -+++ b/include/libzds.h -@@ -803,6 +803,7 @@ int lzds_zdsroot_extract_datasets_from_d - void lzds_DS1RECFM_to_recfm(char DS1RECFM, char *buffer); - - -+int lzds_analyse_open_count(struct zdsroot *root, int warn); - - /** @} */ /* end of group libzds_functions_helper */ - ---- a/include/u2s.h -+++ b/include/u2s.h -@@ -13,7 +13,8 @@ - - #define U2S_BUS_ID_SIZE 32 - --int --u2s_getbusid(char * devicenode, char * busid); -+int u2s_getbusid(char *, char *); -+int u2s_read_attribute(char *, char *, char *, size_t); -+int u2s_get_host_access_count(char *); - - #endif /* U2S_H */ ---- a/libu2s/u2s.c -+++ b/libu2s/u2s.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include "u2s.h" - -@@ -282,3 +283,45 @@ int u2s_getbusid(char *devicenode, char - - return rc; - } -+ -+/* -+ * Attempts to find the sysfs entry for the given busid and reads -+ * the contents of a specified attribute to the buffer -+ */ -+int u2s_read_attribute(char *busid, char *attribute, char *buffer, -+ size_t count) -+{ -+ char path[100]; -+ int rc, fd; -+ ssize_t rcount; -+ -+ rc = 0; -+ snprintf(path, sizeof(path), "/sys/bus/ccw/devices/%s/%s", -+ busid, attribute); -+ fd = open(path, O_RDONLY); -+ if (fd < 0) -+ return errno; -+ rcount = read(fd, buffer, count); -+ if (rcount < 0) -+ rc = errno; -+ close(fd); -+ return rc; -+} -+ -+int u2s_get_host_access_count(char *devicenode) -+{ -+ char busid[BUSIDSIZE]; -+ unsigned long value; -+ char buffer[10]; -+ char *endp; -+ -+ u2s_getbusid(devicenode, busid); -+ u2s_read_attribute(busid, "host_access_count", buffer, sizeof(buffer)); -+ -+ value = strtoul(buffer, &endp, 0); -+ -+ if (endp == buffer) -+ return -EINVAL; -+ -+ return value; -+} ---- a/libzds/Makefile -+++ b/libzds/Makefile -@@ -8,7 +8,7 @@ CFLAGS += -D_FILE_OFFSET_BITS=64 - - all: libzds.a - --libzds.a: libzds.o $(rootdir)/libutil/util_list.o $(rootdir)/libvtoc/vtoc.o -+libzds.a: libzds.o $(rootdir)/libutil/util_list.o $(rootdir)/libvtoc/vtoc.o $(rootdir)/libu2s/u2s.o - - libzds.o: ../include/libzds.h - ---- a/libzds/libzds.c -+++ b/libzds/libzds.c -@@ -29,6 +29,7 @@ - #include "libzds.h" - - #include "util.h" -+#include "u2s.h" - - #include - #include -@@ -72,6 +73,8 @@ struct errorlog { - */ - #define ERRORMSG 240 - -+#define BUSIDSIZE 8 -+ - /** - * @brief An internal structure that represents an entry in the error log. - */ -@@ -3760,15 +3763,46 @@ void lzds_DS1RECFM_to_recfm(char DS1RECF - */ - } - -+int lzds_analyse_open_count(struct zdsroot *root, int warn) -+{ -+ struct dasd *dasd; -+ int value; -+ int rc = 0; - -+ util_list_iterate(root->dasdlist, dasd) { -+ value = u2s_get_host_access_count(dasd->device); - -+ if (value < 0) { -+ fprintf(stderr, -+ "Hosts access information not available for disk %s.\n", -+ dasd->device); -+ rc = value; -+ continue; -+ } - -+ if (value == 1) -+ continue; - -+ if (warn) -+ fprintf(stderr, -+ "\nWARNING:\n" -+ "Disk %s is online on operating system instances in %d different LPARs.\n" -+ "Ensure that the disk is not being used by a system outside your LPAR.\n" -+ "Note: Your installation might include z/VM systems that are configured to\n" -+ "automatically vary on disks, regardless of whether they are subsequently used.\n", -+ dasd->device, value); -+ else { -+ fprintf(stderr, -+ "\nERROR:\n" -+ "Disk %s is online on operating system instances in %d different LPARs.\n" -+ "Ensure that the disk is not being used by a system outside your LPAR.\n" -+ "Note: Your installation might include z/VM systems that are configured to\n" -+ "automatically vary on disks, regardless of whether they are subsequently used.\n", -+ dasd->device, value); -+ rc = -EACCES; -+ } -+ } - -- -- -- -- -- -- -+ return rc; -+} - ---- a/zconf/lsdasd -+++ b/zconf/lsdasd -@@ -30,6 +30,8 @@ function PrintUsage() { - Print old version of lsdasd output. - -l|--long - Print extended information about DASDs. -+ -H|--host-access-list -+ Print information about hosts accessing DASDs. - -v|--verbose - For compatibility/future use. Currently ignored. - --version -@@ -115,6 +117,33 @@ function listDASDDeviceDirectories() { - } - - #------------------------------------------------------------------------------ -+# find dasd directory in debugfs -+#------------------------------------------------------------------------------ -+function findDASDDebugfsDirectorie() { -+ local mntentries -+ -+ while read -a mntentries -+ do -+ if [[ "${mntentries[2]}" == "debugfs" ]] -+ then -+ DASD_DBF_DIR="${mntentries[1]}" -+ break; -+ fi -+ done < /etc/mtab -+ if [[ "$DASD_DBF_DIR" == "" ]] -+ then -+ echo "$CMD: No debugfs mount point found" >&2 -+ exit 1 -+ fi -+ DASD_DBF_DIR="$DASD_DBF_DIR/dasd" -+ if [[ ! -d "$DASD_DBF_DIR" ]] -+ then -+ echo "$CMD: Default DASD debugfs directory $DASD_DBF_DIR does not exist" >&2 -+ exit 1 -+ fi -+} -+ -+#------------------------------------------------------------------------------ - # gather device data and call appropriate output function - #------------------------------------------------------------------------------ - function gatherDeviceData() { -@@ -197,6 +226,8 @@ function gatherDeviceData() { - extended - elif [[ "$PRINTUID" == "true" ]]; then - uid -+ elif [[ "$OUTPUT" == "host" ]]; then -+ host - else - newoutput - fi -@@ -527,6 +558,104 @@ function extended() - "${HPF_PATHS[@]}" ; - } - -+function host() -+{ -+findDASDDebugfsDirectorie -+ -+if [[ ! -f "$DASD_DBF_DIR/$BUSID/host_access_list" ]] -+then -+ printf "\n%s: hosts access information not available\n" "$BUSID" -+ return -+fi -+ -+local temp=`mktemp /tmp/lsdasd.XXXXXX` -+if test -w $temp ; then :; else -+ printf "\nCreating temporary file failed\n" -+ return -+fi -+ -+cat $DASD_DBF_DIR/$BUSID/host_access_list > $temp 2> /dev/null -+ret=$? -+if [[ $ret -ne 0 ]] -+then -+ printf "%s: hosts access information not available\n" "$BUSID" -+ rm -f $temp -+ return $ret -+fi -+ -+unset index -+unset array -+declare -a array -+ -+index=(pgid status_flags sysplex_name supported_cylinder timestamp) -+ -+for element in ${index[@]} -+do -+ count=0 -+ -+ declare -a $element -+ OLDIFS=$IFS -+ IFS=$'\n' -+ for value in `grep $element $temp` -+ do -+ (( ++count )) -+ value=$(echo -e $value | cut -d ' ' -f2) -+ eval $element[$count]=$value -+ done -+ IFS=$OLDIFS -+done -+ -+printf "Host information for %s\n" "$BUSID"; -+printf "Path-Group-ID LPAR CPU FL Status Sysplex Max_Cyls Time\n"; -+printf "================================================================================\n"; -+ -+# mask bits for online and reserved state -+online_reserved_mask=0xE0 -+ -+# print name value lists -+for i in `seq 1 $count`; -+do -+ # get flags field -+ value=${status_flags[$i]} -+ # mark as hex value -+ value=0x$value -+ # mask online and reserved bits -+ value=$(($value & $online_reserved_mask)) -+ -+ case $value in -+ 0 ) # 0x00 -+ STATE="OFF" -+ ;; -+ 32 ) # 0x20 -+ STATE="OFF-RSV" -+ ;; -+ 64 ) # 0x40 -+ STATE="ON" -+ ;; -+ 96 ) # 0x60 -+ STATE="ON-RSV" -+ ;; -+ * ) -+ STATE="-" -+ ;; -+ esac -+ -+ printf "%22s %02s %07s %02s %-6s %-8s %11u %10lu\n" \ -+ "${pgid[$i]}" \ -+ "${pgid[$i]:4:2}" \ -+ "${pgid[$i]:6:4}" \ -+ "${status_flags[$i]}" \ -+ "$STATE" \ -+ "${sysplex_name[$i]}" \ -+ "${supported_cylinder[$i]}" \ -+ "${timestamp[$i]}" \ -+ ; -+done -+printf "\n"; -+ -+rm -f $temp -+} -+ - function uid() - { - #-------------------------------------------# -@@ -586,6 +715,9 @@ while [ $# -gt 0 ]; do - --long|-l) - OUTPUT="extended" - ;; -+ --host-access-list|-H) -+ OUTPUT="host" -+ ;; - --version) - PrintVersion - exit 0 -@@ -626,8 +758,13 @@ fi - - # gather information on devices in list - PROCESSING=" $PROCESSING | gatherDeviceData " -+ - # sort resulting list --PROCESSING=" $PROCESSING | sort -t: -k1n -k2 | cut -d: -f3- " -+if [[ "$OUTPUT" == "host" ]]; then -+ PROCESSING=" $PROCESSING" -+else -+ PROCESSING=" $PROCESSING | sort -t: -k1n -k2 | cut -d: -f3- " -+fi - - if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then - printf "Bus-ID Name UID\n" ---- a/zconf/lsdasd.8 -+++ b/zconf/lsdasd.8 -@@ -40,11 +40,14 @@ Include only base devices. - Old output of lsdasd for compatibility. - .TP - .BR -l | --long --Extended output of lsdasd including UID, attributes and path information. -+Extended output of lsdasd including UID and attributes. - .TP - .BR -u | --uid - Output includes and is sorted by UID. - .TP -+.BR -H | --host-acces -+Show information about all hosts using this device. -+.TP - .BR -v | --verbose - Only for compatibility (and maybe future) use. This option currently does - nothing. ---- a/zdsfs/zdsfs.1 -+++ b/zdsfs/zdsfs.1 -@@ -150,6 +150,10 @@ If \fI\fR is set to 0, no seek histor - case `seek' is still supported, but a `seek' operation might result in a - read from the beginning of the data set. - -+.TP -+\fB\-o\fR check_host_count -+Stop processing if the device is used by another operating system instance. -+ - .SS "Applicable FUSE options (version 2.8):" - This is a selected subset of all FUSE options. Use the zdsfs - \fB\--help\fR option to print a full list. ---- a/zdsfs/zdsfs.c -+++ b/zdsfs/zdsfs.c -@@ -39,6 +39,7 @@ struct zdsfs_info { - int devcount; - int allow_inclomplete_multi_volume; - int keepRDW; -+ int host_count; - unsigned int tracks_per_frame; - unsigned long long seek_buffer_size; - struct zdsroot *zdsroot; -@@ -765,6 +766,7 @@ static const struct fuse_opt zdsfs_opts[ - FUSE_OPT_KEY("seekbuffer=", KEY_SEEKBUFFER), - ZDSFS_OPT("rdw", keepRDW, 1), - ZDSFS_OPT("ignore_incomplete", allow_inclomplete_multi_volume, 1), -+ ZDSFS_OPT("check_host_count", host_count, 1), - FUSE_OPT_END - }; - -@@ -790,7 +792,10 @@ static void usage(const char *progname) - " data set are missing\n" - " -o tracks=N Size of the track buffer in tracks (default 128)\n" - " -o seekbuffer=S Upper limit in bytes for the seek history buffer\n" --" size (default 1048576)\n", progname); -+" size (default 1048576)\n" -+" -o check_host_count Stop processing if the device is used by another\n" -+" operating system instance\n" -+ , progname); - } - - static void zdsfs_process_device(const char *device) -@@ -1014,6 +1019,17 @@ int main(int argc, char *argv[]) - argv[0]); - exit(1); - } -+ -+ if (zdsfsinfo.host_count) { -+ /* check, print error and exit if multiple online */ -+ rc = lzds_analyse_open_count(zdsfsinfo.zdsroot, 0); -+ if (rc == -EACCES) -+ goto cleanup; -+ } else { -+ /* check, print warning if multiple online */ -+ lzds_analyse_open_count(zdsfsinfo.zdsroot, 1); -+ } -+ - rc = zdsfs_verify_datasets(); - if (rc) - goto cleanup; diff --git a/s390-tools-sles12sp2-libu2s-Fix-busid-parsing.patch b/s390-tools-sles12sp2-libu2s-Fix-busid-parsing.patch deleted file mode 100644 index 5283fe9..0000000 --- a/s390-tools-sles12sp2-libu2s-Fix-busid-parsing.patch +++ /dev/null @@ -1,37 +0,0 @@ -Subject: [PATCH] [BZ 140500] libu2s: Fix busid parsing -From: Jan Höppner - -Description: libu2s: Fix busid parsing -Symptom: dasdview displays a wrong busid and shows the error message - "Error: dasdview: Could not retrieve raw_track_access mode - information.", which is wrong as well. -Problem: dasdview retrieves the busid information from libu2s. Whenever - an FBA DASD is listed prior to the target DASD in - /proc/dasd/devices, the parsing will fail due to an additional - whitespace character. For example, an entry for ECKD devices - starts with "0.0.5e30(ECKD)...", while an entry for FBA starts - with "0.0.8000(FBA )...". -Solution: Change the busid parsing in libu2s by explicitly looking for the - closing bracket. -Reproduction: Add an FBA device and then an ECKD device to the system and use - dasdview to display information about the ECKD device. - # dasdview -i /dev/dasdX -Upstream-ID: - -Problem-ID: 140500 - -Signed-off-by: Jan Höppner ---- - libu2s/u2s.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/libu2s/u2s.c -+++ b/libu2s/u2s.c -@@ -237,7 +237,7 @@ static int find_busid_in_proc(int maja, - filp = fopen("/proc/dasd/devices", "r"); - if (!filp) - return rc; -- while (fscanf(filp, "%[^(] %*s at ( %d : %d %*[^\n]\n", -+ while (fscanf(filp, "%[^(] %*[^)] ) at ( %d : %d %*[^\n]\n", - bus, &majb, &minb) != EOF) { - if ((maja == majb) && (mina == minb)) { - strncpy(busid, bus, BUSIDSIZE + 1); diff --git a/s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch b/s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch deleted file mode 100644 index 9677209..0000000 --- a/s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch +++ /dev/null @@ -1,37 +0,0 @@ -Subject: lscss: allow to specify devices from ssid > 2 -From: Sebastian Ott - -Description: lscss: allow to specify devices from ssid > 2 -Symptom: Specifying devices with ssid > 2 results in: - "Syntax error: 0.3.0000" -Problem: SSIDs > 2 are disallowed -Solution: allow SSIDs > 2 -Reproduction: lscss 0.3.0000 -Upstream-ID: - -Problem-ID: 150872 - -Signed-off-by: Sebastian Ott ---- - zconf/lscss | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/zconf/lscss -+++ b/zconf/lscss -@@ -61,7 +61,7 @@ SUBCHANNEL_TYPE_IO=0 - SUBCHANNEL_TYPE_CHSC=1 - SUBCHANNEL_TYPE_EADM=3 - --IDFORMAT=[[:xdigit:]]*.[0-3].[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] -+IDFORMAT=[[:xdigit:]]*.[[:xdigit:]].[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] - - unset SCH_IO SCH_CHSC SCH_EADM SHOW_AVAIL UPPERCASE SHORTID DEVTYPES DEVRANGE - unset RANGE SHOW_VPM -@@ -81,7 +81,7 @@ function check_id() #return 0 if $1 has - fi - ;; - 3) -- if [ ${#__ID[2]} != 4 -o ${#__ID[1]} != 1 -o "${__ID[1]//[012]/}" \ -+ if [ ${#__ID[2]} != 4 -o ${#__ID[1]} != 1 \ - -o \( ${#__ID[0]} != 2 -a ${#__ID[0]} != 1 \) ] ;then - return 1 - fi diff --git a/s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch b/s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch deleted file mode 100644 index 68f199c..0000000 --- a/s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch +++ /dev/null @@ -1,35 +0,0 @@ -Subject: [PATCH] [BZ 143050] zipl/boot: fix failed start subchannel in FBA loader -From: Stefan Haberland - -Description: zipl/boot: fix failed start subchannel in FBA loader -Symptom: IPL of a FBA device fails with: - Start subchannel failed - disabled wait PSW 00020000 80000000 00000000 00004502 -Problem: The FBA loader has only a limited amount of memory to build CCW - requests. Therefore larger I/O requests need to be split. - This splitting was off by one leading to the fact that one CCW - request uses memory of another data structure which in turn leads - to corrupted data. -Solution: Fix by correcting the split rule. -Reproduction: IPL a FBA device. - The error might occur randomly depending on the size of the - kernel image and offsets within it. -Upstream-ID: - -Problem-ID: 143050 - -Signed-off-by: Stefan Haberland ---- - zipl/boot/fba2.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/zipl/boot/fba2.c -+++ b/zipl/boot/fba2.c -@@ -59,7 +59,7 @@ restart: - memset(irb, 0, sizeof(struct irb)); - memset(&orb, 0, sizeof(struct orb)); - -- if (blockptr->blockct > MAX_BLOCKCT) { -+ if (blockptr->blockct >= MAX_BLOCKCT) { - record_number = MAX_BLOCKCT - 1; - blockptr->blockct -= MAX_BLOCKCT; - } else { diff --git a/s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch b/s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch deleted file mode 100644 index 1c58336..0000000 --- a/s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch +++ /dev/null @@ -1,35 +0,0 @@ -Subject: [PATCH] [BZ 156627] chmem: try to online memory to zone movable -From: Gerald Schaefer - -Description: chmem: try to online memory to zone movable -Symptom: Standby/reserved memory that is onlined with chmem will be set - online to zone normal, instead of zone movable, and so it is much - less likely to be able to be offlined again. -Problem: With recent kernels, the default zone for hotplug memory was - changed from zone movable to zone normal. -Solution: Let chmem first try to online memory to the zone movable, before - setting it online to the default zone. -Reproduction: Set standby/reserved memory online with chmem, and check - /proc/zoneinfo for zone allocation. -Upstream-ID: - -Problem-ID: 156627 - -Signed-off-by: Gerald Schaefer ---- - zconf/chmem | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/zconf/chmem -+++ b/zconf/chmem -@@ -86,7 +86,10 @@ sub chmem_online($) - { - my $block = shift; - -- qx(echo online > $memdir/memory$block/state 2>/dev/null); -+ qx(echo online_movable > $memdir/memory$block/state 2>/dev/null); -+ if ($? >> 8 != 0) { -+ qx(echo online > $memdir/memory$block/state 2>/dev/null); -+ } - return $? >> 8; - } - diff --git a/s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch b/s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch deleted file mode 100644 index f05316c..0000000 --- a/s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch +++ /dev/null @@ -1,42 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: 9e49066f5c779e6591b06d2276add744ea8ca4d0 -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Fix behaviour of -t combined with -y - - When -t (testmode) is being combined with -y (noprompt), the - informations about what dasdfmt *would* do, is not being displayed. - - Simply fix this by checking whether testmode is set. - - Signed-off-by: Jan Höppner - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -894,7 +894,7 @@ static void do_format_dasd(dasdfmt_info_ - vtoc_volume_label_set_label(vlabel, "LNX1"); - } - -- if ((info->verbosity > 0) || (!info->withoutprompt)) -+ if ((info->verbosity > 0) || !info->withoutprompt || info->testmode) - dasdfmt_print_info(info, vlabel, cylinders, heads, p); - - count = u2s_get_host_access_count(info->devname); diff --git a/s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch b/s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch deleted file mode 100644 index 73f49ff..0000000 --- a/s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch +++ /dev/null @@ -1,250 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: - -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Fix trailing whitespace - - Signed-off-by: Jan Höppner - Signed-off-by: Stefan Haberland - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.c | 58 +++++++++++++++++++++++++++--------------------------- - 1 file changed, 29 insertions(+), 29 deletions(-) - ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -133,7 +133,7 @@ static void program_interrupt_signal (in - - rc = close(filedes); - if (rc) -- ERRMSG("%s: (signal handler) Unable to close device (%s)\n", -+ ERRMSG("%s: (signal handler) Unable to close device (%s)\n", - prog_name, strerror(errno)); - - signal (sig, SIG_DFL); -@@ -329,7 +329,7 @@ retry: - - - /* -- * check the volume serial for special -+ * check the volume serial for special - * characters and move blanks to the end - */ - static int check_volser(char *s, int devno) -@@ -345,7 +345,7 @@ static int check_volser(char *s, int dev - s[i] = ' '; - s[i] = toupper(s[i]); - } -- s[6] = 0x00; -+ s[6] = 0x00; - - for (i=0; i<6; i++) { - if (s[i] == ' ') -@@ -416,16 +416,16 @@ static format_data_t ask_user_for_blksiz - break; - - rc = sscanf(buffer,"%d%c", ¶ms.blksize, &c); -- if ((rc == 2) && (c == '\n')) -+ if ((rc == 2) && (c == '\n')) - rc = 1; -- if (rc == -1) -+ if (rc == -1) - rc = 1; /* this happens, if enter is pressed */ -- if (rc != 1) -+ if (rc != 1) - printf(" -- wrong input, try again.\n"); - - if (check_param(str, ERR_LENGTH, ¶ms) < 0) { -- printf(" -- %s\n",str); -- rc = 0; -+ printf(" -- %s\n",str); -+ rc = 0; - } - } while (rc != 1); - -@@ -479,7 +479,7 @@ static int dasdfmt_get_volser(char * dev - volume_label_t vlabel; - - if ((f = open(devname, O_RDONLY)) == -1) -- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n", -+ ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n", - prog_name, devname, strerror(errno)); - - if (ioctl(f, BIODASDINFO, &dasd_info) != 0) -@@ -491,7 +491,7 @@ static int dasdfmt_get_volser(char * dev - "failed (%s).\n", prog_name, strerror(errno)); - - if (close(f) != 0) -- ERRMSG("%s: error during close: %s\ncontinuing...\n", -+ ERRMSG("%s: error during close: %s\ncontinuing...\n", - prog_name, strerror(errno)); - - if ((strncmp(dasd_info.type, "ECKD", 4) == 0) && -@@ -505,7 +505,7 @@ static int dasdfmt_get_volser(char * dev - return -1; - } - } -- -+ - /* - * do all the labeling (volume label and initial VTOC) - */ -@@ -577,7 +577,7 @@ static void dasdfmt_write_labels(dasdfmt - rc = lseek(filedes, label_position, SEEK_SET); - if (rc != label_position) - ERRMSG_EXIT(EXIT_FAILURE, "%s: lseek command to %i failed " -- "(%s).\n", prog_name, label_position, -+ "(%s).\n", prog_name, label_position, - strerror(errno)); - - rc = write(filedes, ipl2_record, ipl2_record_len); -@@ -633,9 +633,9 @@ static void dasdfmt_write_labels(dasdfmt - rc = lseek(filedes, label_position, SEEK_SET); - if (rc != label_position) - ERRMSG_EXIT(EXIT_FAILURE, "%s: lseek command to %i failed " -- "(%s).\n", prog_name, label_position, -+ "(%s).\n", prog_name, label_position, - strerror(errno)); -- -+ - /* write VTOC FMT4 DSCB */ - rc = write(filedes, &f4, sizeof(format4_label_t)); - if (rc != sizeof(format4_label_t)) -@@ -695,21 +695,21 @@ static void dasdfmt_format(dasdfmt_info_ - "using the default.\n"); - info->hashstep = 10; - } -- -+ - if(!info->yast_mode) printf("Printing hashmark every %d cylinders.\n", - info->hashstep); - } - - format_step.blksize = format_params->blksize; - format_step.intensity = format_params->intensity; -- -+ - k = 0; - cyl = 1; - if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode) - printf("\n"); - - while (1) { -- p1 = -1; -+ p1 = -1; - p2 = 0; - if (k + heads * reqsize >= format_params->stop_unit) - reqsize = 1; -@@ -734,7 +734,7 @@ static void dasdfmt_format(dasdfmt_info_ - tmp = cyl*50/cylinders; - for (j=1; j<=tmp; j++) - printf("#"); -- for (j=tmp+1; j<=50; j++) -+ for (j=tmp+1; j<=50; j++) - printf("-"); - printf("|%3d%%", p1); - } -@@ -758,15 +758,15 @@ static void dasdfmt_format(dasdfmt_info_ - k += reqsize * heads; - cyl += reqsize; - } -- else -+ else - k += format_params->stop_unit % heads; - -- if (k > format_params->stop_unit) -+ if (k > format_params->stop_unit) - break; - } - - if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode) -- printf("\n\n"); -+ printf("\n\n"); - } - - -@@ -790,7 +790,7 @@ static void dasdfmt_prepare_and_format ( - - if (ioctl(filedes, BIODASDDISABLE, p) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL " -- "BIODASDDISABLE failed. (%s)\n", prog_name, -+ "BIODASDDISABLE failed. (%s)\n", prog_name, - strerror(errno)); - disk_disabled = 1; - -@@ -798,7 +798,7 @@ static void dasdfmt_prepare_and_format ( - - if (ioctl(filedes, BIODASDFMT, &temp) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (invalidate first track) IOCTL " -- "BIODASDFMT failed. (%s)\n", prog_name, -+ "BIODASDFMT failed. (%s)\n", prog_name, - strerror(errno)); - - /* except track 0 from standard formatting procss */ -@@ -814,14 +814,14 @@ static void dasdfmt_prepare_and_format ( - - if (ioctl(filedes, BIODASDFMT, &temp) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (re-validate first track) IOCTL" -- " BIODASDFMT failed (%s)\n", prog_name, -+ " BIODASDFMT failed (%s)\n", prog_name, - strerror(errno)); - - if (info->verbosity > 0) printf("Re-accessing the device...\n"); - - if (ioctl(filedes, BIODASDENABLE, p) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL " -- "BIODASDENABLE failed. (%s)\n", prog_name, -+ "BIODASDENABLE failed. (%s)\n", prog_name, - strerror(errno)); - disk_disabled = 0; - } -@@ -830,7 +830,7 @@ static void dasdfmt_prepare_and_format ( - /* - * - */ --static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p, -+static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p, - volume_label_t *vlabel) - { - char inp_buffer[5]; -@@ -943,7 +943,7 @@ static void do_format_dasd(dasdfmt_info_ - if (!info->yast_mode) - printf("Finished formatting the device.\n"); - -- if (!info->writenolabel) -+ if (!info->writenolabel) - dasdfmt_write_labels(info, vlabel, cylinders, heads); - - if (!info->yast_mode) -@@ -959,7 +959,7 @@ static void do_format_dasd(dasdfmt_info_ - } - - --int main(int argc,char *argv[]) -+int main(int argc,char *argv[]) - { - dasdfmt_info_t info; - volume_label_t vlabel; -@@ -1001,7 +1001,7 @@ int main(int argc,char *argv[]) - rc=getopt_long(argc, argv, dasdfmt_getopt_string, - dasdfmt_getopt_long_options, &index); - -- switch (rc) -+ switch (rc) - { - case 'F': - info.force=1; diff --git a/s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch b/s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch deleted file mode 100644 index bda753a..0000000 --- a/s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch +++ /dev/null @@ -1,892 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: - -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Apply coding convention - - Improve the overall readability of the code by applying the Kernel - coding convention. - - Signed-off-by: Jan Höppner - Signed-off-by: Stefan Haberland - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.c | 362 +++++++++++++++++++++++++----------------------------- - 1 file changed, 171 insertions(+), 191 deletions(-) - ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -37,11 +37,10 @@ int reqsize; - /* - * Print version information. - */ --static void --print_version (void) -+static void print_version(void) - { -- printf ("%s version %s\n", tool_name, RELEASE_STRING); -- printf ("%s\n", copyright_notice); -+ printf("%s version %s\n", tool_name, RELEASE_STRING); -+ printf("%s\n", copyright_notice); - } - - /* -@@ -54,7 +53,7 @@ static void exit_usage(int exitcode) - " [-b | --blocksize=]\n" - " [-d | --disk_layout=]\n" - " [-r | --requestsize=]\n" -- " \n\n",prog_name); -+ " \n\n", prog_name); - - printf(" -t or --test means testmode\n" - " -V or --version means print version\n" -@@ -71,13 +70,13 @@ static void exit_usage(int exitcode) - " -C or --check_host_count means force dasdfmt to check\n" - " the host access open count to ensure the device\n" - " is not online on another operating system instance\n" -- " --norecordzero prevent storage server from modifying" -- " record 0\n\n" -+ " --norecordzero prevent storage server from modifying" -+ " record 0\n\n" - " is the volume identifier, which is converted\n" -- " to EBCDIC and written to disk. \n" -+ " to EBCDIC and written to disk.\n" - " (6 characters, e.g. LNX001\n" - " has to be power of 2 and at least 512\n" -- " is either \n" -+ " is either\n" - " 'cdl' for compatible disk layout (default) or\n" - " 'ldl' for linux disk layout\n" - " device node of the device to format\n"); -@@ -106,38 +105,39 @@ static int reread_partition_table(void) - * signal handler: - * enables the disk again in case of SIGTERM, SIGINT and SIGQUIT - */ --static void program_interrupt_signal (int sig) -+static void program_interrupt_signal(int sig) - { - int rc; - - if (program_interrupt_in_progress) -- raise (sig); -+ raise(sig); - program_interrupt_in_progress = 1; - - if (disk_disabled) { -- printf("Re-accessing the device... \n"); -+ printf("Re-accessing the device...\n"); - rc = ioctl(filedes, BIODASDENABLE, &format_params); - if (rc) -- ERRMSG_EXIT(EXIT_FAILURE, -- "%s: (signal handler) IOCTL BIODASDENABLE " -- "failed (%s)\n",prog_name,strerror(errno)); -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (signal handler) IOCTL " -+ "BIODASDENABLE failed (%s)\n", prog_name, -+ strerror(errno)); - } - -- printf("Rereading the partition table... \n"); -+ printf("Rereading the partition table...\n"); - rc = reread_partition_table(); - if (rc) { - ERRMSG("%s: (signal handler) Re-reading partition table " - "failed. (%s)\n", prog_name, strerror(errno)); -- } else -+ } else { - printf("Exiting...\n"); -+ } - - rc = close(filedes); - if (rc) - ERRMSG("%s: (signal handler) Unable to close device (%s)\n", - prog_name, strerror(errno)); - -- signal (sig, SIG_DFL); -- raise (sig); -+ signal(sig, SIG_DFL); -+ raise(sig); - } - - -@@ -171,13 +171,13 @@ static void get_device_name(dasdfmt_info - char* device; - int i; - -- if ((strchr(name, ' ') != NULL)||(strchr(name, '#') != NULL)|| -- (strchr(name, '[') != NULL)||(strchr(name, ']') != NULL)|| -- (strchr(name, '!') != NULL)||(strchr(name, '>') != NULL)|| -- (strchr(name, '(') != NULL)||(strchr(name, '<') != NULL)|| -- (strchr(name, ')') != NULL)||(strchr(name, ':') != NULL)|| -- (strchr(name, '&') != NULL)||(strchr(name, ';') != NULL)) -- ERRMSG_EXIT(EXIT_MISUSE,"%s: Your filename contains " -+ if ((strchr(name, ' ') != NULL) || (strchr(name, '#') != NULL) || -+ (strchr(name, '[') != NULL) || (strchr(name, ']') != NULL) || -+ (strchr(name, '!') != NULL) || (strchr(name, '>') != NULL) || -+ (strchr(name, '(') != NULL) || (strchr(name, '<') != NULL) || -+ (strchr(name, ')') != NULL) || (strchr(name, ':') != NULL) || -+ (strchr(name, '&') != NULL) || (strchr(name, ';') != NULL)) -+ ERRMSG_EXIT(EXIT_MISUSE, "%s: Your filename contains " - "blanks or special characters!\n", - prog_name); - -@@ -215,14 +215,14 @@ static void get_device_name(dasdfmt_info - info->devname[PATH_MAX - 1] = '\0'; - - if (stat(info->devname, &dev_stat) != 0) -- ERRMSG_EXIT(EXIT_MISUSE, -- "%s: Could not get information for device node %s: %s\n", -- prog_name, info->devname, strerror(errno)); -+ ERRMSG_EXIT(EXIT_MISUSE, "%s: Could not get information for " -+ "device node %s: %s\n", prog_name, info->devname, -+ strerror(errno)); - - if (minor(dev_stat.st_rdev) & PARTN_MASK) { -- ERRMSG_EXIT(EXIT_MISUSE, -- "%s: Unable to format partition %s. Please specify a device.\n", -- prog_name, info->devname); -+ ERRMSG_EXIT(EXIT_MISUSE, "%s: Unable to format partition %s. " -+ "Please specify a device.\n", prog_name, -+ info->devname); - } - - if (util_proc_dev_get_entry(dev_stat.st_rdev, 1, &dev_entry) == 0) { -@@ -253,7 +253,7 @@ static void init_info(dasdfmt_info_t *in - info->force = 0; - info->writenolabel = 0; - info->labelspec = 0; -- info->cdl_format = 0; -+ info->cdl_format = 0; - info->blksize_specified = 0; - info->reqsize_specified = 0; - info->node_specified = 0; -@@ -263,7 +263,6 @@ static void init_info(dasdfmt_info_t *in - info->yast_mode = 0; - } - -- - /* - * check for disk type and set some variables (e.g. usage count) - */ -@@ -280,9 +279,9 @@ static void check_disk(dasdfmt_info_t *i - "status information failed (%s)\n", - prog_name, strerror(errno_save)); - } -- if (ro) { -+ if (ro) - ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n"); -- } -+ - retry: - if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) { - errno_save = errno; -@@ -314,7 +313,7 @@ retry: - - info->usage_count = dasd_info.open_count; - info->devno = dasd_info.devno; -- if (strncmp(dasd_info.type, "ECKD",4) != 0) { -+ if (strncmp(dasd_info.type, "ECKD", 4) != 0) { - ERRMSG_EXIT(EXIT_FAILURE, - "%s: Unsupported disk type\n%s is not an " - "ECKD disk!\n", prog_name, info->devname); -@@ -327,29 +326,28 @@ retry: - } - } - -- - /* - * check the volume serial for special - * characters and move blanks to the end - */ - static int check_volser(char *s, int devno) - { -- int i,j; -+ int i, j; - -- for (i=0; i<6; i++) { -+ for (i = 0; i < 6; i++) { - if ((s[i] < 0x20) || (s[i] > 0x7a) || -- ((s[i] >= 0x21)&&(s[i] <= 0x22)) || /* !" */ -- ((s[i] >= 0x26)&&(s[i] <= 0x2f)) || /* &'()*+,-./ */ -- ((s[i] >= 0x3a)&&(s[i] <= 0x3f)) || /* :;<=>? */ -- ((s[i] >= 0x5b)&&(s[i] <= 0x60))) /* \]^_` */ -+ ((s[i] >= 0x21) && (s[i] <= 0x22)) || /* !" */ -+ ((s[i] >= 0x26) && (s[i] <= 0x2f)) || /* &'()*+,-./ */ -+ ((s[i] >= 0x3a) && (s[i] <= 0x3f)) || /* :;<=>? */ -+ ((s[i] >= 0x5b) && (s[i] <= 0x60))) /* \]^_` */ - s[i] = ' '; - s[i] = toupper(s[i]); - } - s[6] = 0x00; - -- for (i=0; i<6; i++) { -+ for (i = 0; i < 6; i++) { - if (s[i] == ' ') -- for (j=i; j<6; j++) -+ for (j = i; j < 6; j++) - if (s[j] != ' ') { - s[i] = s[j]; - s[j] = ' '; -@@ -360,7 +358,7 @@ static int check_volser(char *s, int dev - if (s[0] == ' ') { - printf("Usage error, switching to default.\n"); - sprintf(s, "0X%04x", devno); -- for (i=0; i<6; i++) -+ for (i = 0; i < 6; i++) - s[i] = toupper(s[i]); - return -1; - } -@@ -368,7 +366,6 @@ static int check_volser(char *s, int dev - return 0; - } - -- - /* - * do some blocksize checks - */ -@@ -377,7 +374,7 @@ static int check_param(char *s, size_t b - int tmp = data->blksize; - - if ((tmp < 512) || (tmp > 4096)) { -- strncpy(s,"Blocksize must be one of the following positive " -+ strncpy(s, "Blocksize must be one of the following positive " - "integers:\n512, 1024, 2048, 4096.", buffsize); - if (buffsize > 0) - s[buffsize - 1] = '\0'; -@@ -386,7 +383,7 @@ static int check_param(char *s, size_t b - - while (tmp > 0) { - if ((tmp % 2) && (tmp != 1)) { -- strncpy(s,"Blocksize must be a power of 2.", buffsize); -+ strncpy(s, "Blocksize must be a power of 2.", buffsize); - if (buffsize > 0) - s[buffsize - 1] = '\0'; - return -1; -@@ -397,7 +394,6 @@ static int check_param(char *s, size_t b - return 0; - } - -- - /* - * ask the user to specify a blocksize - */ -@@ -415,7 +411,7 @@ static format_data_t ask_user_for_blksiz - if (fgets(buffer, sizeof(buffer), stdin) == NULL) - break; - -- rc = sscanf(buffer,"%d%c", ¶ms.blksize, &c); -+ rc = sscanf(buffer, "%d%c", ¶ms.blksize, &c); - if ((rc == 2) && (c == '\n')) - rc = 1; - if (rc == -1) -@@ -424,7 +420,7 @@ static format_data_t ask_user_for_blksiz - printf(" -- wrong input, try again.\n"); - - if (check_param(str, ERR_LENGTH, ¶ms) < 0) { -- printf(" -- %s\n",str); -+ printf(" -- %s\n", str); - rc = 0; - } - } while (rc != 1); -@@ -432,7 +428,6 @@ static format_data_t ask_user_for_blksiz - return params; - } - -- - /* - * print all information needed to format the device - */ -@@ -449,7 +444,7 @@ static void dasdfmt_print_info(dasdfmt_i - printf("%s in the following way:\n", info->devname); - printf(" Device number of device : 0x%x\n", info->devno); - printf(" Labelling device : %s\n", -- (info->writenolabel)?"no":"yes"); -+ (info->writenolabel) ? "no" : "yes"); - - if (!info->writenolabel) { - vtoc_volume_label_get_label(vlabel, vollbl); -@@ -460,31 +455,31 @@ static void dasdfmt_print_info(dasdfmt_i - printf(" Extent start (trk no) : %u\n", p->start_unit); - printf(" Extent end (trk no) : %u\n", p->stop_unit); - printf(" Compatible Disk Layout : %s\n", -- (p->intensity & DASD_FMT_INT_COMPAT)?"yes":"no"); -+ (p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no"); - printf(" Blocksize : %d\n", p->blksize); - - if (info->testmode) - printf("Test mode active, omitting ioctl.\n"); - } - -- - /* - * get volser - */ --static int dasdfmt_get_volser(char * devname, char * volser) -+static int dasdfmt_get_volser(char *devname, char *volser) - { -- dasd_information_t dasd_info; -+ dasd_information_t dasd_info; - int blksize; - int f; - volume_label_t vlabel; - -- if ((f = open(devname, O_RDONLY)) == -1) -- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n", -+ f = open(devname, O_RDONLY); -+ if (f == -1) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", - prog_name, devname, strerror(errno)); - - if (ioctl(f, BIODASDINFO, &dasd_info) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BIODASD" -- "INFO failed (%s).\n",prog_name, strerror(errno)); -+ "INFO failed (%s).\n", prog_name, strerror(errno)); - - if (ioctl(f, BLKSSZGET, &blksize) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET " -@@ -500,8 +495,7 @@ static int dasdfmt_get_volser(char * dev - vtoc_read_volume_label(devname, dasd_info.label_block * blksize, &vlabel); - vtoc_volume_label_get_volser(&vlabel, volser); - return 0; -- } -- else { -+ } else { - return -1; - } - } -@@ -512,22 +506,24 @@ static int dasdfmt_get_volser(char * dev - static void dasdfmt_write_labels(dasdfmt_info_t *info, volume_label_t *vlabel, - unsigned int cylinders, unsigned int heads) - { -- int label_position; -- dasd_information_t dasd_info; -- struct hd_geometry geo; -- format4_label_t f4; -- format5_label_t f5; -- format7_label_t f7; -+ int label_position; -+ dasd_information_t dasd_info; -+ struct hd_geometry geo; -+ format4_label_t f4; -+ format5_label_t f5; -+ format7_label_t f7; - int rc, blksize; - void *ipl1_record, *ipl2_record; - int ipl1_record_len, ipl2_record_len; - - -- if (info->verbosity > 0) printf("Retrieving dasd information... "); -+ if (info->verbosity > 0) -+ printf("Retrieving dasd information... "); - - if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) -- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BIODASD" -- "INFO failed (%s).\n",prog_name, strerror(errno)); -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL " -+ "BIODASDINFO failed (%s).\n", -+ prog_name, strerror(errno)); - - if (ioctl(filedes, BLKSSZGET, &blksize) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET " -@@ -539,13 +535,16 @@ static void dasdfmt_write_labels(dasdfmt - * vary depending on the format. - */ - if (ioctl(filedes, HDIO_GETGEO, &geo) != 0) -- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL HDIO_GET" -- "GEO failed (%s).\n", prog_name, strerror(errno)); -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL " -+ "HDIO_GETGEO failed (%s).\n", -+ prog_name, strerror(errno)); - -- if (info->verbosity > 0) printf("ok\n"); -+ if (info->verbosity > 0) -+ printf("ok\n"); - - /* write empty bootstrap (initial IPL records) */ -- if (info->verbosity > 0) printf("Writing empty bootstrap...\n"); -+ if (info->verbosity > 0) -+ printf("Writing empty bootstrap...\n"); - - /* - * Note: ldl labels do not contain the key field -@@ -596,7 +595,8 @@ static void dasdfmt_write_labels(dasdfmt - - label_position = dasd_info.label_block * blksize; - -- if (info->verbosity > 0) printf("Writing label...\n"); -+ if (info->verbosity > 0) -+ printf("Writing label...\n"); - - rc = lseek(filedes, label_position, SEEK_SET); - if (rc != label_position) -@@ -608,10 +608,10 @@ static void dasdfmt_write_labels(dasdfmt - * Note: cdl volume labels do not contain the 'formatted_blocks' part - * and ldl labels do not contain the key field - */ -- if (info->cdl_format) -+ if (info->cdl_format) { - rc = write(filedes, vlabel, (sizeof(*vlabel) - - sizeof(vlabel->formatted_blocks))); -- else { -+ } else { - vlabel->ldl_version = 0xf2; /* EBCDIC '2' */ - vlabel->formatted_blocks = cylinders * heads * geo.sectors; - rc = write(filedes, &vlabel->vollbl, (sizeof(*vlabel) -@@ -625,7 +625,8 @@ static void dasdfmt_write_labels(dasdfmt - ERRMSG_EXIT(EXIT_FAILURE, "%s: Error writing volume label " - "(%d).\n", prog_name, rc); - -- if (info->verbosity > 0) printf("Writing VTOC... "); -+ if (info->verbosity > 0) -+ printf("Writing VTOC... "); - - label_position = (VTOC_START_CC * heads + VTOC_START_HH) * - geo.sectors * blksize; -@@ -673,10 +674,10 @@ static void dasdfmt_write_labels(dasdfmt - - fsync(filedes); - -- if (info->verbosity > 0) printf("ok\n"); -+ if (info->verbosity > 0) -+ printf("ok\n"); - } - -- - /* - * formats the disk cylinderwise - */ -@@ -720,21 +721,20 @@ static void dasdfmt_format(dasdfmt_info_ - format_step.start_unit += 1; - - if (ioctl(filedes, BIODASDFMT, &format_step) != 0) -- ERRMSG_EXIT(EXIT_FAILURE,"%s: (format cylinder) IOCTL " -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (format cylinder) IOCTL " - "BIODASDFMT failed. (%s)\n", - prog_name, strerror(errno)); - - if (info->print_progressbar) { - printf("cyl %7d of %7d |", cyl, cylinders); - p2 = p1; -- p1 = cyl*100/cylinders; -- if (p1 != p2) -- { -+ p1 = cyl * 100 / cylinders; -+ if (p1 != p2) { - /* percent value has changed */ -- tmp = cyl*50/cylinders; -- for (j=1; j<=tmp; j++) -+ tmp = cyl * 50 / cylinders; -+ for (j = 1; j <= tmp; j++) - printf("#"); -- for (j=tmp+1; j<=50; j++) -+ for (j = tmp + 1; j <= 50; j++) - printf("-"); - printf("|%3d%%", p1); - } -@@ -748,6 +748,7 @@ static void dasdfmt_format(dasdfmt_info_ - fflush(stdout); - hashcount++; - } -+ - if (info->print_percentage) { - printf("cyl %7d of %7d |%3d%%\n", cyl, cylinders, - cyl*100/cylinders); -@@ -757,9 +758,9 @@ static void dasdfmt_format(dasdfmt_info_ - if (k % heads == 0) { - k += reqsize * heads; - cyl += reqsize; -- } -- else -+ } else { - k += format_params->stop_unit % heads; -+ } - - if (k > format_params->stop_unit) - break; -@@ -769,14 +770,9 @@ static void dasdfmt_format(dasdfmt_info_ - printf("\n\n"); - } - -- --/* -- * -- */ --static void dasdfmt_prepare_and_format (dasdfmt_info_t *info, -- unsigned int cylinders, -- unsigned int heads, -- format_data_t *p) -+static void dasdfmt_prepare_and_format(dasdfmt_info_t *info, -+ unsigned int cylinders, -+ unsigned int heads, format_data_t *p) - { - format_data_t temp = { - start_unit: 0, -@@ -786,7 +782,8 @@ static void dasdfmt_prepare_and_format ( - | DASD_FMT_INT_INVAL) - }; - -- if (info->verbosity > 0) printf("Detaching the device...\n"); -+ if (info->verbosity > 0) -+ printf("Detaching the device...\n"); - - if (ioctl(filedes, BIODASDDISABLE, p) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL " -@@ -794,7 +791,8 @@ static void dasdfmt_prepare_and_format ( - strerror(errno)); - disk_disabled = 1; - -- if (info->verbosity > 0) printf("Invalidate first track...\n"); -+ if (info->verbosity > 0) -+ printf("Invalidate first track...\n"); - - if (ioctl(filedes, BIODASDFMT, &temp) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (invalidate first track) IOCTL " -@@ -806,18 +804,21 @@ static void dasdfmt_prepare_and_format ( - - dasdfmt_format(info, cylinders, heads, p); - -- if (info->verbosity > 0) printf("formatting tracks complete...\n"); -+ if (info->verbosity > 0) -+ printf("formatting tracks complete...\n"); - - temp.intensity = p->intensity; - -- if (info->verbosity > 0) printf("Revalidate first track...\n"); -+ if (info->verbosity > 0) -+ printf("Revalidate first track...\n"); - - if (ioctl(filedes, BIODASDFMT, &temp) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (re-validate first track) IOCTL" - " BIODASDFMT failed (%s)\n", prog_name, - strerror(errno)); - -- if (info->verbosity > 0) printf("Re-accessing the device...\n"); -+ if (info->verbosity > 0) -+ printf("Re-accessing the device...\n"); - - if (ioctl(filedes, BIODASDENABLE, p) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL " -@@ -826,20 +827,17 @@ static void dasdfmt_prepare_and_format ( - disk_disabled = 0; - } - -- --/* -- * -- */ - static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p, - volume_label_t *vlabel) - { -- char inp_buffer[5]; -+ char inp_buffer[5]; - dasd_information_t dasd_info; - struct dasd_eckd_characteristics *characteristics; - unsigned int cylinders, heads; - int count; - -- if (info->verbosity > 0) printf("Retrieving disk geometry...\n"); -+ if (info->verbosity > 0) -+ printf("Retrieving disk geometry...\n"); - - if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (retrieving disk information) " -@@ -877,22 +875,23 @@ static void do_format_dasd(dasdfmt_info_ - } - } - } else { -- if (!info->labelspec && !info->keep_volser) { -+ if (!info->labelspec && !info->keep_volser) { - char buf[7]; - -- sprintf(buf, "0X%04x", info->devno); -+ sprintf(buf, "0X%04x", info->devno); - check_volser(buf, info->devno); - vtoc_volume_label_set_volser(vlabel, buf); - } - -- if (p->intensity & DASD_FMT_INT_COMPAT) { -+ if (p->intensity & DASD_FMT_INT_COMPAT) { - info->cdl_format = 1; - vtoc_volume_label_set_label(vlabel, "VOL1"); - vtoc_volume_label_set_key(vlabel, "VOL1"); - vtoc_set_cchhb(&vlabel->vtoc, 0x0000, 0x0001, 0x01); -- } else -+ } else { - vtoc_volume_label_set_label(vlabel, "LNX1"); -- } -+ } -+ } - - if ((info->verbosity > 0) || !info->withoutprompt || info->testmode) - dasdfmt_print_info(info, vlabel, cylinders, heads, p); -@@ -926,15 +925,15 @@ static void do_format_dasd(dasdfmt_info_ - "untouched: "); - if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL) - return; -- if (strcasecmp(inp_buffer,"yes") && -- strcasecmp(inp_buffer,"yes\n")) { -+ if (strcasecmp(inp_buffer, "yes") && -+ strcasecmp(inp_buffer, "yes\n")) { - printf("Omitting ioctl call (disk will " - "NOT be formatted).\n"); - return; - } - } - -- if (!((info->withoutprompt)&&(info->verbosity<1))) -+ if (!((info->withoutprompt) && (info->verbosity < 1))) - printf("Formatting the device. This may take a " - "while (get yourself a coffee).\n"); - -@@ -954,12 +953,11 @@ static void do_format_dasd(dasdfmt_info_ - } else { - if (!info->yast_mode) - printf("ok\n"); -- } -+ } - } - } - -- --int main(int argc,char *argv[]) -+int main(int argc, char *argv[]) - { - dasdfmt_info_t info; - volume_label_t vlabel; -@@ -980,9 +978,9 @@ int main(int argc,char *argv[]) - int running=0; - - /* Establish a handler for interrupt signals. */ -- signal (SIGTERM, program_interrupt_signal); -- signal (SIGINT, program_interrupt_signal); -- signal (SIGQUIT, program_interrupt_signal); -+ signal(SIGTERM, program_interrupt_signal); -+ signal(SIGINT, program_interrupt_signal); -+ signal(SIGQUIT, program_interrupt_signal); - - /******************* initialization ********************/ - prog_name = argv[0]; -@@ -996,102 +994,81 @@ int main(int argc,char *argv[]) - - /*************** parse parameters **********************/ - -- while (1) -- { -- rc=getopt_long(argc, argv, dasdfmt_getopt_string, -- dasdfmt_getopt_long_options, &index); -+ while (1) { -+ rc = getopt_long(argc, argv, dasdfmt_getopt_string, -+ dasdfmt_getopt_long_options, &index); - -- switch (rc) -- { -+ switch (rc) { - case 'F': -- info.force=1; -+ info.force = 1; - break; -- -- case 'd' : -- if (strncmp(optarg,"cdl",3)==0) -- { -+ case 'd': -+ if (strncmp(optarg, "cdl", 3) == 0) { - format_params.intensity |= DASD_FMT_INT_COMPAT; -- if (info.writenolabel) -- { -- printf("WARNING: using the cdl " \ -- "format without writing a " \ -- "label doesn't make much " \ -+ if (info.writenolabel) { -+ printf("WARNING: using the cdl " -+ "format without writing a " -+ "label doesn't make much " - "sense!\n"); - exit(1); - } -- } -- else if (strncmp(optarg,"ldl",3)==0) -+ } else if (strncmp(optarg, "ldl", 3) == 0) { - format_params.intensity &= ~DASD_FMT_INT_COMPAT; -- else -- { -+ } else { - printf("%s is not a valid option!\n", optarg); - exit(1); - } -- break; -- -+ break; - case 'y': -- info.withoutprompt=1; -+ info.withoutprompt = 1; - break; -- - case 'z': -- format_params.intensity |= DASD_FMT_INT_FMT_NOR0; -+ format_params.intensity |= DASD_FMT_INT_FMT_NOR0; - break; -- - case 't': -- info.testmode=1; -+ info.testmode = 1; - break; -- - case 'p': - if (!(info.print_hashmarks || info.print_percentage)) - info.print_progressbar = 1; - break; -- - case 'm': -- if (!(info.print_progressbar || info.print_percentage)) -- { -- hashstep_str=optarg; -- info.print_hashmarks=1; -+ if (!(info.print_progressbar || info.print_percentage)) { -+ hashstep_str = optarg; -+ info.print_hashmarks = 1; - } - break; -- - case 'Q': - if (!(info.print_hashmarks || info.print_progressbar)) - info.print_percentage = 1; - break; -- - case 'v': -- info.verbosity=1; -+ info.verbosity = 1; - break; -- - case 'h': - exit_usage(0); -- - case 'V': - print_version(); - exit(0); -- - case 'l': -- strncpy(buf, optarg, 6); -+ strncpy(buf, optarg, 6); - if (check_volser(buf, 0) < 0) - break; -- vtoc_volume_label_set_volser(&vlabel,buf); -- info.labelspec=1; -+ vtoc_volume_label_set_volser(&vlabel, buf); -+ info.labelspec = 1; - break; -- - case 'L': -- if (format_params.intensity & DASD_FMT_INT_COMPAT) -- { -- printf("WARNING: using the cdl format " \ -- "without writing a label doesn't " \ -+ if (format_params.intensity & DASD_FMT_INT_COMPAT) { -+ printf("WARNING: using the cdl format " -+ "without writing a label doesn't " - "make much sense!\n"); - exit(1); - } -- info.writenolabel=1; -+ info.writenolabel = 1; - break; -- -- case 'b' : -- blksize_param_str=optarg; -- info.blksize_specified=1; -+ case 'b': -+ blksize_param_str = optarg; -+ info.blksize_specified = 1; - break; - case 'r': - reqsize_param_str = optarg; -@@ -1102,7 +1079,7 @@ int main(int argc,char *argv[]) - ERRMSG_EXIT(EXIT_MISUSE,"%s: too many devices specified.\n", - prog_name); - dev_filename[dev_count++]=strdup(optarg); -- info.node_specified=1; -+ info.node_specified = 1; - break; - case 'Y' : /* YaST mode */ - info.yast_mode=1; -@@ -1110,8 +1087,8 @@ int main(int argc,char *argv[]) - case 'P' : /* max parallel formatting processes */ - max_parallel=atoi(optarg); - break; -- case 'k' : -- info.keep_volser=1; -+ case 'k': -+ info.keep_volser = 1; - break; - case 'C': - info.force_host = 1; -@@ -1121,11 +1098,12 @@ int main(int argc,char *argv[]) - info.device_id = optind; - break; - default: -- ERRMSG_EXIT(EXIT_MISUSE, -- "Try '%s --help' for more" -- " information.\n",prog_name); -+ ERRMSG_EXIT(EXIT_MISUSE, "Try '%s --help' for more" -+ " information.\n", prog_name); - } -- if (rc==-1) break; // exit loop if finished -+ -+ if (rc == -1) -+ break; /* exit loop if finished */ - } - - CHECK_SPEC_MAX_ONCE(info.blksize_specified, "blocksize"); -@@ -1222,7 +1200,7 @@ int main(int argc,char *argv[]) - } else - reqsize = DEFAULT_REQUESTSIZE; - if (info.print_hashmarks) -- PARSE_PARAM_INTO(info.hashstep, hashstep_str,10,"hashstep"); -+ PARSE_PARAM_INTO(info.hashstep, hashstep_str, 10, "hashstep"); - - get_device_name(&info, dev_filename[i]); - -@@ -1230,22 +1208,24 @@ int main(int argc,char *argv[]) - format_params = ask_user_for_blksize(format_params); - - if (info.keep_volser) { -- if(format_params.intensity == 0x00) { -- printf("WARNING: VOLSER cannot be kept " \ -+ if (format_params.intensity == 0x00) { -+ printf("WARNING: VOLSER cannot be kept " - "when using the ldl format!\n"); - exit(1); - } - -- if(dasdfmt_get_volser(info.devname, old_volser) == 0) -+ if (dasdfmt_get_volser(info.devname, old_volser) == 0) - vtoc_volume_label_set_volser(&vlabel, old_volser); - else -- ERRMSG_EXIT(EXIT_FAILURE,"%s: VOLSER not found on device %s\n", -+ ERRMSG_EXIT(EXIT_FAILURE, -+ "%s: VOLSER not found on device %s\n", - prog_name, info.devname); - - } - -- if ((filedes = open(info.devname, O_RDWR)) == -1) -- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n", -+ filedes = open(info.devname, O_RDWR); -+ if (filedes == -1) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", - prog_name, info.devname, strerror(errno)); - - check_disk(&info); diff --git a/s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch b/s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch deleted file mode 100644 index 1116f55..0000000 --- a/s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch +++ /dev/null @@ -1,399 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: - -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Use enhanced DASD information - - Currently dasdfmt uses BIODASDINFO as the IOCTL command to retrieve - information about a DASD and stores them in dasd_information_t. - However, BIODASDINFO2 offers a few more useful information (which are - then stored in dasd_information2_t). - - - Replace dasd_information_t with dasd_information2_t. - - Make the corresponding variable part of dasdfmt_info_t, since it is - used in several functions anyway and we can save a few parameters and - IOCTL calls. - - Change the initialization of dasdfmt_info_t. A separate function isn't - necessary for that. - - Put the BIODASDINFO2 IOCTL call in a separate function which is then - called only once. - - Signed-off-by: Jan Höppner - Signed-off-by: Stefan Haberland - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.c | 132 ++++++++++++++++++------------------------------------ - dasdfmt/dasdfmt.h | 21 ++++++-- - 2 files changed, 61 insertions(+), 92 deletions(-) - ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -237,30 +237,18 @@ static void get_device_name(dasdfmt_info - } - - /* -- * initialize the dasdfmt info structure -+ * Retrieve DASD information - */ --static void init_info(dasdfmt_info_t *info) -+static void get_device_info(dasdfmt_info_t *info) - { -- info->devno = 0x0; -- info->usage_count = 0; -- info->testmode = 0; -- info->verbosity = 0; -- info->withoutprompt = 0; -- info->print_progressbar = 0; -- info->print_hashmarks = 0; -- info->print_percentage = 0; -- info->hashstep = 0; -- info->force = 0; -- info->writenolabel = 0; -- info->labelspec = 0; -- info->cdl_format = 0; -- info->blksize_specified = 0; -- info->reqsize_specified = 0; -- info->node_specified = 0; -- info->device_id = 0; -- info->keep_volser = 0; -- info->force_host = 0; -- info->yast_mode = 0; -+ dasd_information2_t dasd_info; -+ -+ if (ioctl(filedes, BIODASDINFO2, &dasd_info)) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl call to retrieve " -+ "device information failed (%s).\n", -+ prog_name, strerror(errno)); -+ -+ info->dasd_info = dasd_info; - } - - /* -@@ -268,7 +256,6 @@ static void init_info(dasdfmt_info_t *in - */ - static void check_disk(dasdfmt_info_t *info) - { -- dasd_information_t dasd_info; - int ro, errno_save, i = 0; - - if (ioctl(filedes, BLKROGET, &ro) != 0) { -@@ -283,15 +270,6 @@ static void check_disk(dasdfmt_info_t *i - ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n"); - - retry: -- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) { -- errno_save = errno; -- close(filedes); -- ERRMSG_EXIT(EXIT_FAILURE, -- "%s: the ioctl call to retrieve device " -- "information failed (%s)\n", -- prog_name, strerror(errno_save)); -- } -- - if (!info->force) - /* - * udev strikes again. -@@ -302,7 +280,7 @@ retry: - * And confusing the hell out ouf anyone else. - * Bah. - */ -- if (dasd_info.open_count > 1) { -+ if (info->dasd_info.open_count > 1) { - if (i < 5) { - ++i; - sleep(1); -@@ -311,9 +289,7 @@ retry: - ERRMSG_EXIT(EXIT_BUSY, "Disk in use!\n"); - } - -- info->usage_count = dasd_info.open_count; -- info->devno = dasd_info.devno; -- if (strncmp(dasd_info.type, "ECKD", 4) != 0) { -+ if (strncmp(info->dasd_info.type, "ECKD", 4) != 0) { - ERRMSG_EXIT(EXIT_FAILURE, - "%s: Unsupported disk type\n%s is not an " - "ECKD disk!\n", prog_name, info->devname); -@@ -442,7 +418,7 @@ static void dasdfmt_print_info(dasdfmt_i - - printf("\nI am going to format the device "); - printf("%s in the following way:\n", info->devname); -- printf(" Device number of device : 0x%x\n", info->devno); -+ printf(" Device number of device : 0x%x\n", info->dasd_info.devno); - printf(" Labelling device : %s\n", - (info->writenolabel) ? "no" : "yes"); - -@@ -465,21 +441,16 @@ static void dasdfmt_print_info(dasdfmt_i - /* - * get volser - */ --static int dasdfmt_get_volser(char *devname, char *volser) -+static int dasdfmt_get_volser(dasdfmt_info_t *info, char *volser) - { -- dasd_information_t dasd_info; - int blksize; - int f; - volume_label_t vlabel; - -- f = open(devname, O_RDONLY); -+ f = open(info->devname, O_RDONLY); - if (f == -1) - ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", -- prog_name, devname, strerror(errno)); -- -- if (ioctl(f, BIODASDINFO, &dasd_info) != 0) -- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BIODASD" -- "INFO failed (%s).\n", prog_name, strerror(errno)); -+ prog_name, info->devname, strerror(errno)); - - if (ioctl(f, BLKSSZGET, &blksize) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET " -@@ -489,10 +460,12 @@ static int dasdfmt_get_volser(char *devn - ERRMSG("%s: error during close: %s\ncontinuing...\n", - prog_name, strerror(errno)); - -- if ((strncmp(dasd_info.type, "ECKD", 4) == 0) && -- (!dasd_info.FBA_layout)) { -+ if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) && -+ (!info->dasd_info.FBA_layout)) { - /* OS/390 and zOS compatible disk layout */ -- vtoc_read_volume_label(devname, dasd_info.label_block * blksize, &vlabel); -+ vtoc_read_volume_label(info->devname, -+ info->dasd_info.label_block * blksize, -+ &vlabel); - vtoc_volume_label_get_volser(&vlabel, volser); - return 0; - } else { -@@ -507,7 +480,6 @@ static void dasdfmt_write_labels(dasdfmt - unsigned int cylinders, unsigned int heads) - { - int label_position; -- dasd_information_t dasd_info; - struct hd_geometry geo; - format4_label_t f4; - format5_label_t f5; -@@ -520,11 +492,6 @@ static void dasdfmt_write_labels(dasdfmt - if (info->verbosity > 0) - printf("Retrieving dasd information... "); - -- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) -- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL " -- "BIODASDINFO failed (%s).\n", -- prog_name, strerror(errno)); -- - if (ioctl(filedes, BLKSSZGET, &blksize) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET " - "failed (%s).\n", prog_name, strerror(errno)); -@@ -586,14 +553,14 @@ static void dasdfmt_write_labels(dasdfmt - - /* write VTOC */ - vtoc_init_format4_label(&f4, geo.cylinders, cylinders, heads, -- geo.sectors, blksize, dasd_info.dev_type); -+ geo.sectors, blksize, info->dasd_info.dev_type); - - vtoc_init_format5_label(&f5); - vtoc_init_format7_label(&f7); - vtoc_set_freespace(&f4, &f5, &f7, '+', 0, FIRST_USABLE_TRK, - (cylinders * heads - 1), cylinders, heads); - -- label_position = dasd_info.label_block * blksize; -+ label_position = info->dasd_info.label_block * blksize; - - if (info->verbosity > 0) - printf("Writing label...\n"); -@@ -831,7 +798,6 @@ static void do_format_dasd(dasdfmt_info_ - volume_label_t *vlabel) - { - char inp_buffer[5]; -- dasd_information_t dasd_info; - struct dasd_eckd_characteristics *characteristics; - unsigned int cylinders, heads; - int count; -@@ -839,13 +805,9 @@ static void do_format_dasd(dasdfmt_info_ - if (info->verbosity > 0) - printf("Retrieving disk geometry...\n"); - -- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) -- ERRMSG_EXIT(EXIT_FAILURE, "%s: (retrieving disk information) " -- "IOCTL BIODASDINFO failed (%s).\n", -- prog_name, strerror(errno)); -- - characteristics = -- (struct dasd_eckd_characteristics *) &dasd_info.characteristics; -+ (struct dasd_eckd_characteristics *) -+ &info->dasd_info.characteristics; - if (characteristics->no_cyl == LV_COMPAT_CYL && - characteristics->long_no_cyl) - cylinders = characteristics->long_no_cyl; -@@ -878,8 +840,8 @@ static void do_format_dasd(dasdfmt_info_ - if (!info->labelspec && !info->keep_volser) { - char buf[7]; - -- sprintf(buf, "0X%04x", info->devno); -- check_volser(buf, info->devno); -+ sprintf(buf, "0X%04x", info->dasd_info.devno); -+ check_volser(buf, info->dasd_info.devno); - vtoc_volume_label_set_volser(vlabel, buf); - } - -@@ -959,7 +921,10 @@ static void do_format_dasd(dasdfmt_info_ - - int main(int argc, char *argv[]) - { -- dasdfmt_info_t info; -+ dasdfmt_info_t info = { -+ .dasd_info = {0}, -+ {0} -+ }; - volume_label_t vlabel; - char old_volser[7]; - -@@ -986,7 +951,6 @@ int main(int argc, char *argv[]) - prog_name = argv[0]; - - /* set default values */ -- init_info(&info); - vtoc_volume_label_init(&vlabel); - - format_params.blksize = DEFAULT_BLOCKSIZE; -@@ -1137,30 +1101,24 @@ int main(int argc, char *argv[]) - - if(info.yast_mode) { - for(i=0;ino_cyl == LV_COMPAT_CYL && - characteristics->long_no_cyl) - cylinders = characteristics->long_no_cyl; -@@ -1204,6 +1162,13 @@ int main(int argc, char *argv[]) - - get_device_name(&info, dev_filename[i]); - -+ filedes = open(info.devname, O_RDWR); -+ if (filedes == -1) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", -+ prog_name, info.devname, strerror(errno)); -+ -+ get_device_info(&info); -+ - if (!info.blksize_specified) - format_params = ask_user_for_blksize(format_params); - -@@ -1214,7 +1179,7 @@ int main(int argc, char *argv[]) - exit(1); - } - -- if (dasdfmt_get_volser(info.devname, old_volser) == 0) -+ if (dasdfmt_get_volser(&info, old_volser) == 0) - vtoc_volume_label_set_volser(&vlabel, old_volser); - else - ERRMSG_EXIT(EXIT_FAILURE, -@@ -1223,11 +1188,6 @@ int main(int argc, char *argv[]) - - } - -- filedes = open(info.devname, O_RDWR); -- if (filedes == -1) -- ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", -- prog_name, info.devname, strerror(errno)); -- - check_disk(&info); - - if (check_param(str, ERR_LENGTH, &format_params) < 0) ---- a/dasdfmt/dasdfmt.h -+++ b/dasdfmt/dasdfmt.h -@@ -32,11 +32,11 @@ - #define DASD_IOCTL_LETTER 'D' - - /* -- * struct dasd_information_t -+ * struct dasd_information2_t - * represents any data about the device, which is visible to userspace. - * including format and features. - */ --typedef struct dasd_information_t { -+typedef struct dasd_information2_t { - unsigned int devno; /* S/390 devno */ - unsigned int real_devno; /* for aliases */ - unsigned int schid; /* S/390 subchannel identifier */ -@@ -56,7 +56,17 @@ typedef struct dasd_information_t { - unsigned int confdata_size; - char characteristics[64]; /* from read_device_characteristics */ - char configuration_data[256]; /* from read_configuration_data */ --} dasd_information_t; -+ unsigned int format; /* format info like formatted/cdl/ldl/... */ -+ unsigned int features; /* dasd features like 'ro',... */ -+ unsigned int reserved0; /* reserved for further use ,... */ -+ unsigned int reserved1; /* reserved for further use ,... */ -+ unsigned int reserved2; /* reserved for further use ,... */ -+ unsigned int reserved3; /* reserved for further use ,... */ -+ unsigned int reserved4; /* reserved for further use ,... */ -+ unsigned int reserved5; /* reserved for further use ,... */ -+ unsigned int reserved6; /* reserved for further use ,... */ -+ unsigned int reserved7; /* reserved for further use ,... */ -+} dasd_information2_t; - - - struct dasd_eckd_characteristics { -@@ -165,7 +175,7 @@ typedef struct format_data_t { - #define BIODASDENABLE _IO(DASD_IOCTL_LETTER,1) - - /* Get information on a dasd device (enhanced) */ --#define BIODASDINFO _IOR(DASD_IOCTL_LETTER,1,dasd_information_t) -+#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t) - - /* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */ - #define BIODASDFMT _IOW(DASD_IOCTL_LETTER,1,format_data_t) -@@ -251,9 +261,8 @@ typedef struct bootstrap2 { - } __attribute__ ((packed)) bootstrap2_t; - - typedef struct dasdfmt_info { -- int devno; -+ dasd_information2_t dasd_info; - char devname[PATH_MAX]; -- int usage_count; - int verbosity; - int testmode; - int withoutprompt; diff --git a/s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch b/s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch deleted file mode 100644 index 46f6372..0000000 --- a/s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch +++ /dev/null @@ -1,210 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: - -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Refactor do_format_dasd - - In order to allow for new features to be integrated properly in the - existing code, certain parts of do_format_dasd() must be moved to - separate functions. This applies to setting VTOC information and - geometrical information. - - Therefore, move the relevant bits to set_geo() and set_label(). - - Signed-off-by: Jan Höppner - Signed-off-by: Stefan Haberland - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.c | 132 +++++++++++++++++++++++++++++++----------------------- - 1 file changed, 76 insertions(+), 56 deletions(-) - ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -371,6 +371,73 @@ static int check_param(char *s, size_t b - } - - /* -+ * Retrieve disk information and set cylinders and heads accordingly. -+ */ -+static void set_geo(dasdfmt_info_t *info, unsigned int *cylinders, -+ unsigned int *heads) -+{ -+ struct dasd_eckd_characteristics *characteristics; -+ -+ if (info->verbosity > 0) -+ printf("Retrieving disk geometry...\n"); -+ -+ characteristics = (struct dasd_eckd_characteristics *) -+ &info->dasd_info.characteristics; -+ if (characteristics->no_cyl == LV_COMPAT_CYL && -+ characteristics->long_no_cyl) -+ *cylinders = characteristics->long_no_cyl; -+ else -+ *cylinders = characteristics->no_cyl; -+ *heads = characteristics->trk_per_cyl; -+} -+ -+/* -+ * Set VTOC label information -+ */ -+static void set_label(dasdfmt_info_t *info, volume_label_t *vlabel, -+ format_data_t *p, unsigned int cylinders) -+{ -+ char inp_buffer[5]; -+ -+ if (info->writenolabel) { -+ if (cylinders > LV_COMPAT_CYL && !info->withoutprompt) { -+ printf("\n--->> ATTENTION! <<---\n"); -+ printf("You specified to write no labels to a" -+ " volume with more then %u cylinders.\n" -+ "Cylinders above this limit will not be" -+ " accessible as a linux partition!\n" -+ "Type \"yes\" to continue, no will leave" -+ " the disk untouched: ", LV_COMPAT_CYL); -+ if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL) -+ return; -+ if (strcasecmp(inp_buffer, "yes") && -+ strcasecmp(inp_buffer, "yes\n")) { -+ printf("Omitting ioctl call (disk will " -+ "NOT be formatted).\n"); -+ return; -+ } -+ } -+ } else { -+ if (!info->labelspec && !info->keep_volser) { -+ char buf[7]; -+ -+ sprintf(buf, "0X%04x", info->dasd_info.devno); -+ check_volser(buf, info->dasd_info.devno); -+ vtoc_volume_label_set_volser(vlabel, buf); -+ } -+ -+ if (p->intensity & DASD_FMT_INT_COMPAT) { -+ info->cdl_format = 1; -+ vtoc_volume_label_set_label(vlabel, "VOL1"); -+ vtoc_volume_label_set_key(vlabel, "VOL1"); -+ vtoc_set_cchhb(&vlabel->vtoc, 0x0000, 0x0001, 0x01); -+ } else { -+ vtoc_volume_label_set_label(vlabel, "LNX1"); -+ } -+ } -+} -+ -+/* - * ask the user to specify a blocksize - */ - static format_data_t ask_user_for_blksize(format_data_t params) -@@ -452,7 +519,7 @@ static int dasdfmt_get_volser(dasdfmt_in - ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", - prog_name, info->devname, strerror(errno)); - -- if (ioctl(f, BLKSSZGET, &blksize) != 0) -+ if (ioctl(filedes, BLKSSZGET, &blksize) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET " - "failed (%s).\n", prog_name, strerror(errno)); - -@@ -794,67 +861,16 @@ static void dasdfmt_prepare_and_format(d - disk_disabled = 0; - } - --static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p, -- volume_label_t *vlabel) -+static void do_format_dasd(dasdfmt_info_t *info, volume_label_t *vlabel, -+ format_data_t *p, unsigned int cylinders, -+ unsigned int heads) - { - char inp_buffer[5]; -- struct dasd_eckd_characteristics *characteristics; -- unsigned int cylinders, heads; - int count; - -- if (info->verbosity > 0) -- printf("Retrieving disk geometry...\n"); -- -- characteristics = -- (struct dasd_eckd_characteristics *) -- &info->dasd_info.characteristics; -- if (characteristics->no_cyl == LV_COMPAT_CYL && -- characteristics->long_no_cyl) -- cylinders = characteristics->long_no_cyl; -- else -- cylinders = characteristics->no_cyl; -- heads = characteristics->trk_per_cyl; -- - p->start_unit = 0; - p->stop_unit = (cylinders * heads) - 1; - -- if (info->writenolabel) { -- if (cylinders > LV_COMPAT_CYL && !info->withoutprompt) { -- printf("\n--->> ATTENTION! <<---\n"); -- printf("You specified to write no labels to a" -- " volume with more then %u cylinders.\n" -- "Cylinders above this limit will not be" -- " accessible as a linux partition!\n" -- "Type \"yes\" to continue, no will leave" -- " the disk untouched: ", LV_COMPAT_CYL); -- if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL) -- return; -- if (strcasecmp(inp_buffer, "yes") && -- strcasecmp(inp_buffer, "yes\n")) { -- printf("Omitting ioctl call (disk will " -- "NOT be formatted).\n"); -- return; -- } -- } -- } else { -- if (!info->labelspec && !info->keep_volser) { -- char buf[7]; -- -- sprintf(buf, "0X%04x", info->dasd_info.devno); -- check_volser(buf, info->dasd_info.devno); -- vtoc_volume_label_set_volser(vlabel, buf); -- } -- -- if (p->intensity & DASD_FMT_INT_COMPAT) { -- info->cdl_format = 1; -- vtoc_volume_label_set_label(vlabel, "VOL1"); -- vtoc_volume_label_set_key(vlabel, "VOL1"); -- vtoc_set_cchhb(&vlabel->vtoc, 0x0000, 0x0001, 0x01); -- } else { -- vtoc_volume_label_set_label(vlabel, "LNX1"); -- } -- } -- - if ((info->verbosity > 0) || !info->withoutprompt || info->testmode) - dasdfmt_print_info(info, vlabel, cylinders, heads, p); - -@@ -938,6 +954,7 @@ int main(int argc, char *argv[]) - char *hashstep_str = NULL; - - int rc, index, i; -+ unsigned int cylinders, heads; - - int max_parallel=1; - int running=0; -@@ -1193,7 +1210,10 @@ int main(int argc, char *argv[]) - if (check_param(str, ERR_LENGTH, &format_params) < 0) - ERRMSG_EXIT(EXIT_MISUSE, "%s: %s\n", prog_name, str); - -- do_format_dasd(&info, &format_params, &vlabel); -+ set_geo(&info, &cylinders, &heads); -+ set_label(&info, &vlabel, &format_params, cylinders); -+ do_format_dasd(&info, &vlabel, &format_params, -+ cylinders, heads); - - if (close(filedes) != 0) - ERRMSG("%s: error during close: %s\ncontinuing...\n", diff --git a/s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch b/s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch deleted file mode 100644 index b078fcf..0000000 --- a/s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch +++ /dev/null @@ -1,93 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: - -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Make the IOCTL BLKSSZGET reusable - - The IOCTL BLKSSZGET is used to get blocksize information of a device. - Since it is used several times already and could be used for new - features as well, move the call to a separate function and make it - reusable. - - Signed-off-by: Jan Höppner - Signed-off-by: Stefan Haberland - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.c | 24 ++++++++++++++++-------- - 1 file changed, 16 insertions(+), 8 deletions(-) - ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -252,6 +252,17 @@ static void get_device_info(dasdfmt_info - } - - /* -+ * Retrieve blocksize of device -+ */ -+static void get_blocksize(unsigned int *blksize) -+{ -+ if (ioctl(filedes, BLKSSZGET, blksize) != 0) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to get the blocksize " -+ "of the device failed (%s).\n", prog_name, -+ strerror(errno)); -+} -+ -+/* - * check for disk type and set some variables (e.g. usage count) - */ - static void check_disk(dasdfmt_info_t *info) -@@ -510,7 +521,7 @@ static void dasdfmt_print_info(dasdfmt_i - */ - static int dasdfmt_get_volser(dasdfmt_info_t *info, char *volser) - { -- int blksize; -+ unsigned int blksize; - int f; - volume_label_t vlabel; - -@@ -519,9 +530,7 @@ static int dasdfmt_get_volser(dasdfmt_in - ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n", - prog_name, info->devname, strerror(errno)); - -- if (ioctl(filedes, BLKSSZGET, &blksize) != 0) -- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET " -- "failed (%s).\n", prog_name, strerror(errno)); -+ get_blocksize(&blksize); - - if (close(f) != 0) - ERRMSG("%s: error during close: %s\ncontinuing...\n", -@@ -551,7 +560,8 @@ static void dasdfmt_write_labels(dasdfmt - format4_label_t f4; - format5_label_t f5; - format7_label_t f7; -- int rc, blksize; -+ unsigned int blksize; -+ int rc; - void *ipl1_record, *ipl2_record; - int ipl1_record_len, ipl2_record_len; - -@@ -559,9 +569,7 @@ static void dasdfmt_write_labels(dasdfmt - if (info->verbosity > 0) - printf("Retrieving dasd information... "); - -- if (ioctl(filedes, BLKSSZGET, &blksize) != 0) -- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET " -- "failed (%s).\n", prog_name, strerror(errno)); -+ get_blocksize(&blksize); - - /* - * Don't rely on the cylinders returned by HDIO_GETGEO, they might be diff --git a/s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch b/s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch deleted file mode 100644 index 555f4d2..0000000 --- a/s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch +++ /dev/null @@ -1,555 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: - -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Add quick format support - - On occasion, a DASD device might have been formatted earlier and could - potentially be re-initialized very easily. For device initalization it - is necessary to write disk information (i.e. volume label (CDL or LDL) - and VTOC) to the first two tracks. Currently you'd need to format the - entire disk, which can take a long time and is totally unnecessary. - - Therefore, add a quick format mode which formats only the first two - tracks and fills them with data accordingly. - Before any formatting is done, several checks regarding the - expected device format are performed. - - The mode can be specified with the new command line switch -M (--mode) - . Where 'mode' can be either 'full' (default) or 'quick'. - - Document the switch -M (--mode) and its options full and quick in the - man page. - - Signed-off-by: Jan Höppner - Signed-off-by: Stefan Haberland - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.8 | 15 ++ - dasdfmt/dasdfmt.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- - dasdfmt/dasdfmt.h | 51 +++++++++ - 3 files changed, 344 insertions(+), 12 deletions(-) - ---- a/dasdfmt/dasdfmt.8 -+++ b/dasdfmt/dasdfmt.8 -@@ -67,7 +67,7 @@ Print version number and exit. - - .TP - \fB-F\fR or \fB--force\fR --Formats the device without checking, if the device is in use. -+Formats the device without performing sanity checking. - - .TP - \fB-C\fR or \fB--check_host_count\fR -@@ -108,6 +108,19 @@ The value will be at least as big as the - .br - - .TP -+\fB-M\fR \fImode\fR or \fB--mode\fR=\fImode\fR -+Specify the \fImode\fR to be used to format the device. Valid modes are: -+.RS -+.IP full -+Format the entire disk with the specified blocksize. (default) -+.IP quick -+Format the first two tracks and write label and partition information. Only use -+this option if you are sure that the target DASD already contains a regular -+format with the specified blocksize. A blocksize can optionally be specified -+using \fB-b\fR (\fB--blocksize\fR). -+.RE -+ -+.TP - \fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR - Number of cylinders to be processed in one formatting step. - The value must be an integer in the range 1 - 255. ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -30,6 +30,7 @@ static const char copyright_notice[] = " - static int filedes; - static int disk_disabled; - static format_data_t format_params; -+static format_mode_t mode; - char *prog_name; - volatile sig_atomic_t program_interrupt_in_progress; - int reqsize; -@@ -53,6 +54,7 @@ static void exit_usage(int exitcode) - " [-b | --blocksize=]\n" - " [-d | --disk_layout=]\n" - " [-r | --requestsize=]\n" -+ " [-M | --mode=]\n" - " \n\n", prog_name); - - printf(" -t or --test means testmode\n" -@@ -65,7 +67,7 @@ static void exit_usage(int exitcode) - " -r x or --requestsize=x means use x cylinders in one " - "format step\n" - " -v means verbose mode\n" -- " -F means don't check if the device is in use\n" -+ " -F means format without performing sanity checking\n" - " -k means keep volume serial\n" - " -C or --check_host_count means force dasdfmt to check\n" - " the host access open count to ensure the device\n" -@@ -79,7 +81,10 @@ static void exit_usage(int exitcode) - " is either\n" - " 'cdl' for compatible disk layout (default) or\n" - " 'ldl' for linux disk layout\n" -- " device node of the device to format\n"); -+ " device node of the device to format\n" -+ " is either\n" -+ " 'full' to fully format the device (default)\n" -+ " 'quick' to format only the first two tracks\n"); - exit(exitcode); - } - -@@ -102,6 +107,131 @@ static int reread_partition_table(void) - } - - /* -+ * Helper function for recs_per_track. -+ */ -+static inline unsigned int ceil_quot(unsigned int d1, unsigned int d2) -+{ -+ return (d1 + (d2 - 1)) / d2; -+} -+ -+/* -+ * Calculate records per track depending on the device characteristics. -+ */ -+static unsigned int recs_per_track(struct dasd_eckd_characteristics *rdc, -+ unsigned int kl, unsigned int dl) -+{ -+ int dn, kn; -+ -+ switch (rdc->dev_type) { -+ case 0x3380: -+ if (kl) -+ return 1499 / (15 + 7 + ceil_quot(kl + 12, 32) + -+ ceil_quot(dl + 12, 32)); -+ else -+ return 1499 / (15 + ceil_quot(dl + 12, 32)); -+ case 0x3390: -+ dn = ceil_quot(dl + 6, 232) + 1; -+ if (kl) { -+ kn = ceil_quot(kl + 6, 232) + 1; -+ return 1729 / (10 + 9 + ceil_quot(kl + 6 * kn, 34) + -+ 9 + ceil_quot(dl + 6 * dn, 34)); -+ } else -+ return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34)); -+ case 0x9345: -+ dn = ceil_quot(dl + 6, 232) + 1; -+ if (kl) { -+ kn = ceil_quot(kl + 6, 232) + 1; -+ return 1420 / (18 + 7 + ceil_quot(kl + 6 * kn, 34) + -+ ceil_quot(dl + 6 * dn, 34)); -+ } else -+ return 1420 / (18 + 7 + ceil_quot(dl + 6 * dn, 34)); -+ } -+ return 0; -+} -+ -+/* -+ * Evaluate errors recognized by format checks and print appropriate error -+ * messages depending on the content of cdata. -+ */ -+static void evaluate_format_error(dasdfmt_info_t *info, format_check_t *cdata, -+ unsigned int heads) -+{ -+ struct dasd_eckd_characteristics *rdc; -+ /* Special blocksize values of the first 3 records of trk 0 of cyl 0 */ -+ const int blksizes_trk0[] = { 24, 144, 80 }; -+ /* Special blocksize value of trk 1 cyl 0 */ -+ const int blksize_trk1 = 96; -+ unsigned int cyl; -+ unsigned int head; -+ unsigned int rpt; -+ unsigned int kl = 0; -+ int blksize = cdata->expect.blksize; -+ -+ /* -+ * Reading record zero will never happen. If the record in error is 0 -+ * nonetheless, the device is not formatted at all! -+ */ -+ if (cdata->rec == 0) { -+ ERRMSG("WARNING: The specified device is not " -+ "formatted at all.\n"); -+ return; -+ } -+ -+ cyl = cdata->unit / heads; -+ head = cyl >> 16; -+ head <<= 4; -+ head |= cdata->unit % heads; -+ -+ /* -+ * Set special expected values for the first 3 records of trk 0 of cyl 0 -+ * and trk 1 of cyl 0 when checking a CDL formatted device. -+ */ -+ if ((cdata->expect.intensity & DASD_FMT_INT_COMPAT) && -+ cyl == 0 && head == 0 && cdata->rec < 4) { -+ kl = 4; -+ blksize = blksizes_trk0[cdata->rec - 1]; -+ } -+ if ((cdata->expect.intensity & DASD_FMT_INT_COMPAT) && -+ cyl == 0 && head == 1) { -+ kl = 44; -+ blksize = blksize_trk1; -+ } -+ -+ rdc = (struct dasd_eckd_characteristics *) -+ &info->dasd_info.characteristics; -+ -+ rpt = recs_per_track(rdc, kl, cdata->expect.blksize); -+ -+ ERRMSG("WARNING: The specified device is not formatted as expected.\n"); -+ switch (cdata->result) { -+ case DASD_FMT_ERR_TOO_FEW_RECORDS: -+ ERRMSG("Too few records (found %d, expected %d) " -+ "at cyl: %d trk: %d rec: %d.\n", -+ cdata->num_records, rpt, cyl, head, cdata->rec); -+ break; -+ case DASD_FMT_ERR_TOO_MANY_RECORDS: -+ ERRMSG("Too many records (found %d, expected %d) " -+ "at cyl: %d trk: %d rec: %d.\n", -+ cdata->num_records, rpt, cyl, head, cdata->rec); -+ break; -+ case DASD_FMT_ERR_BLKSIZE: -+ ERRMSG("Invalid blocksize (found %d, expected %d) " -+ "at cyl: %d trk: %d rec: %d.\n", -+ cdata->blksize, blksize, cyl, head, cdata->rec); -+ break; -+ case DASD_FMT_ERR_RECORD_ID: -+ ERRMSG("Invalid record ID at cyl: %d trk: %d rec: %d.\n", -+ cyl, head, cdata->rec); -+ break; -+ case DASD_FMT_ERR_KEY_LENGTH: -+ ERRMSG("Invalid key length (found %d, expected %d) " -+ "at cyl: %d trk: %d rec: %d.\n", -+ cdata->key_length, kl, cyl, head, cdata->rec); -+ break; -+ } -+} -+ -+/* - * signal handler: - * enables the disk again in case of SIGTERM, SIGINT and SIGQUIT - */ -@@ -263,6 +393,25 @@ static void get_blocksize(unsigned int * - } - - /* -+ * Check whether a specified blocksize matches the blocksize of the device -+ */ -+static void check_blocksize(dasdfmt_info_t *info, unsigned int blksize) -+{ -+ unsigned int dev_blksize; -+ -+ if (!info->blksize_specified || -+ info->dasd_info.format == DASD_FORMAT_NONE) -+ return; -+ -+ get_blocksize(&dev_blksize); -+ if (dev_blksize != blksize) { -+ ERRMSG_EXIT(EXIT_FAILURE, "WARNING: Device is formatted with a " -+ "different blocksize (%d).\nUse --mode=full to " -+ "perform a clean format.\n", dev_blksize); -+ } -+} -+ -+/* - * check for disk type and set some variables (e.g. usage count) - */ - static void check_disk(dasdfmt_info_t *info) -@@ -449,6 +598,35 @@ static void set_label(dasdfmt_info_t *in - } - - /* -+ * This function checks whether a range of tracks is in regular format -+ * with the specified block size. -+ */ -+static format_check_t check_track_format(format_data_t *p) -+{ -+ format_check_t cdata = { -+ .expect = { -+ .blksize = p->blksize, -+ .intensity = p->intensity, -+ .start_unit = p->start_unit, -+ .stop_unit = p->stop_unit -+ }, 0 -+ }; -+ -+ if (ioctl(filedes, BIODASDCHECKFMT, &cdata)) { -+ if (errno == ENOTTY) { -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Missing kernel support " -+ "for format checking (--force to " -+ "override)\n", prog_name); -+ } -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n", -+ prog_name, strerror(errno)); -+ } -+ -+ return cdata; -+} -+ -+ -+/* - * ask the user to specify a blocksize - */ - static format_data_t ask_user_for_blksize(format_data_t params) -@@ -511,6 +689,8 @@ static void dasdfmt_print_info(dasdfmt_i - printf(" Compatible Disk Layout : %s\n", - (p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no"); - printf(" Blocksize : %d\n", p->blksize); -+ printf(" Mode : %s\n", -+ (mode == FULL) ? "Full" : "Quick"); - - if (info->testmode) - printf("Test mode active, omitting ioctl.\n"); -@@ -869,6 +1049,62 @@ static void dasdfmt_prepare_and_format(d - disk_disabled = 0; - } - -+/* -+ * This function will only format the first two tracks of a DASD. -+ * The rest of the DASD is untouched and left as is. -+ */ -+static void dasdfmt_quick_format(dasdfmt_info_t *info, unsigned int cylinders, -+ unsigned int heads, format_data_t *p) -+{ -+ format_check_t cdata = { .expect = {0}, 0 }; -+ format_data_t tmp = *p; -+ -+ if (info->force) { -+ printf("Skipping format check due to --force.\n"); -+ } else { -+ check_blocksize(info, p->blksize); -+ -+ printf("Checking the format of selected tracks...\n"); -+ -+ /* Check device format on the first and last 3 regular tracks */ -+ tmp.start_unit = 2; -+ tmp.stop_unit = 4; -+ cdata = check_track_format(&tmp); -+ if (!cdata.result) { -+ tmp.start_unit = (cylinders * heads) - 3; -+ tmp.stop_unit = (cylinders * heads) - 1; -+ cdata = check_track_format(&tmp); -+ } -+ if (cdata.result) { -+ evaluate_format_error(info, &cdata, heads); -+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform " -+ "a clean format.\n"); -+ } else { -+ printf("Done. Disk seems fine.\n"); -+ } -+ } -+ -+ if (!((info->withoutprompt) && (info->verbosity < 1))) -+ printf("Formatting the first two tracks of the device.\n"); -+ -+ /* Disable the device before we do anything */ -+ if (ioctl(filedes, BIODASDDISABLE, p)) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to disable the device " -+ "failed. (%s)\n", prog_name, strerror(errno)); -+ disk_disabled = 1; -+ -+ /* Now do the actual formatting of our first two tracks */ -+ if (ioctl(filedes, BIODASDFMT, p)) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to format the device " -+ "failed. (%s)\n", prog_name, strerror(errno)); -+ -+ /* Re-Enable the device so that we can continue working with it */ -+ if (ioctl(filedes, BIODASDENABLE, p)) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to enable the device " -+ "failed. (%s)\n", prog_name, strerror(errno)); -+ disk_disabled = 0; -+} -+ - static void do_format_dasd(dasdfmt_info_t *info, volume_label_t *vlabel, - format_data_t *p, unsigned int cylinders, - unsigned int heads) -@@ -877,7 +1113,15 @@ static void do_format_dasd(dasdfmt_info_ - int count; - - p->start_unit = 0; -- p->stop_unit = (cylinders * heads) - 1; -+ -+ switch (mode) { -+ case FULL: /* all tracks */ -+ p->stop_unit = (cylinders * heads) - 1; -+ break; -+ case QUICK: /* just the first two */ -+ p->stop_unit = 1; -+ break; -+ } - - if ((info->verbosity > 0) || !info->withoutprompt || info->testmode) - dasdfmt_print_info(info, vlabel, cylinders, heads, p); -@@ -919,11 +1163,17 @@ static void do_format_dasd(dasdfmt_info_ - } - } - -- if (!((info->withoutprompt) && (info->verbosity < 1))) -- printf("Formatting the device. This may take a " -- "while (get yourself a coffee).\n"); -- -- dasdfmt_prepare_and_format(info, cylinders, heads, p); -+ switch (mode) { -+ case FULL: -+ if (!((info->withoutprompt) && (info->verbosity < 1))) -+ printf("Formatting the device. This may take a " -+ "while (get yourself a coffee).\n"); -+ dasdfmt_prepare_and_format(info, cylinders, heads, p); -+ break; -+ case QUICK: -+ dasdfmt_quick_format(info, cylinders, heads, p); -+ break; -+ } - - if (!info->yast_mode) - printf("Finished formatting the device.\n"); -@@ -981,6 +1231,8 @@ int main(int argc, char *argv[]) - format_params.blksize = DEFAULT_BLOCKSIZE; - format_params.intensity = DASD_FMT_INT_COMPAT; - -+ mode = FULL; -+ - /*************** parse parameters **********************/ - - while (1) { -@@ -1082,6 +1334,18 @@ int main(int argc, char *argv[]) - case 'C': - info.force_host = 1; - break; -+ case 'M': -+ if (strcasecmp(optarg, "full") == 0) -+ mode = FULL; -+ else if (strcasecmp(optarg, "quick") == 0) -+ mode = QUICK; -+ else -+ ERRMSG_EXIT(EXIT_FAILURE, -+ "%s: The specified mode '%s' is " -+ "invalid. Consult the man page for " -+ "more information.\n", -+ prog_name, optarg); -+ break; - case -1: - /* End of options string - start of devices list */ - info.device_id = optind; -@@ -1194,8 +1458,14 @@ int main(int argc, char *argv[]) - - get_device_info(&info); - -- if (!info.blksize_specified) -- format_params = ask_user_for_blksize(format_params); -+ /* Either let the user specify the blksize or get it from the kernel */ -+ if (!info.blksize_specified) { -+ if (!(mode == FULL || -+ info.dasd_info.format == DASD_FORMAT_NONE)) -+ get_blocksize(&format_params.blksize); -+ else -+ format_params = ask_user_for_blksize(format_params); -+ } - - if (info.keep_volser) { - if (format_params.intensity == 0x00) { ---- a/dasdfmt/dasdfmt.h -+++ b/dasdfmt/dasdfmt.h -@@ -143,6 +143,14 @@ struct dasd_eckd_characteristics { - unsigned int long_no_cyl; - } __attribute__ ((packed)); - -+/* -+ * Represents possible format modes that can be specified when formatting -+ * a DASD. -+ */ -+typedef enum format_mode_t { -+ FULL, /* default mode */ -+ QUICK, /* format only the first 2 tracks */ -+} format_mode_t; - - /* - * struct format_data_t -@@ -168,6 +176,43 @@ typedef struct format_data_t { - #define DASD_FMT_INT_COMPAT 8 /* use OS/390 compatible disk layout */ - #define DASD_FMT_INT_FMT_NOR0 16 /* remove permission to write record zero */ - -+/* -+ * struct format_check_t -+ * represents all data necessary to evaluate the format of -+ * different tracks of a dasd -+ */ -+typedef struct format_check_t { -+ /* Input */ -+ struct format_data_t expect; -+ -+ /* Output */ -+ unsigned int result; /* Error indication (DASD_FMT_ERR_*) */ -+ unsigned int unit; /* Track that is in error */ -+ unsigned int rec; /* Record that is in error */ -+ unsigned int num_records; /* Records in the track in error */ -+ unsigned int blksize; /* Block-size of first record in error */ -+ unsigned int key_length; /* Key length of first record in error */ -+} format_check_t; -+ -+/* -+ * values to be used in format_check_t for indicating -+ * possible format errors -+ */ -+#define DASD_FMT_ERR_TOO_FEW_RECORDS 1 -+#define DASD_FMT_ERR_TOO_MANY_RECORDS 2 -+#define DASD_FMT_ERR_BLKSIZE 3 -+#define DASD_FMT_ERR_RECORD_ID 4 -+#define DASD_FMT_ERR_KEY_LENGTH 5 -+ -+/* -+ * values to be used for dasd_information2_t.format -+ * 0x00: NOT formatted -+ * 0x01: Linux disc layout -+ * 0x02: Common disc layout -+ */ -+#define DASD_FORMAT_NONE 0 -+#define DASD_FORMAT_LDL 1 -+#define DASD_FORMAT_CDL 2 - - /* Disable the volume (for Linux) */ - #define BIODASDDISABLE _IO(DASD_IOCTL_LETTER,0) -@@ -180,6 +225,9 @@ typedef struct format_data_t { - /* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */ - #define BIODASDFMT _IOW(DASD_IOCTL_LETTER,1,format_data_t) - -+/* Check device format according to format_data_t */ -+#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t) -+ - /**************************************************************************** - * SECTION: Further IOCTL Definitions (see fs.h and hdreq.h ) * - ****************************************************************************/ -@@ -225,7 +273,7 @@ typedef struct format_data_t { - if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ - "is in invalid format\n",prog_name);} - --#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpQLtyvVFkCYP:" -+#define dasdfmt_getopt_string "b:n:l:f:d:m:M:r:hpQLtyvVFkCYP:" - - static struct option dasdfmt_getopt_long_options[]= - { -@@ -247,6 +295,7 @@ static struct option dasdfmt_getopt_long - { "keep_volser", 0, 0, 'k'}, - { "norecordzero", 0, 0, 'z'}, - { "check_host_count", 0, 0, 'C'}, -+ { "mode", 1, 0, 'M'}, - {0, 0, 0, 0} - }; - diff --git a/s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch b/s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch deleted file mode 100644 index 0063641..0000000 --- a/s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch +++ /dev/null @@ -1,279 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: - -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Make progress output reusable and add ETR - - The progress indicator (in form of a progressbar, hashmarks or - percentages) is created within the formatting loop. - - Put the drawing of the progress into a separate function to make it - reusable. Clean up the formatting loop while at it and make it - more readable. Also, add the estimated time remaining to the output. - - Signed-off-by: Jan Höppner - Signed-off-by: Stefan Haberland - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.c | 198 +++++++++++++++++++++++++++++++++++++----------------- - 1 file changed, 138 insertions(+), 60 deletions(-) - ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -11,6 +11,7 @@ - - #include - #include -+#include - - #include "zt_common.h" - #include "dasdfmt.h" -@@ -20,6 +21,8 @@ - #include - - #define BUSIDSIZE 8 -+#define SEC_PER_DAY (60 * 60 * 24) -+#define SEC_PER_HOUR (60 * 60) - - /* Full tool name */ - static const char tool_name[] = "dasdfmt: zSeries DASD format program"; -@@ -88,6 +91,120 @@ static void exit_usage(int exitcode) - exit(exitcode); - } - -+/* -+ * Helper function to calculate the days, hours, minutes, and seconds -+ * for a given timestamp in seconds -+ */ -+static void calc_time(time_t time, int *d, int *h, int *m, int *s) -+{ -+ *d = time / SEC_PER_DAY; -+ time %= SEC_PER_DAY; -+ *h = time / SEC_PER_HOUR; -+ time %= SEC_PER_HOUR; -+ *m = time / 60; -+ *s = time % 60; -+} -+ -+/* -+ * This function calculates and prints the estimated time remaining. -+ */ -+static void print_etr(int p_new, int started) -+{ -+ static struct timeval start; -+ struct timeval now; -+ time_t time_elapsed; -+ time_t time_end; -+ int d, h, m, s; -+ static int p_init; -+ int p; -+ -+ if (!started) { -+ gettimeofday(&start, NULL); -+ p_init = p_new; -+ } -+ gettimeofday(&now, NULL); -+ time_elapsed = now.tv_sec - start.tv_sec; -+ -+ /* -+ * We might start somewhere in the middle with an initial percentage -+ * value of i.e. 60%. Therefore we need to calculate the relative -+ * percentage of p_new within that remaining range (100 - 60) in order -+ * to correctly estimate the remaining time. -+ */ -+ if (p_init == 100) -+ p = p_init; -+ else -+ p = 100 * (p_new - p_init) / (100 - p_init); -+ -+ if (p == 0) -+ time_end = time_elapsed; -+ else -+ time_end = time_elapsed * (100 - p) / p; -+ -+ /* Calculate days, hours, minutes, and seconds */ -+ calc_time(time_end, &d, &h, &m, &s); -+ if (p_new == 100) -+ calc_time(time_elapsed, &d, &h, &m, &s); -+ -+ /* Avoid printing leading zeros */ -+ if (d > 0) -+ printf(" [%dd %dh %dm %ds%-4s", d, h, m, s, "]"); -+ else if (h > 0) -+ printf(" [%dh %dm %ds%-7s", h, m, s, "]"); -+ else if (m > 0) -+ printf(" [%dm %ds%-6s", m, s, "]"); -+ else if (s > 0 || p > 50) -+ printf(" [%ds%-5s", s, "]"); -+ else -+ printf(" [--%-1s", "]"); -+} -+ -+/* -+ * Draw the progress indicator depending on what command line argument is set. -+ * This can either be a progressbar, hashmarks, or percentage. -+ */ -+static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders) -+{ -+ static int hashcount; -+ static int started; -+ static int p_old; -+ int p_new = 0; -+ int barlength; -+ int i; -+ -+ if (info->print_progressbar) { -+ printf("cyl %7d of %7d |", cyl, cylinders); -+ p_new = cyl * 100 / cylinders; -+ if (p_new != p_old || !started) { -+ /* percent value has changed */ -+ p_old = p_new; -+ barlength = cyl * 33 / cylinders; -+ for (i = 1; i <= barlength; i++) -+ printf("#"); -+ for (i = barlength + 1; i <= 33; i++) -+ printf("-"); -+ printf("|%3d%%", p_new); -+ print_etr(p_new, started); -+ started = 1; -+ } -+ printf("\r"); -+ fflush(stdout); -+ } -+ -+ if (info->print_hashmarks && -+ (cyl / info->hashstep - hashcount) != 0) { -+ printf("%d|", info->procnum); -+ fflush(stdout); -+ hashcount++; -+ } -+ -+ if (info->print_percentage) { -+ printf("cyl %7d of %7d |%3d%%\n", cyl, cylinders, -+ cyl * 100 / cylinders); -+ fflush(stdout); -+ } -+} -+ - static int reread_partition_table(void) - { - int i = 0; -@@ -906,9 +1023,10 @@ static void dasdfmt_write_labels(dasdfmt - static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders, - unsigned int heads, format_data_t *format_params) - { -- format_data_t format_step; -- int j, cyl, tmp, p1, p2, hashcount = 0; -- unsigned int k; -+ unsigned int step_value; -+ unsigned long cur_trk; -+ format_data_t step; -+ int cyl = 0; - - if (info->print_hashmarks) { - if (info->hashstep < reqsize) -@@ -923,73 +1041,33 @@ static void dasdfmt_format(dasdfmt_info_ - info->hashstep); - } - -- format_step.blksize = format_params->blksize; -- format_step.intensity = format_params->intensity; -- -- k = 0; -- cyl = 1; -- if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode) -- printf("\n"); -- -- while (1) { -- p1 = -1; -- p2 = 0; -- if (k + heads * reqsize >= format_params->stop_unit) -- reqsize = 1; -- format_step.start_unit = k; -- format_step.stop_unit = k + reqsize * heads - 1; -+ step = *format_params; -+ cur_trk = format_params->start_unit; - -- if (cyl == 1) -- format_step.start_unit += 1; -+ while (cur_trk < format_params->stop_unit) { -+ step_value = reqsize * heads - (cur_trk % heads); -+ step.start_unit = cur_trk; -+ if (cur_trk + reqsize * heads >= format_params->stop_unit) -+ step.stop_unit = format_params->stop_unit; -+ else -+ step.stop_unit = cur_trk + step_value - 1; - -- if (ioctl(filedes, BIODASDFMT, &format_step) != 0) -+ if (ioctl(filedes, BIODASDFMT, &step) != 0) - ERRMSG_EXIT(EXIT_FAILURE, "%s: (format cylinder) IOCTL " - "BIODASDFMT failed. (%s)\n", - prog_name, strerror(errno)); - -- if (info->print_progressbar) { -- printf("cyl %7d of %7d |", cyl, cylinders); -- p2 = p1; -- p1 = cyl * 100 / cylinders; -- if (p1 != p2) { -- /* percent value has changed */ -- tmp = cyl * 50 / cylinders; -- for (j = 1; j <= tmp; j++) -- printf("#"); -- for (j = tmp + 1; j <= 50; j++) -- printf("-"); -- printf("|%3d%%", p1); -- } -- printf("\r"); -- fflush(stdout); -- } -- -- if (info->print_hashmarks) -- if ((cyl / info->hashstep - hashcount) != 0) { -- printf("%d|",info->procnum); -- fflush(stdout); -- hashcount++; -- } -- -- if (info->print_percentage) { -- printf("cyl %7d of %7d |%3d%%\n", cyl, cylinders, -- cyl*100/cylinders); -- fflush(stdout); -- } -+ cyl = cur_trk / heads + 1; -+ draw_progress(info, cyl, cylinders); - -- if (k % heads == 0) { -- k += reqsize * heads; -- cyl += reqsize; -- } else { -- k += format_params->stop_unit % heads; -- } -- -- if (k > format_params->stop_unit) -- break; -+ cur_trk += step_value; - } -+ /* We're done, draw the 100% mark */ -+ cyl = step.stop_unit / heads + 1; -+ draw_progress(info, cyl, cylinders); - - if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode) -- printf("\n\n"); -+ printf("\n"); - } - - static void dasdfmt_prepare_and_format(dasdfmt_info_t *info, diff --git a/s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch b/s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch deleted file mode 100644 index d06bab5..0000000 --- a/s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch +++ /dev/null @@ -1,453 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: - -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Add command line argument --check - - Provide a function to check a DASD volume for correct formatting. This - can be useful in cases where only a few tracks of a volume are - incorrectly formatted. - - All tracks on the device are checked. In an error case, the check - process is stopped and appropriate messages are displayed. - - The --check command line argument can be combined with either -P, - -p or -m to display progress on the console. - - Signed-off-by: Jan Höppner - Signed-off-by: Stefan Haberland - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.8 | 5 + - dasdfmt/dasdfmt.c | 244 ++++++++++++++++++++++++++++++++++++++++-------------- - dasdfmt/dasdfmt.h | 4 - 3 files changed, 190 insertions(+), 63 deletions(-) - ---- a/dasdfmt/dasdfmt.8 -+++ b/dasdfmt/dasdfmt.8 -@@ -121,6 +121,11 @@ using \fB-b\fR (\fB--blocksize\fR). - .RE - - .TP -+\fB--check\fR -+Perform a complete format check on a DASD volume. A blocksize can be specified -+with \fB-b\fR (\fB--blocksize\fR). -+ -+.TP - \fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR - Number of cylinders to be processed in one formatting step. - The value must be an integer in the range 1 - 255. ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -76,7 +76,8 @@ static void exit_usage(int exitcode) - " the host access open count to ensure the device\n" - " is not online on another operating system instance\n" - " --norecordzero prevent storage server from modifying" -- " record 0\n\n" -+ " record 0\n" -+ " --check perform complete format check on device\n\n" - " is the volume identifier, which is converted\n" - " to EBCDIC and written to disk.\n" - " (6 characters, e.g. LNX001\n" -@@ -163,7 +164,8 @@ static void print_etr(int p_new, int sta - * Draw the progress indicator depending on what command line argument is set. - * This can either be a progressbar, hashmarks, or percentage. - */ --static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders) -+static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders, -+ int aborted) - { - static int hashcount; - static int started; -@@ -175,7 +177,7 @@ static void draw_progress(dasdfmt_info_t - if (info->print_progressbar) { - printf("cyl %7d of %7d |", cyl, cylinders); - p_new = cyl * 100 / cylinders; -- if (p_new != p_old || !started) { -+ if (p_new != p_old || !started || aborted) { - /* percent value has changed */ - p_old = p_new; - barlength = cyl * 33 / cylinders; -@@ -184,6 +186,8 @@ static void draw_progress(dasdfmt_info_t - for (i = barlength + 1; i <= 33; i++) - printf("-"); - printf("|%3d%%", p_new); -+ if (aborted) -+ p_new = 100; - print_etr(p_new, started); - started = 1; - } -@@ -284,11 +288,17 @@ static void evaluate_format_error(dasdfm - unsigned int kl = 0; - int blksize = cdata->expect.blksize; - -+ if (info->print_progressbar || info->print_hashmarks) -+ printf("\n"); -+ - /* -- * Reading record zero will never happen. If the record in error is 0 -- * nonetheless, the device is not formatted at all! -+ * If mode is not QUICK and a device format couldn't be determined, the -+ * device is considered not formatted. -+ * Also, reading record zero will never happen. If the record in error -+ * is 0 nonetheless, the device is not formatted at all as well! - */ -- if (cdata->rec == 0) { -+ if ((info->dasd_info.format == DASD_FORMAT_NONE && mode != QUICK) || -+ cdata->rec == 0) { - ERRMSG("WARNING: The specified device is not " - "formatted at all.\n"); - return; -@@ -529,6 +539,35 @@ static void check_blocksize(dasdfmt_info - } - - /* -+ * Check whether a specified layout matches the layout -+ * a device is formatted with. -+ */ -+static void check_layout(dasdfmt_info_t *info, unsigned int intensity) -+{ -+ char layout[4]; -+ -+ if (!info->layout_specified || -+ info->dasd_info.format == DASD_FORMAT_NONE) -+ return; -+ -+ if ((intensity & DASD_FMT_INT_COMPAT) && -+ info->dasd_info.format == DASD_FORMAT_CDL) -+ return; -+ -+ if (!(intensity & DASD_FMT_INT_COMPAT) && -+ info->dasd_info.format == DASD_FORMAT_LDL) -+ return; -+ -+ if (info->dasd_info.format == DASD_FORMAT_CDL) -+ sprintf(layout, "CDL"); -+ if (info->dasd_info.format == DASD_FORMAT_LDL) -+ sprintf(layout, "LDL"); -+ -+ ERRMSG_EXIT(EXIT_FAILURE, "WARNING: Device is formatted with a " -+ "different layout (%s).\n", layout); -+} -+ -+/* - * check for disk type and set some variables (e.g. usage count) - */ - static void check_disk(dasdfmt_info_t *info) -@@ -715,10 +754,29 @@ static void set_label(dasdfmt_info_t *in - } - - /* -+ * Check whether hashsteps are within the correct interval. -+ */ -+static void check_hashmarks(dasdfmt_info_t *info) -+{ -+ if (info->print_hashmarks) { -+ if (info->hashstep < reqsize) -+ info->hashstep = reqsize; -+ if ((info->hashstep < 1) || (info->hashstep > 1000)) { -+ printf("Hashmark increment is not in range <1,1000>, " -+ "using the default.\n"); -+ info->hashstep = 10; -+ } -+ -+ printf("Printing hashmark every %d cylinders.\n", -+ info->hashstep); -+ } -+} -+ -+/* - * This function checks whether a range of tracks is in regular format - * with the specified block size. - */ --static format_check_t check_track_format(format_data_t *p) -+static format_check_t check_track_format(dasdfmt_info_t *info, format_data_t *p) - { - format_check_t cdata = { - .expect = { -@@ -731,9 +789,11 @@ static format_check_t check_track_format - - if (ioctl(filedes, BIODASDCHECKFMT, &cdata)) { - if (errno == ENOTTY) { -- ERRMSG_EXIT(EXIT_FAILURE, "%s: Missing kernel support " -- "for format checking (--force to " -- "override)\n", prog_name); -+ ERRMSG("%s: Missing kernel support for format checking", -+ prog_name); -+ if (!info->check) -+ ERRMSG(" (--force to override)"); -+ ERRMSG_EXIT(EXIT_FAILURE, ".\n"); - } - ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n", - prog_name, strerror(errno)); -@@ -742,6 +802,97 @@ static format_check_t check_track_format - return cdata; - } - -+/* -+ * Either do the actual format or check depending on the check-value. -+ */ -+static int process_tracks(dasdfmt_info_t *info, unsigned int cylinders, -+ unsigned int heads, format_data_t *format_params) -+{ -+ format_check_t cdata = { .expect = {0}, 0}; -+ format_data_t step = *format_params; -+ unsigned long step_value; -+ unsigned long cur_trk; -+ int cyl = 0; -+ -+ check_hashmarks(info); -+ -+ cur_trk = format_params->start_unit; -+ -+ while (cur_trk < format_params->stop_unit) { -+ step_value = reqsize * heads - (cur_trk % heads); -+ step.start_unit = cur_trk; -+ if (cur_trk + heads * reqsize >= format_params->stop_unit) -+ step.stop_unit = format_params->stop_unit; -+ else -+ step.stop_unit = cur_trk + step_value - 1; -+ -+ if (info->check) { -+ cdata = check_track_format(info, &step); -+ if (cdata.result) { -+ cyl = cur_trk / heads + 1; -+ draw_progress(info, cyl, cylinders, 1); -+ evaluate_format_error(info, &cdata, heads); -+ break; -+ } -+ } else { -+ if (ioctl(filedes, BIODASDFMT, &step) != 0) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl call " -+ "to format tracks failed. (%s)\n", -+ prog_name, strerror(errno)); -+ } -+ -+ cyl = cur_trk / heads + 1; -+ draw_progress(info, cyl, cylinders, 0); -+ -+ cur_trk += step_value; -+ } -+ /* We're done, draw the 100% mark */ -+ if (!cdata.result) { -+ cyl = step.stop_unit / heads + 1; -+ draw_progress(info, cyl, cylinders, 0); -+ printf("\n"); -+ } -+ -+ return cdata.result; -+} -+ -+/* -+ * This function checks the format of the entire disk. -+ */ -+static void check_disk_format(dasdfmt_info_t *info, unsigned int cylinders, -+ unsigned int heads, format_data_t *check_params) -+{ -+ check_params->start_unit = 0; -+ check_params->stop_unit = (cylinders * heads) - 1; -+ -+ printf("Checking format of the entire disk...\n"); -+ -+ if (info->testmode) { -+ printf("Test mode active, omitting ioctl.\n"); -+ return; -+ } -+ -+ check_blocksize(info, check_params->blksize); -+ check_layout(info, check_params->intensity); -+ -+ /* -+ * If no layout was specified, set the intensity -+ * according to what the layout seems to be. -+ */ -+ if (!info->layout_specified) { -+ if (info->dasd_info.format == DASD_FORMAT_CDL) -+ check_params->intensity |= DASD_FMT_INT_COMPAT; -+ else if (info->dasd_info.format == DASD_FORMAT_LDL) -+ check_params->intensity &= ~DASD_FMT_INT_COMPAT; -+ } -+ -+ if (process_tracks(info, cylinders, heads, check_params)) { -+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform a " -+ "clean format.\n"); -+ } -+ -+ printf("Done. Disk is fine.\n"); -+} - - /* - * ask the user to specify a blocksize -@@ -1023,51 +1174,7 @@ static void dasdfmt_write_labels(dasdfmt - static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders, - unsigned int heads, format_data_t *format_params) - { -- unsigned int step_value; -- unsigned long cur_trk; -- format_data_t step; -- int cyl = 0; -- -- if (info->print_hashmarks) { -- if (info->hashstep < reqsize) -- info->hashstep = reqsize; -- if ((info->hashstep < 1) || (info->hashstep > 1000)) { -- printf("Hashmark increment is not in range <1,1000>, " -- "using the default.\n"); -- info->hashstep = 10; -- } -- -- if(!info->yast_mode) printf("Printing hashmark every %d cylinders.\n", -- info->hashstep); -- } -- -- step = *format_params; -- cur_trk = format_params->start_unit; -- -- while (cur_trk < format_params->stop_unit) { -- step_value = reqsize * heads - (cur_trk % heads); -- step.start_unit = cur_trk; -- if (cur_trk + reqsize * heads >= format_params->stop_unit) -- step.stop_unit = format_params->stop_unit; -- else -- step.stop_unit = cur_trk + step_value - 1; -- -- if (ioctl(filedes, BIODASDFMT, &step) != 0) -- ERRMSG_EXIT(EXIT_FAILURE, "%s: (format cylinder) IOCTL " -- "BIODASDFMT failed. (%s)\n", -- prog_name, strerror(errno)); -- -- cyl = cur_trk / heads + 1; -- draw_progress(info, cyl, cylinders); -- -- cur_trk += step_value; -- } -- /* We're done, draw the 100% mark */ -- cyl = step.stop_unit / heads + 1; -- draw_progress(info, cyl, cylinders); -- -- if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode) -- printf("\n"); -+ process_tracks(info, cylinders, heads, format_params); - } - - static void dasdfmt_prepare_and_format(dasdfmt_info_t *info, -@@ -1082,6 +1189,10 @@ static void dasdfmt_prepare_and_format(d - | DASD_FMT_INT_INVAL) - }; - -+ if (!((info->withoutprompt) && (info->verbosity < 1))) -+ printf("Formatting the device. This may take a while " -+ "(get yourself a coffee).\n"); -+ - if (info->verbosity > 0) - printf("Detaching the device...\n"); - -@@ -1147,11 +1258,11 @@ static void dasdfmt_quick_format(dasdfmt - /* Check device format on the first and last 3 regular tracks */ - tmp.start_unit = 2; - tmp.stop_unit = 4; -- cdata = check_track_format(&tmp); -+ cdata = check_track_format(info, &tmp); - if (!cdata.result) { - tmp.start_unit = (cylinders * heads) - 3; - tmp.stop_unit = (cylinders * heads) - 1; -- cdata = check_track_format(&tmp); -+ cdata = check_track_format(info, &tmp); - } - if (cdata.result) { - evaluate_format_error(info, &cdata, heads); -@@ -1243,9 +1354,6 @@ static void do_format_dasd(dasdfmt_info_ - - switch (mode) { - case FULL: -- if (!((info->withoutprompt) && (info->verbosity < 1))) -- printf("Formatting the device. This may take a " -- "while (get yourself a coffee).\n"); - dasdfmt_prepare_and_format(info, cylinders, heads, p); - break; - case QUICK: -@@ -1337,6 +1445,7 @@ int main(int argc, char *argv[]) - printf("%s is not a valid option!\n", optarg); - exit(1); - } -+ info.layout_specified = 1; - break; - case 'y': - info.withoutprompt = 1; -@@ -1424,6 +1533,9 @@ int main(int argc, char *argv[]) - "more information.\n", - prog_name, optarg); - break; -+ case OPT_CHECK: -+ info.check = 1; -+ break; - case -1: - /* End of options string - start of devices list */ - info.device_id = optind; -@@ -1539,7 +1651,7 @@ int main(int argc, char *argv[]) - /* Either let the user specify the blksize or get it from the kernel */ - if (!info.blksize_specified) { - if (!(mode == FULL || -- info.dasd_info.format == DASD_FORMAT_NONE)) -+ info.dasd_info.format == DASD_FORMAT_NONE) || info.check) - get_blocksize(&format_params.blksize); - else - format_params = ask_user_for_blksize(format_params); -@@ -1568,8 +1680,14 @@ int main(int argc, char *argv[]) - - set_geo(&info, &cylinders, &heads); - set_label(&info, &vlabel, &format_params, cylinders); -- do_format_dasd(&info, &vlabel, &format_params, -- cylinders, heads); -+ -+ if (info.check) { -+ check_disk_format(&info, cylinders, heads, -+ &format_params); -+ } else { -+ do_format_dasd(&info, &vlabel, &format_params, -+ cylinders, heads); -+ } - - if (close(filedes) != 0) - ERRMSG("%s: error during close: %s\ncontinuing...\n", ---- a/dasdfmt/dasdfmt.h -+++ b/dasdfmt/dasdfmt.h -@@ -273,6 +273,7 @@ typedef struct format_check_t { - if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ - "is in invalid format\n",prog_name);} - -+#define OPT_CHECK 128 - #define dasdfmt_getopt_string "b:n:l:f:d:m:M:r:hpQLtyvVFkCYP:" - - static struct option dasdfmt_getopt_long_options[]= -@@ -296,6 +297,7 @@ static struct option dasdfmt_getopt_long - { "norecordzero", 0, 0, 'z'}, - { "check_host_count", 0, 0, 'C'}, - { "mode", 1, 0, 'M'}, -+ { "check", 0, 0, OPT_CHECK}, - {0, 0, 0, 0} - }; - -@@ -328,6 +330,8 @@ typedef struct dasdfmt_info { - int device_id; - int keep_volser; - int force_host; -+ int layout_specified; -+ int check; - int yast_mode; - int procnum; - } dasdfmt_info_t; diff --git a/s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch b/s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch deleted file mode 100644 index 840edfb..0000000 --- a/s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch +++ /dev/null @@ -1,266 +0,0 @@ -Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes -From: Jan Höppner - -Summary: dasdfmt: Add new formatting modes -Description: Introduce new formatting modes 'quick' and 'expand' to either - format an earlier formatted DASD that could potentially be - re-initialized very easily or format unformatted tracks at the - end of a device that was previously extended. - - Also add the command line argument --check to provide a function - that checks a DASD volume for correct formatting. -Upstream-ID: - -Problem-ID: LS1501 - -Upstream-Description: - - dasdfmt: Add expand format mode - - If a DASD was extended, the format of the first part of the disk - can be assumed to be correct. Usually, a full format would be necessary - to ensure a fully functional disk. However, this would also format - the already formatted part resulting in the loss of the data stored in - that part. - - Add an expand mode which will search for the start of the unformatted - area and begin formatting from there. - - The mode is being specified by --mode=expand (or -M expand for short). - - Furthermore: - - Add string array for the individual modes for output purposes - - Avoid writing labels when EXPAND mode is active since they can be - assumed to be correct - - Add man page description - - -Signed-off-by: Jan Höppner ---- - dasdfmt/dasdfmt.8 | 7 +++ - dasdfmt/dasdfmt.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++----- - dasdfmt/dasdfmt.h | 5 ++ - 3 files changed, 123 insertions(+), 9 deletions(-) - ---- a/dasdfmt/dasdfmt.8 -+++ b/dasdfmt/dasdfmt.8 -@@ -118,6 +118,13 @@ Format the first two tracks and write la - this option if you are sure that the target DASD already contains a regular - format with the specified blocksize. A blocksize can optionally be specified - using \fB-b\fR (\fB--blocksize\fR). -+.IP expand -+Format all unformatted tracks at the end of the target DASD. This mode assumes -+that tracks at the beginning of the DASD volume have already been correctly -+formatted, while a consecutive set of tracks at the end are unformatted. You can -+use this mode to make added space available for Linux use after dynamically -+increasing the size of a DASD volume. A blocksize can optionally be specified -+using \fB-b\fR (\fB--blocksize\fR). - .RE - - .TP ---- a/dasdfmt/dasdfmt.c -+++ b/dasdfmt/dasdfmt.c -@@ -88,7 +88,9 @@ static void exit_usage(int exitcode) - " device node of the device to format\n" - " is either\n" - " 'full' to fully format the device (default)\n" -- " 'quick' to format only the first two tracks\n"); -+ " 'quick' to format only the first two tracks\n" -+ " 'expand' to format only the unformatted end" -+ " of a device\n"); - exit(exitcode); - } - -@@ -791,8 +793,11 @@ static format_check_t check_track_format - if (errno == ENOTTY) { - ERRMSG("%s: Missing kernel support for format checking", - prog_name); -- if (!info->check) -+ if (mode == EXPAND) { -+ ERRMSG(". Mode 'expand' cannot be used"); -+ } else if (!info->check) { - ERRMSG(" (--force to override)"); -+ } - ERRMSG_EXIT(EXIT_FAILURE, ".\n"); - } - ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n", -@@ -957,8 +962,7 @@ static void dasdfmt_print_info(dasdfmt_i - printf(" Compatible Disk Layout : %s\n", - (p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no"); - printf(" Blocksize : %d\n", p->blksize); -- printf(" Mode : %s\n", -- (mode == FULL) ? "Full" : "Quick"); -+ printf(" Mode : %s\n", mode_str[mode]); - - if (info->testmode) - printf("Test mode active, omitting ioctl.\n"); -@@ -1169,6 +1173,60 @@ static void dasdfmt_write_labels(dasdfmt - } - - /* -+ * This function will search for the beginning of an unformatted area -+ * on the device. It checks selected tracks beforehand and makes sure -+ * that the device is formatted to a certain extent. Otherwise the -+ * process is terminated. -+ */ -+static void dasdfmt_find_start(dasdfmt_info_t *info, unsigned int cylinders, -+ unsigned heads, format_data_t *format_params) -+{ -+ format_check_t cdata; -+ unsigned int middle; -+ unsigned int left = 2; -+ unsigned int right = (cylinders * heads) - 1; -+ unsigned int first = left; -+ -+ check_blocksize(info, format_params->blksize); -+ -+ format_params->start_unit = 0; -+ format_params->stop_unit = 4; -+ cdata = check_track_format(info, format_params); -+ -+ if (cdata.result) { -+ evaluate_format_error(info, &cdata, heads); -+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform a " -+ "clean format.\n"); -+ } -+ -+ printf("Expansion mode active. Searching for starting position...\n"); -+ -+ while (left <= right) { -+ /* new track number to look at */ -+ middle = left + ((right - left) / 2); -+ -+ format_params->start_unit = middle; -+ format_params->stop_unit = middle; -+ cdata = check_track_format(info, format_params); -+ if (cdata.blksize != format_params->blksize) { -+ first = middle; -+ right = middle - 1; -+ } else { -+ left = middle + 1; -+ } -+ } -+ -+ if (first == 2 && cdata.blksize == format_params->blksize) -+ ERRMSG_EXIT(EXIT_FAILURE, -+ "No unformatted part found, aborting.\n"); -+ -+ printf("Done. Unformatted part starts at track %d.\n", first); -+ -+ /* return format_params with start_unit set to the correct value */ -+ format_params->start_unit = first; -+} -+ -+/* - * formats the disk cylinderwise - */ - static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders, -@@ -1239,6 +1297,40 @@ static void dasdfmt_prepare_and_format(d - } - - /* -+ * This function will start the expand format process. -+ */ -+static void dasdfmt_expand_format(dasdfmt_info_t *info, unsigned int cylinders, -+ unsigned int heads, format_data_t *p) -+{ -+ if (!((info->withoutprompt) && (info->verbosity < 1))) -+ printf("Formatting the device. This may take a while " -+ "(get yourself a coffee).\n"); -+ -+ if (info->verbosity > 0) -+ printf("Detaching the device...\n"); -+ -+ if (ioctl(filedes, BIODASDDISABLE, p) != 0) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL " -+ "BIODASDDISABLE failed. (%s)\n", prog_name, -+ strerror(errno)); -+ disk_disabled = 1; -+ -+ dasdfmt_format(info, cylinders, heads, p); -+ -+ if (info->verbosity > 0) -+ printf("Formatting tracks complete...\n"); -+ -+ if (info->verbosity > 0) -+ printf("Re-accessing the device...\n"); -+ -+ if (ioctl(filedes, BIODASDENABLE, p) != 0) -+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL " -+ "BIODASDENABLE failed. (%s)\n", prog_name, -+ strerror(errno)); -+ disk_disabled = 0; -+} -+ -+/* - * This function will only format the first two tracks of a DASD. - * The rest of the DASD is untouched and left as is. - */ -@@ -1310,6 +1402,10 @@ static void do_format_dasd(dasdfmt_info_ - case QUICK: /* just the first two */ - p->stop_unit = 1; - break; -+ case EXPAND: /* only the end of the disk */ -+ dasdfmt_find_start(info, cylinders, heads, p); -+ p->stop_unit = (cylinders * heads) - 1; -+ break; - } - - if ((info->verbosity > 0) || !info->withoutprompt || info->testmode) -@@ -1338,10 +1434,12 @@ static void do_format_dasd(dasdfmt_info_ - - if (!info->testmode) { - if (!info->withoutprompt) { -- printf("\n--->> ATTENTION! <<---\n"); -- printf("All data of that device will be lost.\nType " -- "\"yes\" to continue, no will leave the disk " -- "untouched: "); -+ printf("\n"); -+ if (mode != EXPAND) -+ printf("--->> ATTENTION! <<---\nAll data of " -+ "that device will be lost.\n"); -+ printf("Type \"yes\" to continue, no will leave the " -+ "disk untouched: "); - if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL) - return; - if (strcasecmp(inp_buffer, "yes") && -@@ -1359,12 +1457,14 @@ static void do_format_dasd(dasdfmt_info_ - case QUICK: - dasdfmt_quick_format(info, cylinders, heads, p); - break; -+ case EXPAND: -+ dasdfmt_expand_format(info, cylinders, heads, p); - } - - if (!info->yast_mode) - printf("Finished formatting the device.\n"); - -- if (!info->writenolabel) -+ if (!(info->writenolabel || mode == EXPAND)) - dasdfmt_write_labels(info, vlabel, cylinders, heads); - - if (!info->yast_mode) -@@ -1526,6 +1626,8 @@ int main(int argc, char *argv[]) - mode = FULL; - else if (strcasecmp(optarg, "quick") == 0) - mode = QUICK; -+ else if (strcasecmp(optarg, "expand") == 0) -+ mode = EXPAND; - else - ERRMSG_EXIT(EXIT_FAILURE, - "%s: The specified mode '%s' is " ---- a/dasdfmt/dasdfmt.h -+++ b/dasdfmt/dasdfmt.h -@@ -150,8 +150,13 @@ struct dasd_eckd_characteristics { - typedef enum format_mode_t { - FULL, /* default mode */ - QUICK, /* format only the first 2 tracks */ -+ EXPAND, /* search for unformatted area and format only that part*/ - } format_mode_t; - -+static const char mode_str[3][10] = { -+ "Full", "Quick", "Expand" -+}; -+ - /* - * struct format_data_t - * represents all data necessary to format a dasd diff --git a/s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch b/s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch deleted file mode 100644 index 5fed129..0000000 --- a/s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch +++ /dev/null @@ -1,1053 +0,0 @@ -Subject: [PATCH] [FEAT RTL1601] libutil: Add utility functions -From: Peter Oberparleiter - -Summary: libutil: Add utility functions -Description: Introduce utility functions for use by s390-tools. -Upstream-ID: - -Problem-ID: RTL1601 - -Signed-off-by: Peter Oberparleiter ---- - include/util_base.h | 2 - include/util_libc.h | 125 +++++++++++++++++++ - include/util_opt.h | 82 ++++++++++++ - include/util_panic.h | 45 ++++++ - include/util_prg.h | 55 ++++++++ - libutil/Makefile | 11 + - libutil/util_libc.c | 155 +++++++++++++++++++++++ - libutil/util_opt.c | 281 +++++++++++++++++++++++++++++++++++++++++++ - libutil/util_panic.c | 119 ++++++++++++++++++ - libutil/util_prg.c | 111 ++++++++++++++++ - 10 files changed, 985 insertions(+), 1 deletion(-) - ---- a/include/util_base.h -+++ b/include/util_base.h -@@ -15,4 +15,6 @@ void util_hexdump(FILE *fh, const char * - void util_hexdump_grp(FILE *fh, const char *tag, const void *data, int group, - int cnt, int indent); - -+#define UTIL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) -+ - #endif /* UTIL_BASE_H */ ---- /dev/null -+++ b/include/util_libc.h -@@ -0,0 +1,125 @@ -+/** -+ * @defgroup util_libc_h util_libc: Libc wrapper interface -+ * @{ -+ * @brief Handle standard errors for libc functions -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef UTIL_LIBC_H -+#define UTIL_LIBC_H -+ -+#include -+ -+/** -+ * Allocate memory or panic in case of failure -+ * -+ * @param[in] size Number of bytes to be allocated -+ * -+ * @returns Pointer to allocated memory buffer -+ */ -+#define util_malloc(size) \ -+ __util_malloc(__func__, __FILE__, __LINE__, size) -+ -+void *__util_malloc(const char *func, const char *file, int line, size_t size); -+ -+/** -+ * Allocate zero-initialized memory or panic in case of failure -+ * -+ * @param[in] size Number of bytes to be allocated -+ * -+ * @returns Pointer to allocated memory buffer initialized with zeroes -+ */ -+#define util_zalloc(size) \ -+ __util_zalloc(__func__, __FILE__, __LINE__, size) -+ -+void *__util_zalloc(const char *func, const char *file, int line, size_t size); -+ -+ -+/** -+ * Re-allocate memory or exit in case of failure -+ * -+ * @param[in] ptr Pointer ot old memory buffer -+ * @param[in] size Number of bytes to be allocated -+ * -+ * @returns Pointer to allocated memory buffer -+ */ -+#define util_realloc(ptr, size) \ -+ __util_realloc(__func__, __FILE__, __LINE__, ptr, size) -+ -+void *__util_realloc(const char *func, const char *file, int line, -+ void *ptr, size_t size); -+ -+/** -+ * Duplicate a string buffer or exit in case of failure -+ * -+ * @param[in] str String to be duplicated -+ * -+ * @returns Pointer to newly allocated and copied string -+ */ -+#define util_strdup(str) \ -+ __util_strdup(__func__, __FILE__, __LINE__, str) -+ -+void *__util_strdup(const char *func, const char *file, int line, -+ const char *str); -+ -+/** -+ * Print to allocated string or exit in case of failure -+ * -+ * @param[in] strp String to be allocated -+ * @param[in] fmt Format string for generation of string -+ * @param[in] ap Parameters for format string -+ * -+ * @returns num Number of formatted characters -+ */ -+#define util_vasprintf(strp, fmt, ap) \ -+ __util_vasprintf(__func__, __FILE__, __LINE__, strp, fmt, ap) -+ -+#define UTIL_VASPRINTF(strp, fmt, ap) \ -+do { \ -+ va_start(ap, fmt); \ -+ util_vasprintf(strp, fmt, ap); \ -+ va_end(ap); \ -+} while (0) -+ -+int __util_vasprintf(const char *func, const char *file, int line, -+ char **strp, const char *fmt, va_list ap); -+ -+/** -+ * Print to newly allocated string or exit in case of failure -+ * -+ * @param[in] strp String to be allocated -+ * @param[in] ... Format string and parameters for format string -+ * -+ * @returns num Number of formatted characters -+ */ -+#define util_asprintf(strp, ...) \ -+ __util_asprintf(__func__, __FILE__, __LINE__, strp, ##__VA_ARGS__) -+ -+int __util_asprintf(const char *func, const char *file, int line, -+ char **strp, const char *fmt, ...); -+ -+ -+/** -+ * Print to string buffer or exit in case of failure -+ * -+ * @param[in] str String buffer -+ * @param[in] fmt Format string for generation of string -+ * @param[in] ap Parameters for format string -+ * -+ * @returns num Number of formatted characters -+ */ -+#define util_vsprintf(str, fmt, ap) \ -+ __util_vsprintf(__func__, __FILE__, __LINE__, str, fmt, ap) -+ -+#define UTIL_VSPRINTF(str, fmt, ap) \ -+do { \ -+ va_start(ap, fmt); \ -+ util_vsprintf(str, fmt, ap); \ -+ va_end(ap); \ -+} while (0) -+ -+int __util_vsprintf(const char *func, const char *file, int line, -+ char *str, const char *fmt, va_list ap); -+ -+#endif /** UTIL_LIBC_H @} */ ---- /dev/null -+++ b/include/util_opt.h -@@ -0,0 +1,82 @@ -+/** -+ * @defgroup util_opt_h util_opt: Command line options interface -+ * @{ -+ * @brief Parse the command line options -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef UTIL_OPT_H -+#define UTIL_OPT_H -+ -+#include -+#include -+ -+/* Flag indicating that an option does not have a short form */ -+#define UTIL_OPT_FLAG_NOSHORT 1 -+ -+/* Flag indicating that an option does not have a long form */ -+#define UTIL_OPT_FLAG_NOLONG 2 -+ -+/* Flag indicating that this is a section heading */ -+#define UTIL_OPT_FLAG_SECTION 4 -+ -+/** -+ * Command line option -+ */ -+struct util_opt { -+ /** Defined by getopt.h, see "man getopt_long" */ -+ struct option option; -+ /** For options with arguments: Argument name */ -+ char *argument; -+ /** Description displayed for --help */ -+ char *desc; -+ /** Flags for this option */ -+ int flags; -+}; -+ -+/** -+ * Standard option: --help -+ */ -+#define UTIL_OPT_HELP \ -+{ \ -+ .option = { "help", 0, NULL, 'h' }, \ -+ .desc = "Print this help, then exit", \ -+} -+ -+/** -+ * Standard option: --version -+ */ -+#define UTIL_OPT_VERSION \ -+{ \ -+ .option = { "version", 0, NULL, 'v' }, \ -+ .desc = "Print version information, then exit", \ -+} -+ -+/** -+ * End-marker for the option pointer vector -+ */ -+#define UTIL_OPT_END \ -+{ \ -+ .option = { NULL, 0, NULL, 0 }, \ -+} -+ -+/** -+ * Section header -+ */ -+#define UTIL_OPT_SECTION(title) \ -+{ \ -+ .desc = (title), \ -+ .flags = UTIL_OPT_FLAG_SECTION, \ -+} -+ -+/* -+ * Option functions -+ */ -+void util_opt_init(struct util_opt *opt_vec, const char *opt_prefix); -+int util_opt_getopt_long(int argc, char *argv[]); -+void util_opt_print_help(void); -+void util_opt_print_indented(const char *opt, const char *desc); -+void util_opt_print_parse_error(char opt, char *argv[]); -+ -+#endif /** UTIL_OPT_H @} */ ---- /dev/null -+++ b/include/util_panic.h -@@ -0,0 +1,45 @@ -+/** -+ * @defgroup util_panic_h util_panic: Panic interface -+ * @{ -+ * @brief Collect FFDC data for unexpected errors -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef UTIL_PANIC_H -+#define UTIL_PANIC_H -+ -+#include "zt_common.h" -+ -+#ifndef __noreturn -+#define __noreturn -+#endif -+ -+/** -+ * Write message, print backtrace and then call the abort() function -+ * -+ * @param[in] ... Format string and parameters describing the panic reason -+ */ -+#define util_panic(...) \ -+ __util_panic(__func__, __FILE__, __LINE__, ##__VA_ARGS__) -+ -+void __util_panic(const char *func, const char *file, int line, -+ const char *fmt, ...) __noreturn; -+ -+/** -+ * Ensure that assumption is not true, otherwise panic -+ * -+ * Example: util_assert(ptr == NULL, "The ptr must be NULL, but is %p", ptr) -+ * -+ * @param[in] assumption This assumption has to be true -+ * @param[in] ... Format string and parameters describing the assumption -+ */ -+#define util_assert(assumption, ...) \ -+ __util_assert(#assumption, __func__, __FILE__, __LINE__, \ -+ assumption, ##__VA_ARGS__) -+ -+void __util_assert(const char *assertion_string, -+ const char *func, const char *file, int line, -+ int assumption, const char *fmt, ...); -+ -+#endif /** UTIL_PANIC_H @} */ ---- /dev/null -+++ b/include/util_prg.h -@@ -0,0 +1,55 @@ -+/** -+ * @defgroup util_prg_h util_prg: Program interface -+ * @{ -+ * @brief Print standard program messages -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef UTIL_PRG_H -+#define UTIL_PRG_H -+ -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * Copyright description -+ */ -+struct util_prg_copyright { -+ /** Name of the copyright owner, e.g. IBM */ -+ const char *owner; -+ /** Year of first publishing */ -+ int pub_first; -+ /** Year of last major changes */ -+ int pub_last; -+}; -+ -+/** -+ * @brief Coypright end marker -+ */ -+#define UTIL_PRG_COPYRIGHT_END {NULL, 0, 0} -+ -+/** -+ * Program description -+ */ -+struct util_prg { -+ /** Description for help */ -+ const char *desc; -+ /** Positional arguments */ -+ const char *args; -+ /** Copyright list */ -+ struct util_prg_copyright copyright_vec[]; -+}; -+ -+void util_prg_init(const struct util_prg *prg); -+void util_prg_print_parse_error(void); -+void util_prg_print_required_arg(const char *option); -+void util_prg_print_invalid_option(const char *option); -+void util_prg_print_arg_error(const char *arg_name); -+void util_prg_print_version(void); -+void util_prg_print_help(void); -+ -+#endif /** UTIL_PRG_H @} */ ---- a/libutil/Makefile -+++ b/libutil/Makefile -@@ -2,12 +2,21 @@ include ../common.mak - - CPPFLAGS += -I../include - --all: util_base.o util_list.o util_part.o util_proc.o -+all: util_base.o util_list.o util_part.o util_proc.o util_libc.o util_opt.o \ -+ util_panic.o util_prg.o - - util_list.o: util_list.c ../include/util.h - - util_proc.o: util_proc.c ../include/util_proc.h - -+util_libc.o: util_libc.c ../include/util_libc.h -+ -+util_opt.o: util_opt.c ../include/util_opt.h -+ -+util_panic.o: util_panic.c ../include/util_panic.h -+ -+util_prg.o: util_prg.c ../include/util_prg.h -+ - install: all - - clean: ---- /dev/null -+++ b/libutil/util_libc.c -@@ -0,0 +1,155 @@ -+/* -+ * util - Utility function library -+ * -+ * Handle standard errors for libc functions -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#define _GNU_SOURCE /* for program_invocation_short_name */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "util_base.h" -+#include "util_panic.h" -+#include "util_libc.h" -+ -+/* -+ * Return size as string of largest unit, e.g. 1025 = "1 KiB" -+ */ -+static void format_size(char *str, size_t size) -+{ -+ static const char * const unit_vec[] = -+ {"byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"}; -+ unsigned int i; -+ -+ for (i = 0; i < UTIL_ARRAY_SIZE(unit_vec); i++) { -+ if (size / 1024 == 0) { -+ sprintf(str, "%zu %s", size, unit_vec[i]); -+ return; -+ } -+ size /= 1024; -+ } -+ sprintf(str, "huge"); -+} -+ -+static void __util_oom(const char *func, const char *file, int line, -+ size_t size) -+{ -+ char size_str[256]; -+ -+ fprintf(stderr, "%s: Failed to allocate memory", -+ program_invocation_short_name); -+ if (size > 0) { -+ format_size(size_str, size); -+ fprintf(stderr, " (%s)", size_str); -+ } -+ fprintf(stderr, " at %s:%d %s()\n", file, line, func); -+ exit(EXIT_FAILURE); -+} -+ -+/* -+ * Allocate memory or exit in case of failure -+ */ -+void *__util_malloc(const char *func, const char *file, int line, size_t size) -+{ -+ void *buf; -+ -+ buf = malloc(size); -+ -+ if (buf == NULL) -+ __util_oom(func, file, line, size); -+ -+ return buf; -+} -+ -+/* -+ * Allocate zero-initialized memory or exit in case of failure -+ */ -+void *__util_zalloc(const char *func, const char *file, int line, size_t size) -+{ -+ void *buf = __util_malloc(func, file, line, size); -+ -+ memset(buf, 0, size); -+ -+ return buf; -+} -+ -+/* -+ * Re-allocate memory or exit in case of failure -+ */ -+void *__util_realloc(const char *func, const char *file, int line, -+ void *ptr, size_t size) -+{ -+ void *buf; -+ -+ buf = realloc(ptr, size); -+ -+ if (buf == NULL) -+ __util_oom(func, file, line, size); -+ -+ return buf; -+} -+ -+/* -+ * Duplicate a string buffer or exit in case of failure -+ */ -+void *__util_strdup(const char *func, const char *file, int line, -+ const char *str) -+{ -+ void *buf = strdup(str); -+ -+ if (buf == NULL) -+ __util_oom(func, file, line, strlen(str) + 1); -+ -+ return buf; -+} -+ -+/* -+ * Print to newly allocated string or exit in case of failure -+ */ -+int __util_vasprintf(const char *func, const char *file, int line, -+ char **strp, const char *fmt, va_list ap) -+{ -+ int rc; -+ -+ rc = vasprintf(strp, fmt, ap); -+ if (rc == -1) -+ __util_oom(func, file, line, 0); -+ -+ return rc; -+} -+ -+/* -+ * Print to newly allocated string or exit in case of failure -+ */ -+int __util_asprintf(const char *func, const char *file, int line, -+ char **strp, const char *fmt, ...) -+{ -+ va_list ap; -+ int rc; -+ -+ va_start(ap, fmt); -+ rc = __util_vasprintf(func, file, line, strp, fmt, ap); -+ va_end(ap); -+ return rc; -+} -+ -+/* -+ * Print to string buffer or exit in case of failure -+ */ -+int __util_vsprintf(const char *func, const char *file, int line, -+ char *str, const char *fmt, va_list ap) -+{ -+ int rc; -+ -+ rc = vsprintf(str, fmt, ap); -+ if (rc == -1) -+ __util_assert("rc != -1", func, file, line, -+ rc != -1, "Could not format string\n"); -+ return rc; -+} ---- /dev/null -+++ b/libutil/util_opt.c -@@ -0,0 +1,281 @@ -+/* -+ * util - Utility function library -+ * -+ * Parse the command line options -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "util_base.h" -+#include "util_libc.h" -+#include "util_opt.h" -+#include "util_panic.h" -+#include "util_prg.h" -+ -+/* -+ * Private data -+ */ -+/// @cond -+static struct util_opt_l { -+ /* Option character string for getopt_long() */ -+ char *opt_str; -+ /* Option array for getopt_long() */ -+ struct option *option_vec; -+ /* Original util_opt array */ -+ struct util_opt *opt_vec; -+ /* Length of longest option string */ -+ int opt_max; -+} l; -+ -+struct util_opt_l *util_opt_l = &l; -+/// @endcond -+ -+#define util_opt_iterate(opt) \ -+ for (opt = &l.opt_vec[0]; opt->desc != NULL; opt++) -+ -+#define MAX(x, y) ((x) < (y) ? (y) : (x)) -+#define MAX_OPTLEN 256 -+ -+static int opt_max_len(void); -+ -+/** -+ * Initialize the command line options -+ * -+ * Build short option string and long option array to be used for getopt_long(). -+ * The ":" prefix is added to the short option string for handling of "missing -+ * required arguments". -+ * -+ * @param[in] opt_vec Option array -+ * @param[in] opt_prefix Optional option string prefix -+ */ -+void util_opt_init(struct util_opt *opt_vec, const char *opt_prefix) -+{ -+ int i, j, count; -+ char *str; -+ size_t prefix_len = opt_prefix ? strlen(opt_prefix) : 0; -+ -+ opterr = 0; -+ /* Get number of options */ -+ for (count = 0; opt_vec[count].desc != NULL; count++); -+ /* -+ * Allocate short option string for worst case when all options have -+ * optional parameters e.g "x::" and long option string. -+ */ -+ l.opt_str = util_malloc(sizeof(char) * count * 3 + 2 + prefix_len); -+ l.option_vec = util_malloc(sizeof(struct option) * (count + 1)); -+ l.opt_vec = opt_vec; -+ -+ str = l.opt_str; -+ if (opt_prefix) { -+ strcpy(str, opt_prefix); -+ str += prefix_len; -+ } -+ /* Force getopt_long() to return ':' for missing required arguments */ -+ *str++ = ':'; -+ /* Construction of input structures for getopt_long() function. */ -+ for (i = 0, j = 0; i < count; i++) { -+ if (opt_vec[i].flags & UTIL_OPT_FLAG_SECTION) -+ continue; -+ memcpy(&l.option_vec[j++], &opt_vec[i].option, -+ sizeof(struct option)); -+ if (opt_vec[i].flags & UTIL_OPT_FLAG_NOSHORT) -+ continue; -+ *str++ = opt_vec[i].option.val; -+ switch (opt_vec[i].option.has_arg) { -+ case no_argument: -+ break; -+ case required_argument: -+ *str++ = ':'; -+ break; -+ case optional_argument: -+ *str++ = ':'; -+ *str++ = ':'; -+ break; -+ default: -+ util_panic("Unexpected \"has_arg\" parameter: %d\n", -+ opt_vec[i].option.has_arg); -+ } -+ } -+ /* Add end marker to option array and short option string */ -+ memset(&l.option_vec[j], 0, sizeof(struct option)); -+ *str = '\0'; -+ -+ l.opt_max = opt_max_len(); -+} -+ -+/** -+ * Wrapper for getopt_long -+ * -+ * @param[in] argc Count of command line parameters -+ * @param[in] argv Array of command line parameters -+ */ -+int util_opt_getopt_long(int argc, char *argv[]) -+{ -+ return getopt_long(argc, argv, l.opt_str, l.option_vec, NULL); -+} -+ -+/* -+ * Format option name: Add short, long option and argument (as applicable) -+ */ -+static void format_opt(char *buf, size_t maxlen, const struct util_opt *opt) -+{ -+ int has_arg, flags, rc; -+ char val, *arg_str; -+ const char *name; -+ -+ has_arg = opt->option.has_arg; -+ name = opt->option.name; -+ val = opt->option.val; -+ flags = opt->flags; -+ -+ /* Prepare potential option argument string */ -+ if (has_arg == optional_argument) { -+ if (flags & UTIL_OPT_FLAG_NOLONG) -+ util_asprintf(&arg_str, "[%s]", opt->argument); -+ else -+ util_asprintf(&arg_str, "[=%s]", opt->argument); -+ } else if (has_arg == required_argument) { -+ util_asprintf(&arg_str, " %s", opt->argument); -+ } else { -+ util_asprintf(&arg_str, ""); -+ } -+ -+ /* Format the option */ -+ if (flags & UTIL_OPT_FLAG_NOLONG) -+ rc = snprintf(buf, maxlen, "-%c%s", val, arg_str); -+ else if (flags & UTIL_OPT_FLAG_NOSHORT) -+ rc = snprintf(buf, maxlen, " --%s%s", name, arg_str); -+ else -+ rc = snprintf(buf, maxlen, "-%c, --%s%s", val, name, arg_str); -+ -+ util_assert(rc < (int)maxlen, "Option too long: %s\n", name); -+ free(arg_str); -+} -+ -+/* -+ * Return size of the longest formatted option -+ */ -+static int opt_max_len(void) -+{ -+ const struct util_opt *opt; -+ unsigned int max = 0; -+ char opt_str[MAX_OPTLEN]; -+ -+ util_opt_iterate(opt) { -+ if (opt->flags & UTIL_OPT_FLAG_SECTION) -+ continue; -+ format_opt(opt_str, MAX_OPTLEN, opt); -+ max = MAX(max, strlen(opt_str)); -+ } -+ return max; -+} -+ -+/* -+ * Print option description with indentation -+ */ -+static void print_opt_description(const char *desc_in, int indent) -+{ -+ char *word, *line, *desc, *desc_ptr; -+ int word_len, pos = indent; -+ -+ desc = desc_ptr = util_strdup(desc_in); -+ line = strsep(&desc, "\n"); -+ while (line) { -+ word = strsep(&line, " "); -+ pos = indent; -+ while (word) { -+ word_len = strlen(word); -+ if (pos + word_len + 1 > 80) { -+ printf("\n%*s", indent, " "); -+ pos = indent; -+ } -+ printf(" %s", word); -+ pos += word_len + 1; -+ word = strsep(&line, " "); -+ } -+ if (desc) -+ printf("\n%*s", indent, " "); -+ line = strsep(&desc, "\n"); -+ } -+ printf("\n"); -+ free(desc_ptr); -+} -+ -+/** -+ * Print an option name, followed by a description indented to fit the -+ * longest option name -+ */ -+void util_opt_print_indented(const char *opt, const char *desc) -+{ -+ printf(" %-*s ", l.opt_max, opt); -+ print_opt_description(desc, 2 + l.opt_max); -+} -+ -+/** -+ * Print the usage of the command line options to the console -+ */ -+void util_opt_print_help(void) -+{ -+ char opt_str[MAX_OPTLEN]; -+ struct util_opt *opt; -+ int first = 1; -+ -+ /* -+ * Create format string: " -%c, --%-s %s" -+ * -+ * Example: -+ * -+ * -p, --print STRING Print STRING to console -+ */ -+ util_opt_iterate(opt) { -+ if (opt->flags & UTIL_OPT_FLAG_SECTION) { -+ printf("%s%s\n", first ? "" : "\n", opt->desc); -+ first = 0; -+ continue; -+ } -+ format_opt(opt_str, MAX_OPTLEN, opt); -+ util_opt_print_indented(opt_str, opt->desc); -+ } -+} -+ -+/** -+ * Print option parsing error message -+ * -+ * This function should be used when the return code of the -+ * util_opt_getopt_long() function returns a character that does -+ * not match any of the expected options. -+ * -+ * @param[in] opt Short option returned by getopt_long() -+ * @param[in] argv Option array -+ */ -+void util_opt_print_parse_error(char opt, char *argv[]) -+{ -+ char optopt_str[3]; -+ -+ switch (opt) { -+ case ':': -+ /* A required option argument has not been specified */ -+ util_prg_print_required_arg(argv[optind - 1]); -+ break; -+ case '?': -+ /* An invalid option has been specified */ -+ if (optopt) { -+ /* Short option */ -+ sprintf(optopt_str, "-%c", optopt); -+ util_prg_print_invalid_option(optopt_str); -+ } else { -+ /* Long option */ -+ util_prg_print_invalid_option(argv[optind - 1]); -+ } -+ break; -+ default: -+ util_panic("Option '%c' should not be handled here\n", opt); -+ } -+} -+ ---- /dev/null -+++ b/libutil/util_panic.c -@@ -0,0 +1,119 @@ -+/* -+ * util - Utility function library -+ * -+ * Collect FFDC data for unexpected errors -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "util_base.h" -+#include "util_panic.h" -+ -+/* -+ * Obtain a backtrace and print it to stderr -+ * -+ * To get symbols, compile the code with "-rdynamic". -+ */ -+static void print_backtrace(void) -+{ -+ void *array[256]; -+ size_t i, size; -+ char **strings; -+ -+ fprintf(stderr, "Backtrace:\n\n"); -+ size = backtrace(array, UTIL_ARRAY_SIZE(array)); -+ strings = backtrace_symbols(array, size); -+ if (strings == NULL) { -+ fprintf(stderr, " Could not obtain backtrace (ENOMEM)\n"); -+ return; -+ } -+ for (i = 0; i < size; i++) -+ fprintf(stderr, " %s\n", strings[i]); -+ -+ free(strings); -+} -+ -+/* -+ * Check for core ulimit -+ */ -+static void ulimit_core_check(void) -+{ -+ struct rlimit limit; -+ -+ if (getrlimit(RLIMIT_CORE, &limit) != 0) -+ return; -+ if (limit.rlim_cur != 0) -+ return; -+ fprintf(stderr, "Core dump size is zero. To get a full core dump use 'ulimit -c unlimited'.\n"); -+} -+ -+/* -+ * Print FFDC data and then abort -+ */ -+static void panic_finish(const char *func, const char *file, int line, -+ const char *fmt, va_list ap) -+{ -+ /* Write panic error string */ -+ fprintf(stderr, "\n"); -+ fprintf(stderr, "Error string:\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, " "); -+ vfprintf(stderr, fmt, ap); -+ fprintf(stderr, "\n"); -+ /* Write file, line number, and function name */ -+ fprintf(stderr, "Location:\n\n"); -+ fprintf(stderr, " %s:%d: %s()\n", file, line, func); -+ fprintf(stderr, "\n"); -+ -+ /* Print the function backtrace */ -+ print_backtrace(); -+ fprintf(stderr, "\n"); -+ -+ ulimit_core_check(); -+ fprintf(stderr, "----------------------------------------------------------------------->8-----\n"); -+ abort(); -+} -+ -+/* -+ * Do panic processing if the assumption is not true -+ */ -+void __util_assert(const char *assertion_str, -+ const char *func, const char *file, int line, -+ int assumption, const char *fmt, ...) -+{ -+ va_list ap; -+ -+ if (assumption) -+ return; -+ va_start(ap, fmt); -+ fprintf(stderr, "---8<-------------------------------------------------------------------------\n"); -+ fprintf(stderr, "ASSERTION FAILED: The application terminated due to an internal or OS error\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, "The following assumption was *not* true:\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, " %s\n", assertion_str); -+ panic_finish(func, file, line, fmt, ap); -+} -+ -+/* -+ * Do panic processing -+ */ -+void __util_panic(const char *func, const char *file, int line, -+ const char *fmt, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, fmt); -+ fprintf(stderr, "---8<-------------------------------------------------------------------------\n"); -+ fprintf(stderr, "PANIC: The application terminated due to an unrecoverable error\n"); -+ panic_finish(func, file, line, fmt, ap); -+ while(1); -+} ---- /dev/null -+++ b/libutil/util_prg.c -@@ -0,0 +1,111 @@ -+/* -+ * util - Utility function library -+ * -+ * Print standard program messages -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#define _GNU_SOURCE /* for program_invocation_short_name */ -+ -+#include -+#include -+ -+#include "util_prg.h" -+#include "zt_common.h" -+ -+/* -+ * Private data -+ */ -+static struct util_prg_l { -+ const struct util_prg *prg; -+} l; -+ -+struct util_prg_l *util_prg_l = &l; -+ -+/** -+ * Print program usage information for the --help option -+ */ -+void util_prg_print_help(void) -+{ -+ printf("Usage: %s [OPTIONS]", program_invocation_short_name); -+ if (l.prg->args) -+ printf(" %s", l.prg->args); -+ printf("\n\n%s\n\n", l.prg->desc); -+} -+ -+/** -+ * Print program version information for the --version option -+ */ -+void util_prg_print_version(void) -+{ -+ const struct util_prg_copyright *copyright; -+ -+ printf("%s version %s\n", program_invocation_short_name, -+ RELEASE_STRING); -+ copyright = l.prg->copyright_vec; -+ while (copyright->owner) { -+ if (copyright->pub_first == copyright->pub_last) -+ printf("Copyright %s %d\n", copyright->owner, -+ copyright->pub_first); -+ else -+ printf("Copyright %s %d, %d\n", copyright->owner, -+ copyright->pub_first, copyright->pub_last); -+ copyright++; -+ } -+} -+ -+/* -+ * Ask user to use the --help option -+ */ -+void util_prg_print_parse_error(void) -+{ -+ fprintf(stderr, "Try '%s --help' for more information.\n", -+ program_invocation_short_name); -+} -+ -+/** -+ * An option has been specified that is not supported -+ * -+ * @param[in] option Option string (short or long) -+ */ -+void util_prg_print_invalid_option(const char *opt_name) -+{ -+ fprintf(stderr, "%s: Invalid option '%s'\n", -+ program_invocation_short_name, opt_name); -+ util_prg_print_parse_error(); -+} -+ -+/** -+ * A required argument for an option is missing -+ * -+ * @param[in] option Option string -+ */ -+void util_prg_print_required_arg(const char *opt_name) -+{ -+ fprintf(stderr, "%s: Option '%s' requires an argument\n", -+ program_invocation_short_name, opt_name); -+ util_prg_print_parse_error(); -+} -+ -+/** -+ * A superfluous invalid positional argument has been specified -+ * -+ * @param[in] arg_name Name of the invalid argument -+ */ -+void util_prg_print_arg_error(const char *arg_name) -+{ -+ fprintf(stderr, "%s: Invalid argument '%s'\n", -+ program_invocation_short_name, arg_name); -+ util_prg_print_parse_error(); -+} -+ -+/** -+ * Initialize the program module -+ * -+ * @param[in] prg Program description -+ */ -+void util_prg_init(const struct util_prg *prg) -+{ -+ l.prg = prg; -+} diff --git a/s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch b/s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch deleted file mode 100644 index e0c486d..0000000 --- a/s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch +++ /dev/null @@ -1,4687 +0,0 @@ -Subject: [PATCH] [FEAT RTL1601] dump2tar: Add sysfs collection helper for dbginfo.sh -From: Peter Oberparleiter - -Summary: dump2tar: Add sysfs collection helper for dbginfo.sh -Description: Certain files in virtual filesystems such as sysfs, - debugfs and procfs do not correctly report their size. - As a result, tools like tar, cp or rsync cannot be easily - used to collect these files. - - This patch adds a tool to efficiently dump such files - into a compressed tar archive. It is intended to be used - by the dbginfo.sh script to significantly speed up data - collection. -Upstream-ID: - -Problem-ID: RTL1601 - -Changelog: - - - v2: Fix compiler warning and missing DESTDIR logic in Makefiles - -Signed-off-by: Peter Oberparleiter ---- - Makefile | 2 - README | 5 - dump2tar/Makefile | 12 - dump2tar/include/buffer.h | 47 + - dump2tar/include/dref.h | 26 - dump2tar/include/dump.h | 60 + - dump2tar/include/global.h | 20 - dump2tar/include/idcache.h | 23 - dump2tar/include/misc.h | 98 ++ - dump2tar/include/strarray.h | 23 - dump2tar/include/tar.h | 41 - dump2tar/man/Makefile | 12 - dump2tar/man/dump2tar.1 | 454 ++++++++++ - dump2tar/src/Makefile | 36 - dump2tar/src/buffer.c | 271 ++++++ - dump2tar/src/dref.c | 92 ++ - dump2tar/src/dump.c | 1850 ++++++++++++++++++++++++++++++++++++++++++++ - dump2tar/src/dump2tar.c | 474 +++++++++++ - dump2tar/src/global.c | 17 - dump2tar/src/idcache.c | 153 +++ - dump2tar/src/misc.c | 492 +++++++++++ - dump2tar/src/strarray.c | 81 + - dump2tar/src/tar.c | 270 ++++++ - 23 files changed, 4558 insertions(+), 1 deletion(-) - ---- a/Makefile -+++ b/Makefile -@@ -8,7 +8,7 @@ SUB_DIRS = $(LIB_DIRS) zipl zdump fdasd - tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \ - vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \ - ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \ -- systemd hmcdrvfs cpacfstats zdev -+ systemd hmcdrvfs cpacfstats zdev dump2tar - - all: subdirs_make - ---- a/README -+++ b/README -@@ -210,6 +210,11 @@ s390-tools (1.34.0) - configuration of devices and device drivers which are specific to the s390 - platform. - -+ * dump2tar: -+ dump2tar is a tool for creating a tar archive from the contents of -+ arbitrary files. It works even when the size of the actual file content -+ is not known beforehand (e.g. FIFOs, sysfs files). -+ - For more information refer to the following publications: - * "Device Drivers, Features, and Commands" chapter "Useful Linux commands" - * "Using the dump tools" ---- /dev/null -+++ b/dump2tar/Makefile -@@ -0,0 +1,12 @@ -+# Common definitions -+include ../common.mak -+ -+all: -+ $(MAKE) -C src -+ -+install: all -+ $(MAKE) -C src install -+ $(MAKE) -C man install -+ -+clean: -+ $(MAKE) -C src clean ---- /dev/null -+++ b/dump2tar/include/buffer.h -@@ -0,0 +1,47 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Data buffering functions -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef BUFFER_H -+#define BUFFER_H -+ -+#include -+#include -+#include -+ -+/* Buffers for building tar file entries */ -+struct buffer { -+ size_t total; /* Total number of bytes in buffer */ -+ size_t off; /* Current offset to next free byte in memory buffer */ -+ size_t size; /* Memory buffer size */ -+ char *addr; /* Memory buffer address */ -+ bool fd_open; /* Has fd been openend yet? */ -+ FILE *file; /* FILE * of file containing previous buffer data */ -+ int fd; /* Handle of file containing previous buffer data */ -+}; -+ -+void buffer_init(struct buffer *buffer, size_t size); -+struct buffer *buffer_alloc(size_t size); -+void buffer_reset(struct buffer *buffer); -+void buffer_close(struct buffer *buffer); -+void buffer_free(struct buffer *buffer, bool dyn); -+int buffer_open(struct buffer *buffer); -+int buffer_flush(struct buffer *buffer); -+ssize_t buffer_make_room(struct buffer *buffer, size_t size, bool usefile, -+ size_t max_buffer_size); -+int buffer_truncate(struct buffer *buffer, size_t len); -+ -+ssize_t buffer_read_fd(struct buffer *buffer, int fd, size_t chunk, -+ bool usefile, size_t max_buffer_size); -+int buffer_add_data(struct buffer *buffer, char *addr, size_t len, -+ bool usefile, size_t max_buffer_size); -+ -+typedef int (*buffer_cb_t)(void *data, void *addr, size_t len); -+int buffer_iterate(struct buffer *buffer, buffer_cb_t cb, void *data); -+void buffer_print(struct buffer *buffer); -+ -+#endif /* BUFFER_H */ ---- /dev/null -+++ b/dump2tar/include/dref.h -@@ -0,0 +1,26 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Reference counting for directory handles -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef DREF_H -+#define DREF_H -+ -+#include -+#include -+ -+/* Multiple jobs may refer to an open DIR * - need reference counting */ -+struct dref { -+ DIR *dd; -+ int dirfd; -+ unsigned int count; -+}; -+ -+struct dref *dref_create(const char *dirname); -+struct dref *dref_get(struct dref *dref); -+void dref_put(struct dref *dref); -+ -+#endif /* DREF_H */ ---- /dev/null -+++ b/dump2tar/include/dump.h -@@ -0,0 +1,60 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Main dump logic -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef DUMP_H -+#define DUMP_H -+ -+#include -+#include -+#include -+ -+#include "strarray.h" -+ -+#define NUM_EXCLUDE_TYPES 7 -+ -+struct dump_spec { -+ char *inname; -+ char *outname; -+ bool is_cmd; -+}; -+ -+struct dump_opts { -+ bool add_cmd_status; -+ bool append; -+ bool dereference; -+ bool exclude_type[NUM_EXCLUDE_TYPES]; -+ bool gzip; -+ bool ignore_failed_read; -+ bool no_eof; -+ bool quiet; -+ bool recursive; -+ bool threaded; -+ bool verbose; -+ const char *output_file; -+ int file_timeout; -+ int timeout; -+ long jobs; -+ long jobs_per_cpu; -+ size_t file_max_size; -+ size_t max_buffer_size; -+ size_t max_size; -+ size_t read_chunk_size; -+ struct strarray exclude; -+ struct dump_spec *specs; -+ unsigned int num_specs; -+}; -+ -+struct dump_opts *dump_opts_new(void); -+int dump_opts_set_type_excluded(struct dump_opts *opts, char c); -+void dump_opts_add_spec(struct dump_opts *opts, char *inname, char *outname, -+ bool is_cmd); -+void dump_opts_free(struct dump_opts *opts); -+ -+int dump_to_tar(struct dump_opts *opts); -+ -+#endif /* DUMP_H */ ---- /dev/null -+++ b/dump2tar/include/global.h -@@ -0,0 +1,20 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Global variables -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef GLOBAL_H -+#define GLOBAL_H -+ -+#include -+ -+extern bool global_threaded; -+extern bool global_debug; -+extern bool global_verbose; -+extern bool global_quiet; -+extern bool global_timestamps; -+ -+#endif /* GLOBAL_H */ ---- /dev/null -+++ b/dump2tar/include/idcache.h -@@ -0,0 +1,23 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Caches for user and group ID lookups -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef IDCACHE_H -+#define IDCACHE_H -+ -+#include -+#include -+ -+/* Buffer sizes for getpwuid_r and getgid_r calls (bytes) */ -+#define PWD_BUFFER_SIZE 4096 -+#define GRP_BUFFER_SIZE 4096 -+ -+void uid_to_name(uid_t uid, char *name, size_t len); -+void gid_to_name(gid_t gid, char *name, size_t len); -+void idcache_cleanup(void); -+ -+#endif /* IDCACHE_H */ ---- /dev/null -+++ b/dump2tar/include/misc.h -@@ -0,0 +1,98 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Helper functions -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef MISC_H -+#define MISC_H -+ -+#include -+#include -+#include -+#include -+ -+#include "global.h" -+ -+#include "util_libc.h" -+ -+#define MSG_LEN 256 -+ -+#define DBG(...) \ -+ do { \ -+ if (global_debug) \ -+ debug(__FILE__, __LINE__, ##__VA_ARGS__); \ -+ } while (0) -+ -+#define mwarn(fmt, ...) _mwarn(true, (fmt), ##__VA_ARGS__) -+#define mwarnx(fmt, ...) _mwarn(false, (fmt), ##__VA_ARGS__) -+ -+/* Helper macro for constructing messages in variables */ -+#define HANDLE_RC(rc, max, off, label) \ -+ do { \ -+ if ((rc) > 0) \ -+ (off) += (rc); \ -+ if ((off) > (max)) \ -+ goto label; \ -+ } while (0) -+ -+/* Program exit codes */ -+#define EXIT_OK 0 -+#define EXIT_RUNTIME 1 -+#define EXIT_USAGE 2 -+ -+/* Number of nanoseconds in a second */ -+#define NSEC_PER_SEC 1000000000L -+#define NSEC_PER_MSEC 1000000L -+#define NSEC_PER_USEC 1000L -+ -+extern struct timespec main_start_ts; -+struct dref; -+ -+int misc_write_data(int fd, char *addr, size_t len); -+ssize_t misc_read_data(int fd, char *addr, size_t len); -+void inc_timespec(struct timespec *ts, time_t sec, long nsec); -+void set_timespec(struct timespec *ts, time_t sec, long nsec); -+bool ts_before(struct timespec *a, struct timespec *b); -+int snprintf_duration(char *buff, size_t len, struct timespec *start, -+ struct timespec *end); -+char *get_threadname(void); -+void debug(const char *file, unsigned long line, const char *format, ...); -+void _mwarn(bool print_errno, const char *format, ...); -+void verb(const char *format, ...); -+void info(const char *format, ...); -+#define mmalloc(len) util_zalloc(len) -+#define mcalloc(n, len) util_zalloc((n) * (len)) -+#define mrealloc(ptr, len) util_realloc((ptr), (len)) -+#define mstrdup(str) util_strdup(str) -+#define masprintf(fmt, ...) __masprintf(__func__, __FILE__, __LINE__, \ -+ (fmt), ##__VA_ARGS__) -+char *__masprintf(const char *func, const char *file, int line, -+ const char *fmt, ...); -+#define set_threadname(fmt, ...) __set_threadname(__func__, __FILE__, \ -+ __LINE__, (fmt), \ -+ ##__VA_ARGS__) -+void __set_threadname(const char *func, const char *file, int line, -+ const char *fmt, ...); -+ -+void clear_threadname(void); -+void chomp(char *str, char *c); -+void lchomp(char *str, char *c); -+void remove_double_slashes(char *str); -+int stat_file(bool dereference, const char *abs, const char *rel, -+ struct dref *dref, struct stat *st); -+void set_dummy_stat(struct stat *st); -+bool starts_with(const char *str, const char *prefix); -+bool ends_with(const char *str, const char *suffix); -+ -+int cmd_child(int fd, char *cmd); -+int cmd_open(char *cmd, pid_t *pid_ptr); -+int cmd_close(int fd, pid_t pid, int *status_ptr); -+ -+void misc_init(void); -+void misc_cleanup(void); -+void set_stdout_data(void); -+ -+#endif /* MISC_H */ ---- /dev/null -+++ b/dump2tar/include/strarray.h -@@ -0,0 +1,23 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Dynamically growing string arrays -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef STRARRAY_H -+#define STRARRAY_H -+ -+/* A string array that can grow in size */ -+struct strarray { -+ unsigned int num; -+ char **str; -+}; -+ -+void free_strarray(struct strarray *array); -+void add_str_to_strarray(struct strarray *array, const char *str); -+void add_vstr_to_strarray(struct strarray *array, const char *fmt, ...); -+int add_file_to_strarray(struct strarray *array, const char *filename); -+ -+#endif /* STRARRAY_H */ ---- /dev/null -+++ b/dump2tar/include/tar.h -@@ -0,0 +1,41 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * TAR file generation -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#ifndef TAR_H -+#define TAR_H -+ -+#include -+#include -+#include -+ -+#define TYPE_REGULAR '0' -+#define TYPE_LINK '2' -+#define TYPE_DIR '5' -+ -+#define TAR_BLOCKSIZE 512 -+ -+struct buffer; -+ -+/* emit_cb_t - Callback used for emitting chunks of a byte stream -+ * @data: Arbitrary pointer passed via the @data parameter of the -+ * tar_emit_file_* functions -+ * @addr: Pointer to data -+ * @len: Size of data -+ * Return %0 on success. Returning non-zero will indicate failure and abort -+ * further data emission. */ -+typedef int (*emit_cb_t)(void *data, void *addr, size_t len); -+ -+int tar_emit_file_from_buffer(char *filename, char *link, size_t len, -+ struct stat *stat, char type, -+ struct buffer *content, emit_cb_t emit_cb, -+ void *data); -+int tar_emit_file_from_data(char *filename, char *link, size_t len, -+ struct stat *stat, char type, void *addr, -+ emit_cb_t emit_cb, void *data); -+ -+#endif /* TAR_H */ ---- /dev/null -+++ b/dump2tar/man/Makefile -@@ -0,0 +1,12 @@ -+# Common definitions -+include ../../common.mak -+ -+all: -+ -+install: -+ $(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man1 -+ $(INSTALL) -m 644 -c dump2tar.1 $(DESTDIR)$(MANDIR)/man1 -+ -+clean: -+ -+.PHONY: all clean ---- /dev/null -+++ b/dump2tar/man/dump2tar.1 -@@ -0,0 +1,454 @@ -+.\" Macro for inserting an option description prologue. -+.\" .OD [] [args] -+.de OD -+. ds args " -+. if !'\\$3'' .as args \fI\\$3\fP -+. if !'\\$4'' .as args \\$4 -+. if !'\\$5'' .as args \fI\\$5\fP -+. if !'\\$6'' .as args \\$6 -+. if !'\\$7'' .as args \fI\\$7\fP -+. PD 0 -+. if !'\\$2'' .IP "\fB\-\\$2\fP \\*[args]" 4 -+. if !'\\$1'' .IP "\fB\-\-\\$1\fP \\*[args]" 4 -+. PD -+.. -+.\" Macro for inserting code line. -+.\" .CL -+.de CL -+. ds pfont \\n[.f] -+. nh -+. na -+. ft CW -+\\$* -+. ft \\*[pfont] -+. ad -+. hy -+. br -+.. -+.\" Macro for inserting a man page reference. -+.\" .MP man-page section [suffix] -+.de MP -+. nh -+. na -+. BR \\$1 (\\$2)\\$3 -+. ad -+. hy -+.. -+. -+.TH "dump2tar" "1" "2016\-09\-02" "" "" -+. -+.SH "NAME" -+dump2tar - Gather file contents and command output into a tar archive -+. -+. -+.SH "SYNOPSIS" -+.B "dump2tar " -+.RI "[" "OPTIONS" "] " "SPECS" -+. -+. -+.SH "DESCRIPTION" -+.B dump2tar -+creates a tar archive from the contents of any files, including files of -+unknown size. -+ -+Examples for files of unknown size are: -+.IP \(bu 3 -+Named pipes (FIFOs) -+.PP -+.IP \(bu 3 -+Particular Linux kernel debugfs or sysfs files -+.PP -+.IP \(bu 3 -+Character or block devices -+.PP -+ -+When adding such a file, -+.B dump2tar -+first reads all available data until an end-of-file indication is found. From -+this data, it then creates a regular file entry in the resulting tar archive. -+By default, symbolic links and directories are preserved in the archive in -+their original form. -+ -+.B dump2tar -+can also: -+.IP \(bu 3 -+Add files under a different name -+.PP -+.IP \(bu 3 -+Run arbitrary commands and add the resulting command output as a -+regular file -+.PP -+. -+. -+.SH "FILE SPECIFICATIONS" -+. -+This section describes the format of the -+.I SPECS -+argument mentioned in the command synopsis. -+Use the following command line syntax to identify data sources and -+to specify file names within the archive: -+.PP -+ -+.TP -+.I "PATH" -+Adds the contents of the file system subtree at file system location -+.I PATH -+(with possible exceptions described by options) in the archive under the same -+file name as on the file system. -+.PP -+. -+. -+.TP -+.IR "FILENAME" ":=" "PATH" -+Adds the contents of the file at file system location -+.I PATH -+in the archive under the name specified by -+.IR FILENAME . -+.PP -+. -+. -+.TP -+.IR "FILENAME" "|=" "CMDLINE" -+Runs the command -+.IR CMDLINE -+and captures both the resulting standard output and standard error streams. -+Adds the collected output as a regular file named -+.I FILENAME -+in the resulting archive. You can also include the resulting program exit code -+by using option \-\-add\-cmd\-status. -+.PP -+. -+You can also specify "\-\-". All specifications that follow are interpreted as -+simple file names. This is useful for archiving files that contain ":=" or "|=". -+.PP -+. -+. -+.SH "OUTPUT OPTIONS" -+. -+.OD "output\-file" "o" "TARFILE" -+Writes the resulting tar archive to -+.IR TARFILE . -+An existing file at the specified file system location is overwritten. -+ -+If this option is omitted or if "\-" is specified for -+.IR TARFILE , -+the archive is written to the standard output stream. -+.PP -+. -+. -+.OD "gzip" "z" "" -+Compresses the resulting tar archive using gzip. -+.PP -+. -+. -+.OD "max\-size" "m" "VALUE" -+Sets an upper size limit, in bytes, for the resulting archive. If this limit -+is exceeded after adding a file, no further files are added. -+.PP -+. -+. -+.OD "timeout" "t" "VALUE" -+Sets an upper time limit, in seconds, for the archiving process. If this limit -+is exceeded while adding a file, that file is truncated and no -+further files are added. -+.PP -+. -+. -+.OD "no-eof" "" "" -+Does not write an end-of-file marker. -+ -+Use this option if you want to create an archive that can be extended by -+appending additional tar archive data. -+ -+Note: Do not use this option for the final data to be added. -+A valid tar archive requires a trailing end-of-file marker. -+.PP -+. -+. -+.OD "append" "" "" -+Appends data to the end of the archive. -+ -+Use this option to incrementally build a tar file by repeatedly calling -+.BR dump2tar . -+You must specify the \-\-no\-eof option for each but the final call of -+.BR dump2tar . -+.PP -+. -+. -+.OD "add-cmd-status" "" "" -+Adds a separate file named -+.RI \(dq FILENAME .cmdstatus\(dq -+for each command output added through the -+.RI \(dq FILENAME |= CMDLINE \(dq -+notation (see FILE SPECIFICATIONS). -+This file contains information about the exit status of the -+process that executed the command: -+. -+.RS 8 -+.TP -+.RI EXITSTATUS= VALUE -+Unless -+.I VALUE -+is -1, the process ended normally with the specified exit value. -+.PP -+. -+.TP -+.RI TERMSIG= VALUE -+Unless -+.I VALUE -+is -1, the process was stopped by a signal of the specified number. -+.PP -+. -+.TP -+.RI WAITPID_ERRNO= VALUE -+Unless -+.I VALUE -+is -1, an attempt to obtain the status of the process failed with the -+specified error. -+.PP -+.RE -+. -+. -+. -+.SH "INPUT OPTIONS" -+. -+.OD "files\-from" "F" "FILENAME" -+Reads input data specifications (see FILE SPECIFICATIONS) from -+.IR FILENAME , -+one specification per line. Each line contains either a file name or a -+.IR FILENAME := PATH -+or -+.IR FILENAME |= CMDLINE -+specification. Empty lines are ignored. -+ -+A line can also consist of only "\-\-". All lines following this specification -+are interpreted as simple file names. This is useful for archiving files that -+contain ":=" or "|=". -+.PP -+. -+. -+.OD "ignore\-failed\-read" "i" "" -+Continues after read errors. -+ -+By default, -+.B dump2tar -+stops processing after encountering errors while reading an input file. -+With this option, -+.B dump2tar -+prints a warning message and adds an empty entry for the erroneous file in -+the archive. -+.PP -+. -+. -+.OD "buffer\-size" "b" "VALUE" -+Reads data from input files in chunks of -+.I VALUE -+bytes. Large values can accelerate the archiving process for large files -+at the cost of increased memory usage. The default value is 1048576. -+.PP -+. -+. -+.OD "file\-timeout" "T" "VALUE" -+Sets an upper time limit, in seconds, for reading an input file. -+ -+.B dump2tar -+stops processing a file when the time limit is exceeded. Archive entries for -+such files are truncated to the amount of data that is collected by the time -+the limit is reached. -+.PP -+. -+. -+.OD "file\-max\-size" "M" "N" -+Sets an upper size limit, in bytes, for an input file. -+ -+.B dump2tar -+stops processing a file when the size limit is exceeded. Archive entries for -+such files are truncated to the specified size. -+.PP -+. -+. -+.OD "jobs" "j" "N" -+By default, -+.B dump2tar -+processes one file at a time. With this option, -+.B dump2tar -+processes -+.I N -+files in parallel. -+ -+Parallel processing can accelerate the archiving process, -+especially if input files are located on slow devices, or when output from -+multiple commands is added to the archive. -+ -+Note: Use -+.B tar -+option \-\-delay\-directory\-restore when extracting files from an archive -+created with \-\-jobs to prevent conflicts with directory permissions and -+modification times. -+.PP -+. -+. -+.OD "jobs\-per\-cpu" "J" "N" -+Processes -+.I N -+files for each online CPU in parallel. -+ -+Parallel processing can accelerate the -+archiving process, especially if input files are located on slow devices, or -+when output from multiple commands is added to the archive. -+ -+Note: Use -+.B tar -+option \-\-delay\-directory\-restore when extracting files from an archive -+created with \-\-jobs\-per\-cpu to prevent conflicts with directory permissions -+and modification times. -+.PP -+. -+. -+.OD "exclude" "x" "PATTERN" -+Does not add files to the archive if their file names match -+.IR PATTERN . -+.I PATTERN -+is an expression that uses the shell wildcards. -+.PP -+. -+. -+.OD "exclude\-from" "X" "FILENAME" -+Does not add files to the archive if their names match at least one of the -+patterns listed in the pattern file with name -+.IR FILENAME . -+In the pattern file, each line specifies an expression that uses the -+shell wildcards. -+.PP -+. -+. -+.OD "exclude\-type" "" "TYPE" -+Does not add files to the archive if they match at least one of the file types -+specified with -+.IR TYPE . -+.I TYPE -+uses one or more of the characters "fdcbpls", where: -+ -+.RS 8 -+.IP f 3 -+regular files -+.PP -+.IP d 3 -+directories -+.PP -+.IP c 3 -+character devices -+.PP -+.IP b 3 -+block devices -+.PP -+.IP p 3 -+named pipes (FIFOs) -+.PP -+.IP l 3 -+symbolic links -+.PP -+.IP s 3 -+sockets -+.PP -+.RE -+. -+.PP -+. -+. -+.OD "dereference" "" "" -+Adds the content of link targets instead of symbolic links. -+.PP -+. -+. -+.OD "no\-recursion" "" "" -+Does not add files from sub\-directories. -+ -+By default, -+.B dump2tar -+adds archive entries for specified directories, and for the files within these -+directories. With this option, a specified directory results in a single entry -+for the directory. Any contained files to be included must be specified -+explicitly. -+.PP -+. -+. -+.SH "MISC OPTIONS" -+. -+.OD "help" "h" "" -+Prints an overview of available options, then exits. -+.PP -+. -+. -+.OD "verbose" "V" "" -+Prints additional informational output. -+.PP -+. -+. -+.OD "quiet" "q" "" -+Suppresses printing of informational output. -+.PP -+. -+. -+. -+.SH "EXAMPLES" -+. -+.\fB -+.CL # dump2tar a b \-o archive.tar -+.\fR -+ -+.RS 4 -+Creates a tar archive named archive.tar containing files a and b. -+.RE -+.PP -+. -+.\fB -+.CL # dump2tar /proc \-o procdump.tar.gz \-z \-i \-T 1 \-M 1048576 -+.\fR -+ -+.RS 4 -+Creates a gzip compressed tar archive named procdump.tar.gz that contains -+all procfs files. Unreadable files are ignored. Files are truncated when the -+first of the two limiting conditions is reached, either 1048576 bytes of -+content or the reading time of 1 second. -+.RE -+.PP -+. -+.\fB -+.CL # dump2tar '|=dmesg' '|=lspci' \-o data.tar -+.\fR -+ -+.RS 4 -+Creates a tar archive named data.tar containing the output of the 'dmesg' -+and 'lspci' commands. -+.RE -+.PP -+. -+.\fB -+.CL # dump2tar /sys/kernel/debug/ -x '*/tracing/*' -o debug.tar -i -+.\fR -+ -+.RS 4 -+Creates a tar archive named debug.tar containing the contents of directory -+/sys/kernel/debug/ while excluding any file that is located in a sub-directory -+named 'tracing'. -+.RE -+.PP -+. -+. -+.SH "EXIT CODES" -+.TP -+.B 0 -+The program finished successfully -+.TP -+.B 1 -+A run-time error occurred -+.TP -+.B 2 -+The specified command was not valid -+.PP -+. -+. -+.SH "SEE ALSO" -+.MP dump2tar 1 , -+.MP tar 1 ---- /dev/null -+++ b/dump2tar/src/Makefile -@@ -0,0 +1,36 @@ -+# Common definitions -+include ../../common.mak -+ -+CPPFLAGS += -I ../../include -I../include -std=gnu99 -Wno-unused-parameter -+LDLIBS += -lpthread -lrt -+ifneq ($(HAVE_ZLIB),0) -+CPPFLAGS += -DHAVE_ZLIB -+LDLIBS += -lz -+endif -+ -+core_objects = buffer.o dref.o global.o dump.o idcache.o misc.o strarray.o tar.o -+libs = $(rootdir)/libutil/util_libc.o $(rootdir)/libutil/util_opt.o \ -+ $(rootdir)/libutil/util_prg.o $(rootdir)/libutil/util_panic.o -+ -+check_dep_zlib: -+ $(call check_dep, \ -+ "dump2tar", \ -+ "zlib.h", \ -+ "zlib-devel", \ -+ "HAVE_ZLIB=0") -+ -+all: check_dep_zlib dump2tar -+ -+dump2tar: $(core_objects) dump2tar.o $(libs) -+ -+install: dump2tar -+ $(INSTALL) -c dump2tar $(DESTDIR)$(USRBINDIR) -+ -+clean: -+ @rm -f dump2tar *.o -+ -+.PHONY: all install clean -+ -+# Additional manual dependencies -+../../libutil/%.o: -+ make -C ../../libutil $< ---- /dev/null -+++ b/dump2tar/src/buffer.c -@@ -0,0 +1,271 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Data buffering functions -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#include "buffer.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "misc.h" -+ -+void buffer_print(struct buffer *buffer) -+{ -+ fprintf(stderr, "DEBUG: buffer at %p\n", (void *) buffer); -+ if (!buffer) -+ return; -+ fprintf(stderr, "DEBUG: total=%zu\n", buffer->total); -+ fprintf(stderr, "DEBUG: off=%zu\n", buffer->off); -+ fprintf(stderr, "DEBUG: size=%zu\n", buffer->size); -+ fprintf(stderr, "DEBUG: addr=%p\n", (void *) buffer->addr); -+ fprintf(stderr, "DEBUG: fd_open=%d\n", buffer->fd_open); -+ fprintf(stderr, "DEBUG: fd=%d\n", buffer->fd); -+ if (buffer->fd_open) { -+ fprintf(stderr, "DEBUG: fd->pos=%zu\n", -+ lseek(buffer->fd, 0, SEEK_CUR)); -+ } -+} -+ -+/* Initialize @buffer to hold @size bytes in memory */ -+void buffer_init(struct buffer *buffer, size_t size) -+{ -+ memset(buffer, 0, sizeof(struct buffer)); -+ buffer->addr = mmalloc(size); -+ buffer->size = size; -+} -+ -+/* Allocate a new buffer for holding @size bytes in memory */ -+struct buffer *buffer_alloc(size_t size) -+{ -+ struct buffer *buffer; -+ -+ buffer = mmalloc(sizeof(struct buffer)); -+ buffer_init(buffer, size); -+ -+ return buffer; -+} -+ -+/* Forget about any data stored in @buffer */ -+void buffer_reset(struct buffer *buffer) -+{ -+ buffer->total = 0; -+ buffer->off = 0; -+ if (buffer->fd_open) { -+ if (ftruncate(buffer->fd, 0)) -+ mwarn("Cannot truncate temporary file"); -+ if (lseek(buffer->fd, 0, SEEK_SET) == (off_t) -1) -+ mwarn("Cannot seek in temporary file"); -+ } -+} -+ -+/* Close buffer file associated with @buffer */ -+void buffer_close(struct buffer *buffer) -+{ -+ if (!buffer->fd_open) -+ return; -+ -+ fclose(buffer->file); -+ buffer->fd = 0; -+ buffer->fd_open = false; -+} -+ -+/* Release all resources associated with @buffer. If @dyn is %true, also free -+ * @buffer itself. */ -+void buffer_free(struct buffer *buffer, bool dyn) -+{ -+ if (!buffer) -+ return; -+ buffer_reset(buffer); -+ buffer_close(buffer); -+ free(buffer->addr); -+ if (dyn) -+ free(buffer); -+} -+ -+/* Open a buffer file for @buffer. Return %EXIT_OK on success, %EXIT_RUNTIME -+ * otherwise. */ -+int buffer_open(struct buffer *buffer) -+{ -+ if (buffer->fd_open) -+ return EXIT_OK; -+ -+ buffer->file = tmpfile(); -+ if (!buffer->file) { -+ mwarn("Could not create temporary file"); -+ return EXIT_RUNTIME; -+ } -+ -+ buffer->fd = fileno(buffer->file); -+ buffer->fd_open = true; -+ -+ return EXIT_OK; -+} -+ -+/* Write data in memory of @buffer to buffer file. Return %EXIT_OK on success, -+ * %EXIT_RUNTIME otherwise. */ -+int buffer_flush(struct buffer *buffer) -+{ -+ if (buffer->off == 0) -+ return EXIT_OK; -+ if (buffer_open(buffer)) -+ return EXIT_RUNTIME; -+ if (misc_write_data(buffer->fd, buffer->addr, buffer->off)) { -+ mwarn("Could not write to temporary file"); -+ return EXIT_RUNTIME; -+ } -+ buffer->off = 0; -+ -+ return EXIT_OK; -+} -+ -+/* Try to ensure that at least @size bytes are available at -+ * @buffer->addr[buffer->off]. Return the actual number of bytes available or -+ * @-1 on error. If @usefile is %true, make use of a buffer file if -+ * the total buffer size exceeds @max_buffer_size. */ -+ssize_t buffer_make_room(struct buffer *buffer, size_t size, bool usefile, -+ size_t max_buffer_size) -+{ -+ size_t needsize; -+ -+ if (size > max_buffer_size && usefile) -+ size = max_buffer_size; -+ -+ needsize = buffer->off + size; -+ if (needsize <= buffer->size) { -+ /* Room available */ -+ return size; -+ } -+ -+ if (needsize > max_buffer_size && usefile) { -+ /* Need to write out memory buffer to buffer file */ -+ if (buffer_flush(buffer)) -+ return -1; -+ if (size <= buffer->size) -+ return size; -+ needsize = size; -+ } -+ -+ /* Need to increase memory buffer size */ -+ buffer->size = needsize; -+ buffer->addr = mrealloc(buffer->addr, buffer->size); -+ -+ return size; -+} -+ -+/* Try to read @chunk bytes from @fd to @buffer. Return the number of bytes -+ * read on success, %0 on EOF or %-1 on error. */ -+ssize_t buffer_read_fd(struct buffer *buffer, int fd, size_t chunk, -+ bool usefile, size_t max_buffer_size) -+{ -+ ssize_t c = buffer_make_room(buffer, chunk, usefile, max_buffer_size); -+ -+ DBG("buffer_read_fd wanted %zd got %zd", chunk, c); -+ if (c < 0) -+ return c; -+ -+ c = read(fd, buffer->addr + buffer->off, c); -+ if (c > 0) { -+ buffer->total += c; -+ buffer->off += c; -+ } -+ -+ return c; -+} -+ -+/* Add @len bytes at @addr to @buffer. If @addr is %NULL, add zeroes. Return -+ * %EXIT_OK on success, %EXIT_RUNTIME otherwise. */ -+int buffer_add_data(struct buffer *buffer, char *addr, size_t len, bool usefile, -+ size_t max_buffer_size) -+{ -+ ssize_t c; -+ -+ while (len > 0) { -+ c = buffer_make_room(buffer, len, usefile, max_buffer_size); -+ if (c < 0) -+ return EXIT_RUNTIME; -+ if (addr) { -+ memcpy(buffer->addr + buffer->off, addr, c); -+ addr += c; -+ } else { -+ memset(buffer->addr + buffer->off, 0, c); -+ } -+ buffer->total += c; -+ buffer->off += c; -+ -+ len -= c; -+ } -+ -+ return EXIT_OK; -+} -+ -+/* Call @cb for all chunks of data in @buffer. @data is passed to @cb. */ -+int buffer_iterate(struct buffer *buffer, buffer_cb_t cb, void *data) -+{ -+ int rc; -+ ssize_t r; -+ -+ if (buffer->total == 0) -+ return EXIT_OK; -+ -+ if (!buffer->fd_open) -+ return cb(data, buffer->addr, buffer->off); -+ -+ /* Free memory buffer to be used as copy buffer */ -+ if (buffer_flush(buffer)) -+ return EXIT_RUNTIME; -+ if (lseek(buffer->fd, 0, SEEK_SET) == (off_t) -1) { -+ mwarn("Cannot seek in temporary file"); -+ return EXIT_RUNTIME; -+ } -+ -+ /* Copy data from temporary file to target file */ -+ while ((r = misc_read_data(buffer->fd, buffer->addr, -+ buffer->size)) != 0) { -+ if (r < 0) { -+ mwarn("Cannot read from temporary file"); -+ return EXIT_RUNTIME; -+ } -+ rc = cb(data, buffer->addr, r); -+ if (rc) -+ return rc; -+ } -+ -+ return EXIT_OK; -+} -+ -+/* Truncate @buffer to at most @len bytes */ -+int buffer_truncate(struct buffer *buffer, size_t len) -+{ -+ size_t delta; -+ -+ if (buffer->total <= len) -+ return EXIT_OK; -+ -+ delta = buffer->total - len; -+ -+ buffer->total = len; -+ if (buffer->fd_open && delta > buffer->off) { -+ /* All of memory and some of file buffer is truncated */ -+ buffer->off = 0; -+ if (ftruncate(buffer->fd, len)) { -+ mwarn("Cannot truncate temporary file"); -+ return EXIT_RUNTIME; -+ } -+ if (lseek(buffer->fd, len, SEEK_SET) == (off_t) -1) { -+ mwarn("Cannot seek in temporary file"); -+ return EXIT_RUNTIME; -+ } -+ } else { -+ /* Only memory buffer is truncated */ -+ buffer->off -= delta; -+ } -+ -+ return EXIT_OK; -+} ---- /dev/null -+++ b/dump2tar/src/dref.c -@@ -0,0 +1,92 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Reference counting for directory handles -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#include "dref.h" -+ -+#include -+#include -+#include -+ -+#include "global.h" -+#include "misc.h" -+ -+/* dref_mutex serializes access to drefs */ -+static pthread_mutex_t dref_mutex = PTHREAD_MUTEX_INITIALIZER; -+ -+static unsigned long num_open_dirs; -+static unsigned long num_open_dirs_max; -+ -+/* Lock dref mutex */ -+static void dref_lock(void) -+{ -+ if (!global_threaded) -+ return; -+ pthread_mutex_lock(&dref_mutex); -+} -+ -+/* Unlock dref mutex */ -+static void dref_unlock(void) -+{ -+ if (!global_threaded) -+ return; -+ pthread_mutex_unlock(&dref_mutex); -+} -+ -+/* Create a reference count managed directory handle for @dirname */ -+struct dref *dref_create(const char *dirname) -+{ -+ struct dref *dref; -+ DIR *dd; -+ -+ dd = opendir(dirname); -+ DBG("opendir(%s)=%p (total=%lu)", dirname, dd, ++num_open_dirs); -+ if (!dd) { -+ num_open_dirs--; -+ return NULL; -+ } -+ -+ if (num_open_dirs > num_open_dirs_max) -+ num_open_dirs_max = num_open_dirs; -+ -+ dref = mmalloc(sizeof(struct dref)); -+ dref->dd = dd; -+ dref->dirfd = dirfd(dd); -+ dref->count = 1; -+ -+ return dref; -+} -+ -+/* Obtain a reference to @dref */ -+struct dref *dref_get(struct dref *dref) -+{ -+ if (dref) { -+ dref_lock(); -+ dref->count++; -+ dref_unlock(); -+ } -+ -+ return dref; -+} -+ -+/* Release a reference to @dref. If this was the last reference, lose the -+ * associated directory handle and free @dref. */ -+void dref_put(struct dref *dref) -+{ -+ if (dref) { -+ dref_lock(); -+ dref->count--; -+ if (dref->count == 0) { -+ num_open_dirs--; -+ DBG("closedir(%p) (total=%lu, max=%lu)", dref->dd, -+ num_open_dirs, num_open_dirs_max); -+ closedir(dref->dd); -+ free(dref); -+ } -+ dref_unlock(); -+ } -+} ---- /dev/null -+++ b/dump2tar/src/dump.c -@@ -0,0 +1,1850 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Main dump logic -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#include "dump.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef HAVE_ZLIB -+#include -+#endif /* HAVE_ZLIB */ -+ -+#include "buffer.h" -+#include "dref.h" -+#include "global.h" -+#include "idcache.h" -+#include "misc.h" -+#include "tar.h" -+ -+/* Default input file read size (bytes) */ -+#define DEFAULT_READ_CHUNK_SIZE (512 * 1024) -+#define DEFAULT_MAX_BUFFER_SIZE (2 * 1024 * 1024) -+ -+#define _SET_ABORTED(task) _set_aborted((task), __func__, __LINE__) -+#define SET_ABORTED(task) set_aborted((task), __func__, __LINE__) -+ -+#define read_error(task, filename, fmt, ...) \ -+ do { \ -+ if (!(task)->opts->ignore_failed_read) \ -+ SET_ABORTED((task)); \ -+ _mwarn(true, "%s: " fmt, (filename), ##__VA_ARGS__); \ -+ } while (0) -+ -+#define write_error(task, fmt, ...) \ -+ do { \ -+ SET_ABORTED((task)); \ -+ _mwarn(true, "%s: " fmt, (task)->opts->output_file, \ -+ ##__VA_ARGS__); \ -+ } while (0) -+ -+#define tverb(fmt, ...) \ -+ do { \ -+ if (task->opts->verbose) \ -+ verb((fmt), ##__VA_ARGS__); \ -+ } while (0) -+ -+ -+/* Jobs representing a file or command output to add */ -+struct job { -+ struct job *next_job; -+ enum job_type { -+ JOB_INIT, /* Initialization work */ -+ JOB_FILE, /* Add a regular file */ -+ JOB_LINK, /* Add a symbolic link */ -+ JOB_DIR, /* Add a directory */ -+ JOB_CMD, /* Add command output */ -+ } type; -+ enum job_status { -+ JOB_QUEUED, /* Transient: Job processing has not started */ -+ JOB_IN_PROGRESS,/* Transient: Job processing has started */ -+ JOB_EXCLUDED, /* Final: File was excluded */ -+ JOB_FAILED, /* Final: Data could not be obtained */ -+ JOB_DONE, /* Final: All data was obtained */ -+ JOB_PARTIAL, /* Final: Only some data was obtained */ -+ } status; -+ char *outname; -+ char *inname; -+ char *relname; -+ struct stat stat; -+ bool timed; -+ struct timespec deadline; -+ struct dref *dref; -+ int cmd_status; -+ struct buffer *content; -+}; -+ -+/* Run-time statistics */ -+struct stats { -+ unsigned long num_done; -+ unsigned long num_excluded; -+ unsigned long num_failed; -+ unsigned long num_partial; -+}; -+ -+/* Information specific to a single dump task */ -+struct task { -+ /* Input */ -+ struct dump_opts *opts; -+ -+ /* State */ -+ -+ /* mutex serializes access to global data */ -+ pthread_mutex_t mutex; -+ pthread_cond_t worker_cond; -+ pthread_cond_t cond; -+ unsigned long num_jobs_active; -+ struct job *jobs_head; -+ struct job *jobs_tail; -+ bool aborted; -+ -+ /* output_mutex serializes access to output file */ -+ pthread_mutex_t output_mutex; -+ int output_fd; -+ size_t output_written; -+#ifdef HAVE_ZLIB -+ gzFile output_gzfd; -+#endif /* HAVE_ZLIB */ -+ unsigned long output_num_files; -+ -+ /* No protection needed (only accessed in single-threaded mode) */ -+ struct stats stats; -+ struct timespec start_ts; -+}; -+ -+/* Per thread management data */ -+struct per_thread { -+ long num; -+ pthread_t thread; -+ bool running; -+ bool timed_out; -+ struct stats stats; -+ struct job *job; -+ struct buffer buffer; -+ struct task *task; -+}; -+ -+static const struct { -+ mode_t mode; -+ char c; -+} exclude_types[NUM_EXCLUDE_TYPES] = { -+ { S_IFREG, 'f' }, -+ { S_IFDIR, 'd' }, -+ { S_IFCHR, 'c' }, -+ { S_IFBLK, 'b' }, -+ { S_IFIFO, 'p' }, -+ { S_IFLNK, 'l' }, -+ { S_IFSOCK, 's' }, -+}; -+ -+/* Lock main mutex */ -+static void main_lock(struct task *task) -+{ -+ if (!global_threaded) -+ return; -+ DBG("main lock"); -+ pthread_mutex_lock(&task->mutex); -+} -+ -+/* Unlock main mutex */ -+static void main_unlock(struct task *task) -+{ -+ if (!global_threaded) -+ return; -+ DBG("main unlock"); -+ pthread_mutex_unlock(&task->mutex); -+} -+ -+/* Lock output mutex */ -+static void output_lock(struct task *task) -+{ -+ if (!global_threaded) -+ return; -+ pthread_mutex_lock(&task->output_mutex); -+} -+ -+/* Unlock output mutex */ -+static void output_unlock(struct task *task) -+{ -+ if (!global_threaded) -+ return; -+ pthread_mutex_unlock(&task->output_mutex); -+} -+ -+/* Wake up all waiting workers */ -+static void _worker_wakeup_all(struct task *task) -+{ -+ if (!global_threaded) -+ return; -+ DBG("waking up all worker threads"); -+ pthread_cond_broadcast(&task->worker_cond); -+} -+ -+/* Wake up one waiting worker */ -+static void _worker_wakeup_one(struct task *task) -+{ -+ if (!global_threaded) -+ return; -+ DBG("waking up one worker thread"); -+ pthread_cond_signal(&task->worker_cond); -+} -+ -+/* Wait for a signal to a worker */ -+static int _worker_wait(struct task *task) -+{ -+ int rc; -+ -+ DBG("waiting for signal to worker"); -+ rc = pthread_cond_wait(&task->worker_cond, &task->mutex); -+ DBG("waiting for signal to worker done (rc=%d)", rc); -+ -+ return rc; -+} -+ -+/* Wake up main thread */ -+static void _main_wakeup(struct task *task) -+{ -+ if (!global_threaded) -+ return; -+ DBG("waking up main thread"); -+ pthread_cond_broadcast(&task->cond); -+} -+ -+/* Wait for a signal to the main thread */ -+static int _main_wait(struct task *task) -+{ -+ int rc; -+ -+ DBG("waiting for status change"); -+ rc = pthread_cond_wait(&task->cond, &task->mutex); -+ DBG("waiting for status change done (rc=%d)", rc); -+ -+ return rc; -+} -+ -+/* Wait for a signal to the main thread. Abort waiting after @deadline */ -+static int _main_wait_timed(struct task *task, struct timespec *deadline) -+{ -+ int rc; -+ -+ DBG("timed waiting for status change"); -+ rc = pthread_cond_timedwait(&task->cond, &task->mutex, deadline); -+ DBG("timed waiting for status change done (rc=%d)", rc); -+ -+ return rc; -+} -+ -+/* Allow thread to be canceled */ -+static void cancel_enable(void) -+{ -+ if (!global_threaded) -+ return; -+ if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) -+ mwarn("pthread_setcancelstate"); -+} -+ -+/* Prevent thread from being canceled */ -+static void cancel_disable(void) -+{ -+ if (!global_threaded) -+ return; -+ if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0) -+ mwarn("pthread_setcancelstate"); -+} -+ -+/* Abort processing and inform all threads to shutdown. Must be called with -+ * task->mutex locked */ -+static void _set_aborted(struct task *task, const char *func, unsigned int line) -+{ -+ DBG("set aborted at %s:%u", func, line); -+ task->aborted = true; -+ _worker_wakeup_all(task); -+ _main_wakeup(task); -+} -+ -+/* Abort processing and inform all threads to shutdown */ -+static void set_aborted(struct task *task, const char *func, unsigned int line) -+{ -+ main_lock(task); -+ _set_aborted(task, func, line); -+ main_unlock(task); -+} -+ -+/* Check if abort processing has been initiated */ -+static bool is_aborted(struct task *task) -+{ -+ bool result; -+ -+ main_lock(task); -+ result = task->aborted; -+ main_unlock(task); -+ -+ return result; -+} -+ -+/* Release resources associated with @job */ -+static void free_job(struct task *task, struct job *job) -+{ -+ DBG("free job %p (%s)", job, job->inname); -+ if (!job) -+ return; -+ free(job->inname); -+ free(job->outname); -+ free(job->relname); -+ dref_put(job->dref); -+ free(job); -+} -+ -+/* Check if file type specified by mode @m was marked as excluded */ -+static bool is_type_excluded(struct dump_opts *opts, mode_t m) -+{ -+ int i; -+ -+ m &= S_IFMT; -+ for (i = 0; i < NUM_EXCLUDE_TYPES; i++) { -+ if (exclude_types[i].mode == m) -+ return opts->exclude_type[i]; -+ } -+ return false; -+} -+ -+/* Replace all '/' characters in @filename with '_' */ -+static void escape_filename(char *filename) -+{ -+ for (; *filename; filename++) { -+ if (*filename == '/') -+ *filename = '_'; -+ } -+} -+ -+/* Determine filename in archive from original filename @inname and -+ * requested new filename @outname and depending on @type. */ -+static void set_outname(char **result_ptr, const char *outname, -+ const char *inname, enum job_type type) -+{ -+ const char *prefix = "", *name, *suffix; -+ char *result, *end; -+ size_t olen = outname ? strlen(outname) : 0, plen, nlen; -+ -+ if (olen == 0) { -+ /* No output name specified: outname = inname */ -+ name = inname; -+ } else if (outname[olen - 1] == '/') { -+ /* Output name is a directory: outname = outname/inname */ -+ prefix = outname; -+ name = inname; -+ } else { -+ /* Output name is a filename: outname = inname */ -+ name = outname; -+ } -+ -+ if (type == JOB_DIR) -+ suffix = "/"; -+ else -+ suffix = ""; -+ -+ plen = strlen(prefix); -+ nlen = strlen(name); -+ -+ result = mmalloc(plen + nlen + strlen(suffix) + /* NUL */ 1); -+ -+ /* Add prefix */ -+ strcpy(result, prefix); -+ -+ /* Add name */ -+ end = result + plen; -+ strcpy(end, name); -+ if (type == JOB_CMD) -+ escape_filename(end); -+ -+ /* Add suffix */ -+ end = end + nlen; -+ strcpy(end, suffix); -+ -+ remove_double_slashes(result); -+ -+ *result_ptr = result; -+} -+ -+static void sanitize_dirname(char **name_ptr) -+{ -+ char *name; -+ -+ name = mmalloc(strlen(*name_ptr) + /* Slash */ 1 + /* NUL */ 1); -+ strcpy(name, *name_ptr); -+ remove_double_slashes(name); -+ chomp(name, "/"); -+ strcat(name, "/"); -+ free(*name_ptr); -+ *name_ptr = name; -+} -+ -+/* Allocate and initialize a new job representation to add an entry according -+ * to the specified parameters. @relname and @dref are used for opening files -+ * more efficiently using *at() functions if specified. @is_cmd specifies if -+ * the specified inname is a command line. */ -+static struct job *create_job(struct task *task, const char *inname, -+ const char *outname, bool is_cmd, -+ const char *relname, struct dref *dref, -+ struct stats *stats) -+{ -+ struct job *job = mmalloc(sizeof(struct job)); -+ int rc; -+ -+ DBG("create job inname=%s outname=%s is_cmd=%d relname=%s dref=%p", -+ inname, outname, is_cmd, relname, dref); -+ -+ job->status = JOB_QUEUED; -+ -+ if (!inname) { -+ job->type = JOB_INIT; -+ return job; -+ } -+ -+ job->inname = mstrdup(inname); -+ -+ if (is_cmd) { -+ /* Special case - read from command output */ -+ job->type = JOB_CMD; -+ set_dummy_stat(&job->stat); -+ goto out; -+ } -+ -+ if (!relname && strcmp(job->inname, "-") == 0) { -+ /* Special case - read from standard input */ -+ job->type = JOB_FILE; -+ set_dummy_stat(&job->stat); -+ goto out; -+ } -+ -+ rc = stat_file(task->opts->dereference, job->inname, relname, dref, -+ &job->stat); -+ -+ if (rc < 0) { -+ read_error(task, job->inname, "Cannot stat file"); -+ free_job(task, job); -+ stats->num_failed++; -+ return NULL; -+ } -+ -+ if (is_type_excluded(task->opts, job->stat.st_mode)) { -+ free_job(task, job); -+ stats->num_excluded++; -+ return NULL; -+ } -+ -+ if (S_ISLNK(job->stat.st_mode)) { -+ job->type = JOB_LINK; -+ } else if (S_ISDIR(job->stat.st_mode)) { -+ job->type = JOB_DIR; -+ sanitize_dirname(&job->inname); -+ -+ /* No need to keep parent directory open */ -+ relname = NULL; -+ dref = NULL; -+ } else { -+ job->type = JOB_FILE; -+ } -+ -+ if (relname) -+ job->relname = mstrdup(relname); -+ job->dref = dref_get(dref); -+ -+out: -+ set_outname(&job->outname, outname, inname, job->type); -+ -+ return job; -+} -+ -+void job_print(struct job *job) -+{ -+ printf("DEBUG: job_print at %p\n", job); -+ printf("DEBUG: next_job=%p\n", job->next_job); -+ printf("DEBUG: type=%d\n", job->type); -+ printf("DEBUG: status==%d\n", job->status); -+ printf("DEBUG: outname=%s\n", job->outname); -+ printf("DEBUG: inname=%s\n", job->inname); -+ printf("DEBUG: relname=%s\n", job->relname); -+ printf("DEBUG: timed=%d\n", job->timed); -+ printf("DEBUG: dref=%p\n", job->dref); -+ printf("DEBUG: cmd_status=%d\n", job->cmd_status); -+ printf("DEBUG: content=%p\n", job->content); -+} -+ -+/* Return the number of bytes written to the output file */ -+static size_t get_output_size(struct task *task) -+{ -+#ifdef HAVE_ZLIB -+ if (task->opts->gzip) { -+ gzflush(task->output_gzfd, Z_SYNC_FLUSH); -+ return gztell(task->output_gzfd); -+ } -+#endif /* HAVE_ZLIB */ -+ return task->output_written; -+} -+ -+/* Write @len bytes at address @ptr to the output file */ -+static int write_output(struct task *task, const char *ptr, size_t len) -+{ -+ size_t todo = len; -+ ssize_t w; -+ -+#ifdef HAVE_ZLIB -+ if (task->opts->gzip) { -+ if (gzwrite(task->output_gzfd, ptr, len) == 0) -+ goto err_write; -+ task->output_written += len; -+ -+ return EXIT_OK; -+ } -+#endif /* HAVE_ZLIB */ -+ -+ while (todo > 0) { -+ w = write(task->output_fd, ptr, todo); -+ if (w < 0) -+ goto err_write; -+ todo -= w; -+ ptr += w; -+ } -+ task->output_written += len; -+ -+ return EXIT_OK; -+ -+err_write: -+ write_error(task, "Cannot write output"); -+ -+ return EXIT_RUNTIME; -+} -+ -+/* Write an end-of-file marker to the output file */ -+static void write_eof(struct task *task) -+{ -+ char zeroes[TAR_BLOCKSIZE]; -+ -+ memset(zeroes, 0, sizeof(zeroes)); -+ write_output(task, zeroes, TAR_BLOCKSIZE); -+ write_output(task, zeroes, TAR_BLOCKSIZE); -+} -+ -+/* Callback for writing out chunks of job data */ -+static int _write_job_data_cb(void *data, void *addr, size_t len) -+{ -+ struct task *task = data; -+ -+ return write_output(task, addr, len); -+} -+ -+/* Write tar entry for a file containing the exit status of the process that -+ * ran command job @job */ -+static int write_job_status_file(struct task *task, struct job *job) -+{ -+ char *name, *content; -+ size_t len; -+ struct stat st; -+ int rc, status = job->cmd_status, exitstatus = -1, termsig = -1, -+ waitpid_errno = -1; -+ -+ name = masprintf("%s.cmdstatus", job->outname); -+ if (status < 0) -+ waitpid_errno = -status; -+ else if (WIFEXITED(status)) -+ exitstatus = WEXITSTATUS(status); -+ else if (WIFSIGNALED(status)) -+ termsig = WTERMSIG(status); -+ -+ content = masprintf("EXITSTATUS=%d\n" -+ "TERMSIG=%d\n" -+ "WAITPID_ERRNO=%d\n", exitstatus, termsig, -+ waitpid_errno); -+ -+ len = strlen(content); -+ set_dummy_stat(&st); -+ rc = tar_emit_file_from_data(name, NULL, len, &st, TYPE_REGULAR, -+ content, _write_job_data_cb, task); -+ free(name); -+ free(content); -+ -+ return rc; -+} -+ -+/* Write tar entry for data in @job to output. Must be called with output_lock -+ * held. */ -+static void _write_job_data(struct task *task, struct job *job) -+{ -+ struct buffer *buffer = job->content; -+ -+ switch (job->status) { -+ case JOB_DONE: -+ case JOB_PARTIAL: -+ break; -+ case JOB_FAILED: -+ /* Create empty entries for failed reads */ -+ if (task->opts->ignore_failed_read) -+ break; -+ return; -+ default: -+ return; -+ } -+ -+ switch (job->type) { -+ case JOB_CMD: -+ tar_emit_file_from_buffer(job->outname, NULL, buffer->total, -+ &job->stat, TYPE_REGULAR, buffer, -+ _write_job_data_cb, task); -+ task->output_num_files++; -+ if (task->opts->add_cmd_status) { -+ write_job_status_file(task, job); -+ task->output_num_files++; -+ } -+ break; -+ case JOB_FILE: -+ tar_emit_file_from_buffer(job->outname, NULL, buffer->total, -+ &job->stat, TYPE_REGULAR, buffer, -+ _write_job_data_cb, task); -+ task->output_num_files++; -+ break; -+ case JOB_LINK: -+ tar_emit_file_from_buffer(job->outname, buffer->addr, 0, -+ &job->stat, TYPE_LINK, NULL, -+ _write_job_data_cb, task); -+ task->output_num_files++; -+ break; -+ case JOB_DIR: -+ tar_emit_file_from_buffer(job->outname, NULL, 0, &job->stat, -+ TYPE_DIR, NULL, _write_job_data_cb, -+ task); -+ task->output_num_files++; -+ break; -+ default: -+ break; -+ } -+ -+ if (task->opts->max_size > 0 && -+ get_output_size(task) > task->opts->max_size) { -+ mwarnx("Archive size exceeds maximum of %ld bytes - aborting", -+ task->opts->max_size); -+ SET_ABORTED(task); -+ } -+} -+ -+/* Read the contents of the symbolic link at @filename. On success, the -+ * contents is returned in @buffer and the return value is %EXIT_OK. -+ * If @relname is non-null it points to the name of the file relative -+ * to its parent directory for which @dirfd is an open file handle. */ -+static int read_symlink(struct task *task, const char *filename, -+ const char *relname, int dirfd, struct buffer *buffer) -+{ -+ ssize_t actual = 0; -+ size_t currlen = buffer->size ? buffer->size : -+ task->opts->read_chunk_size; -+ int rc = EXIT_OK; -+ -+ while (!is_aborted(task)) { -+ buffer_make_room(buffer, currlen, false, -+ task->opts->max_buffer_size); -+ -+ cancel_enable(); -+ if (relname) -+ actual = readlinkat(dirfd, relname, buffer->addr, -+ buffer->size); -+ else -+ actual = readlink(filename, buffer->addr, buffer->size); -+ cancel_disable(); -+ -+ if (actual == -1) { -+ read_error(task, filename, "Cannot read link"); -+ rc = EXIT_RUNTIME; -+ /* Reset actual counter to get an empty buffer */ -+ actual = 0; -+ break; -+ } -+ -+ /* Ensure that content doesn't exceed --file-max-size limit */ -+ if (task->opts->file_max_size > 0 && -+ (size_t) actual > task->opts->file_max_size) { -+ actual = task->opts->file_max_size;/* Don't count NUL */ -+ mwarnx("%s: Warning: Data exceeds maximum size of %ld " -+ "bytes - truncating", filename, -+ task->opts->file_max_size); -+ break; -+ } -+ -+ if ((size_t) actual < buffer->size) -+ break; -+ -+ currlen += task->opts->read_chunk_size; -+ } -+ -+ if (rc == EXIT_OK && is_aborted(task)) -+ rc = EXIT_RUNTIME; -+ -+ buffer->addr[actual] = 0; -+ buffer->total = actual + 1; -+ -+ return rc; -+} -+ -+/* Read data from the file descriptor @fd until an end-of-file condition is -+ * encountered. On success, *@done bytes in @buffer contain the read data -+ * and the return value is %EXIT_OK. */ -+static int read_fd(struct task *task, const char *name, int fd, -+ struct buffer *buffer) -+{ -+ ssize_t rc = 0; -+ size_t c = buffer->size ? buffer->size : task->opts->read_chunk_size; -+ -+ while (!is_aborted(task)) { -+ cancel_enable(); -+ rc = buffer_read_fd(buffer, fd, c, true, -+ task->opts->max_buffer_size); -+ cancel_disable(); -+ -+ if (rc <= 0) -+ break; -+ -+ /* Ensure that content doesn't exceed --file-max-size limit */ -+ if (task->opts->file_max_size > 0 && -+ buffer->total >= task->opts->file_max_size) { -+ buffer_truncate(buffer, task->opts->file_max_size); -+ rc = 0; -+ mwarnx("%s: Warning: Data exceeds maximum size of %ld " -+ "bytes - truncating", name, -+ task->opts->file_max_size); -+ break; -+ } -+ -+ c = buffer->size - buffer->off; -+ if (c > 0) { -+ /* Read to memory */ -+ } else if (buffer->size + task->opts->read_chunk_size < -+ task->opts->max_buffer_size) { -+ /* Enlarge memory buffer */ -+ c = task->opts->read_chunk_size; -+ } else { -+ /* Use full memory buffer size */ -+ c = task->opts->max_buffer_size; -+ } -+ } -+ -+ if (is_aborted(task) || rc != 0) -+ return EXIT_RUNTIME; -+ -+ return EXIT_OK; -+} -+ -+/* Read data from the file at @filename until an end-of-file condition is -+ * encountered. On success, @buffer contains the data read and the return -+ * value is %EXIT_OK. If @relname is non-null it points to the name of the -+ * file relative to its parent directory for which @dirfd is an open file -+ * handle. */ -+static int read_regular(struct task *task, const char *filename, -+ const char *relname, int dirfd, struct buffer *buffer) -+{ -+ int fd, rc = EXIT_OK; -+ bool need_close = true; -+ -+ /* Opening a named pipe can block when peer is not ready */ -+ cancel_enable(); -+ if (strcmp(filename, "-") == 0) { -+ fd = STDIN_FILENO; -+ need_close = false; -+ filename = "Standard input"; -+ } else if (relname) -+ fd = openat(dirfd, relname, O_RDONLY); -+ else -+ fd = open(filename, O_RDONLY); -+ cancel_disable(); -+ -+ if (fd < 0) { -+ read_error(task, filename, "Cannot open file"); -+ return EXIT_RUNTIME; -+ } -+ -+ rc = read_fd(task, filename, fd, buffer); -+ if (rc) { -+ if (is_aborted(task)) -+ mwarnx("%s: Read aborted", filename); -+ else -+ read_error(task, filename, "Cannot read file"); -+ } -+ -+ if (need_close) -+ close(fd); -+ -+ return rc; -+} -+ -+/* Read the output of command @cmd until an end-of-file condition is -+ * encountered. On success, @buffer contain the output and the return value -+ * is %EXIT_OK. When not %NULL, use @status_ptr to store the resulting process -+ * status. */ -+static int read_cmd_output(struct task *task, char *cmd, struct buffer *buffer, -+ int *status_ptr) -+{ -+ int fd, rc = EXIT_RUNTIME; -+ pid_t pid; -+ -+ fd = cmd_open(cmd, &pid); -+ if (fd < 0) { -+ read_error(task, cmd, "Cannot run command"); -+ return rc; -+ } -+ -+ if (read_fd(task, cmd, fd, buffer)) { -+ if (is_aborted(task)) -+ mwarnx("%s: Command aborted", cmd); -+ else -+ read_error(task, cmd, "Cannot read command output"); -+ } else -+ rc = EXIT_OK; -+ -+ cmd_close(fd, pid, status_ptr); -+ -+ return rc; -+ -+} -+ -+/* Check the exclude patterns in @task->opts->exclude for a match of @filename. -+ * If found, return the matching pattern string, otherwise return %NULL. */ -+static const char *get_exclude_match(struct task *task, const char *filename) -+{ -+ unsigned int i; -+ int mode = FNM_PERIOD | FNM_NOESCAPE; -+ -+ for (i = 0; i < task->opts->exclude.num; i++) { -+ if (fnmatch(task->opts->exclude.str[i], filename, mode) == 0) -+ return task->opts->exclude.str[i]; -+ } -+ -+ return NULL; -+} -+ -+/* Add the specified @job to the start of the job queue */ -+static void _queue_job_head(struct task *task, struct job *job) -+{ -+ DBG("queue job type=%d inname=%s at head", job->type, job->inname); -+ job->next_job = task->jobs_head; -+ task->jobs_head = job; -+ if (!task->jobs_tail) -+ task->jobs_tail = job; -+} -+ -+/* Add the specified @job to the end of the job queue */ -+static void _queue_job_tail(struct task *task, struct job *job) -+{ -+ DBG("queue job type=%d inname=%s at tail", job->type, job->inname); -+ if (task->jobs_tail) -+ task->jobs_tail->next_job = job; -+ else -+ task->jobs_head = job; -+ task->jobs_tail = job; -+} -+ -+/* Add the specified @job to the job queue and trigger processing. -+ * If @head is %true, the new job is inserted at the start of the job queue, -+ * otherwise at the end. */ -+static void queue_job(struct task *task, struct job *job, bool head) -+{ -+ main_lock(task); -+ task->num_jobs_active++; -+ if (head) -+ _queue_job_head(task, job); -+ else -+ _queue_job_tail(task, job); -+ _worker_wakeup_one(task); -+ main_unlock(task); -+} -+ -+/* Add the specified list of jobs starting with @first up to @last to the start -+ * of the job queue and trigger processing */ -+static void queue_jobs(struct task *task, struct job *first, struct job *last, -+ int num) -+{ -+ main_lock(task); -+ last->next_job = task->jobs_head; -+ task->jobs_head = first; -+ task->num_jobs_active += num; -+ _worker_wakeup_all(task); -+ main_unlock(task); -+} -+ -+/* Remove the head of the job queue and return it to the caller */ -+static struct job *_dequeue_job(struct task *task) -+{ -+ struct job *job = NULL; -+ -+ if (task->jobs_head) { -+ job = task->jobs_head; -+ task->jobs_head = job->next_job; -+ job->next_job = NULL; -+ if (job == task->jobs_tail) -+ task->jobs_tail = NULL; -+ DBG("dequeueing job type=%d inname=%s", job->type, job->inname); -+ job->status = JOB_IN_PROGRESS; -+ } else { -+ DBG("no job to dequeue"); -+ } -+ -+ return job; -+} -+ -+/* Create and queue job for file at @filename */ -+static void queue_file(struct task *task, const char *inname, -+ const char *outname, bool is_cmd, -+ const char *relname, struct dref *dref, -+ struct stats *stats, bool head) -+{ -+ struct job *job; -+ -+ job = create_job(task, inname, outname, is_cmd, relname, dref, stats); -+ if (job) -+ queue_job(task, job, head); -+} -+ -+/* Queue initial job */ -+static void init_queue(struct task *task) -+{ -+ queue_file(task, NULL, NULL, false, NULL, NULL, NULL, true); -+} -+ -+/* Create and queue jobs for all files found in @dirname */ -+static void queue_dir(struct task *task, const char *dirname, -+ const char *outname, struct stats *stats) -+{ -+ struct dirent *de; -+ char *inpath, *outpath; -+ struct dref *dref; -+ struct job *job, *first = NULL, *last = NULL; -+ int num = 0; -+ -+ dref = dref_create(dirname); -+ if (!dref) { -+ read_error(task, dirname, "Cannot read directory"); -+ return; -+ } -+ -+ while ((de = readdir(dref->dd))) { -+ if (de->d_name[0] == '.') { -+ if (de->d_name[1] == 0) -+ continue; -+ if (de->d_name[1] == '.' && de->d_name[2] == 0) -+ continue; -+ } -+ DBG("next file %s", de->d_name); -+ inpath = masprintf("%s%s", dirname, de->d_name); -+ outpath = masprintf("%s%s", outname, de->d_name); -+ job = create_job(task, inpath, outpath, false, de->d_name, dref, -+ stats); -+ if (job) { -+ if (last) { -+ last->next_job = job; -+ last = job; -+ } else { -+ first = job; -+ last = job; -+ } -+ num++; -+ } -+ free(inpath); -+ free(outpath); -+ } -+ -+ if (first) -+ queue_jobs(task, first, last, num); -+ -+ dref_put(dref); -+} -+ -+/* Create and queue jobs for all files specified on the command line */ -+static void queue_jobs_from_opts(struct task *task, struct stats *stats) -+{ -+ struct dump_opts *opts = task->opts; -+ unsigned int i; -+ -+ /* Queue directly specified entries */ -+ for (i = 0; i < opts->num_specs && !is_aborted(task); i++) { -+ queue_file(task, opts->specs[i].inname, opts->specs[i].outname, -+ opts->specs[i].is_cmd, NULL, NULL, stats, false); -+ } -+} -+ -+/* Prepare output stream */ -+static int open_output(struct task *task) -+{ -+ bool to_stdout = !task->opts->output_file || -+ strcmp(task->opts->output_file, "-") == 0; -+ int rc = EXIT_OK; -+ -+ if (to_stdout) { -+ set_stdout_data(); -+ task->opts->output_file = "Standard output"; -+ } -+ -+ cancel_enable(); -+#ifdef HAVE_ZLIB -+ if (task->opts->gzip) { -+ if (to_stdout) { -+ task->output_gzfd = -+ gzdopen(STDOUT_FILENO, -+ task->opts->append ? "ab" : "wb"); -+ } else { -+ task->output_gzfd = -+ gzopen(task->opts->output_file, -+ task->opts->append ? "ab" : "wb"); -+ } -+ -+ if (!task->output_gzfd) -+ rc = EXIT_RUNTIME; -+ goto out; -+ } -+#endif /* HAVE_ZLIB */ -+ -+ if (to_stdout) { -+ task->output_fd = STDOUT_FILENO; -+ } else { -+ task->output_fd = -+ open(task->opts->output_file, O_WRONLY | O_CREAT | -+ (task->opts->append ? O_APPEND : 0), 0666); -+ } -+ -+ if (task->output_fd < 0) -+ rc = EXIT_RUNTIME; -+ else if (!task->opts->append && ftruncate(task->output_fd, 0) == -1) -+ rc = EXIT_RUNTIME; -+ -+#ifdef HAVE_ZLIB -+out: -+#endif /* HAVE_ZLIB */ -+ cancel_disable(); -+ -+ if (rc != EXIT_OK) { -+ mwarn("%s: Cannot open output file", task->opts->output_file); -+ return rc; -+ } -+ -+ return EXIT_OK; -+} -+ -+/* Determine if the specified @job should be excluded from archiving */ -+static bool is_job_excluded(struct task *task, struct job *job) -+{ -+ const char *pat; -+ -+ if (job->type == JOB_INIT || job->type == JOB_CMD) -+ return false; -+ -+ pat = get_exclude_match(task, job->inname); -+ if (!pat) -+ return false; -+ -+ tverb("Excluding '%s' due to exclude pattern '%s'\n", job->inname, pat); -+ -+ return true; -+} -+ -+/* Perform all actions necessary to process @job and add resulting tar -+ * data buffers to the buffer list of @thread. */ -+static void process_job(struct per_thread *thread, struct job *job) -+{ -+ struct task *task = thread->task; -+ const char *relname = job->dref ? job->relname : NULL; -+ int dirfd = job->dref ? job->dref->dirfd : -1; -+ struct buffer *buffer = &thread->buffer; -+ enum job_status status = JOB_DONE; -+ -+ DBG("processing job type=%d inname=%s", job->type, job->inname); -+ -+ if (is_job_excluded(task, job)) { -+ status = JOB_EXCLUDED; -+ goto out; -+ } -+ -+ switch (job->type) { -+ case JOB_INIT: /* Perform initial setup steps */ -+ if (open_output(task)) { -+ SET_ABORTED(task); -+ status = JOB_FAILED; -+ goto out; -+ } -+ queue_jobs_from_opts(task, &thread->stats); -+ break; -+ case JOB_CMD: /* Capture command output */ -+ tverb("Dumping command output '%s'\n", job->inname); -+ -+ set_dummy_stat(&job->stat); -+ if (read_cmd_output(task, job->inname, buffer, -+ &job->cmd_status)) -+ status = JOB_FAILED; -+ -+ break; -+ case JOB_LINK: /* Read symbolic link */ -+ tverb("Dumping link '%s'\n", job->inname); -+ -+ if (read_symlink(task, job->inname, relname, dirfd, buffer)) -+ status = JOB_FAILED; -+ -+ break; -+ case JOB_DIR: /* Read directory contents */ -+ tverb("Dumping directory '%s'\n", job->inname); -+ -+ if (task->opts->recursive) { -+ queue_dir(task, job->inname, job->outname, -+ &thread->stats); -+ } -+ break; -+ case JOB_FILE: /* Read file contents */ -+ tverb("Dumping file '%s'\n", job->inname); -+ -+ if (read_regular(task, job->inname, relname, dirfd, buffer)) -+ status = JOB_FAILED; -+ -+ break; -+ default: -+ break; -+ } -+ -+out: -+ job->status = status; -+ DBG("processing done status=%d", job->status); -+} -+ -+/* Add @job results to statistics @stats */ -+static void account_stats(struct task *task, struct stats *stats, -+ struct job *job) -+{ -+ DBG("accounting job %s", job->inname); -+ -+ if (job->type == JOB_INIT) -+ return; -+ -+ switch (job->status) { -+ case JOB_DONE: -+ stats->num_done++; -+ if (job->type == JOB_CMD && task->opts->add_cmd_status) -+ stats->num_done++; -+ break; -+ case JOB_PARTIAL: -+ stats->num_done++; -+ stats->num_partial++; -+ if (job->type == JOB_CMD && task->opts->add_cmd_status) -+ stats->num_done++; -+ break; -+ case JOB_FAILED: -+ stats->num_failed++; -+ break; -+ case JOB_EXCLUDED: -+ stats->num_excluded++; -+ break; -+ default: -+ break; -+ } -+} -+ -+/* Add statistics @from to @to */ -+static void add_stats(struct stats *to, struct stats *from) -+{ -+ to->num_done += from->num_done; -+ to->num_partial += from->num_partial; -+ to->num_excluded += from->num_excluded; -+ to->num_failed += from->num_failed; -+} -+ -+/* Release resources allocated to @thread */ -+static void cleanup_thread(struct per_thread *thread) -+{ -+ if (thread->job) -+ free_job(thread->task, thread->job); -+ buffer_free(&thread->buffer, false); -+} -+ -+/* Register activate @job at @thread */ -+static void start_thread_job(struct per_thread *thread, struct job *job) -+{ -+ struct task *task = thread->task; -+ -+ thread->job = job; -+ job->content = &thread->buffer; -+ if (task->opts->file_timeout > 0 && job->type != JOB_INIT) { -+ /* Set up per-job timeout */ -+ set_timespec(&job->deadline, task->opts->file_timeout, 0); -+ job->timed = true; -+ -+ /* Signal main thread to update deadline timeout */ -+ _main_wakeup(task); -+ } -+} -+ -+/* Unregister active @job at @thread */ -+static void stop_thread_job(struct per_thread *thread, struct job *job) -+{ -+ thread->job = NULL; -+ job->content = NULL; -+ buffer_reset(&thread->buffer); -+} -+ -+/* Wait until a job is available in the job queue. When a job becomes -+ * available, dequeue and return it. Return %NULL if no more jobs are -+ * available, or if processing was aborted. Must be called with task->mutex -+ * locked. */ -+static struct job *_get_next_job(struct task *task) -+{ -+ struct job *job = NULL; -+ -+ do { -+ DBG("checking for jobs"); -+ if (task->aborted) -+ break; -+ job = _dequeue_job(task); -+ if (job) -+ break; -+ if (task->num_jobs_active == 0) -+ break; -+ DBG("found no jobs (%d active)", task->num_jobs_active); -+ } while (_worker_wait(task) == 0); -+ -+ return job; -+} -+ -+/* Unlock the mutex specified by @data */ -+static void cleanup_unlock(void *data) -+{ -+ pthread_mutex_t *mutex = data; -+ -+ pthread_mutex_unlock(mutex); -+} -+ -+/* Write entry for data in @job to output */ -+static void write_job_data(struct task *task, struct job *job) -+{ -+ DBG("write_job_data"); -+ output_lock(task); -+ pthread_cleanup_push(cleanup_unlock, &task->output_mutex); -+ cancel_enable(); -+ -+ _write_job_data(task, job); -+ -+ cancel_disable(); -+ pthread_cleanup_pop(0); -+ output_unlock(task); -+} -+ -+/* Perform second part of job processing for @job at @thread by writing the -+ * resulting tar file entry */ -+static void postprocess_job(struct per_thread *thread, struct job *job, -+ bool cancelable) -+{ -+ struct task *task = thread->task; -+ -+ account_stats(task, &thread->stats, job); -+ if (cancelable) -+ write_job_data(task, job); -+ else -+ _write_job_data(task, job); -+} -+ -+/* Mark @job as complete by releasing all associated resources. If this was -+ * the last active job inform main thread. Must be called with main_lock -+ * mutex held. */ -+static void _complete_job(struct task *task, struct job *job) -+{ -+ task->num_jobs_active--; -+ if (task->num_jobs_active == 0) -+ _main_wakeup(task); -+ free_job(task, job); -+} -+ -+static void init_thread(struct per_thread *thread, struct task *task, long num) -+{ -+ memset(thread, 0, sizeof(struct per_thread)); -+ thread->task = task; -+ thread->num = num; -+} -+ -+/* Dequeue and process all jobs on the job queue */ -+static int process_queue(struct task *task) -+{ -+ struct job *job; -+ struct per_thread thread; -+ -+ init_thread(&thread, task, 0); -+ -+ while ((job = _dequeue_job(task)) && !is_aborted(task)) { -+ start_thread_job(&thread, job); -+ process_job(&thread, job); -+ postprocess_job(&thread, job, false); -+ stop_thread_job(&thread, job); -+ _complete_job(task, job); -+ } -+ -+ task->stats = thread.stats; -+ cleanup_thread(&thread); -+ -+ return EXIT_OK; -+} -+ -+/* Return %true if @job is in a final state, %false otherwise */ -+static bool job_is_final(struct job *job) -+{ -+ switch (job->status) { -+ case JOB_DONE: -+ case JOB_PARTIAL: -+ case JOB_EXCLUDED: -+ case JOB_FAILED: -+ return true; -+ default: -+ break; -+ } -+ -+ return false; -+} -+ -+/* Main thread function: process jobs on the job queue until all jobs -+ * are processed or processing was aborted. */ -+static void *worker_thread_main(void *d) -+{ -+ struct per_thread *thread = d; -+ struct task *task = thread->task; -+ struct job *job; -+ -+ /* Allow cancel only at specific code points */ -+ cancel_disable(); -+ set_threadname("%*sworker %d", (thread->num + 1) * 2, "", thread->num); -+ -+ /* Handle jobs left over from canceled thread */ -+ job = thread->job; -+ if (job) { -+ DBG("handle aborted job %p", job); -+ -+ postprocess_job(thread, job, true); -+ -+ main_lock(task); -+ if (thread->timed_out) -+ goto out; -+ stop_thread_job(thread, job); -+ _complete_job(task, job); -+ main_unlock(task); -+ } -+ -+ DBG("enter worker loop"); -+ -+ main_lock(task); -+ while ((job = _get_next_job(task))) { -+ start_thread_job(thread, job); -+ main_unlock(task); -+ -+ process_job(thread, job); -+ postprocess_job(thread, job, true); -+ -+ main_lock(task); -+ if (thread->timed_out) -+ goto out; -+ stop_thread_job(thread, job); -+ _complete_job(task, job); -+ } -+ -+out: -+ thread->running = false; -+ _main_wakeup(task); -+ main_unlock(task); -+ -+ cancel_enable(); -+ DBG("leave work loop"); -+ -+ return NULL; -+} -+ -+/* Start a worker thread associated with the specified @data. Return %EXIT_OK on -+ * success. */ -+static int start_worker_thread(struct per_thread *data) -+{ -+ int rc; -+ -+ DBG("start thread"); -+ global_threaded = true; -+ data->timed_out = false; -+ rc = pthread_create(&data->thread, NULL, &worker_thread_main, data); -+ if (rc) { -+ mwarnx("Cannot start thread: %s", strerror(rc)); -+ return EXIT_RUNTIME; -+ } -+ data->running = true; -+ -+ return EXIT_OK; -+} -+ -+/* Perform timeout handling for thread associated with @data by canceling and -+ * restarting the corresponding thread. Must be called with task->mutex -+ * held. */ -+static void _timeout_thread(struct per_thread *data) -+{ -+ struct task *task = data->task; -+ struct job *job = data->job; -+ pthread_t thread = data->thread; -+ const char *op, *action; -+ -+ if (!job) { -+ /* Timeout raced with job completion */ -+ return; -+ } -+ if (job_is_final(job)) { -+ /* Job processing done, timeout does not apply */ -+ return; -+ } -+ -+ data->timed_out = true; -+ -+ /* Allow thread to obtain main lock during cancel handling */ -+ main_unlock(task); -+ DBG("cancel num=%d thread=%p", data->num, thread); -+ pthread_cancel(thread); -+ DBG("join num=%d thread=%p", data->num, thread); -+ -+ pthread_join(thread, NULL); -+ main_lock(task); -+ -+ DBG("join done"); -+ -+ if (job->type == JOB_CMD) -+ op = "Command"; -+ else -+ op = "Read"; -+ -+ if (task->opts->ignore_failed_read) -+ action = "skipping"; -+ else -+ action = "aborting"; -+ -+ if (!job->inname || !*job->inname) -+ job_print(job); -+ mwarnx("%s: %s%s timed out after %d second%s - %s", job->inname, -+ task->opts->ignore_failed_read ? "Warning: " : "", op, -+ task->opts->file_timeout, -+ task->opts->file_timeout > 1 ? "s" : "", action); -+ if (!task->opts->ignore_failed_read) -+ _SET_ABORTED(task); -+ -+ /* Interrupted job will be handled by new thread - adjust status */ -+ if (job->status == JOB_IN_PROGRESS) -+ job->status = JOB_PARTIAL; -+ else if (!job_is_final(job)) -+ job->status = JOB_FAILED; -+ -+ if (start_worker_thread(data)) -+ _SET_ABORTED(task); -+} -+ -+/* Return the number of currently running jobs */ -+static long num_jobs_running(struct task *task, struct per_thread *threads) -+{ -+ long i, num = 0; -+ -+ for (i = 0; i < task->opts->jobs; i++) { -+ if (threads[i].running) -+ num++; -+ } -+ -+ return num; -+} -+ -+/* Wait until all jobs are done or timeout occurs */ -+static int wait_for_completion(struct task *task, struct per_thread *threads) -+{ -+ int rc = 0, earliest_timeout; -+ long i; -+ struct per_thread *earliest_thread; -+ struct timespec tool_deadline_ts, deadline_ts, *earliest_ts; -+ struct job *job; -+ -+ /* Set tool deadline */ -+ tool_deadline_ts = task->start_ts; -+ inc_timespec(&tool_deadline_ts, task->opts->timeout, 0); -+ -+ main_lock(task); -+ while (!task->aborted && task->num_jobs_active > 0) { -+ /* Calculate nearest timeout */ -+ earliest_timeout = 0; -+ earliest_ts = NULL; -+ earliest_thread = NULL; -+ -+ if (task->opts->timeout > 0) { -+ earliest_timeout = task->opts->timeout; -+ earliest_ts = &tool_deadline_ts; -+ } -+ -+ for (i = 0; i < task->opts->jobs; i++) { -+ job = threads[i].job; -+ if (!job || !job->timed) -+ continue; -+ if (task->opts->file_timeout == 0) -+ continue; -+ if (!earliest_ts || -+ ts_before(&job->deadline, earliest_ts)) { -+ earliest_timeout = task->opts->file_timeout; -+ earliest_ts = &job->deadline; -+ earliest_thread = &threads[i]; -+ } -+ } -+ -+ /* Wait for status change or timeout */ -+ if (earliest_ts) { -+ deadline_ts = *earliest_ts; -+ rc = _main_wait_timed(task, &deadline_ts); -+ } else { -+ rc = _main_wait(task); -+ } -+ -+ if (rc == 0) -+ continue; -+ if (rc != ETIMEDOUT) { -+ mwarnx("Cannot wait for status change: %s", -+ strerror(rc)); -+ _SET_ABORTED(task); -+ break; -+ } -+ -+ /* Timeout handling */ -+ if (earliest_thread) { -+ /* Per-file timeout, restart */ -+ _timeout_thread(earliest_thread); -+ rc = 0; -+ } else { -+ /* Global timeout, abort */ -+ mwarnx("Operation timed out after %d second%s - " -+ "aborting", earliest_timeout, -+ earliest_timeout > 1 ? "s" : ""); -+ _SET_ABORTED(task); -+ break; -+ } -+ } -+ -+ if (task->aborted) -+ DBG("aborted"); -+ else -+ DBG("all work done"); -+ _worker_wakeup_all(task); -+ -+ /* Allow jobs to finish */ -+ set_timespec(&deadline_ts, 0, NSEC_PER_SEC / 4); -+ while (!task->aborted && num_jobs_running(task, threads) > 0) { -+ DBG("waiting for %lu processes", -+ num_jobs_running(task, threads)); -+ -+ if (_main_wait_timed(task, &deadline_ts)) -+ break; -+ } -+ -+ main_unlock(task); -+ -+ return rc; -+} -+ -+/* Finalize output stream */ -+static void close_output(struct task *task) -+{ -+#ifdef HAVE_ZLIB -+ if (task->opts->gzip) { -+ gzclose(task->output_gzfd); -+ return; -+ } -+#endif /* HAVE_ZLIB */ -+ -+ if (task->output_fd != STDOUT_FILENO) -+ close(task->output_fd); -+} -+ -+/* Start multi-threaded processing of job queue */ -+static int process_queue_threaded(struct task *task) -+{ -+ struct per_thread *threads, *thread; -+ int rc; -+ long i; -+ -+ tverb("Using %ld threads\n", task->opts->jobs); -+ threads = mcalloc(sizeof(struct per_thread), task->opts->jobs); -+ -+ rc = 0; -+ for (i = 0; i < task->opts->jobs; i++) { -+ init_thread(&threads[i], task, i); -+ rc = start_worker_thread(&threads[i]); -+ if (rc) -+ break; -+ } -+ -+ if (!rc) -+ wait_for_completion(task, threads); -+ -+ DBG("thread cleanup"); -+ for (i = 0; i < task->opts->jobs; i++) { -+ thread = &threads[i]; -+ if (thread->running) { -+ DBG("cancel %p", thread->thread); -+ pthread_cancel(thread->thread); -+ } -+ DBG("join %p", thread->thread); -+ pthread_join(thread->thread, NULL); -+ add_stats(&task->stats, &thread->stats); -+ cleanup_thread(thread); -+ } -+ -+ free(threads); -+ -+ return rc; -+} -+ -+/* Abort any remaining queued jobs and account to @stats */ -+static void abort_queued_jobs(struct task *task) -+{ -+ struct job *job; -+ -+ while ((job = _dequeue_job(task))) { -+ DBG("aborting job %s", job->inname); -+ task->stats.num_failed++; -+ job->status = JOB_FAILED; -+ _complete_job(task, job); -+ } -+} -+ -+/* Print a summary line */ -+static void print_summary(struct task *task) -+{ -+ char msg[MSG_LEN]; -+ size_t off = 0; -+ int rc; -+ struct stats *stats = &task->stats; -+ struct timespec end_ts; -+ int num_special; -+ unsigned long num_added; -+ -+ if (task->opts->quiet) -+ return; -+ set_timespec(&end_ts, 0, 0); -+ -+ num_special = 0; -+ num_special += stats->num_partial > 0 ? 1 : 0; -+ num_special += stats->num_excluded > 0 ? 1 : 0; -+ num_special += stats->num_failed > 0 ? 1 : 0; -+ -+ num_added = stats->num_done; -+ if (task->opts->ignore_failed_read) -+ num_added += stats->num_partial + stats->num_failed; -+ -+ rc = snprintf(&msg[off], MSG_LEN - off, "Dumped %lu entries ", -+ num_added); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ -+ if (num_special > 0) { -+ rc = snprintf(&msg[off], MSG_LEN - off, "("); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ if (stats->num_partial > 0) { -+ rc = snprintf(&msg[off], MSG_LEN - off, "%lu partial", -+ stats->num_partial); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ if (--num_special > 0) { -+ rc = snprintf(&msg[off], MSG_LEN - off, ", "); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ } -+ } -+ if (stats->num_excluded > 0) { -+ rc = snprintf(&msg[off], MSG_LEN - off, "%lu excluded", -+ stats->num_excluded); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ if (--num_special > 0) { -+ rc = snprintf(&msg[off], MSG_LEN - off, ", "); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ } -+ } -+ if (stats->num_failed > 0) { -+ rc = snprintf(&msg[off], MSG_LEN - off, "%lu failed", -+ stats->num_failed); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ } -+ rc = snprintf(&msg[off], MSG_LEN - off, ") "); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ } -+ -+ rc = snprintf(&msg[off], MSG_LEN - off, "in "); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ snprintf_duration(&msg[off], MSG_LEN - off, &task->start_ts, &end_ts); -+ -+out: -+ info("%s\n", msg); -+} -+ -+static int init_task(struct task *task, struct dump_opts *opts) -+{ -+ pthread_condattr_t attr; -+ -+ memset(task, 0, sizeof(struct task)); -+ set_timespec(&task->start_ts, 0, 0); -+ task->opts = opts; -+ pthread_mutex_init(&task->mutex, NULL); -+ pthread_mutex_init(&task->output_mutex, NULL); -+ pthread_cond_init(&task->worker_cond, NULL); -+ -+ pthread_condattr_init(&attr); -+ if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) || -+ pthread_cond_init(&task->cond, &attr)) { -+ mwarn("Could not adjust pthread clock"); -+ return EXIT_RUNTIME; -+ } -+ -+ return EXIT_OK; -+} -+ -+struct dump_opts *dump_opts_new(void) -+{ -+ struct dump_opts *opts = mmalloc(sizeof(struct dump_opts)); -+ -+ opts->recursive = true; -+ opts->read_chunk_size = DEFAULT_READ_CHUNK_SIZE; -+ opts->max_buffer_size = DEFAULT_MAX_BUFFER_SIZE; -+ -+ return opts; -+} -+ -+void dump_opts_free(struct dump_opts *opts) -+{ -+ unsigned int i; -+ -+ if (!opts) -+ return; -+ -+ free_strarray(&opts->exclude); -+ for (i = 0; i < opts->num_specs; i++) { -+ free(opts->specs[i].inname); -+ free(opts->specs[i].outname); -+ } -+ free(opts->specs); -+ free(opts); -+} -+ -+void dump_opts_print(struct dump_opts *opts) -+{ -+ unsigned int i; -+ -+ printf("DEBUG: dump_opts at %p\n", opts); -+ if (!opts) -+ return; -+ printf("DEBUG: add_cmd_status=%d\n", opts->add_cmd_status); -+ printf("DEBUG: append=%d\n", opts->append); -+ printf("DEBUG: dereference=%d\n", opts->dereference); -+ for (i = 0; i < NUM_EXCLUDE_TYPES; i++) -+ printf("DEBUG: exclude_type[%d]=%d\n", i, -+ opts->exclude_type[i]); -+ printf("DEBUG: gzip=%d\n", opts->gzip); -+ printf("DEBUG: ignore_failed_read=%d\n", opts->ignore_failed_read); -+ printf("DEBUG: no_eof=%d\n", opts->no_eof); -+ printf("DEBUG: quiet=%d\n", opts->quiet); -+ printf("DEBUG: recursive=%d\n", opts->recursive); -+ printf("DEBUG: threaded=%d\n", opts->threaded); -+ printf("DEBUG: verbose=%d\n", opts->verbose); -+ printf("DEBUG: output_file=%s\n", opts->output_file); -+ printf("DEBUG: file_timeout=%d\n", opts->file_timeout); -+ printf("DEBUG: timeout=%d\n", opts->timeout); -+ printf("DEBUG: jobs=%ld\n", opts->jobs); -+ printf("DEBUG: jobs_per_cpu=%ld\n", opts->jobs_per_cpu); -+ printf("DEBUG: file_max_size=%zu\n", opts->file_max_size); -+ printf("DEBUG: max_buffer_size=%zu\n", opts->max_buffer_size); -+ printf("DEBUG: max_size=%zu\n", opts->max_size); -+ printf("DEBUG: read_chunk_size=%zu\n", opts->read_chunk_size); -+ for (i = 0; i < opts->exclude.num; i++) -+ printf("DEBUG: exclude[%d]=%s\n", i, opts->exclude.str[i]); -+ for (i = 0; i < opts->num_specs; i++) { -+ printf("DEBUG: specs[%d]:\n", i); -+ printf("DEBUG: inname=%s\n", opts->specs[i].inname); -+ printf("DEBUG: outname=%s\n", opts->specs[i].outname); -+ printf("DEBUG: is_cmd=%d\n", opts->specs[i].is_cmd); -+ } -+} -+ -+/* Mark file type associated with character @c as excluded */ -+int dump_opts_set_type_excluded(struct dump_opts *opts, char c) -+{ -+ int i; -+ -+ for (i = 0; i < NUM_EXCLUDE_TYPES; i++) { -+ if (exclude_types[i].c == c) { -+ opts->exclude_type[i] = true; -+ return 0; -+ } -+ } -+ return -1; -+} -+ -+/* Add entry specification defined by @iname, @outname and @op to @opts. */ -+void dump_opts_add_spec(struct dump_opts *opts, char *inname, char *outname, -+ bool is_cmd) -+{ -+ unsigned int i = opts->num_specs; -+ -+ opts->specs = mrealloc(opts->specs, (i + 1) * sizeof(struct dump_spec)); -+ opts->specs[i].inname = mstrdup(inname); -+ if (outname) -+ opts->specs[i].outname = mstrdup(outname); -+ else -+ opts->specs[i].outname = NULL; -+ opts->specs[i].is_cmd = is_cmd; -+ opts->num_specs++; -+} -+ -+int dump_to_tar(struct dump_opts *opts) -+{ -+ struct task task; -+ int rc; -+ long num_cpus; -+ -+ if (opts->jobs_per_cpu > 0) { -+ num_cpus = sysconf(_SC_NPROCESSORS_ONLN); -+ if (num_cpus < 1) { -+ mwarn("Cannot determine number of CPUs - assuming 1 " -+ "CPU"); -+ num_cpus = 1; -+ } -+ opts->jobs = num_cpus; -+ } -+ -+ if (opts->jobs == 0 && (opts->timeout > 0 || opts->file_timeout > 0)) { -+ /* Separate thread needed to implement timeout via cancel */ -+ opts->jobs = 1; -+ } -+ -+ rc = init_task(&task, opts); -+ if (rc) -+ return rc; -+ -+ /* Queue initial job */ -+ init_queue(&task); -+ -+ /* Process queue */ -+ if (opts->jobs > 0) -+ rc = process_queue_threaded(&task); -+ else -+ rc = process_queue(&task); -+ abort_queued_jobs(&task); -+ -+ if (task.output_num_files > 0 && !opts->no_eof) -+ write_eof(&task); -+ -+ print_summary(&task); -+ -+ close_output(&task); -+ -+ if (rc == 0 && task.aborted) -+ rc = EXIT_RUNTIME; -+ -+ return rc; -+} ---- /dev/null -+++ b/dump2tar/src/dump2tar.c -@@ -0,0 +1,474 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Command line interface -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dump.h" -+#include "global.h" -+#include "idcache.h" -+#include "misc.h" -+#include "strarray.h" -+#include "util_opt.h" -+#include "util_prg.h" -+ -+#define MIN_BUFFER_SIZE 4096 -+ -+#define OPT_NOSHORT_BASE 256 -+ -+#define OPT_DEREFERENCE (OPT_NOSHORT_BASE + 0) -+#define OPT_NORECURSION (OPT_NOSHORT_BASE + 1) -+#define OPT_EXCLUDETYPE (OPT_NOSHORT_BASE + 2) -+ -+/* Program description */ -+static const struct util_prg dump2tar_prg = { -+ .desc = "Use dump2tar to create a tar archive from the contents " -+ "of arbitrary files.\nIt works even when the size of actual " -+ "file content is not known beforehand,\nsuch as with FIFOs, " -+ "character devices or certain Linux debugfs or sysfs files.\n" -+ "\nYou can also add files under different names and add " -+ "command output using the\nformat described in section SPECS " -+ "below. When no additional options are\nspecified, the " -+ "resulting archive is written to the standard output stream\n" -+ "in uncompressed tar format.", -+ .args = "SPECS", -+ .copyright_vec = { -+ { "IBM Corp.", 2016, 2016 }, -+ UTIL_PRG_COPYRIGHT_END -+ }, -+}; -+ -+/* Definition of command line options */ -+static struct util_opt dump2tar_opts[] = { -+ UTIL_OPT_SECTION("OUTPUT OPTIONS"), -+ { -+ .option = { "output-file", required_argument, NULL, 'o' }, -+ .argument = "FILE", -+ .desc = "Write archive to FILE (default: standard output)", -+ }, -+#ifdef HAVE_ZLIB -+ { -+ .option = { "gzip", no_argument, NULL, 'z' }, -+ .desc = "Write a gzip compressed archive", -+ }, -+#endif /* HAVE_ZLIB */ -+ { -+ .option = { "max-size", required_argument, NULL, 'm' }, -+ .argument = "N", -+ .desc = "Stop adding files when archive size exceeds N bytes", -+ }, -+ { -+ .option = { "timeout", required_argument, NULL, 't' }, -+ .argument = "SEC", -+ .desc = "Stop adding files after SEC seconds", -+ }, -+ { -+ .option = { "no-eof", no_argument, NULL, 131 }, -+ .desc = "Do not write an end-of-file marker", -+ .flags = UTIL_OPT_FLAG_NOSHORT, -+ }, -+ { -+ .option = { "add-cmd-status", no_argument, NULL, 132 }, -+ .desc = "Add status of commands as separate file", -+ .flags = UTIL_OPT_FLAG_NOSHORT, -+ }, -+ { -+ .option = { "append", no_argument, NULL, 133 }, -+ .desc = "Append output to end of file", -+ .flags = UTIL_OPT_FLAG_NOSHORT, -+ }, -+ -+ UTIL_OPT_SECTION("INPUT OPTIONS"), -+ { -+ .option = { "files-from", required_argument, NULL, 'F' }, -+ .argument = "FILE", -+ .desc = "Read filenames from FILE (- for standard input)", -+ }, -+ { -+ .option = { "ignore-failed-read", no_argument, NULL, 'i' }, -+ .desc = "Continue after read errors", -+ }, -+ { -+ .option = { "buffer-size", required_argument, NULL, 'b' }, -+ .argument = "N", -+ .desc = "Read data in chunks of N byte (default: 16384)", -+ }, -+ { -+ .option = { "file-timeout", required_argument, NULL, 'T' }, -+ .desc = "Stop reading file after SEC seconds", -+ }, -+ { -+ .option = { "file-max-size", required_argument, NULL, 'M' }, -+ .argument = "N", -+ .desc = "Stop reading file after N bytes", -+ }, -+ { -+ .option = { "jobs", required_argument, NULL, 'j' }, -+ .argument = "N", -+ .desc = "Read N files in parallel (default: 1)", -+ }, -+ { -+ .option = { "jobs-per-cpu", required_argument, NULL, 'J' }, -+ .argument = "N", -+ .desc = "Read N files per CPU in parallel", -+ }, -+ { -+ .option = { "exclude", required_argument, NULL, 'x' }, -+ .argument = "PATTERN", -+ .desc = "Don't add files matching PATTERN", -+ }, -+ { -+ .option = { "exclude-from", required_argument, NULL, 'X' }, -+ .argument = "FILE", -+ .desc = "Don't add files matching patterns in FILE", -+ }, -+ { -+ .option = { "exclude-type", required_argument, NULL, -+ OPT_EXCLUDETYPE }, -+ .argument = "TYPE", -+ .desc = "Don't add files of specified TYPE (one of: fdcbpls)", -+ .flags = UTIL_OPT_FLAG_NOSHORT, -+ }, -+ { -+ .option = { "dereference", no_argument, NULL, OPT_DEREFERENCE }, -+ .desc = "Add link targets instead of links", -+ .flags = UTIL_OPT_FLAG_NOSHORT, -+ }, -+ { -+ .option = { "no-recursion", no_argument, NULL, -+ OPT_NORECURSION }, -+ .desc = "Don't add files from sub-directories", -+ .flags = UTIL_OPT_FLAG_NOSHORT, -+ }, -+ -+ UTIL_OPT_SECTION("MISC OPTIONS"), -+ UTIL_OPT_HELP, -+ UTIL_OPT_VERSION, -+ { -+ .option = { "verbose", no_argument, NULL, 'V' }, -+ .desc = "Print additional informational output", -+ }, -+ { -+ .option = { "quiet", no_argument, NULL, 'q' }, -+ .desc = "Suppress printing of informational output", -+ }, -+ UTIL_OPT_END, -+}; -+ -+/* Split buffer size specification in @arg into two numbers to be stored in -+ * @from_ptr and @to_ptr. Return %EXIT_OK on success. */ -+static int parse_buffer_size(char *arg, size_t *from_ptr, size_t *to_ptr) -+{ -+ char *err; -+ unsigned long from, to; -+ -+ if (!*arg) { -+ mwarnx("Empty buffer size specified"); -+ return EXIT_USAGE; -+ } -+ -+ from = strtoul(arg, &err, 10); -+ -+ if (*err == '-') -+ to = strtoul(err + 1, &err, 10); -+ else -+ to = *to_ptr; -+ -+ if (*err) { -+ mwarnx("Invalid buffer size: %s", arg); -+ return EXIT_USAGE; -+ } -+ -+ if (from < MIN_BUFFER_SIZE || to < MIN_BUFFER_SIZE) { -+ mwarnx("Buffer size too low (minimum %u)", MIN_BUFFER_SIZE); -+ return EXIT_USAGE; -+ } -+ -+ if (to < from) -+ to = from; -+ -+ *from_ptr = from; -+ *to_ptr = to; -+ -+ return EXIT_OK; -+} -+ -+static void parse_and_add_spec(struct dump_opts *opts, const char *spec) -+{ -+ char *op, *s, *inname, *outname = NULL; -+ bool is_cmd = false; -+ -+ s = mstrdup(spec); -+ op = strstr(s, "|="); -+ if (op) -+ is_cmd = true; -+ else -+ op = strstr(s, ":="); -+ -+ if (op) { -+ *op = 0; -+ inname = op + 2; -+ outname = s; -+ } else { -+ inname = s; -+ } -+ dump_opts_add_spec(opts, inname, outname, is_cmd); -+ free(s); -+} -+ -+static int add_specs_from_file(struct dump_opts *opts, const char *filename) -+{ -+ FILE *fd; -+ char *line = NULL; -+ size_t line_size; -+ int rc = EXIT_RUNTIME; -+ bool need_close = false, parse_spec = true; -+ -+ if (strcmp(filename, "-") == 0) -+ fd = stdin; -+ else { -+ fd = fopen(filename, "r"); -+ if (!fd) { -+ mwarn("%s: Cannot open file", filename); -+ goto out; -+ } -+ need_close = true; -+ } -+ -+ while ((getline(&line, &line_size, fd) != -1)) { -+ chomp(line, "\n"); -+ if (line[0] == 0) -+ continue; -+ if (parse_spec && strcmp(line, "--") == 0) { -+ /* After a line containing --, no more := or |= specs -+ * are expected */ -+ parse_spec = false; -+ continue; -+ } -+ if (parse_spec) -+ parse_and_add_spec(opts, line); -+ else -+ dump_opts_add_spec(opts, line, NULL, false); -+ } -+ -+ if (ferror(fd)) -+ mwarn("%s: Cannot read file", filename); -+ else -+ rc = EXIT_OK; -+ -+out: -+ if (need_close) -+ fclose(fd); -+ free(line); -+ -+ return rc; -+} -+ -+static void print_help(void) -+{ -+ static const struct { -+ const char *name; -+ const char *desc; -+ } specs[] = { -+ { "PATH", "Add file or directory at PATH" }, -+ { "NEWPATH:=PATH", "Add file or directory at PATH as NEWPATH" }, -+ { "NEWPATH|=CMDLINE", "Add output of command line CMDLINE as " -+ "NEWPATH" }, -+ { NULL, NULL }, -+ }; -+ int i; -+ -+ util_prg_print_help(); -+ printf("SPECS\n"); -+ for (i = 0; specs[i].name; i++) -+ util_opt_print_indented(specs[i].name, specs[i].desc); -+ printf("\n"); -+ util_opt_print_help(); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ int rc = EXIT_USAGE, opt; -+ long i; -+ struct dump_opts *opts; -+ -+ if (getenv("DUMP2TAR_DEBUG")) -+ global_debug = true; -+ -+ util_prg_init(&dump2tar_prg); -+ util_opt_init(dump2tar_opts, "-"); -+ misc_init(); -+ -+ opts = dump_opts_new(); -+ opterr = 0; -+ while ((opt = util_opt_getopt_long(argc, argv)) != -1) { -+ switch (opt) { -+ case 'h': /* --help */ -+ print_help(); -+ rc = EXIT_OK; -+ goto out; -+ case 'v': /* --version */ -+ util_prg_print_version(); -+ rc = EXIT_OK; -+ goto out; -+ case 'V': /* --verbose */ -+ global_verbose = true; -+ global_quiet = false; -+ opts->verbose = true; -+ opts->quiet = false; -+ break; -+ case 'q': /* --quiet */ -+ global_quiet = true; -+ global_verbose = false; -+ opts->quiet = true; -+ opts->verbose = false; -+ break; -+ case 'i': /* --ignore-failed-read */ -+ opts->ignore_failed_read = true; -+ break; -+ case 'j': /* --jobs N */ -+ opts->jobs = atoi(optarg); -+ if (opts->jobs < 1) { -+ mwarnx("Invalid number of jobs: %s", optarg); -+ goto out; -+ } -+ break; -+ case 'J': /* --jobs-per-cpu N */ -+ opts->jobs_per_cpu = atoi(optarg); -+ if (opts->jobs_per_cpu < 1) { -+ mwarnx("Invalid number of jobs: %s", optarg); -+ goto out; -+ } -+ break; -+ case 'b': /* --buffer-size N */ -+ if (parse_buffer_size(optarg, &opts->read_chunk_size, -+ &opts->max_buffer_size)) -+ goto out; -+ break; -+ case 'x': /* --exclude PATTERN */ -+ add_str_to_strarray(&opts->exclude, optarg); -+ break; -+ case 'X': /* --exclude-from FILE */ -+ if (add_file_to_strarray(&opts->exclude, optarg)) -+ goto out; -+ break; -+ case 'F': /* --files-from FILE */ -+ if (add_specs_from_file(opts, optarg)) -+ goto out; -+ break; -+ case 'o': /* --output-file FILE */ -+ if (opts->output_file) { -+ mwarnx("Output file specified multiple times"); -+ goto out; -+ } -+ opts->output_file = optarg; -+ break; -+ case OPT_DEREFERENCE: /* --dereference */ -+ opts->dereference = true; -+ break; -+ case OPT_NORECURSION: /* --no-recursion */ -+ opts->recursive = false; -+ break; -+ case OPT_EXCLUDETYPE: /* --exclude-type TYPE */ -+ for (i = 0; optarg[i]; i++) { -+ if (dump_opts_set_type_excluded(opts, -+ optarg[i])) -+ break; -+ -+ } -+ if (optarg[i]) { -+ mwarnx("Unrecognized file type: %c", optarg[i]); -+ goto out; -+ } -+ break; -+ case 131: /* --no-eof */ -+ opts->no_eof = true; -+ break; -+ case 132: /* --add-cmd-status */ -+ opts->add_cmd_status = true; -+ break; -+ case 133: /* --append */ -+ opts->append = true; -+ break; -+ case 't': /* --timeout VALUE */ -+ opts->timeout = atoi(optarg); -+ if (opts->timeout < 1) { -+ mwarnx("Invalid timeout value: %s", optarg); -+ goto out; -+ } -+ break; -+ case 'T': /* --file-timeout VALUE */ -+ opts->file_timeout = atoi(optarg); -+ if (opts->file_timeout < 1) { -+ mwarnx("Invalid timeout value: %s", optarg); -+ goto out; -+ } -+ break; -+ case 'm': /* --max-size N */ -+ opts->max_size = atol(optarg); -+ if (opts->max_size < 2) { -+ mwarnx("Invalid maximum size: %s", optarg); -+ goto out; -+ } -+ break; -+ case 'M': /* --file-max-size N */ -+ opts->file_max_size = atol(optarg); -+ if (opts->file_max_size < 2) { -+ mwarnx("Invalid maximum size: %s", optarg); -+ goto out; -+ } -+ break; -+ case 'z': /* --gzip */ -+ opts->gzip = true; -+ break; -+ case 1: /* Filename specification or unrecognized option */ -+ if (optarg[0] == '-') { -+ mwarnx("Invalid option '%s'", optarg); -+ goto out; -+ } -+ parse_and_add_spec(opts, optarg); -+ break; -+ case '?': /* Unrecognized option */ -+ if (optopt) -+ mwarnx("Invalid option '-%c'", optopt); -+ else -+ mwarnx("Invalid option '%s'", argv[optind - 1]); -+ goto out; -+ case ':': /* Missing argument */ -+ mwarnx("Option '%s' requires an argument", -+ argv[optind - 1]); -+ goto out; -+ default: -+ break; -+ } -+ } -+ if (optind >= argc && opts->num_specs == 0) { -+ mwarnx("Please specify files to dump"); -+ goto out; -+ } -+ -+ for (i = optind; i < argc; i++) -+ dump_opts_add_spec(opts, argv[i], NULL, false); -+ -+ rc = dump_to_tar(opts); -+ -+out: -+ idcache_cleanup(); -+ misc_cleanup(); -+ dump_opts_free(opts); -+ -+ if (rc == EXIT_USAGE) -+ util_prg_print_parse_error(); -+ -+ return rc; -+} ---- /dev/null -+++ b/dump2tar/src/global.c -@@ -0,0 +1,17 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Global variables -+ * -+ * Copyright IBM Corp. 2016 -+ * -+ */ -+ -+#include "global.h" -+ -+/* Global settings */ -+bool global_threaded; -+bool global_debug; -+bool global_verbose; -+bool global_quiet; -+bool global_timestamps; ---- /dev/null -+++ b/dump2tar/src/idcache.c -@@ -0,0 +1,153 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Caches for user and group ID lookups -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#include "idcache.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "global.h" -+#include "misc.h" -+ -+/* Maximum user and group name lengths as defined in tar header */ -+#define ID_NAME_MAXLEN 32 -+ -+/* Types for user and group ID caches */ -+typedef uid_t generic_id_t; /* Assumes that uid_t == gid_t */ -+ -+struct id_cache_entry { -+ generic_id_t id; -+ char name[ID_NAME_MAXLEN]; -+}; -+ -+struct id_cache { -+ unsigned int num; -+ struct id_cache_entry entries[]; -+}; -+ -+/* cache_mutex serializes access to cached uid and gid data */ -+static pthread_mutex_t id_cache_mutex = PTHREAD_MUTEX_INITIALIZER; -+static struct id_cache *id_cache_uid; -+static struct id_cache *id_cache_gid; -+ -+/* Lock cache mutex */ -+static void cache_lock(void) -+{ -+ if (!global_threaded) -+ return; -+ pthread_mutex_lock(&id_cache_mutex); -+} -+ -+/* Unlock cache mutex */ -+static void cache_unlock(void) -+{ -+ if (!global_threaded) -+ return; -+ pthread_mutex_unlock(&id_cache_mutex); -+} -+ -+/* Copy the name associated with @id in @cache to at most @len bytes at @dest. -+ * Return %true if name was found in cache, %false otherwise. */ -+static bool strncpy_id_cache_entry(char *dest, struct id_cache *cache, -+ generic_id_t id, size_t len) -+{ -+ unsigned int i; -+ bool hit = false; -+ -+ cache_lock(); -+ if (cache) { -+ for (i = 0; i < cache->num; i++) { -+ if (cache->entries[i].id == id) { -+ strncpy(dest, cache->entries[i].name, len); -+ hit = true; -+ break; -+ } -+ } -+ } -+ cache_unlock(); -+ -+ return hit; -+} -+ -+/* Add a new entry consisting of @id and @name to ID cache in @*cache_ptr. -+ * Update @cache_ptr if necessary. */ -+static void add_id_cache_entry(struct id_cache **cache_ptr, generic_id_t id, -+ char *name) -+{ -+ struct id_cache *cache; -+ unsigned int cache_num; -+ size_t new_size; -+ struct id_cache *new_cache; -+ -+ cache_lock(); -+ -+ cache = *cache_ptr; -+ cache_num = cache ? cache->num : 0; -+ new_size = sizeof(struct id_cache) + -+ sizeof(struct id_cache_entry) * (cache_num + 1); -+ new_cache = mrealloc(cache, new_size); -+ if (cache_num == 0) -+ new_cache->num = 0; -+ new_cache->entries[cache_num].id = id; -+ strncpy(new_cache->entries[cache_num].name, name, ID_NAME_MAXLEN); -+ new_cache->num++; -+ *cache_ptr = new_cache; -+ -+ cache_unlock(); -+} -+ -+/* Copy the user name corresponding to user ID @uid to at most @len bytes -+ * at @name */ -+void uid_to_name(uid_t uid, char *name, size_t len) -+{ -+ struct passwd pwd, *pwd_ptr; -+ char buffer[PWD_BUFFER_SIZE], *result; -+ -+ if (strncpy_id_cache_entry(name, id_cache_uid, uid, len)) -+ return; -+ -+ /* getpwuid() can be slow so cache results */ -+ getpwuid_r(uid, &pwd, buffer, PWD_BUFFER_SIZE, &pwd_ptr); -+ if (!pwd_ptr || !pwd_ptr->pw_name) -+ return; -+ result = pwd_ptr->pw_name; -+ -+ add_id_cache_entry(&id_cache_uid, uid, result); -+ -+ strncpy(name, result, len); -+} -+ -+/* Copy the group name corresponding to group ID @gid to at most @len bytes -+ * at @name */ -+void gid_to_name(gid_t gid, char *name, size_t len) -+{ -+ struct group grp, *grp_ptr; -+ char buffer[GRP_BUFFER_SIZE], *result; -+ -+ if (strncpy_id_cache_entry(name, id_cache_gid, gid, len)) -+ return; -+ -+ /* getgrgid() can be slow so cache results */ -+ getgrgid_r(gid, &grp, buffer, GRP_BUFFER_SIZE, &grp_ptr); -+ if (!grp_ptr || !grp_ptr->gr_name) -+ return; -+ result = grp_ptr->gr_name; -+ -+ add_id_cache_entry(&id_cache_gid, gid, result); -+ -+ strncpy(name, result, len); -+} -+ -+void idcache_cleanup(void) -+{ -+ free(id_cache_uid); -+ free(id_cache_gid); -+} ---- /dev/null -+++ b/dump2tar/src/misc.c -@@ -0,0 +1,492 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Helper functions -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#define _GNU_SOURCE /* for program_invocation_short_name */ -+ -+#include "misc.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dref.h" -+#include "global.h" -+ -+struct timespec main_start_ts; -+ -+static pthread_key_t thread_name_key; -+static bool stdout_data; -+ -+/* Write @len bytes at @addr to @fd. Return %EXIT_OK on success, %EXIT_RUNTIME -+ * otherwise. */ -+int misc_write_data(int fd, char *addr, size_t len) -+{ -+ ssize_t w; -+ -+ while (len > 0) { -+ w = write(fd, addr, len); -+ if (w < 0) -+ return EXIT_RUNTIME; -+ len -= w; -+ addr += w; -+ } -+ -+ return EXIT_OK; -+} -+ -+/* Read at most @len bytes from @fd to @addr. Return the number of bytes read -+ * or %-1 on error. */ -+ssize_t misc_read_data(int fd, char *addr, size_t len) -+{ -+ size_t done = 0; -+ ssize_t r; -+ -+ while (len > 0) { -+ r = read(fd, addr, len); -+ if (r < 0) -+ return -1; -+ if (r == 0) -+ break; -+ len -= r; -+ addr += r; -+ done += r; -+ } -+ -+ return done; -+} -+ -+/* Advance timespec @ts by @sec seconds and @nsec nanoseconds */ -+void inc_timespec(struct timespec *ts, time_t sec, long nsec) -+{ -+ ts->tv_nsec += nsec; -+ ts->tv_sec += sec; -+ if (ts->tv_nsec > NSEC_PER_SEC) { -+ ts->tv_nsec -= NSEC_PER_SEC; -+ ts->tv_sec++; -+ } -+} -+ -+/* Set timespec @ts to point to @sec seconds and @nsec nanoseconds in the -+ * future */ -+void set_timespec(struct timespec *ts, time_t sec, long nsec) -+{ -+ clock_gettime(CLOCK_MONOTONIC, ts); -+ inc_timespec(ts, sec, nsec); -+} -+ -+/* Return true if timespec @a refers to a point in time before @b */ -+bool ts_before(struct timespec *a, struct timespec *b) -+{ -+ if (a->tv_sec < b->tv_sec || -+ (a->tv_sec == b->tv_sec && a->tv_nsec < b->tv_nsec)) -+ return true; -+ -+ return false; -+} -+ -+/* Store a string representing the time duration between @start and @end in -+ * at most @len bytes of @buff. */ -+int snprintf_duration(char *buff, size_t len, struct timespec *start, -+ struct timespec *end) -+{ -+ time_t sec; -+ long nsec, msec, s, m, h; -+ -+ sec = end->tv_sec - start->tv_sec; -+ nsec = end->tv_nsec - start->tv_nsec; -+ -+ if (nsec < 0) { -+ nsec += NSEC_PER_SEC; -+ sec--; -+ } -+ -+ msec = nsec / NSEC_PER_MSEC; -+ s = sec % 60; -+ sec /= 60; -+ m = sec % 60; -+ sec /= 60; -+ h = sec; -+ -+ if (h > 0) -+ return snprintf(buff, len, "%luh%lum%lu.%03lus", h, m, s, msec); -+ else if (m > 0) -+ return snprintf(buff, len, "%lum%lu.%03lus", m, s, msec); -+ else -+ return snprintf(buff, len, "%lu.%03lus", s, msec); -+} -+ -+/* Return the name of the current thread */ -+char *get_threadname(void) -+{ -+ return pthread_getspecific(thread_name_key); -+} -+ -+static int snprintf_timestamp(char *str, size_t size) -+{ -+ struct timespec now_ts; -+ -+ set_timespec(&now_ts, 0, 0); -+ now_ts.tv_sec -= main_start_ts.tv_sec; -+ now_ts.tv_nsec -= main_start_ts.tv_nsec; -+ if (now_ts.tv_nsec < 0) { -+ now_ts.tv_nsec += NSEC_PER_SEC; -+ now_ts.tv_sec--; -+ } -+ -+ return snprintf(str, size, "[%3lu.%06lu] ", now_ts.tv_sec, -+ now_ts.tv_nsec / NSEC_PER_USEC); -+} -+ -+/* When DUMP2TAR_DEBUG is set to non-zero, print debugging information */ -+void debug(const char *file, unsigned long line, const char *format, ...) -+{ -+ char msg[MSG_LEN]; -+ size_t off = 0; -+ int rc; -+ va_list args; -+ -+ /* Debug marker */ -+ rc = snprintf(&msg[off], MSG_LEN - off, "DEBUG: "); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ -+ /* Timestamp */ -+ rc = snprintf_timestamp(&msg[off], MSG_LEN - off); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ -+ /* Thread name */ -+ rc = snprintf(&msg[off], MSG_LEN - off, "%s: ", get_threadname()); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ -+ /* Message */ -+ va_start(args, format); -+ rc = vsnprintf(&msg[off], MSG_LEN - off, format, args); -+ va_end(args); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ -+ /* Call site */ -+ rc = snprintf(&msg[off], MSG_LEN - off, " (%s:%lu)", file, line); -+ -+out: -+ fprintf(stderr, "%s\n", msg); -+} -+ -+/* Print a warning message consisting of @format and variable arguments. -+ * If @print_errno is true, also print the text corresponding to errno. -+ * We're not using err.h's warn since we want timestamps and synchronized -+ * output. */ -+void _mwarn(bool print_errno, const char *format, ...) -+{ -+ char msg[MSG_LEN]; -+ size_t off = 0; -+ int rc; -+ va_list args; -+ -+ if (global_timestamps) { -+ rc = snprintf_timestamp(&msg[off], MSG_LEN - off); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ } -+ -+ rc = snprintf(&msg[off], MSG_LEN - off, "%s: ", -+ program_invocation_short_name); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ -+ va_start(args, format); -+ rc = vsnprintf(&msg[off], MSG_LEN - off, format, args); -+ va_end(args); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ -+ if (print_errno) -+ snprintf(&msg[off], MSG_LEN - off, ": %s", strerror(errno)); -+ -+out: -+ fprintf(stderr, "%s\n", msg); -+} -+ -+/* Provide informational output if --verbose was specified */ -+void verb(const char *format, ...) -+{ -+ char msg[MSG_LEN]; -+ size_t off = 0; -+ int rc; -+ va_list args; -+ FILE *fd; -+ -+ if (!global_verbose) -+ return; -+ if (stdout_data) -+ fd = stderr; -+ else -+ fd = stdout; -+ if (global_timestamps) { -+ rc = snprintf_timestamp(&msg[off], MSG_LEN - off); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ } -+ -+ va_start(args, format); -+ rc = vsnprintf(&msg[off], MSG_LEN - off, format, args); -+ va_end(args); -+ -+out: -+ fprintf(fd, "%s", msg); -+} -+ -+/* Provide informational output. */ -+void info(const char *format, ...) -+{ -+ char msg[MSG_LEN]; -+ size_t off = 0; -+ int rc; -+ va_list args; -+ FILE *fd; -+ -+ if (global_quiet) -+ return; -+ if (stdout_data) -+ fd = stderr; -+ else -+ fd = stdout; -+ -+ if (global_timestamps) { -+ rc = snprintf_timestamp(&msg[off], MSG_LEN - off); -+ HANDLE_RC(rc, MSG_LEN, off, out); -+ } -+ -+ va_start(args, format); -+ rc = vsnprintf(&msg[off], MSG_LEN - off, format, args); -+ va_end(args); -+ -+out: -+ fprintf(fd, "%s", msg); -+} -+ -+/* Return a newly allocated buffer containing the result of the specified -+ * string format arguments */ -+char *__masprintf(const char *func, const char *file, int line, const char *fmt, -+ ...) -+{ -+ char *str; -+ va_list args; -+ -+ va_start(args, fmt); -+ __util_vasprintf(func, file, line, &str, fmt, args); -+ va_end(args); -+ -+ return str; -+} -+ -+/* Set the internal name of the calling thread */ -+void __set_threadname(const char *func, const char *file, int line, -+ const char *fmt, ...) -+{ -+ char *str; -+ va_list args; -+ -+ va_start(args, fmt); -+ __util_vasprintf(func, file, line, &str, fmt, args); -+ va_end(args); -+ -+ pthread_setspecific(thread_name_key, str); -+} -+ -+/* Clear any previously set thread name */ -+void clear_threadname(void) -+{ -+ void *addr = pthread_getspecific(thread_name_key); -+ -+ if (addr) { -+ pthread_setspecific(thread_name_key, NULL); -+ free(addr); -+ } -+} -+ -+/* Remove any number of trailing characters @c in @str */ -+void chomp(char *str, char *c) -+{ -+ ssize_t i; -+ -+ for (i = strlen(str) - 1; i >= 0 && strchr(c, str[i]); i--) -+ str[i] = 0; -+} -+ -+/* Remove any number of leading characters @c in @str */ -+void lchomp(char *str, char *c) -+{ -+ char *from; -+ -+ for (from = str; *from && strchr(c, *from); from++) -+ ; -+ if (str != from) -+ memmove(str, from, strlen(from) + 1); -+} -+ -+/* Perform a stat on file referenced by either @abs or @rel and @dref. Store -+ * results in @stat and return stat()'s return code. */ -+int stat_file(bool dereference, const char *abs, const char *rel, -+ struct dref *dref, struct stat *st) -+{ -+ int rc; -+ -+ if (dref) { -+ if (dereference) -+ rc = fstatat(dref->dirfd, rel, st, 0); -+ else -+ rc = fstatat(dref->dirfd, rel, st, AT_SYMLINK_NOFOLLOW); -+ } else { -+ if (dereference) -+ rc = stat(abs, st); -+ else -+ rc = lstat(abs, st); -+ } -+ -+ return rc; -+} -+ -+/* Fill stat buffer @st with dummy values. */ -+void set_dummy_stat(struct stat *st) -+{ -+ /* Fake stat */ -+ memset(st, 0, sizeof(struct stat)); -+ st->st_mode = S_IRUSR | S_IWUSR | S_IFREG; -+ st->st_uid = geteuid(); -+ st->st_gid = getegid(); -+ st->st_mtime = time(NULL); -+} -+ -+/* Redirect all output streams to @fd and execute command @CMD */ -+int cmd_child(int fd, char *cmd) -+{ -+ char *argv[] = { "/bin/sh", "-c", NULL, NULL }; -+ char *env[] = { NULL }; -+ -+ argv[2] = cmd; -+ if (dup2(fd, STDOUT_FILENO) == -1 || dup2(fd, STDERR_FILENO) == -1) { -+ mwarn("Could not redirect command output"); -+ return EXIT_RUNTIME; -+ } -+ -+ execve("/bin/sh", argv, env); -+ -+ return EXIT_RUNTIME; -+} -+ -+#define PIPE_READ 0 -+#define PIPE_WRITE 1 -+ -+/* Run command @cmd as a child process and store its PID in @pid_ptr. On -+ * success, return a file descriptor that is an output pipe to the standard -+ * output and standard error streams of the child process. Return %-1 on -+ * error. */ -+int cmd_open(char *cmd, pid_t *pid_ptr) -+{ -+ int pfd[2]; -+ pid_t pid; -+ -+ if (pipe(pfd) < 0) -+ return -1; -+ -+ pid = fork(); -+ if (pid < 0) { -+ /* Fork error */ -+ close(pfd[PIPE_READ]); -+ close(pfd[PIPE_WRITE]); -+ return -1; -+ } else if (pid == 0) { -+ /* Child process */ -+ close(pfd[PIPE_READ]); -+ exit(cmd_child(pfd[PIPE_WRITE], cmd)); -+ } -+ -+ /* Parent process */ -+ close(pfd[PIPE_WRITE]); -+ -+ *pid_ptr = pid; -+ -+ return pfd[PIPE_READ]; -+} -+ -+/* Close the file descriptor @fd and end the process with PID @pid. When -+ * not %NULL, use @status_ptr to store the resulting process status. */ -+int cmd_close(int fd, pid_t pid, int *status_ptr) -+{ -+ int status, rc = EXIT_OK; -+ -+ close(fd); -+ kill(pid, SIGQUIT); -+ if (waitpid(pid, &status, 0) == -1) { -+ status = -errno; -+ rc = EXIT_RUNTIME; -+ } -+ if (status_ptr) -+ *status_ptr = status; -+ -+ return rc; -+} -+ -+void misc_init(void) -+{ -+ set_timespec(&main_start_ts, 0, 0); -+ pthread_key_create(&thread_name_key, free); -+ set_threadname("main"); -+} -+ -+void misc_cleanup(void) -+{ -+ clear_threadname(); -+ pthread_key_delete(thread_name_key); -+} -+ -+void set_stdout_data(void) -+{ -+ stdout_data = true; -+} -+ -+bool starts_with(const char *str, const char *prefix) -+{ -+ size_t len; -+ -+ len = strlen(prefix); -+ -+ if (strncmp(str, prefix, len) == 0) -+ return true; -+ return false; -+} -+ -+bool ends_with(const char *str, const char *suffix) -+{ -+ size_t str_len, s_len; -+ -+ str_len = strlen(str); -+ s_len = strlen(suffix); -+ -+ if (str_len < s_len) -+ return false; -+ if (strcmp(str + str_len - s_len, suffix) != 0) -+ return false; -+ -+ return true; -+} -+ -+/* Remove subsequent slashes in @str */ -+void remove_double_slashes(char *str) -+{ -+ size_t i, to; -+ char last; -+ -+ last = 0; -+ for (i = 0, to = 0; str[i]; i++) { -+ if (last != '/' || str[i] != '/') -+ last = str[to++] = str[i]; -+ } -+ str[to] = 0; -+} ---- /dev/null -+++ b/dump2tar/src/strarray.c -@@ -0,0 +1,81 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * Dynamically growing string arrays -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#include "strarray.h" -+ -+#include -+#include -+#include -+ -+#include "misc.h" -+ -+/* Release resources associated with string array @array */ -+void free_strarray(struct strarray *array) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < array->num; i++) -+ free(array->str[i]); -+ free(array->str); -+ array->str = NULL; -+ array->num = 0; -+} -+ -+/* Add string @str to string array @array */ -+void add_str_to_strarray(struct strarray *array, const char *str) -+{ -+ array->str = mrealloc(array->str, sizeof(char *) * (array->num + 2)); -+ array->str[array->num + 1] = NULL; -+ array->str[array->num] = mstrdup(str); -+ array->num++; -+} -+ -+/* Add string resulting from @fmt and additional arguments to @array */ -+void add_vstr_to_strarray(struct strarray *array, const char *fmt, ...) -+{ -+ va_list args; -+ char *str; -+ -+ va_start(args, fmt); -+ util_vasprintf(&str, fmt, args); -+ va_end(args); -+ -+ array->str = mrealloc(array->str, sizeof(char *) * (array->num + 2)); -+ array->str[array->num + 1] = NULL; -+ array->str[array->num] = str; -+ array->num++; -+} -+ -+/* Add all lines in file at @filename to @array */ -+int add_file_to_strarray(struct strarray *array, const char *filename) -+{ -+ FILE *fd; -+ char *line = NULL; -+ size_t line_size; -+ int rc = EXIT_OK; -+ -+ fd = fopen(filename, "r"); -+ if (!fd) { -+ mwarn("%s: Cannot open file", filename); -+ return EXIT_RUNTIME; -+ } -+ -+ while (!feof(fd) && !ferror(fd)) { -+ if (getline(&line, &line_size, fd) == -1) -+ continue; -+ chomp(line, "\n"); -+ add_str_to_strarray(array, line); -+ } -+ if (ferror(fd)) -+ rc = EXIT_RUNTIME; -+ free(line); -+ -+ fclose(fd); -+ -+ return rc; -+} ---- /dev/null -+++ b/dump2tar/src/tar.c -@@ -0,0 +1,270 @@ -+/* -+ * dump2tar - tool to dump files and command output into a tar archive -+ * -+ * TAR file generation -+ * -+ * Copyright IBM Corp. 2016 -+ */ -+ -+#include "tar.h" -+ -+#include -+#include -+ -+#include "buffer.h" -+#include "idcache.h" -+#include "misc.h" -+ -+#define LONGLINK "././@LongLink" -+#define TYPE_LONGLINK 'K' -+#define TYPE_LONGNAME 'L' -+ -+#define BLOCKSIZE 512 -+ -+/* Basic TAR header */ -+struct tar_header { -+ char name[100]; -+ char mode[8]; -+ char uid[8]; -+ char gid[8]; -+ char size[12]; -+ char mtime[12]; -+ char chksum[8]; -+ char typeflag; -+ char linkname[100]; -+ char magic[6]; -+ char version[2]; -+ char uname[32]; -+ char gname[32]; -+ char devmajor[8]; -+ char devminor[8]; -+ char prefix[155]; -+}; -+ -+/* Store the octal value of @value to at most @len bytes at @dest */ -+static void set_octal(char *dest, size_t len, unsigned long value) -+{ -+ int i; -+ -+ dest[len - 1] = 0; -+ for (i = len - 2; i >= 0; i--) { -+ dest[i] = '0' + (value & 7); -+ value >>= 3; -+ } -+} -+ -+/* Store time @value to at most @len bytes at @dest */ -+static void set_time(char *dest, size_t len, time_t value) -+{ -+ time_t max = (1ULL << (3 * (len - 1))) - 1; -+ -+ if (value >= 0 && value <= max) { -+ set_octal(dest, len, value); -+ return; -+ } -+ -+ for (; len > 0; len--) { -+ dest[len - 1] = value & 0xff; -+ value >>= 8; -+ } -+ -+ dest[0] |= 0x80; -+} -+ -+#define SET_FIELD(obj, name, value) \ -+ set_octal((obj)->name, sizeof((obj)->name), (unsigned long) (value)) -+#define SET_TIME_FIELD(obj, name, value) \ -+ set_time((obj)->name, sizeof((obj)->name), (time_t) (value)) -+#define SET_STR_FIELD(obj, name, value) \ -+ strncpy((obj)->name, (value), sizeof((obj)->name)) -+ -+/* Initialize the tar file @header with the provided data */ -+static void init_header(struct tar_header *header, const char *filename, -+ const char *link, size_t len, struct stat *stat, -+ char type) -+{ -+ unsigned int i, checksum; -+ unsigned char *c; -+ -+ memset(header, 0, sizeof(*header)); -+ -+ /* Fill in header fields */ -+ SET_STR_FIELD(header, name, filename); -+ if (link) -+ SET_STR_FIELD(header, linkname, link); -+ SET_FIELD(header, size, len); -+ if (stat) { -+ SET_FIELD(header, mode, stat->st_mode & 07777); -+ SET_FIELD(header, uid, stat->st_uid); -+ SET_FIELD(header, gid, stat->st_gid); -+ SET_TIME_FIELD(header, mtime, stat->st_mtime); -+ uid_to_name(stat->st_uid, header->uname, sizeof(header->uname)); -+ gid_to_name(stat->st_gid, header->gname, sizeof(header->gname)); -+ } else { -+ SET_FIELD(header, mode, 0644); -+ SET_FIELD(header, uid, 0); -+ SET_FIELD(header, gid, 0); -+ SET_TIME_FIELD(header, mtime, 0); -+ uid_to_name(0, header->uname, sizeof(header->uname)); -+ gid_to_name(0, header->gname, sizeof(header->gname)); -+ } -+ header->typeflag = type; -+ memcpy(header->magic, "ustar ", sizeof(header->magic)); -+ memcpy(header->version, " ", sizeof(header->version)); -+ -+ /* Calculate checksum */ -+ memset(header->chksum, ' ', sizeof(header->chksum)); -+ checksum = 0; -+ c = (unsigned char *) header; -+ for (i = 0; i < sizeof(*header); i++) -+ checksum += c[i]; -+ snprintf(header->chksum, 7, "%06o", checksum); -+} -+ -+/* Emit zero bytes via @emit_cb to pad @len to a multiple of BLOCKSIZE */ -+static int emit_padding(emit_cb_t emit_cb, void *data, size_t len) -+{ -+ size_t pad = BLOCKSIZE - len % BLOCKSIZE; -+ char zeroes[BLOCKSIZE]; -+ -+ if (len % BLOCKSIZE > 0) { -+ memset(zeroes, 0, BLOCKSIZE); -+ return emit_cb(data, zeroes, pad); -+ } -+ -+ return 0; -+} -+ -+/* Emit @len bytes at @addr via @emit_cb and pad data to BLOCKSIZE with zero -+ * bytes */ -+static int emit_data(emit_cb_t emit_cb, void *data, void *addr, size_t len) -+{ -+ int rc; -+ -+ if (len == 0) -+ return 0; -+ -+ rc = emit_cb(data, addr, len); -+ if (rc) -+ return rc; -+ return emit_padding(emit_cb, data, len); -+} -+ -+/* Emit a tar header via @emit_cb */ -+static int emit_header(emit_cb_t emit_cb, void *data, char *filename, -+ char *link, size_t len, struct stat *stat, char type) -+{ -+ struct tar_header header; -+ size_t namelen = strlen(filename); -+ size_t linklen; -+ int rc; -+ -+ /* /proc can contain unreadable links which causes tar to complain -+ * during extract - use a dummy value to handle this more gracefully */ -+ if (link && !*link) -+ link = " "; -+ -+ linklen = link ? strlen(link) : 0; -+ if (linklen > sizeof(header.linkname)) { -+ rc = emit_header(emit_cb, data, LONGLINK, NULL, linklen + 1, -+ NULL, TYPE_LONGLINK); -+ if (rc) -+ return rc; -+ rc = emit_data(emit_cb, data, link, linklen + 1); -+ if (rc) -+ return rc; -+ } -+ if (namelen > sizeof(header.name)) { -+ rc = emit_header(emit_cb, data, LONGLINK, NULL, namelen + 1, -+ NULL, TYPE_LONGNAME); -+ if (rc) -+ return rc; -+ rc = emit_data(emit_cb, data, filename, namelen + 1); -+ if (rc) -+ return rc; -+ } -+ -+ init_header(&header, filename, link, len, stat, type); -+ return emit_data(emit_cb, data, &header, sizeof(header)); -+} -+ -+struct emit_content_cb_data { -+ emit_cb_t emit_cb; -+ void *data; -+ size_t len; -+ int rc; -+}; -+ -+/* Callback for emitting a single chunk of data of a buffer */ -+static int emit_content_cb(void *data, void *addr, size_t len) -+{ -+ struct emit_content_cb_data *cb_data = data; -+ -+ if (len > cb_data->len) -+ len = cb_data->len; -+ cb_data->len -= len; -+ -+ cb_data->rc = cb_data->emit_cb(cb_data->data, addr, len); -+ -+ if (cb_data->rc || cb_data->len == 0) -+ return 1; -+ -+ return 0; -+} -+ -+/* Emit at most @len bytes of contents of @buffer via @emit_cb and pad output -+ * to BLOCKSIZE with zero bytes */ -+static int emit_content(emit_cb_t emit_cb, void *data, struct buffer *buffer, -+ size_t len) -+{ -+ struct emit_content_cb_data cb_data; -+ -+ cb_data.emit_cb = emit_cb; -+ cb_data.data = data; -+ cb_data.len = len; -+ cb_data.rc = 0; -+ buffer_iterate(buffer, emit_content_cb, &cb_data); -+ if (cb_data.rc) -+ return cb_data.rc; -+ -+ return emit_padding(emit_cb, data, buffer->total); -+} -+ -+/* Convert file meta data and content specified as @content into a -+ * stream of bytes that is reported via the @emit_cb callback. @data is -+ * passed through to the callback for arbitrary use. */ -+int tar_emit_file_from_buffer(char *filename, char *link, size_t len, -+ struct stat *stat, char type, -+ struct buffer *content, emit_cb_t emit_cb, -+ void *data) -+{ -+ int rc; -+ -+ DBG("emit tar file=%s type=%d len=%zu", filename, type, len); -+ rc = emit_header(emit_cb, data, filename, link, len, stat, type); -+ if (rc) -+ return rc; -+ if (content) -+ rc = emit_content(emit_cb, data, content, len); -+ -+ return rc; -+} -+ -+/* Convert file meta data and content specified as @addr and @len into a -+ * stream of bytes that is reported via the @emit_cb callback. @data is -+ * passed through to the callback for arbitrary use. */ -+int tar_emit_file_from_data(char *filename, char *link, size_t len, -+ struct stat *stat, char type, void *addr, -+ emit_cb_t emit_cb, void *data) -+{ -+ int rc; -+ -+ DBG("emit tar file=%s type=%d len=%zu", filename, type, len); -+ rc = emit_header(emit_cb, data, filename, link, len, stat, type); -+ if (rc) -+ return rc; -+ if (addr) -+ rc = emit_data(emit_cb, data, addr, len); -+ -+ return rc; -+} diff --git a/s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch b/s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch deleted file mode 100644 index e37fd0a..0000000 --- a/s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch +++ /dev/null @@ -1,72 +0,0 @@ -Subject: [PATCH] [FEAT RTL1601] dbginfo.sh: Make use of sysfs collection helper -From: Peter Oberparleiter - -Summary: dbginfo.sh: Make use of sysfs collection helper -Description: If available, use dump2tar in dbginfo.sh for sysfs - file collection to significantly speed up dbginfo.sh - processing. Example speedup on an LPAR with ~190k - sysfs files: - - Unpatched: - # time ./dbginfo.sh - real 1m19.624s - user 0m44.985s - sys 0m45.173s - - Patched: - # time ./dbginfo.sh - real 0m5.822s - user 0m4.523s - sys 0m2.636s -Upstream-ID: - -Problem-ID: RTL1601 - -Signed-off-by: Peter Oberparleiter ---- - scripts/dbginfo.sh | 33 +++++++++++++++++++++------------ - 1 file changed, 21 insertions(+), 12 deletions(-) - ---- a/scripts/dbginfo.sh -+++ b/scripts/dbginfo.sh -@@ -620,20 +620,29 @@ collect_sysfs() { - fi - fi - -- call_run_command "find /sys -print0 | sort -z | xargs -0 -n 10 ls -ld" "${OUTPUT_FILE_SYSFS}" -+ # Collect sysfs files using multiple threads (-J 1) while excluding -+ # files known to block on read (-x). Stop reading a file that takes -+ # more than 5 seconds (-T 5) such as an active ftrace buffer. -+ dump2tar /sys -z -o "${WORKPATH}/sysfs.tgz" -x '*/tracing/trace_pipe*' \ -+ -x '*/tracing/per_cpu/*' --ignore-failed-read -J 1 -T 5 - -- find /sys -noleaf -type d 2>/dev/null | while IFS= read -r dir_name; do -- mkdir -p "${WORKPATH}${dir_name}" -- done -+ if [ $? -ne 0 ] ; then -+ echo "${SCRIPTNAME}: Warning: dump2tar failed or is unavailable - falling back to slow path" -+ call_run_command "find /sys -print0 | sort -z | xargs -0 -n 10 ls -ld" "${OUTPUT_FILE_SYSFS}" - -- find /sys -noleaf -type f -perm /444\ -- -a -not -name "*trace_pipe*"\ -- 2>/dev/null | while IFS= read -r file_name; do -- echo " ${file_name}" -- if ! dd if="${file_name}" status=noxfer iflag=nonblock of="${WORKPATH}${file_name}" >/dev/null 2>&1; then -- echo "${SCRIPTNAME}: Warning: failed to copy \"${file_name}\"" -- fi -- done -+ find /sys -noleaf -type d 2>/dev/null | while IFS= read -r dir_name; do -+ mkdir -p "${WORKPATH}${dir_name}" -+ done -+ -+ find /sys -noleaf -type f -perm /444\ -+ -a -not -name "*trace_pipe*"\ -+ 2>/dev/null | while IFS= read -r file_name; do -+ echo " ${file_name}" -+ if ! dd if="${file_name}" status=noxfer iflag=nonblock of="${WORKPATH}${file_name}" >/dev/null 2>&1; then -+ echo "${SCRIPTNAME}: Warning: failed to copy \"${file_name}\"" -+ fi -+ done -+ fi - - if test ${debugfs_mounted} -eq 1; then - umount "${MOUNT_POINT_DEBUGFS}" diff --git a/s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch b/s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch deleted file mode 100644 index d62ad51..0000000 --- a/s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch +++ /dev/null @@ -1,142 +0,0 @@ -Subject: [PATCH] [BZ 151594] dbginfo: Collect docker debug output. -From: Karsten Graul - -Description: dbginfo: Collect docker debug output. -Symptom: dbginfo.sh output does not contain docker debug output. -Problem: dbginfo.sh does not collect docker debug output. -Solution: Add invocation of docker debug commands to dbginfo.sh. -Reproduction: - -Upstream-ID: - -Problem-ID: 151594 - -Signed-off-by: Karsten Graul ---- - scripts/dbginfo.sh | 58 +++++++++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 54 insertions(+), 4 deletions(-) - ---- a/scripts/dbginfo.sh -+++ b/scripts/dbginfo.sh -@@ -2,7 +2,7 @@ - # - # dbginfo.sh - Tool to collect runtime, configuration, and trace information - # --# Copyright IBM Corp. 2002, 2016 -+# Copyright IBM Corp. 2002, 2017 - # - - # Switching to neutral locale -@@ -18,7 +18,7 @@ readonly SCRIPTNAME="${0##*/}" - print_version() { - cat </dev/null | cut -d'.' -f1) -@@ -301,6 +304,8 @@ LOGFILES="\ - /var/log/yum.log\ - /var/log/openvswitch/ovs-vswitchd.log\ - /var/log/openvswitch/ovsdb-server.log\ -+ /var/run/docker/libcontainerd/containerd/events.log\ -+ /run/containerd/events.log\ - " - - ######################################## -@@ -351,6 +356,9 @@ CONFIGFILES="\ - /etc/xinet.d\ - /etc/*release\ - $(find /lib/modules -name modules.dep 2>/dev/null)\ -+ /etc/docker\ -+ /usr/lib/systemd\ -+ /etc/apparmor.d\ - " - - ######################################## -@@ -436,6 +444,16 @@ CMDS="uname -a\ - :systemctl --all --no-pager show\ - :systemctl --all --no-pager list-units\ - :systemctl --all --no-pager list-unit-files\ -+ :docker info\ -+ :docker images\ -+ :docker network ls\ -+ :docker ps\ -+ :docker ps -a\ -+ :docker stats --no-stream\ -+ :docker version\ -+ :systemctl status docker.service\ -+ :df /var/lib/docker\ -+ :df --inodes /var/lib/docker\ - " - - ######################################## -@@ -767,13 +785,43 @@ collect_domain_xml() { - } - - ######################################## -+collect_docker() { -+ local item_list -+ local item -+ -+ # call docker inspect for all containers -+ item_list=$(docker ps -qa) -+ if test -n "${item_list}"; then -+ pr_syslog_stdout "10a of ${COLLECTION_COUNT}: Collecting docker container output" -+ for item in ${item_list}; do -+ call_run_command "docker inspect ${item}" "${OUTPUT_FILE_DOCKER}" -+ done -+ else -+ pr_syslog_stdout "10a of ${COLLECTION_COUNT}: Collecting docker container output skipped" -+ fi -+ -+ # call docker inspect for all networks -+ item_list=$(docker network ls -q) -+ if test -n "${item_list}"; then -+ pr_syslog_stdout "10b of ${COLLECTION_COUNT}: Collecting docker network output" -+ for item in ${item_list}; do -+ call_run_command "docker network inspect ${item}" "${OUTPUT_FILE_DOCKER}" -+ done -+ else -+ pr_syslog_stdout "10b of ${COLLECTION_COUNT}: Collecting docker network output skipped" -+ fi -+ -+ pr_log_stdout " " -+} -+ -+######################################## - post_processing() { - local file_mtime - local file_mtime_epoche - local tmp_file - local file_name - -- pr_syslog_stdout "10 of ${COLLECTION_COUNT}: Postprocessing" -+ pr_syslog_stdout "11 of ${COLLECTION_COUNT}: Postprocessing" - - find "${WORKPATH}etc/libvirt/qemu/" -maxdepth 1 -name "*.xml" 2>/dev/null | while IFS= read -r file_name; do - file_mtime_epoche=$(stat --format=%Y "${file_name}") -@@ -1056,6 +1104,8 @@ collect_ovs - - collect_domain_xml - -+collect_docker -+ - post_processing - - create_package diff --git a/s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch b/s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch deleted file mode 100644 index b8a89d3..0000000 --- a/s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch +++ /dev/null @@ -1,558 +0,0 @@ -Subject: [PATCH] [FEAT LS1502] lsdasd/tunedasd: Add channel path aware erp -From: Stefan Haberland - -Summary: lsdasd/tunedasd: Add channel path aware erp -Description: Add tools support for channel path aware error recovery. - lsdasd shows the newly added IFCC path mask and HPF availability. - tunedasd gets an option to reset channel paths for a device. -Upstream-ID: - -Problem-ID: LS1502 - -Signed-off-by: Stefan Haberland ---- - include/dasd_sys.h | 1 - libdasd/dasd_sys.c | 94 +++++++++++++++++++++++++++++++++++++ - tunedasd/include/disk.h | 3 - - tunedasd/man/tunedasd.8 | 17 ++++++ - tunedasd/src/Makefile | 2 - tunedasd/src/disk.c | 35 ++++++++++++++ - tunedasd/src/tunedasd.c | 120 ++++++++++++++++++++++++++++-------------------- - zconf/lsdasd | 36 +++++++++++--- - 8 files changed, 251 insertions(+), 57 deletions(-) - ---- a/include/dasd_sys.h -+++ b/include/dasd_sys.h -@@ -13,5 +13,6 @@ - #include "u2s.h" - - int dasd_sys_raw_track_access(char *); -+int dasd_reset_chpid(char *, char *); - - #endif /* DASD_SYS_H */ ---- a/libdasd/dasd_sys.c -+++ b/libdasd/dasd_sys.c -@@ -6,6 +6,9 @@ - * Copyright IBM Corp. 2016 - */ - -+#include -+#include -+ - #include "dasd_sys.h" - - /** -@@ -44,3 +47,94 @@ int dasd_sys_raw_track_access(char *devn - - return (rc == 1) ? 1 : 0; - } -+ -+ -+int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask) -+{ -+ unsigned int val; -+ char path[40]; -+ int count, i; -+ FILE *fp; -+ -+ sprintf(path, "/sys/bus/ccw/devices/%s/../chpids", busid); -+ *mask = 0; -+ fp = fopen(path, "r"); -+ if (!fp) -+ return ENODEV; -+ -+ for (i = 0; i < 8; i++) { -+ count = fscanf(fp, " %x", &val); -+ if (count != 1) { -+ fclose(fp); -+ return EIO; -+ } -+ if (val == chpid) -+ *mask = 0x80 >> i; -+ } -+ fclose(fp); -+ -+ return 0; -+} -+ -+/** -+ * reset chpid -+ * -+ * The "devnode" parameter can be any valid relative or absolute path to -+ * a DASD device node, for example: -+ * -+ * - /dev/dasda -+ * - /dev/disk/by-path/ccw-0.0.bf20 -+ * -+ * @param[in] devnode Device node of interest -+ * @param[in] chpid The chpid to reset -+ * If NULL all chpids will be reset -+ * -+ * @return 0 on success, otherwise one of the following error codes: -+ * - EINVAL No valid chpid specified. -+ * - ENODEV Could not open device. -+ * - ENOENT Specified chpid not found. -+ * - EIO Other I/O error -+ * -+ */ -+int dasd_reset_chpid(char *devnode, char *chpid_char) -+{ -+ unsigned int chpid; -+ char path[41]; -+ char busid[9]; -+ int mask, rc; -+ char *endptr; -+ FILE *fp; -+ -+ if (u2s_getbusid(devnode, busid)) -+ return ENODEV; -+ -+ if (!chpid_char) { -+ sprintf(path, "/sys/bus/ccw/devices/%s/path_reset", busid); -+ fp = fopen(path, "w"); -+ if (!fp) -+ return ENODEV; -+ fprintf(fp, "%s", "all\n"); -+ fclose(fp); -+ return 0; -+ } -+ -+ errno = 0; -+ chpid = strtoul(chpid_char, &endptr, 16); -+ if (errno || (endptr && (*endptr != '\0'))) -+ return EINVAL; -+ -+ rc = dasd_get_pm_from_chpid(busid, chpid, &mask); -+ if (rc) -+ return rc; -+ if (!mask) -+ return ENOENT; -+ -+ sprintf(path, "/sys/bus/ccw/devices/%s/path_reset", busid); -+ fp = fopen(path, "w"); -+ if (!fp) -+ return ENODEV; -+ fprintf(fp, "%02x", mask); -+ fclose(fp); -+ -+ return 0; -+} ---- a/tunedasd/include/disk.h -+++ b/tunedasd/include/disk.h -@@ -27,7 +27,8 @@ int disk_release (char* device); - int disk_slock (char* device); - int disk_query_reserve_status(char* device); - int disk_profile (char* device, char* prof_item); --int disk_reset_prof (char* device); -+int disk_reset_prof(char *device); -+int disk_reset_chpid(char *device, char *chpid); - - #endif /* not DISK_H */ - ---- a/tunedasd/man/tunedasd.8 -+++ b/tunedasd/man/tunedasd.8 -@@ -149,6 +149,18 @@ Following rows are supported: - .TP - .BR "\-R" " or " "\-\-reset_prof" - Reset profile info of device. -+.TP -+.BR "\-p" " or " "\-\-path_reset " -+Reset a channel path of a selected device. A channel path -+might be suspended due to high IFCC error rates or a High Performance -+FICON failure. Use this option to resume considering the channel path -+for I/O. -+.TP -+.BR "\-\-path_reset_all" -+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 "\-o" " or " "\-\-online" -@@ -166,8 +178,13 @@ Reset profile info of device. - .br - - tunedasd -c prestage -n 1 /dev/dasdc -+ -+.br -+3. Scenario: Reset failed channel path with CHPID 45 - .br - -+ tunedasd -p 45 /dev/dasdc -+.br - .SH "SEE ALSO" - .BR dasdview (8), - .BR dasdfmt (8), ---- a/tunedasd/src/Makefile -+++ b/tunedasd/src/Makefile -@@ -5,7 +5,7 @@ includes = $(wildcard ../include/*.h) - - all: tunedasd - --objects = tunedasd.o disk.o -+objects = tunedasd.o disk.o ../../libdasd/dasd_sys.o ../../libu2s/u2s.o - $(objects): $(includes) - - tunedasd: $(objects) ---- a/tunedasd/src/disk.c -+++ b/tunedasd/src/disk.c -@@ -9,6 +9,7 @@ - - #include "disk.h" - #include "tunedasd.h" -+#include "dasd_sys.h" - - #include - #include -@@ -682,3 +683,37 @@ disk_reset_prof (char* device) - return 0; - } - -+int disk_reset_chpid(char *device, char *chpid) -+{ -+ int rc; -+ -+ if (chpid) -+ printf("Resetting chpid %s for device <%s>...\n", chpid, -+ device); -+ else -+ printf("Resetting all chpids for device <%s>...\n", device); -+ -+ rc = dasd_reset_chpid(device, chpid); -+ switch (rc) { -+ case 0: -+ printf("Done.\n"); -+ return 0; -+ case ENODEV: -+ error_print("%s: %s", device, strerror(errno)); -+ break; -+ case EINVAL: -+ error_print("%s: Could not reset chpid %s: Invalid CHPID", -+ device, chpid); -+ break; -+ case ENOENT: -+ error_print("%s: Could not reset chpid %s: CHPID not defined for device", -+ device, chpid); -+ break; -+ default: -+ error_print("%s: Could not reset chpid %s", -+ device, chpid); -+ break; -+ } -+ -+ return -1; -+} ---- a/tunedasd/src/tunedasd.c -+++ b/tunedasd/src/tunedasd.c -@@ -34,28 +34,30 @@ static const char* usage_text[] = { - "(e.g. '/dev/dasda') or a list of devices separated by a space " - "character.", - "", -- "-h, --help Print this help, then exit", -- "-v, --version Print version information, then exit", -- "-g, --get_cache Get current storage server caching behaviour", -- "-c, --cache Define caching behavior on storage server", -- " (normal/bypass/inhibit/sequential/prestage/" -- "record)", -- "-n, --no_cyl Number of cylinders to be cached ", -- " (only valid together with --cache)", -- "-S, --reserve Reserve device", -- "-L, --release Release device", -- "-O, --slock Unconditional reserve device", -- " Note: Use with care, this breaks an existing " -- "lock", -- "-Q, --query_reserve Print reserve status of device ", -- "-P, --profile Print profile info of device", -- "-I, --prof_item Print single profile item", -- " (reqs/sects/sizes/total/totsect/start/irq/", -- " irqsect/end/queue)", -- "-R, --reset_prof Reset profile info of device" -+ "-h, --help Print this help, then exit", -+ "-v, --version Print version information, then exit", -+ "-g, --get_cache Get current storage server caching behaviour", -+ "-c, --cache Define caching behavior on storage server", -+ " (normal/bypass/inhibit/sequential/prestage/" -+ "record)", -+ "-n, --no_cyl Number of cylinders to be cached ", -+ " (only valid together with --cache)", -+ "-S, --reserve Reserve device", -+ "-L, --release Release device", -+ "-O, --slock Unconditional reserve device", -+ " Note: Use with care, this breaks an existing " -+ "lock", -+ "-Q, --query_reserve Print reserve status of device ", -+ "-P, --profile Print profile info of device", -+ "-I, --prof_item Print single profile item", -+ " (reqs/sects/sizes/total/totsect/start/irq/", -+ " irqsect/end/queue)", -+ "-R, --reset_prof Reset profile info of device", -+ "-p, --path_reset Reset channel path of a device", -+ " --path_reset_all Reset all channel paths of a device" - }; - --#define CMD_KEYWORD_NUM 12 -+#define CMD_KEYWORD_NUM 14 - #define DEVICES_NUM 256 - - enum cmd_keyword_id { -@@ -71,6 +73,8 @@ enum cmd_keyword_id { - cmd_keyword_prof_item = 9, - cmd_keyword_reset_prof = 10, - cmd_keyword_query_reserve = 11, -+ cmd_keyword_path = 12, -+ cmd_keyword_path_all = 13, - }; - - -@@ -79,18 +83,20 @@ static const struct { - char* keyword; - enum cmd_keyword_id id; - } keyword_list[] = { -- { "help", cmd_keyword_help }, -- { "version", cmd_keyword_version }, -- { "get_cache", cmd_keyword_get_cache }, -- { "cache", cmd_keyword_cache }, -- { "no_cyl", cmd_keyword_no_cyl }, -- { "reserve", cmd_keyword_reserve }, -- { "release", cmd_keyword_release }, -- { "slock", cmd_keyword_slock }, -- { "profile", cmd_keyword_profile }, -- { "prof_item", cmd_keyword_prof_item }, -- { "reset_prof", cmd_keyword_reset_prof }, -- { "query_reserve", cmd_keyword_query_reserve } -+ { "help", cmd_keyword_help }, -+ { "version", cmd_keyword_version }, -+ { "get_cache", cmd_keyword_get_cache }, -+ { "cache", cmd_keyword_cache }, -+ { "no_cyl", cmd_keyword_no_cyl }, -+ { "reserve", cmd_keyword_reserve }, -+ { "release", cmd_keyword_release }, -+ { "slock", cmd_keyword_slock }, -+ { "profile", cmd_keyword_profile }, -+ { "prof_item", cmd_keyword_prof_item }, -+ { "reset_prof", cmd_keyword_reset_prof }, -+ { "query_reserve", cmd_keyword_query_reserve }, -+ { "path_reset", cmd_keyword_path }, -+ { "path_reset_all", cmd_keyword_path_all } - }; - - -@@ -103,22 +109,24 @@ enum cmd_key_state { - - /* Determines which combination of keywords are valid */ - 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 -- * ion cach e yl rve ase k ile _ite t_pr y_re -+ /* 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 */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv }, -- /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, -- /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv }, -- /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv }, -- /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv }, -- /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv }, -- /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv }, -- /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv }, -- /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv }, -- /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv }, -- /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv }, -- /* query_reserve */ { 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 }, -+ /* version */ { inv, req, 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 }, -+ /* cache */ { opt, opt, inv, req, opt, 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 }, -+ /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv }, -+ /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv }, -+ /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv }, -+ /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv, inv, inv }, -+ /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv }, -+ /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv }, -+ /* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv }, -+ /* path */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv }, -+ /* path_all */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req }, - }; - - struct parameter { -@@ -146,11 +154,13 @@ static struct option options[] = { - { "prof_item", required_argument, NULL, 'I'}, - { "reset_prof", no_argument, NULL, 'R'}, - { "query_reserve", no_argument, NULL, 'Q'}, -+ { "path_reset", required_argument, NULL, 'p'}, -+ { "path_reset_all", no_argument, NULL, 'A'}, - { NULL, 0, NULL, 0 } - }; - - /* Command line option abbreviations */ --static const char option_string[] = "hvgc:n:SLOPI:RQ"; -+static const char option_string[] = "hvgc:n:SLOPI:RQp:"; - - - /* Error message string */ -@@ -348,6 +358,14 @@ get_command_line (int argc, char* argv[] - optarg); - } - break; -+ case 'p': -+ rc = store_option(&cmdline, cmd_keyword_path, -+ optarg); -+ break; -+ case 'A': -+ rc = store_option(&cmdline, cmd_keyword_path_all, -+ optarg); -+ break; - case 'S': - rc = store_option (&cmdline, cmd_keyword_reserve, - optarg); -@@ -400,7 +418,6 @@ get_command_line (int argc, char* argv[] - return 0; - } - -- - /* - * Execute the command. - */ -@@ -444,6 +461,13 @@ do_command (char* device, struct command - case cmd_keyword_query_reserve: - rc = disk_query_reserve_status(device); - break; -+ case cmd_keyword_path: -+ rc = disk_reset_chpid(device, -+ cmdline.parm[cmd_keyword_path].data); -+ break; -+ case cmd_keyword_path_all: -+ rc = disk_reset_chpid(device, NULL); -+ break; - default: - error_print ("Unknown command '%s' specified", - get_keyword_name (i)); ---- a/zconf/lsdasd -+++ b/zconf/lsdasd -@@ -368,13 +368,15 @@ function extended() - CABLEPM=0 - CUIRPM=0 - HPFPM=0 -+ IFCCPM=0 - - # additional information - read DIAG 2> /dev/null < $DEVPATH/use_diag || continue - read EER 2> /dev/null < $DEVPATH/eer_enabled || continue - read ERP 2> /dev/null < $DEVPATH/erplog || continue -+ read HPF 2> /dev/null < $DEVPATH/hpf - # in case the path_masks do not exist simply ignore it -- read OPM NPPM CABLEPM CUIRPM HPFPM 2> /dev/null < $DEVPATH/path_masks -+ read OPM NPPM CABLEPM CUIRPM HPFPM IFCCPM 2> /dev/null < $DEVPATH/path_masks - read -a C 2> /dev/null < $DEVPATH/../chpids || continue - read PIM PAM POM 2> /dev/null < $DEVPATH/../pimpampom || continue - -@@ -385,6 +387,7 @@ function extended() - CABLEPM=0x$CABLEPM - CUIRPM=0x$CUIRPM - HPFPM=0x$HPFPM -+ IFCCPM=0x$IFCCPM - - #-----------------------------------------------------------# - # aggregate chpids and path mask to useful information # -@@ -397,6 +400,7 @@ function extended() - CUIR_PATHS=(" " " " " " " " " " " " " " " ") - CABLE_PATHS=(" " " " " " " " " " " " " " " ") - HPF_PATHS=(" " " " " " " " " " " " " " " ") -+ IFCC_PATHS=(" " " " " " " " " " " " " " " ") - - # installed paths - j=0 -@@ -470,13 +474,25 @@ function extended() - (( mask>>=1 )) - done - -+ # IFCC unusable paths -+ j=0 -+ mask=0x80 -+ for (( i=0; i<8; i++ )) ;do -+ PM=$(($IFCCPM&$mask)) -+ if [ $PM -gt 0 ] ;then -+ IFCC_PATHS[j]=${C[$i]} ; -+ ((j++)) ; -+ fi -+ (( mask>>=1 )) -+ done -+ - #-------------------------------------------# - # format data for output # - #-------------------------------------------# - - if [[ "$ONLINE" == 0 ]]; then - ACTIVE="offline" -- printf "%s:%s:%s# status:\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# uid: \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#\n" \ -+ printf "%s:%s:%s# status:\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# 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" \ - "$SORTKEYLEN" "$SORTKEY" \ - "$BUSID" \ - "$ACTIVE" \ -@@ -484,18 +500,20 @@ function extended() - "$READONLY" \ - "$EER" \ - "$ERP" \ -+ "$HPF" \ - "$DEV_UID" \ - "${INSTALLED_PATHS[@]}" \ - "${USED_PATHS[@]}" \ - "${NP_PATHS[@]}" \ - "${CABLE_PATHS[@]}" \ - "${CUIR_PATHS[@]}" \ -- "${HPF_PATHS[@]}" ; -+ "${HPF_PATHS[@]}" \ -+ "${IFCC_PATHS[@]}" ; - continue - 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 # uid: \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#\n" \ -+ 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# 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" \ - "$SORTKEYLEN" "$SORTKEY" \ - "$BUSID" \ - "$ACTIVE" \ -@@ -504,13 +522,15 @@ function extended() - "$READONLY" \ - "$EER" \ - "$ERP" \ -+ "$HPF" \ - "$DEV_UID" \ - "${INSTALLED_PATHS[@]}" \ - "${USED_PATHS[@]}" \ - "${NP_PATHS[@]}" \ - "${CABLE_PATHS[@]}" \ - "${CUIR_PATHS[@]}" \ -- "${HPF_PATHS[@]}" ; -+ "${HPF_PATHS[@]}" \ -+ "${IFCC_PATHS[@]}" ; - continue - else - continue -@@ -533,7 +553,7 @@ function extended() - COLON=":" - 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# 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# uid: \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#\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# 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# 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" \ - "$SORTKEYLEN" "$SORTKEY" \ - "$BUSID" \ - "$BLOCKNAME" \ -@@ -549,13 +569,15 @@ function extended() - "$READONLY" \ - "$EER" \ - "$ERP" \ -+ "$HPF" \ - "$DEV_UID" \ - "${INSTALLED_PATHS[@]}" \ - "${USED_PATHS[@]}" \ - "${NP_PATHS[@]}" \ - "${CABLE_PATHS[@]}" \ - "${CUIR_PATHS[@]}" \ -- "${HPF_PATHS[@]}" ; -+ "${HPF_PATHS[@]}" \ -+ "${IFCC_PATHS[@]}" ; - } - - function host() diff --git a/s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch b/s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch deleted file mode 100644 index 0a5236a..0000000 --- a/s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch +++ /dev/null @@ -1,65 +0,0 @@ -Subject: [PATCH] [BZ 151416] mon_fsstatd: fix double free in error path and skip virtual fs -From: Gerald Schaefer - -Description: mon_fsstatd: fix double free in error path and skip virtual fs -Symptom: The daemon is stopped and the following messages can be found - in syslog: "statvfs error on /run/user/0: Permission denied" - and "double free or corruption (!prev)". -Problem: The error handling code for a failing statvfs() call erroneously - does an extra fclose(), conflicting with the later fclose(). - Also, breaking out of the inner loop at this point doesn't make - sense, because there may be other mounted filesystems that would - be skipped. - The reason for the failing statvfs() (on /run/user/0) is a wrong - selinux context (when started via systemctl), and this error will - spam the syslog if we only fix the double free. Since /run/user/0 - is a tmpfs, and mon_fsstatd is supposed to collect only physical - filesystem data, it is wrong to even try to access /run/user/0. -Solution: Remove the extra fclose(), replace the break with a continue, - and add tmpfs (and others) to the list of ignored virtual - filesystems. -Reproduction: Start mon_fsstatd via service/systemctl. -Upstream-ID: - -Problem-ID: 151416 - -Signed-off-by: Gerald Schaefer ---- - mon_tools/mon_fsstatd.c | 19 +++++++++++++++++-- - 1 file changed, 17 insertions(+), 2 deletions(-) - ---- a/mon_tools/mon_fsstatd.c -+++ b/mon_tools/mon_fsstatd.c -@@ -323,16 +323,31 @@ static int fsstatd_do_work(void) - strncmp(ent->mnt_type, "none", 4) == 0 || - strncmp(ent->mnt_type, "proc", 4) == 0 || - strncmp(ent->mnt_type, "subfs", 5) == 0 || -+ strncmp(ent->mnt_type, "nfsd", 4) == 0 || -+ strncmp(ent->mnt_type, "tmpfs", 5) == 0 || -+ strncmp(ent->mnt_type, "sysfs", 5) == 0 || -+ strncmp(ent->mnt_type, "pstore", 6) == 0 || -+ strncmp(ent->mnt_type, "cgroup", 6) == 0 || -+ strncmp(ent->mnt_type, "mqueue", 6) == 0 || -+ strncmp(ent->mnt_type, "devpts", 6) == 0 || -+ strncmp(ent->mnt_type, "debugfs", 7) == 0 || -+ strncmp(ent->mnt_type, "devtmpfs", 8) == 0 || -+ strncmp(ent->mnt_type, "configfs", 8) == 0 || -+ strncmp(ent->mnt_type, "selinuxfs", 9) == 0 || -+ strncmp(ent->mnt_type, "hugetlbfs", 9) == 0 || -+ strncmp(ent->mnt_type, "securityfs", 10) == 0 || -+ strncmp(ent->mnt_type, "rpc_pipefs", 10) == 0 || -+ strncmp(ent->mnt_type, "binfmt_misc", 11) == 0 || - strncmp(ent->mnt_type, "ignore", 6) == 0)) { - ent = getmntent(mnttab); - continue; - } - result = statvfs(ent->mnt_dir, &buf); - if (result != 0) { -- fclose(mnttab); - syslog(LOG_ERR, "statvfs error on %s: %s\n", - ent->mnt_dir, strerror(errno)); -- break; -+ ent = getmntent(mnttab); -+ continue; - } - - if (buf.f_blocks > 0) diff --git a/s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch b/s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch deleted file mode 100644 index 8b19b8a..0000000 --- a/s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch +++ /dev/null @@ -1,30 +0,0 @@ -util_proc: Fix memory allocation error messages - -Signed-off-by: Michael Holzheu ---- - libutil/util_proc.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - ---- a/libutil/util_proc.c -+++ b/libutil/util_proc.c -@@ -54,8 +54,7 @@ util_proc_read_special_file(const char * - count = 0; - data = (char *) malloc(current_size); - if (data == NULL) { -- printf("Could not allocate %lld bytes of memory", -- (unsigned long long) size); -+ printf("Could not allocate %zu bytes of memory", current_size); - fclose(file); - return -1; - } -@@ -69,8 +68,8 @@ util_proc_read_special_file(const char * - if (count >= current_size) { - new_data = (char *) malloc(current_size * 2); - if (new_data == NULL) { -- printf("Could not allocate %lld bytes of memory", -- (unsigned long long) size); -+ printf("Could not allocate %zu bytes of memory", -+ current_size * 2); - free(data); - fclose(file); - return -1; diff --git a/s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch b/s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch deleted file mode 100644 index 7782dd1..0000000 --- a/s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch +++ /dev/null @@ -1,144 +0,0 @@ -Subject: [PATCH] [BZ 149058] ziomon: no blktrace kill which can corrupt kernel blktrace state -From: Steffen Maier - -Description: ziomon: no blktrace kill which can corrupt kernel blktrace state -Symptom: Ziomon terminates with the following error messages: - - $ ziomon -d -o ... - ... - ziomon: Failed to stop trace on /dev/sdX - ... - ziomon: Failed to stop trace on /dev/sdY - ziomon: blktrace has leftovers, manual cleanup required! - - Subsequent ziomon runs fail likely until the next reboot: - - $ ziomon -d -o ... - ... - Collecting data...BLKTRACESETUP(2) /dev/sdX failed: \ - 2/No such file or directory - BLKTRACESETUP(2) /dev/sdY failed: 2/No such file or directory - ... - Thread Z failed open /sys/kernel/debug/block/(null)/traceZ: \ - 2/No such file or directory - FAILED to start thread on CPU 0: 1/Operation not permitted - ... - Error: blktrace has errors, aborting - ... - ziomon: Failed to stop trace on /dev/sdX - ... - ziomon: Failed to stop trace on /dev/sdY - ziomon: blktrace has leftovers, manual cleanup required! -Problem: While we call blktrace with stopwatch option '-w $WRP_DURATION' - to have itself terminate automatically after the (mandatory) - sampling duration, there might be a race - with our own timed blktrace checking loop between "Collecting - data..." and "done" - or any of SIGHUP SIGTERM SIGINT SIGQUIT from the user might - prematurely trigger emergency_shutdown(), - so blktrace might still be running or not have completed its - cleanup when we reach the blktrace leftover checks in shutdown(). - - In that case, ziomon uses the meanwhile hidden kill option of - blktrace which can corrupt kernel state if blktrace user space - has not yet completed its regular cleanup. -Solution: The correct way to have the blktrace process terminate and - cleanup properly including any dependent kernel state, before - blktrace's stopwatch makes it terminate and cleanup - automatically, is to only send SIGINT to it. - - http://git.kernel.org/cgit/linux/kernel/git/axboe/blktrace.git - 86596c7579c6 ("blktrace: remove -k from manpage synopsis") - fb7f86674a51 ("blktrace: disable kill option - take 2") - Additional explanation for blktrace -k: - http://marc.info/?l=linux-btrace&m=131245973528087&w=2i - linux-btrace ("Re: Recent changes") - The following kernel commits do not change above termination - statement: - http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git - 39cbb602b543 ("Remove double removal of blktrace directory") - fd51d251e4cd ("blktrace: remove debugfs entries on bad path") - f48fc4d32e24 - ("block: get rid of the manual directory counting in blktrace") - - As of this writing, the (multithreaded) blktrace also wires - SIGHUP SIGTERM SIGALRM with the same signal handler - handle_sigint(), but to adhere to its documentation move from - SIGTERM to SIGINT anyway. - - We must not use the meanwhile hidden kill option of blktrace - because this corrupts kernel state if blktrace user space has not - yet completed its regular cleanup. - - In order to avoid zombies we wait for all children. After all, we - want everything to be completed before ziomon terminates and the - user could safely run another instance of ziomon. Also, we get - the possibility for users to detect and report issues with - children that don't finish timely. - - Since we do not know how to manually cleanup, drop the check for - blktrace leftovers in shutdown(). -Reproduction: Run ziomon with many devices on the command line. - Possibly (other) load on the system increases probability. -Upstream-ID: - -Problem-ID: 149058 - -Signed-off-by: Steffen Maier ---- - ziomon/ziomon | 17 ++++++----------- - 1 file changed, 6 insertions(+), 11 deletions(-) - ---- a/ziomon/ziomon -+++ b/ziomon/ziomon -@@ -5,7 +5,7 @@ - # - # Wrapper script to start all processes - # --# Copyright IBM Corp. 2008 -+# Copyright IBM Corp. 2008, 2016 - # - # Author(s): Stefan Raspl - # -@@ -84,7 +84,7 @@ function check_for_int() { - - function print_version() { - echo "$WRP_TOOLNAME: I/O data collection utility, version %S390_TOOLS_VERSION%"; -- echo "Copyright IBM Corp. 2008"; -+ echo "Copyright IBM Corp. 2008, 2016"; - } - - -@@ -356,8 +356,6 @@ function start_trace() { - - - function shutdown() { -- local failed=0; -- - echo "Shutting down"; - # one more second to write final result - sleep 2; -@@ -365,7 +363,7 @@ function shutdown() { - [ -d /proc/$WRP_ZIOMON_UTIL_PID ] && echo "Shutting down utilization process" && kill -s SIGTERM $WRP_ZIOMON_UTIL_PID; - fi - if [ "$WRP_BLKTRACE_PID" != "" ]; then -- [ -d /proc/$WRP_BLKTRACE_PID ] && echo "Shutting down blktrace process" && kill -s SIGTERM $WRP_BLKTRACE_PID; -+ [ -d /proc/$WRP_BLKTRACE_PID ] && echo "Shutting down blktrace process" && kill -s SIGINT $WRP_BLKTRACE_PID; - fi - if [ "$WRP_BLKIOMON_PID" != "" ]; then - [ -d /proc/$WRP_BLKIOMON_PID ] && echo "Shutting down blkiomon process" && kill -s SIGTERM $WRP_BLKIOMON_PID; -@@ -381,12 +379,9 @@ function shutdown() { - kill -s SIGTERM $WRP_ZIOMON_MGR_PID; - fi - fi -- # kill running traces on devices -- for dev in ${WRP_DEVICES[@]}; do -- [ -d /sys/kernel/debug/block/${dev##*/} ] && debug "Trace on $dev exists, attempt to kill..." && blktrace -k $dev >/dev/null 2>&1; -- [ -d /sys/kernel/debug/block/${dev##*/} ] && echo "$WRP_TOOLNAME: Failed to stop trace on $dev" && (( failed++ )); -- done -- [ $failed -ne 0 ] && echo "$WRP_TOOLNAME: blktrace has leftovers, manual cleanup required!"; -+ # synchronize with all children to avoid zombies -+ # and to prepare for a clean subsequent re-run of ziomon -+ wait - - if [ -e $WRP_MSG_Q_PATH ]; then - if [ $WRP_DEBUG -gt 1 ]; then diff --git a/s390-tools.changes b/s390-tools.changes index e6fabeb..e08e73e 100644 --- a/s390-tools.changes +++ b/s390-tools.changes @@ -1,3 +1,179 @@ +------------------------------------------------------------------- +Thu Oct 5 20:47:52 UTC 2017 - mpost@suse.com + +- Modified mkdump perl script to work with the updated version + of the IBM tools dasdview, zipl and zgetdump. (bsc#1020336). + +------------------------------------------------------------------- +Wed Oct 4 19:45:29 UTC 2017 - mpost@suse.com + +- Upgraded to version 2.1.0 (Fate#323291). + Changes from 2.0.0 to 2.1.0 + * Added the following tools: + netboot: Scripts for building a PXE-style netboot image for KVM + 90-cpi.rules/cpictl: New udev rule to update CPI when KVM is used + * Modified lsqeth/zdev to add VNIC Characteristics support + Bug fixes + * chzcrypt: Corrected handling of insufficient permissions + * cpacfstats: Add size setting to perf event + * fdasd: Skip partition check with the force option + * ttyrun: Fix deprecated BindTo usage in ttyrun-getty@.service.in + * lszcrypt: Fix core dump caused by stack overwrite + * lszcrypt: Fix random domain printout when no config available + * zdev: Fix segfault with unknown qeth attribute + * zdev: Fix IPv6 NDP proxy description + * zdev: Fix zdev dracut module temp file location + * zkey: Correctly detect abbreviated commands + * zkey: Validate XTS key: ignore domain and card + * zkey: Use octal values instead of S_IRWX* constants + * zkey: Properly set umask to prohibit permissions to group and others + * zkey: Add -ldl to LDLIBS (not LDFLAGS) + * znetconf: Re-add missing line in lsznet.raw + * Fix several gcc 7 warnings +- Modified s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch + to apply cleanly to this version. +- Removed the following obsolete patches: + * s390-tools-sles15-zgetdump-Fix-gcc-7-warning.patch + * s390-tools-sles15-lscss-Get-rid-of-gcc-7-buffer-truncation-warnings.patch + * s390-tools-sles15-Get-rid-of-gcc-7-fall-through-warnings.patch + * s390-tools-sles15-lszcrypt-Fix-core-dump-caused-by-stack-overwrite.patch + * s390-tools-sles15-dasdinfo-Fix-GCC-7-overflow-warning.patch + +------------------------------------------------------------------- +Thu Sep 8 21:06:37 UTC 2017 - mpost@suse.com + +- Added the following patches (bsc#1056498) + - s390-tools-sles15-zgetdump-Fix-gcc-7-warning.patch + - s390-tools-sles15-lscss-Get-rid-of-gcc-7-buffer-truncation-warnings.patch + - s390-tools-sles15-Get-rid-of-gcc-7-fall-through-warnings.patch + - s390-tools-sles15-lszcrypt-Fix-core-dump-caused-by-stack-overwrite.patch + - s390-tools-sles15-dasdinfo-Fix-GCC-7-overflow-warning.patch + +------------------------------------------------------------------- +Tue Sep 8 20:01:35 UTC 2017 - mpost@suse.com + +- Upgraded to version 2.0.0 (Fate#323291). + - Changes from 1.34.0 to 1.35.0 + - cpuplugd: Make default config file location more distribution agnostic + Add systemd service unit to start/stop the cpuplug daemon + Add force-reload action to init script for LSB-compliance + - mon_statd: Add force-reload action to init script for LSB-compliance + - chiucvallow: corrected verification return code + - lczdev/chzdev: Add support for resolving iSCSI block devices + Bug fixes + - chzdev, lszdev: Fix incorrect zfcp module parameter name + - chreipl: Fix chreipl node for virtio devices + - libus2s: Fix busid parsing + - zipl/boot: Fix failed start subchannel in FBA loader + - Changes from 1.35.0 to 1.36.0 + - chzdev/lszdev: Add device resolution for vlan and bonding devices + - dasdfmt: Add quick format support + - lsdasd/fdasd/dasdfmt/zdsfs: Add query host access to volume support + - zfcpdbf: Make timestamp the first field in record output + Exclude Payload hex field from log message record output + Add Area field to record output + Add missing header fields to area record output + Print the Record id field for Area area class records + Mark oldest and newest trace area records + Mark oldest and newest def_err pseudo area records + Mark oldest and newest foreign area records + Mark oldest and newest log message records + Add a warning about low resolution timestamps + Add Trace Area Statistics table to script output + Add time zone command line option + Add collection of domain xml files + Bug fixes + - zfcpdbf: Move and fix CPU id field output to print_header function + Include microseconds in warning threshold calculation + Fix parsing of precise syslog timestamps + Fix labels for REC ERP action status and ERP step fields + - Changes from 1.36.0 to 1.36.1 + - zfcpdbf: Support basic HBA record type without warning + Restore tracing of handle for port and LUN with HBA records + Print full payload for all SAN traces (req, resp, iels) + Print payload length everywhere applicable + Disambiguate printing of payload record content + Bug fixes + - fdasd: Prevent buffer overflow + - znetconf: Fix detection of chpids as OSX instead of OSM + - Changes from 1.36.1 to 1.37.0 + - Added dump2tar: sysfs collection helper for dbginfo.sh + - qethconf: Remove check for OSN-device + - znetconf: Remove OSN-support + - lsdasd/tunedasd: Add channel path aware erp + - zcrypt: Add multi domain support for zcrypt device driver + - scm: Reimplement lsscm in C + - chp: Reimplement chchp and lschp in C + - dbginfo.sh: Make use of sysinfo collection helper + Bug fixes + - zfcpdbf: Only cap SAN short payload if pl_len exists + - chzdev: Fix bug when configuring QETH devices + - libu2s: Prevent buffer overflow + - ziomon: No blktrace kill which can corrupt kernel blktrace state + - Changes from 1.37.0 to 1.37.1 + - dbginfo.sh: Add Docker debug data + Bug fixes + - lsdasd: Replace continue with return + - lscss: Allow to specify devices from subchannel set 3 + - mon_fsstatd: Only use physical filesystems + Fix double free in error path + - mon_procd: Fix segmentation fault + - Changes from 1.37.1 to 1.38.0 + - systemd: Add new units for cpi, dumpconf, mon_fsstatd, and mon_procd + - fdasd: Add new command action 'l' to list known partition types + - chmem: Try to online memory to zone movable + Starting with kernel 4.13 (commit f1dd2cd1), the default zone for + hotplug memory is changed from zone movable to zone normal. In order + to preserve the previous default behaviour, chmem will now always try + to set memory online to the zone movable, before trying to set it + online to the default zone. + - zfcpdbf: Print high part of "new" 64 bit SCSI LUN + Print payload with full FCP_RSP IU in SCSI trace records + - util_opt: Add command specific command line parsing + - util_rec: Implement util_rec_iterate() function + - util_rec: Record field values can be stored and processed in argz format + Bug fixes + - zipl/zgetdump: Add missing SCSI multipath dump information to man pages + - lsqeth: Fix attributes name: ipa -> ipa_takeover and parp -> rxip + Fix lsqeth output of ipa/vipa/rxip addresses of interfaces + - zfcpdbf: Fix payload length for zfcp_dbf_hba_bit_err + - chzdev: Add implicit qeth layer settings handling + - qethqoat: Fix OSA 6S detection + - Changes from 1.38.0 to 2.0.0 (also known as 1.39.0) + - IBM changed the license to MIT. + - Added zkey: Generate, re-encipher, and validate secure AES keys + - cpumf: Add hardware counters for z13 and z13s + - lscss: Reimplement lscss script in C + - lsqeth: Reimplement lsqeth script in C + Bug fixes + - lscpumf: Fix Perl warnings + - Removed the following obsolete patches: + s390-tools-sles12sp2-chiucvallow-verify.patch + s390-tools-sles12sp2-chreipl-virtio.patch + s390-tools-sles12sp2-chzdev-disable-root-update.patch + s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch + s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch + s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch + s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch + s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch + s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch + s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch + s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch + s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch + s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch + s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch + s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch + s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch + s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch + s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch + s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch + s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch + s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch + s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch + s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch + s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch +- Added s390-tools-sles15-add--ldl-to-LDLIBS.patch to fix a problem with zkey/Makefile. + ------------------------------------------------------------------- Thu Sep 7 19:41:39 UTC 2017 - mpost@suse.com diff --git a/s390-tools.spec b/s390-tools.spec index 5d7cb49..bb08904 100644 --- a/s390-tools.spec +++ b/s390-tools.spec @@ -17,11 +17,11 @@ Name: s390-tools -Version: 1.34.0 +Version: 2.1.0 Release: 0 -Url: https://www.ibm.com/developerworks/linux/linux390/ +Url: https://github.com/ibm-s390-tools/s390-tools Summary: S/390 tools like zipl and dasdfmt -License: GPL-2.0+ and BSD-2-Clause +License: MIT Group: System/Kernel BuildRequires: dracut BuildRequires: fuse-devel @@ -46,7 +46,7 @@ Requires: util-linux Provides: s390utils:/sbin/dasdfmt # Don't build with pie to avoid problems with zipl #!BuildIgnore: gcc-PIE -Source: s390-tools-%{version}.tar.bz2 +Source: s390-tools-%{version}.tar.gz Source1: s390-tools-rpmlintrc Source2: zipl.conf Source3: hsnc @@ -62,8 +62,6 @@ Source12: mkdump.pl Source13: sysconfig.osasnmpd Source14: zfcp_san_disc Source15: mkdump.8 -Source16: boot.cpi -Source17: sysconfig.cpi Source18: zpxe.rexx Source19: rules.xpram Source20: rules.hw_random @@ -106,36 +104,10 @@ Patch1: s390-tools-sles12-zipl_boot_msg.patch Patch2: s390-tools-sles12-sysconfig-compatible-dumpconf.patch Patch3: s390-tools-sles12-create-filesystem-links.patch Patch4: s390-tools-sles12-update-by_id-links-on-change-and-add-action.patch -Patch5: s390-tools-sles12sp2-feat-01-dasd-query-host.patch -Patch6: s390-tools-sles12-pardasdfmt.patch -Patch7: dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch -Patch8: 59-dasd.rules-wait_for.patch -Patch9: s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch -Patch10: s390-tools-sles12sp2-libu2s-Fix-busid-parsing.patch -Patch11: s390-tools-sles12sp2-chiucvallow-verify.patch -Patch12: s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch -Patch13: s390-tools-sles12sp2-chreipl-virtio.patch -Patch14: s390-tools-sles12sp2-chzdev-disable-root-update.patch -Patch15: s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch -Patch16: s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch -Patch17: s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch -Patch18: s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch -Patch19: s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch -Patch20: s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch -Patch21: s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch -Patch22: s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch -Patch23: s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch -Patch24: s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch -Patch25: s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch -Patch26: s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch -Patch27: s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch -Patch28: s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch -Patch29: s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch -Patch30: s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch -Patch31: s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch -Patch32: s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch -Patch33: s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch -Patch34: s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch +Patch5: s390-tools-sles12-pardasdfmt.patch +Patch6: dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch +Patch7: 59-dasd.rules-wait_for.patch +Patch8: s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build ExclusiveArch: s390 s390x @@ -196,36 +168,10 @@ to list files and directories. %patch2 -p1 %patch3 -p1 %patch4 -p1 -%patch5 -p1 +#patch5 -p1 %patch6 -p1 %patch7 -p1 %patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 -%patch16 -p1 -%patch17 -p1 -%patch18 -p1 -%patch19 -p1 -%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -%patch24 -p1 -%patch25 -p1 -%patch26 -p1 -%patch27 -p1 -%patch28 -p1 -%patch29 -p1 -%patch30 -p1 -%patch31 -p1 -%patch32 -p1 -%patch33 -p1 -%patch34 -p1 cp -vi %{S:22} CAUTION @@ -253,15 +199,15 @@ install -m644 -t $RPM_BUILD_ROOT/%{_mandir}/man8 %{S:87} export ROOT_BUILD_DIR="$RPM_BUILD_DIR/%{name}-%{version}/zfcpdump/kernel" install -D -m600 /boot/image-*-zfcpdump $RPM_BUILD_ROOT/usr/lib/s390-tools/zfcpdump/zfcpdump_part.image -install -D -m644 etc/sysconfig/dumpconf $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.dumpconf -install -D -m755 etc/init.d/dumpconf $RPM_BUILD_ROOT/etc/init.d/dumpconf install -D -m644 etc/udev/rules.d/40-z90crypt.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/40-z90crypt.rules -install -D -m644 etc/udev/rules.d/59-dasd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-dasd.rules install -D -m644 etc/udev/rules.d/57-osasnmpd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/57-osasnmpd.rules +install -D -m644 etc/udev/rules.d/59-dasd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-dasd.rules +install -D -m644 etc/udev/rules.d/90-cpi.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/90-cpi.rules +install -D -m644 etc/sysconfig/cpi $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.cpi +install -D -m644 etc/sysconfig/dumpconf $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.dumpconf +install -D -m644 etc/sysconfig/mon_fsstatd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.mon_fsstatd +install -D -m644 etc/sysconfig/mon_procd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.mon_procd install -D -m644 etc/sysconfig/mon_statd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.mon_statd -install -D -m755 etc/init.d/mon_statd $RPM_BUILD_ROOT/etc/init.d/mon_statd -install -D -m644 etc/sysconfig/cpuplugd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.cpuplugd -install -D -m755 etc/init.d/cpuplugd $RPM_BUILD_ROOT/etc/init.d/cpuplugd mv iucvterm/doc/ts-shell/iucvconn_on_login $RPM_BUILD_ROOT/usr/bin/iucvconn_on_login install -D -m644 %{S:26} $RPM_BUILD_ROOT/%{_unitdir}/cio_ignore.service install -D -m755 %{S:27} $RPM_BUILD_ROOT/usr/lib/systemd/scripts/setup_cio_ignore.sh @@ -287,8 +233,6 @@ install -D -m755 %{S:12} sbin/mkdump install -D -m644 %{S:13} var/adm/fillup-templates/sysconfig.osasnmpd install -D -m755 %{S:14} sbin/zfcp_san_disc install -D -m644 %{S:15} $RPM_BUILD_ROOT/%{_mandir}/man8 -install -D -m755 %{S:16} etc/init.d/boot.cpi -install -D -m644 %{S:17} var/adm/fillup-templates/sysconfig.cpi install -D -m644 %{S:19} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/52-xpram.rules install -D -m644 %{S:20} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/52-hw_random.rules install -D -m644 %{S:21} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-graf.rules @@ -304,14 +248,16 @@ if [ ! -d %{_sbindir} ]; then mkdir -p %{_sbindir} fi (cd usr/sbin; ln -s ../../etc/init.d/appldata rcappldata) -(cd usr/sbin; ln -s ../../etc/init.d/cpuplugd rccpuplugd) -(cd usr/sbin; ln -s ../../etc/init.d/dumpconf rcdumpconf) (cd usr/sbin; ln -s ../../etc/init.d/hsnc rchsnc) -(cd usr/sbin; ln -s ../../etc/init.d/mon_statd rcmon_statd) (cd usr/sbin; ln -s ../../etc/init.d/vmlogrdr rcvmlogrdr) (cd usr/sbin; ln -s ../../etc/init.d/xpram rcxpram) (cd usr/sbin; ln -s service rccio_ignore) (cd usr/sbin; ln -s service rccpacfstatsd) +(cd usr/sbin; ln -s service rccpi) +(cd usr/sbin; ln -s service rccpuplugd) +(cd usr/sbin; ln -s service rcdumpconf) +(cd usr/sbin; ln -s service rcmon_fsstatd) +(cd usr/sbin; ln -s service rcmon_procd) (cd usr/sbin; ln -s service rcvirtsetup) if [ ! -d %{_bindir} ]; then @@ -364,6 +310,13 @@ chmod 755 osasnmpd getent group ts-shell >/dev/null 2>&1 || groupadd -r ts-shell %service_add_pre cio_ignore.service %service_add_pre cpacfstatsd.service +%service_add_pre cpi.service +%service_add_pre cpuplugd.service +%service_add_pre dumpconf.service +%service_add_pre iucvtty-login@.service +%service_add_pre mon_fsstatd.service +%service_add_pre mon_procd.service +%service_add_pre ttyrun-getty@.service %service_add_pre virtsetup.service %post @@ -378,17 +331,25 @@ fi # Create symbolic links to the scripts from setup and boot directories %service_add_post cio_ignore.service %service_add_post cpacfstatsd.service +%service_add_post cpi.service +%service_add_post cpuplugd.service +%service_add_post dumpconf.service +%service_add_post iucvtty-login@.service +%service_add_post mon_fsstatd.service +%service_add_post mon_procd.service +%service_add_post ttyrun-getty@.service %service_add_post virtsetup.service + # -i: skip insserv parts - has to be configured before use: %{fillup_and_insserv -i -n appldata} -%{fillup_and_insserv -i -n cpuplugd} +%{fillup_and_insserv -i -n cpi} %{fillup_and_insserv -i -n dumpconf} %{fillup_and_insserv -i -n hsnc} +%{fillup_and_insserv -i -n mon_fsstatd} +%{fillup_and_insserv -i -n mon_procd} %{fillup_and_insserv -i -n mon_statd} -%{fillup_and_insserv -i -n vmlogrdr} %{fillup_and_insserv -i -n virtsetup} %{fillup_and_insserv -i -n xpram} -%{fillup_and_insserv -y -n cpi boot.cpi} %triggerin -- kernel-default grep -q '^/usr/bin/ts-shell$' /etc/shells \ @@ -399,28 +360,35 @@ grep -q '^/usr/bin/ts-shell$' /etc/shells \ %preun %{stop_on_removal appldata} -%{stop_on_removal cpuplugd} -%{stop_on_removal dumpconf} %{stop_on_removal hsnc} -%{stop_on_removal mon_statd} %{stop_on_removal vmlogrdr} %{stop_on_removal xpram} %service_del_preun cio_ignore.service %service_del_preun cpacfstatsd.service +%service_del_preun cpi.service +%service_del_preun cpuplugd.service +%service_del_preun dumpconf.service +%service_del_preun iucvtty-login@.service +%service_del_preun mon_fsstatd.service +%service_del_preun mon_procd.service %service_del_preun virtsetup.service %postun -%{restart_on_update boot.cpi} %{restart_on_update appldata} -%{restart_on_update cpuplugd} -%{restart_on_update dumpconf} %{restart_on_update hsnc} -%{restart_on_update mon_statd} %{restart_on_update vmlogrdr} %{restart_on_update xpram} %service_del_postun cio_ignore.service %service_del_postun cpacfstatsd.service +%service_del_postun cpi.service +%service_del_postun cpuplugd.service +%service_del_postun dumpconf.service +%service_del_postun iucvtty-login@.service +%service_del_postun mon_fsstatd.service +%service_del_postun mon_procd.service +%service_del_postun ttyrun-getty@.service %service_del_postun virtsetup.service + read INITPGM < /proc/1/comm if [ "${INITPGM}" == "systemd" ]; then echo "Running systemctl daemon-reload." @@ -447,7 +415,7 @@ rm -rf $RPM_BUILD_ROOT %files -f %{_builddir}/%{name}.list %defattr(-,root,root) -%doc README +%doc README.md %doc README.SUSE %doc iucvterm/doc/ts-shell @@ -470,6 +438,7 @@ rm -rf $RPM_BUILD_ROOT %dir %{_unitdir} %dir /usr/share/s390-tools %dir /usr/share/s390-tools/cpumf +%dir /usr/share/s390-tools/netboot %dir /boot/zipl %dir /lib/s390-tools/ %exclude /usr/lib/udev/rules.d/57-osasnmpd.rules diff --git a/sysconfig.cpi b/sysconfig.cpi deleted file mode 100644 index 33651c8..0000000 --- a/sysconfig.cpi +++ /dev/null @@ -1,22 +0,0 @@ -## Path: Kernel/CPI -## Description: set Control Program Indentification data -## Type: list(yes,no) -## Default: no -# -# Set Control Program Identification data -# -CPI_SET="yes" - -## Type: string -## Default: "" -# -# CPI system name -# -CPI_SYSTEM_NAME="" - -## Type: string -## Default: "" -# -# CPI sysplex name -# -CPI_SYSPLEX_NAME=""