Compare commits

...

117 Commits

Author SHA1 Message Date
Jan Höppner
dc2ac0c916 New release s390-tools-2.11.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 14:13:09 +02:00
Stefan Haberland
367598b187 zipl: set correct secure IPL default value
Set secure IPL to auto as default value to match documented behavior.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Marc Hartmayer
c01bcfa73a Use TOOLS_SYSCONFDIR for the default zipl.conf path
Use the configurable sysconf path instead of a hard-coded path for the
default zipl location.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Marc Hartmayer
fe457e2082 zipl: don't leak @script_file
...
==9448== 32 bytes in 1 blocks are definitely lost in loss record 1 of 3
==9448==    at 0x4831010: malloc (vg_replace_malloc.c:309)
==9448==    by 0x48E2205: __vasprintf_internal (vasprintf.c:71)
==9448==    by 0x1005061: misc_asprintf (misc.c:48)
==9448==    by 0x10131F3: disk_get_info (disk.c:239)
==9448==    by 0x1013C41: disk_get_info_from_file (disk.c:517)
==9448==    by 0x1011C87: bootmap_create (bootmap.c:1127)
==9448==    by 0x1004C73: main (zipl.c:192)
...

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Philipp Rudo
1d25112589 zipl: Fix error message printed with --dumptofs
The option --dump does not exist. Adjust it to --dumpto.

Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Marc Hartmayer
27a8c4434c zipl: fix freeing of uninitialized pointer
Not in every case ppn_cmd is initialized. Therefore, set it explicitly
to NULL.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Ursula Braun
e6a3b18104 dbginfo.sh: add ethtool output
This patch adds ethtool commands for network interfaces.
Especially the offload settings are important.

Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Ursula Braun
36292cb166 dbginfo.sh: add lspci and smc output
This patch adds the base lspci command to list pci devices
and the smc_dbg command from the smc-tools package to show
SMC socket related information.

Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Peter Oberparleiter
49da03e2e7 zdev: Fix broken zfcp-lun udev rule check
zdev incorrectly reports an invalid udev rule for zfcp-lun type rules.
This is caused by a faulty check for an empty udev rule file. This
commit fixes the check to only report invalid rules when there was no
valid configuration directive found in a zfcp-lun type udev rule.

Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reported-by: Steffen Maier <maier@linux.ibm.com>
Reported-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Ingo Franzki
139dff3525 zkey: Make confirmation prompts more user friendly
Show '[y/N]' on all user confirmation prompts to give the user a
hint what to reply. Also indicate that the operation was aborted
on a negative confirmation.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Ingo Franzki
94227b44d5 zkey: Store volume type property all uppercase
The volume type of a secure key is not really case sensitive,
but for better usability store and display it in uppercase always,
regardless in whatever case it was specified.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-09-06 12:44:34 +02:00
Stefan Haberland
a9f4ae2db3 zipl: fix zfcp dump image location
The zfcp dumper fails with the following error:

MLOPDM003I: Machine loader finished, moving data to final storage
	    location.

	    uncompression error
--- System halted

HCPGIR450W CP entered; disabled wait
PSW 00020001 80000000 00000000 DEADBEEF

The zipl command shows overlapping components when installing the dumper
to a zfcp disk:

zipl -d /dev/sda1
Building bootmap directly on partition '/dev/sda1'
Adding dump section
  kernel image......: /lib/s390-tools/zfcpdump/zfcpdump-image
  kernel parmline...: 'root=/dev/ram0 dump_mem=1 possible_cpus=1
  	 	      cgroup_disable=memory '
  component address:
    heap area.......: 0x00002000-0x00005fff
    stack area......: 0x0000f000-0x0000ffff
    internal loader.: 0x0000a000-0x0000dfff
    parameters......: 0x00009000-0x000091ff
    kernel image....: 0x00010000-0x005761ff
				     ^^^^^^
    parmline........: 0x00567000-0x005671ff
			  ^^^^^^
Preparing boot device: sda.
Done.

With the secure IPL patchset the offset of the kernel image has been
removed for the normal IPL case but it has not been removed for the dump
image which leads to the overlap of 0x10000.

Fix by removing the offset for the dump case.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewd-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Tested-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-08-08 15:27:27 +02:00
Jan Höppner
15b7f9d83f lsdasd: Add support for thin-provisioned volumes
Make lsdasd aware of thinly provisioned (Extent Space Efficient (ESE))
DASD volumes.

The ESE information is added to the discipline output and the extended
output additionally lists information about logical capacity, allocated
space, and the extent size.

Output before:

Bus-ID     Status      Name      Device  Type  BlkSz  Size      Blocks
==============================================================================
0.0.95e0   alias                         ECKD
0.0.7eb4   active      dasda     94:0    ECKD  4096   7043MB    1803060
0.0.7eb7   active      dasdb     94:4    ECKD  4096   7043MB    1803060
0.0.95d0   active      dasdc     94:8    ECKD  4096   42259MB   10818360
0.0.95d1   n/f         dasdd     94:12   ECKD
0.0.95d4   n/f         dasde     94:16   ECKD
0.0.95d5   active      dasdh     94:28   ECKD  4096   831097MB  212761080

Output after:

Bus-ID    Status    Name      Device  Type         BlkSz  Size      Blocks
================================================================================
0.0.95e0  alias                       ECKD
0.0.7eb4  active    dasda     94:0    ECKD         4096   7043MB    1803060
0.0.7eb7  active    dasdb     94:4    ECKD         4096   7043MB    1803060
0.0.95d0  active    dasdc     94:8    ECKD (ESE)   4096   42259MB   10818360
0.0.95d1  n/f       dasdd     94:12   ECKD (ESE)
0.0.95d4  n/f       dasde     94:16   ECKD (ESE)
0.0.95d5  active    dasdh     94:28   ECKD (ESE)   4096   831097MB  212761080

Extended output before:

0.0.95d0/dasdc/94:8
  status:                               active
  type:                                 ECKD
  blksz:                                4096
  size:                                 42259MB
  blocks:                               10818360
  use_diag:                             0
  readonly:                             0
  eer_enabled:                          0
  erplog:                               0
  hpf:                                  1
  uid:                                  IBM.750000000ABT31.9500.d0
  paths_installed:                      38 39 3a 3b
  paths_in_use:                         38 39 3a 3b
  paths_non_preferred:
  paths_invalid_cabling:
  paths_cuir_quiesced:
  paths_invalid_hpf_characteristics:
  paths_error_threshold_exceeded:

Extended output after:

0.0.95d0/dasdc/94:8
  status:                               active
  type:                                 ECKD (ESE)
  blksz:                                4096
  size:                                 42259MB
  blocks:                               10818360
  extent_size:                          1113
  logical_capacity:                     60102
  space_allocated:                      18921
  use_diag:                             0
  readonly:                             0
  eer_enabled:                          0
  erplog:                               0
  hpf:                                  1
  uid:                                  IBM.750000000ABT31.9500.d0
  paths_installed:                      38 39 3a 3b
  paths_in_use:                         38 39 3a 3b
  paths_non_preferred:
  paths_invalid_cabling:
  paths_cuir_quiesced:
  paths_invalid_hpf_characteristics:
  paths_error_threshold_exceeded:

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-08-08 15:27:21 +02:00
Jan Höppner
214580a704 dasdfmt: Add support for thin-provisioned volumes
Make dasdfmt aware of thinly provisioned (Extent Space Efficient (ESE))
DASD volumes.
If an ESE volume is recognised a QUICK format is performed, formatting
only the first two tracks. The mode can always be overwritten by --mode.

Previously allocated space is always released before formatting, if not
specified otherwise. The option --no-discard (-D) is provided to omit
the space release.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-08-08 15:27:16 +02:00
Jan Höppner
96f13ead2b libdasd: Provide function to utilise release space ioctl
The BIODASDRAS (Release Allocated Space) ioctl allows to release
track-wise or full space of an Extent Space Efficient DASD volume.

Provide a library function to utilise this functionality.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-08-08 15:27:09 +02:00
Jan Höppner
8023a72b11 libdasd: Provide function to read ese sysfs attribute
Provide a function to determine whether a DASD is an Extent Space
Efficient (ESE) volume.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-08-08 15:27:03 +02:00
Jan Höppner
abc1875300 libdasd/dasdfmt: Move definitions to libdasd
Move definitions mostly used by IOCTLs to libdasd. Clean up unused and
old definitions while at it as well.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-08-08 15:26:56 +02:00
Ingo Franzki
7d4c8c2781 zkey: Missing blank in command description
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-08-08 15:25:25 +02:00
Jan Höppner
f0afc6c89a Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-08-08 15:25:25 +02:00
Jan Höppner
8565e591bd New release s390-tools-2.10.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-31 16:26:57 +02:00
Jan Höppner
80443ab629 fdasd: Fix exit status in error cases
In error cases, fdasd returns -1 which results in the return value 255.
This is due to the fact that only the low-order 8 bits are used for the
status value. See 2.13 Status Information [1] in the POSIX standard and
the exit() POSIX man page [2] for more details.

Instead of returning -1, use the EXIT_FAILURE constant to indicate
unsuccessful termination properly.

[1]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
[2]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/exit.html

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-31 16:00:40 +02:00
Peter Oberparleiter
8b3cc6e4c1 zdev: Improve handling of invalid udev rules
Add basic checking when reading udev rules and print a warning when an
invalid udev rule file is found. This addresses the current inconsistent
behavior:

  - CCW devices: invalid udev rules are considered valid
  - CCW group devices: invalid udev rules are silently ignored
  - zFCP LUNs: invalid rules cause chzdev/lszdev to silently terminate
    with non-zero exit code

Checks include a test for empty or truncated rule files that might be
the result of an interrupted chzdev operation, or a file system or I/O
error.

Note: The recommended way to correct invalid udev rules is to either
remove the offending rules file, or to repeat the associated persistent
configuration step.

Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reported-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-31 16:00:40 +02:00
Peter Oberparleiter
5693c16894 zdev: Add helper to report warnings only once
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-31 16:00:40 +02:00
Stefan Haberland
8bf5f8d0e2 zipl: do not overwrite BOOT_IMAGE entry
The zipl internal loader adds a variable BOOT_IMAGE= to the commandline
so that it is visible in the operating system which menu entry has been
chosen.

This entry was overwritten by the stage3 parameter page.

Fix by re-arranging the internal memory layout and putting the command
line extra param, which contains the BOOT_IMAGE entry, at 0xe000.
This location is available because less than  one page is used for the
stack.

Fixes: https://github.com/ibm-s390-tools/s390-tools/issues/67
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-31 15:59:50 +02:00
Ingo Franzki
99ab2db6ad zkey: Fix auto-detection of clear key bitsize for XTS keys
When 'zkey generate' is used with options '--clearkey <file>' and
'--xts', but without the '--keybits <bitsize>' option, then the
auto-detection of the bitsize of the specified clear key fails.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-31 15:59:50 +02:00
Ingo Franzki
784ac7d190 zcryptstats: Add note about loading kernel module chsc_sch
Dependent on kernel config option CHSC_SCH the device node /dev/chsc may
exist per default or not. In case the kernel is built with CHSC_SCH=M,
then the device driver is built as separate kernel module, and must
therefore be loaded using modprobe chsc_sch to make device node /dev/chsc
available.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-31 15:59:50 +02:00
Javier Martinez Canillas
53f166673d zipl: remove trailing spaces from the fields defined in BLS files
Currently the zipl tool doesn't remove trailing spaces from the BLS field
values. So for example if a 'title' field has trailing spaces and is used
as the default, zipl will complain that there's no section with that name:

Using config file '/etc/zipl.conf'
Using BLS config file '/boot/loader/entries/f871a0cf218348c5ba921f61c92b7eac-4.18.0-80.20.el8.s390x.conf'
Using BLS config file '/boot/loader/entries/f871a0cf218348c5ba921f61c92b7eac-0-rescue.conf'
Error: Config file '/etc/zipl.conf': Line 6: no such section 'Red Hat Enterprise Linux (4.18.0-80.20.el8.s390x) 8.1 (Ootpa)'

Since the trailing spaces are also removed from the fields defined in the
zipl.conf file, do the same for the ones that are defined in the BLS file.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/62
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-18 16:21:17 +02:00
Dimitri John Ledkov
d4ea321a97 zipl/boot/Makefile: fix failure to build, do not specify .lds twice.
Whilst stage3.lds is a dependency, it is specified via SFLAGS and must
not be repeated again along all the .o files. Filter anything but .o
files.

Fixes failure to build from source on Ubuntu 19.10.

Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/s390-tools/+bug/1833238
Closes: https://github.com/ibm-s390-tools/s390-tools/pull/63
Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
Acked-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-18 15:02:06 +02:00
Dimitri John Ledkov
1a63894487 zipl/boot/Makefile: do not suppress echo in verbose builds.
By default, non-verbose builds don't echo the full command anyway. And
supressed echos in verbose builds make it harder to debug the build
failure.

GitHub-ID: https://github.com/ibm-s390-tools/s390-tools/pull/63
Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
Acked-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-18 15:02:06 +02:00
Stefan Haberland
e3fc9478bf zipl: secure IPL man page update
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-15 16:06:53 +02:00
Thomas Richter
f110a77b68 cpumf: Add support for CPU-Measurement Facility counters SVN 6
Add support for CPU-Measurement facility counter second version
number 6. This adds some more counters to the crypto counter set.
Extended counter set is the same as for z14.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-15 16:06:53 +02:00
Ingo Franzki
712433d7f9 util_opt: Correct util_opt_example to handle all possible options
The util_opt_example allows to specify '-l' and '-m, --manual' options,
but does not handle them. This leads to error message 'PANIC: The
application terminated due to an unrecoverable error' with 'Option 'l'
should not be handled here' and the program is aborted.

Add the required case statements in the switch to handle those options.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-15 16:06:53 +02:00
Fedor Loshakov
2c4c210ca8 zdev: add zfcp dix parameter handling
The zfcp kernel module was changed to introduce separate parameters for
selecting DIF and DIF&DIX. This commit implements the corresponding
changes in chzdev and lszdev.

Signed-off-by: Fedor Loshakov <loshakov@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Karsten Graul
58e2135d87 znetconf: show help and version without ccwgroup driver loaded
When directory $SYSFSDIR/bus/ccwgroup does not exist znetconf issues an
error message and terminates. Its not even possible to get the output of
--help or --version. Fix that by moving the responsible check behind the
parameter evaluation.

Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Ingo Franzki
5dbe73403f zkey: Fix option check for validate command
The validate command should allow to specify the --no-apqn-check
option even when --apqns is not specified.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Ingo Franzki
819513ab38 zkey: Fix misspelled option name in error messages
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Ingo Franzki
7e6d782699 zkey: Fix typo in function name
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Heiko Carstens
cc82be3135 zipl: add missing inline
please merge with previous commit.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Heiko Carstens
1b318fe114 zipl: fix stfle zero padding
The stfle inline assembly returns the number of double words written
(condition code 0) or the double words it would have written
(condition code 3), if the memory array it got as parameter would have
been large enough.

The current stfle implementation assumes that the array is always
large enough and clears those parts of the array that have not been
written to with a subsequent memset call.

If however the array is not large enough memset will get a negative
length parameter, which means that memset clears memory until it gets
an exception and the system crashes.

To fix this simply limit the maximum length. Move also the inline
assembly to an extra function to avoid clobbering of register 0, which
might happen because of the added MIN invocation together with code
instrumentation.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
87f47f60e4 zdev: Add comment that zfcp LUNs do not support ranges
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
0f55dab2de zdev: Add missing includes
The header exit_code.h is required for the exit_code_t type and
the header misc.h for the err_t type.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
b58adc26f4 zdev: Cleanup zfcp attribute help
Add missing punctuation, remove duplicate newline, and add missing
spacing.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
91509973fe zdev: Do not pass user input as format string
The function util_path_exists() consumes its first parameter as format
string. Passing the user input specified to the chzdev option --export
as-is to the function opens up the possibility for a format string
injection.

Fixes: d542138868 ("zdev: use libutil provided path functions")
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
39520546c5 chcp: Use macro S_ISDIR() to test type of file
Testing whether a file is a directory by comparing the struct stat
field st_mode against S_IFDIR is wrong. If st_mode has any access
permission bits set along with the file type code the test will always
fail.

The file type encoded in the struct stat field st_mode is actually an
enumeration. To test whether a file is a directory either extract the
file type from st_mode using the mask S_IFMT and compare it against
S_IFDIR or simply use the macro S_ISDIR().

Fixes: b627b8d8e1 ("Initial s390-tools-2.0.0 import")
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
8d1a7fecd0 zkey: Use libutil provided path functions
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Acked-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
a6507b330d zkey: Use macro S_ISDIR() to test type of file
Testing whether a file is a directory by masking the struct stat field
st_mode with S_IFDIR is wrong. Depending on the values of the macros
S_IF* block special devices might be considered as directories.

The file type encoded in the struct stat field st_mode is actually an
enumeration. To test whether a file is a directory either extract the
file type from st_mode using the mask S_IFMT and compare it against
S_IFDIR or simply use the macro S_ISDIR().

Fixes: c944f23d7e ("zkey: Add keystore implementation")
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Acked-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
d37dc68693 util_path: Get rid of "? true : false"
The functions use the C99 _Bool type in form of the alias bool from
stdbool.h as return type. Scalars are implicitly converted to _Bool.
Values equal to zero to 0 (false). Nonzero values to 1 (true).
Therefore the explicit conversion using the ternary operator ?: with
true and false is not required.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
b0007fea98 util_path: Simplify logic and get rid of goto
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
1e248abd53 util_path: Use S_IS*() macros to test type of file
Testing whether a file is a directory or a regular file by masking the
struct stat field st_mode with S_IFDIR or S_IFREG is wrong. Depending
on the values of the macros S_IF* sockets and symbolic links might
erroneously be considered as regular files and block special files as
directories.

The file type encoded in the struct stat field st_mode is actually an
enumeration. To test whether a file is a directory or a regular file
either extract the file type from st_mode using the mask S_IFMT and
compare it against S_IFDIR or S_IFREG or simply use the macros S_ISDIR()
and S_ISREG().

Fixes: b627b8d8e1 ("Initial s390-tools-2.0.0 import")
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
61baa23e48 zdev: Fix reporting of read-only sysfs attributes
Since commit d542138868 ("zdev: use libutil provided path functions")
lszdev fails to correctly report most read-only sysfs attributes as such
in its detailed information output (options -i or -ii). This is because
the libutil function util_path_is_writable() is not equivalent to the
former function file_writable().
util_path_is_writable() always returns true (the underlying function
access() indicates the file is writable), if the path exists and the user
is root, regardless of the path's effective access permissions. This is
correct for most use cases, as root can effectively read/write any path
regardless of its effective access permissions). util_path_is_writable()
behaves exactly like Bash -w in this regard.
The former function file_writable() examined the file's access permissions
to check if one or more of user, group, and other have write permission.

For lszdev it is irrelevant whether a file is effectively writable by
the current user. Instead it needs to determine whether sysfs attributes
access permissions contain write access in any form. If not it lists
those sysfs attributes in a separate read-only section.

Use the new function util_path_is_readonly_file(), which does explicitly
check the file's effective read and write access permissions. It behaves
similar to the former function file_writable(), except that it does test
whether any of user, group, and other have read permission.

Fixes: d542138868 ("zdev: use libutil provided path functions")
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
261763f133 util_path_example: Add example for util_path_is_{read|write}only_file() functions
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jens Remus
f4b2da6c9d util_path: Add functions to test path is read/write-only
For root the functions util_path_is_readable() and util_path_is_writable()
do not take the path's permissions into account. The function access()
succeeds as root is allowed to read/write any file regardless of its
permissions.

Introduce the functions util_path_is_readonly_file() and
util_path_is_writeonly_file() to test whether a path is a regular file and
is either read-only (neither user, group, nor other have write permission,
but one or more of user, group, and other have read permission) or
write-only (neither user, group, nor other have read permission, but one
or more of user, group, and other have write permission).

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jan Höppner
1f607fed3d Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-07-09 16:24:17 +02:00
Jan Höppner
bf9fd47918 New release s390-tools-2.9.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 15:13:36 +02:00
Jan Höppner
5aec1dc2a1 cpuplugd: Always free file pointer
The file pointer in the functions is_online() and cpu_is_configured() is
only freed in the good case. Make sure it is always freed.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:17:40 +02:00
Jan Höppner
cf730a9632 zipl: Fix compile warning
bootmap.c: In function ‘check_secure_boot_support’:
bootmap.c:131:2: warning: ignoring return value of ‘fscanf’, declared
with attribute warn_unused_result [-Wunused-result]
  fscanf(fp, "%d", &val);
  ^~~~~~~~~~~~~~~~~~~~~~

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:17:40 +02:00
Jan Höppner
73bab8e1a1 zpcictl: Fix compile warning
zpcictl.c: In function ‘sysfs_read_value’:
zpcictl.c:154:2: warning: ignoring return value of ‘fscanf’, declared with
attribute warn_unused_result [-Wunused-result]
  fscanf(fp, "%x", &val);
  ^~~~~~~~~~~~~~~~~~~~~~

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:17:40 +02:00
Ingo Franzki
f97d048643 zkey: Allow to associate non-existing APQNs with a key
Add option --no-apqn-check to the generate, import, change, and
validate commands to disable checking of the specified APQNs.

With this option a currently non-existing APQN can be associated
with a key. This is useful to associate APQNs that exist only on
other systems, such as disaster recovery systems, but not on the
current system. When generating keys, at least one of the specified
APQNs must be available to generate the key.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Steffen Maier
d8c630e5f4 zfcpdbf: warn about ambiguous payload records with dup reqid & payarea
Function get_payload_records() reading from disk, blindly adds payload
record (junks) to a list in a 2-stage hierarchical hash keyed with
request ID and PAY area.

On adapter offline/online, zfcp resets the request ID to re-start with 1.
Hence it's not a unique foreign key in the lifetime of the PAY area.

The last payload record (junks) read for the same request ID and PAY area
is the one printed as named PAY field in the tool output.
This is not necessarily the chronologically last record due to PAY area
wrapping.

With this workaround, we:
* warn on reading PAY records if ambiguous entries occurred,
* print additional PAY timestamps which the user can compare
  with the actual trace record timestamps to determine if they are close
  enough to indicate a match.

We only found this by accident because we kept "short" "payload" being a
built-in part of some actual trace record types in areas HBA, SAN, SCSI.
For above cases, the full PAYload did not match the
built-in "short" "payload".

While at it, also add a comment that PAY output can also be wrong
in another case when junks of multi-part PAY records are missing due
to PAY area wrapping.

Below is an abbreviated example output with this workaround:

Loading trace records ...(this might take a while)
Warning: Ambiguous PAYload records. reqid:0000000000000037 area:san_res

...

Timestamp      : 2017-07-07-18:01:34:574827
Area           : SAN
...
Tag            : fssct_1
Request ID     : 0x0000000000000037
Destination ID : 0x00fffffc
SAN req short  : 01000000 fc020000 01720ffc 00000000
                 00000008
SAN req length : 20

Timestamp      : 2017-07-07-18:01:34:619310         ------------------+
Area           : SAN                                                  |
...                                                                   |
Tag            : fsscth2                                              |
Request ID     : 0x0000000000000037                                   |
Destination ID : 0x00fffffc                                           |
SAN resp short : 01000000 fc020000 80020000 00000000                  |
                 00671a07 00000000 c05076ff d6801850                  |
                 00671a7e 00000000 c05076ff d6801968                  |
SAN resp length: 16384                                                |
Payload time   : 2017-07-07-18:16:17:165708          <== does not match
San resp info  : 01000000 fc020000 80020000 00000000 <== wrong
                 4a49424d 20202020 20323936 34202020 <== wrong
                 20202020 20202020 20303230 30303030 <== wrong
                 30303745 43383720 20504348 49443a20 <== wrong
                 30313938 204e5049 5620556c 7049643a <== wrong
                 20303536 30303330 30202020 00000000 <== wrong
                 00000000 00000000 00000000 00000000 <== wrong
                 ...                                 <== wrong

...

Timestamp      : 2017-07-07-18:16:17:165713
Area           : SAN
...
Tag            : fsscth2
Request ID     : 0x0000000000000037             <== same reqid & pay "area"
Destination ID : 0x00fffffc
SAN resp short : 01000000 fc020000 80020000 00000000
                 4a49424d 20202020 20323936 34202020
                 20202020 20202020 20303230 30303030
SAN resp length: 273
Payload time   : 2017-07-07-18:16:17:165708          <== 2nd & last, match
                                                         close to Timestamp
San resp info  : 01000000 fc020000 80020000 00000000
                 4a49424d 20202020 20323936 34202020
                 20202020 20202020 20303230 30303030
                 30303745 43383720 20504348 49443a20
                 30313938 204e5049 5620556c 7049643a
                 20303536 30303330 30202020 00000000
                 00000000 00000000 00000000 00000000
                 ...

Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Heiko Carstens
45132ce1ee libutil: fix build breakage
/usr/bin/ld: ../..//libutil/libutil.a(util_sys.o): in function `util_sys_get_dev_addr':
/home/builder/s390-tools/libutil/util_sys.c:52: undefined reference to `major'
/usr/bin/ld: /home/builder/s390-tools/libutil/util_sys.c:53: undefined reference to `minor'
collect2: error: ld returned 1 exit status
make[2]: *** [../../common.mak:243: zipl] Error 1
make[1]: *** [Makefile:8: all] Error 2
make: *** [Makefile:52: zipl] Error 2

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Jan Höppner
57a797350c libu2s: Remove the library
There are no users of libu2s anymore. Remove it.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Jan Höppner
75e3afb6a0 libdasd: Move get_host_access_count() to libdasd
Reading DASD specific sysfs attributes should be collected in one
library. Move get_host_access_count() to libdasd/dasd_sys.

Remove the old implementation and update any user accordingly.
Also, fix the build order for zdsfs.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Jan Höppner
7915c9257b zpcictl: Use libutil to identify the slot id of a device
Rather than using an own implementation, use util_sys_get_dev_addr()
provided by libutil instead.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Jan Höppner
6014d07cb1 dasdview/libdasd/zipl: Use util_sys_get_dev_addr() instead of u2s_getbusid()
Use the newer and more robust libutil provided function
util_sys_get_dev_addr() to identify a device address for any former user
of u2s_getbusid().

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Jan Höppner
5d2ebe5301 libutil: Introduce util_sys and util_sys_get_dev_addr()
Many tools need to identify the device address of a given device. So
far, either the tool had its own implementation, or u2s_getbusid() was
used. Though, u2s_getbusid() was mainly designed for and used by the
DASD tools.

Introduce util_sys with a first function util_sys_get_dev_addr() which
provides a more universal way to identify the device address which is
not limited to one particular device type. The device address represents
either a busid (e.g. DASD), slot address (NVMe), H:C:T:L tuple (SCSI),
or other id types associated with a device.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Jan Höppner
ab510cff39 libdasd: Provide definition for bus id size
dasdview and libdasd deal with DASD bus ids and should use a definition
for the size. libu2s already provides a definition, which is used by
dasdview. However, the size of 32 is a bit much and the definition
should be part of libdasd.

Including the terminating null byte ('\0') and considering a DASD bus id
length of 8 characters (e.g. 0.0.4711), this leads to a size of 9.

Provide such a definition via libdasd and update any user.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Jan Höppner
8c06dea4e5 libdasd: Use util_path_sysfs() to construct sysfs paths
Don't rely on rather arbitrary values for the string buffer size of
different sysfs paths. Instead use util_path_sysfs(), which allocates
the exact amount of memory necessary for a certain path string.

As these path strings are dynamically constructed, potential buffer
overflows can hereby be avoided and make the library functions more
robust.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Dan Horák
0efacac5b8 zipl: update stage3 objcopy command for gcc9
The objcopy command for stage3.bin needs to take the new rodata section
into account.
See also PR https://github.com/ibm-s390-tools/s390-tools/pull/60.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/61
Signed-off-by: Dan Horák <dan@danny.cz>
Acked-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00
Stefan Haberland
6ea645b345 zipl: add secure boot man page updates
Add zipl and zipl.conf man page updates.

The zipl man page will look like:

       -S <SWITCH> or --secure <SWITCH>
               Control the zIPL secure boot support.  <SWITCH> can take one of three values:

                 auto (default)
                   Write signatures if available and supported by the system.
                 1
                   Signatures are written independent of support indicated by the local
                   system. Also missing signatures for stage 3 and kernel IPL files
                   will result in an error.
                 0
                   No signatures will be written.

The zipl.conf man page will look like:

       secure = auto/1/0 (configuration only)

              Configuration section:
              Control the zIPL secure boot support.  Set this option to one of the following:

                -  auto: Write signatures if available and supported by the system.

                -  1: Signatures are written independent of support indicated by the local system.
		   Also missing signatures for stage 3 and kernel IPL files will result in an error.

                -  0: No signatures will be written.

                   The default value for 'secure' is auto.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:48 +02:00
Stefan Haberland
331b54d573 zipl: secure boot - verify load address
To ensure that only verified code is executed the stage 3 loader has
to check if the load psw points to an address that has previously been
verified by the machine loader.

If secure boot is enabled the IPL process will only continue if the
verification was successful.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:45 +02:00
Stefan Haberland
7e7a77675d zipl: re-order variable declaration
For better readbility re-arrange the variable declaration.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:42 +02:00
Stefan Haberland
dc2e439550 zipl: add dummy section for stage3 heap and stack
The firmware needs to know which memory locations are used by
the stage 3 loader so that it can allocate its own memory.
To indicate the usage of the heap and stack area of the stage 3 loader
add a dummy component to block this memory area for the firmware.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:40 +02:00
Stefan Haberland
75d4317f20 zipl: pad stage3 binary
The stage 3 loader size has to be a multiple of the filesystem
blocksize so that the signature maps with the later in memory
stage 3 loader. The lowest common blocksize is 4k so the image
is padded to a 4k boundary.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:37 +02:00
Stefan Haberland
58a7462f65 zipl: add secure boot switch
Add a command line option and configuration section keyword to control
the zIPL secure boot support. This option is named "secure" and can take
one of three values:

  auto (default)
    Write signatures if available and supported by the system.
  1
    Signatures are written independent of support indicated by the local
    system. Also missing signatures for stage 3 and kernel IPL files
    will result in an error.
  0
    No signatures will be written.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:33 +02:00
Stefan Haberland
7c7e10ed8f zipl: detect signed files and create bootmap components
Add support for parsing IPL file signatures as produced by the Linux
kernel's sign-file tool. When preparing a disk for IPL, the signatures
will be added as separate data components that can be used by the Secure
Boot firmware feature to validate the integrity of the IPL files.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:30 +02:00
Stefan Haberland
0c1a63ce5e zipl: dynamically build component name array
Change the fixed component entry text array to a more dynamic approach
to allow easier extension and make the order changeable.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:25 +02:00
Stefan Haberland
6825645a21 zipl: Move stage 3 loader to external file
The first component that gets control after IPL is the zIPL-provided
stage 3 boot loader. This boot loader is based on a binary image linked
into the zIPL executable. When preparing a disk for IPL, zIPL updates
runtime parameters in the boot loader image and writes the resulting
data to disk.

To support the Secure Boot firmware feature, the stage 3 code must be
signed, and can therefore no longer contain variable parameter portions.
Also the boot loader image should be accessible as a separate file to
enable the use of external programs for creating the signature.

This patch moves the stage 3 boot loader code to an external file
location and splits out the parameter portion into a separate, unsigned
on-disk component.

The new memory layout of the stage 3 loader during its execution looks
as follows:

 * 0x0000-0x1fff        Lowcore
 * 0x2000-0x5fff        Memory allocation (heap)
 * 0x7000-0x8fff        free
 * 0x9000-0x9fff        Stage3 parameter
 * 0xa000-0xcfff        Stage3 code
 * 0xd000-0xefff        Section: bss, rodata, data
 * 0xf000-0xffff        Stack

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:21 +02:00
Stefan Haberland
e764f460c4 zipl: Do not strip kernel image IPL header
The binary Linux kernel image is built to be loaded to memory address
0x0 but the first 64 kbyte contain an IPL header that is not used for
disk IPL. zIPL strips away this IPL header when writing IPL records to
disk, loads the remaining data to memory address 0x10000 and uses the
memory area below that for its own boot loader code.

The Secure Boot firmware feature checks the integrity of an installed
image during IPL using a checksum that was generated for the full image.
Since the checksum becomes invalid if the IPL header is removed, zIPL
must be changed to write the full image to disk.

This patch modifies the zIPL logic to no longer strip away the IPL
header. Instead the full image is loaded to a higher memory address and
relocated by the stage 3 boot loader code to its final location.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:16 +02:00
Jan Höppner
63089835b0 README.md: Add runtime requirement for dbginfo.sh
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-29 17:17:16 +02:00
Ingo Franzki
e4cd42900f zkey: Fix a problem with changing a volume association of a key
When a 'zkey change' command is used to change (i.e. set) the volume
association of a key, and the new volume association contains a volume
that is already assigned to the key to be changed, the command fails
with an error that the volume is already associated to the key.

This commit fixes the problems and allows to set such a volume
association. When setting a new association the current association of
the key to be changed is of no relevance, since the set operation
replaces the current association with the new association.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-15 15:17:55 +02:00
Stefan Raspl
7f033938b8 lschp: add support for specifying a CHPID
We keep things simple and allow for only a single CHPID to be specified.

Signed-off-by: Stefan Raspl <raspl@linux.ibm.com>
Reviewed-by: Sebastian Ott <sebott@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-15 15:16:25 +02:00
Fedor Loshakov
f2dee9f542 ziomon: fix utilization data recording with multi-digit scsi hosts
s390-tools-1.9.0 introduced a new way of recognizing of multipath
device paths with using of sed command invocation in ziomon script.
With this new way of recognizing, if there are paths, related to
multipath device, with SCSI host ID longer, than one digit,
ziomon incorrectly parses the multipath -l command output. It
erroneously cuts off all but the least significant digit of the
SCSI host ID (H) of paths in H:B:T:L format (Host:Bus:Target:Lun).
This leads to passing of hosts (-a) and paths (-l) with
non-existing SCSI host ID to ziomon_util. In turn ziomon_util
cannot recognize hosts with non-existing SCSI host ID and issues
an error.

Also, wrong sed command invocation could lead to receiving of
duplicate LUNs by ziomon after parsing of multipath -l command
output. Then ziomon excludes duplicates from WRP_LUNS, which
leads to mismatch between number of LUNs and number of detected
block devices and issues ziomon script error, without starting
ziomon_util and without writing to specified log file.

The regular expression to match a path in H:B:T:L format started
with a greedy ".*", which erroneously consumed parts of the SCSI
host ID (H). This patch replaces the greedy ".*" by "[^0-9]*",
so that sed command does not consume parts of the SCSI host ID
any more.

Test example with unique SCSI host IDs:
$ multipath -l
...
mpathc (36005076307ffc5e300000000000083f5) dm-2 IBM     ,2107900
size=20G features='1 queue_if_no_path' hwhandler='0' wp=rw
`-+- policy='service-time 0' prio=0 status=active
  |- 10:0:0:1089814659 sdb 8:16  active undef running
  `- 11:0:0:1089814659 sdf 8:80  active undef running
...

Behavior without fix applied:
$ ziomon -d 5 -o log /dev/mapper/mpathc
Check devices...done
NOTE: No size limit specified, run without a limit.
Estimated maximum disk space required for log data: approx. <1 MBytes
Collecting configuration data...done
Start data collection processes...ziomon_util: Path does not exist: /sys/class/scsi_host/host0/utilization - correct kernel version?
ziomon_util: Path does not exist: /sys/class/scsi_host/host0/utilization - correct kernel version?
ziomon_util: Path does not exist: /sys/class/scsi_host/host0/queue_full - correct kernel version?
ziomon_util: Path does not exist: /sys/class/scsi_host/host1/utilization - correct kernel version?
ziomon_util: Path does not exist: /sys/class/scsi_host/host1/queue_full - correct kernel version?
failed
ziomon: Failed to determine ziomon_util pid
Shutting down
Shutting down blktrace process
Shutting down blkiomon process
Shutting down ziomon_zfcpdd process
blkiomon: terminated by signal
Shutting down data manager

User can see more information, when using ziomon with -V option:
...
=== WRP_LUNS         : 0:0:0:1089814659 1:0:0:1089814659
=== WRP_HOST_ADAPTERS: host0 host1
...
=== starting ziomon_util: ziomon_util -V  -a 0 -a 1  -l 0:0:0:1089814659 -l 1:0:0:1089814659 ...
...

User can also see this type of errors, while using
ziorep_traffic or ziorep_utilization tools:
$ ziorep_traffic -t1 log.log
Extracting config data...done
ziorep_traffic: Could not retrieve initial data - data files corrupted or broken, or the .agg file is missing.

Behavior with fix applied:
$ ziomon -d 5 -o log /dev/mapper/mpathc
Check devices...done
NOTE: No size limit specified, run without a limit.
Estimated maximum disk space required for log data: approx. <1 MBytes
Collecting configuration data...done
Start data collection processes...done
Collecting data...done
Shutting down
Shutting down data manager

User can see more information, when using ziomon with -V option:
...
=== WRP_LUNS         : 10:0:0:1089814659 11:0:0:1089814659
=== WRP_HOST_ADAPTERS: host10 host11
...
=== starting ziomon_util: ziomon_util -V  -a 10 -a 11  -l 10:0:0:1089814659 -l 11:0:0:1089814659 ...
...

Test example with duplicate SCSI host IDs:
$ multipath -l
...
mpathc (36005076307ffc5e300000000000083f5) dm-1 IBM     ,2107900
size=20G features='1 queue_if_no_path' hwhandler='0' wp=rw
`-+- policy='service-time 0' prio=0 status=active
  |- 0:0:0:1089814659  sdb 8:16  active undef running
  `- 10:0:0:1089814659 sdf 8:80  active undef running
...

Behavior without fix applied:
$ ziomon -d 5 -o log /dev/mapper/mpathc
Check devices...done
ziomon: Number of LUNs does not match number of devices: 2 devices and 1 LUNs

User can see more information, when using ziomon with -V option:
...
    === #Devices total   : 2
    === WRP_DEVICES      : /dev/sdb /dev/sdf
    === WRP_LUNS         : 0:0:0:1089814659
    === WRP_HOST_ADAPTERS: host0
...

Behavior with fix applied:
$ ziomon -d 5 -o log /dev/mapper/mpathc
Check devices...done
NOTE: No size limit specified, run without a limit.
Estimated maximum disk space required for log data: approx. <1 MBytes
Collecting configuration data...done
Start data collection processes...done
Collecting data...done
Shutting down
Shutting down data manager

User can see more information, when using ziomon with -V option:
...
=== #Devices total   : 2
=== WRP_DEVICES      : /dev/sdb /dev/sdf
=== WRP_LUNS         : 0:0:0:1089814659 10:0:0:1089814659
=== WRP_HOST_ADAPTERS: host0 host10
...
=== starting ziomon_util: ziomon_util -V  -a 0 -a 10  -l 0:0:0:1089814659 -l 10:0:0:1089814659 ...
...

Signed-off-by: Fedor Loshakov <loshakov@linux.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-11 13:19:36 +02:00
Jan Höppner
c7a255fcd9 zpcictl: Check for regular directory
In case a regular directory was specified, rather than a device node,
the check if the device exists will pass. The following code paths then
assume a slot id was specified. This in turn may lead to a buffer
overflow when the device data is copied to to the zpci_device struct.

Check if the specified path is a regular directory and prevent a
possible later buffer overflow and copying wrong data respectively.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-04-01 12:41:17 +02:00
Steffen Maier
be7b854969 lszfcp: also mark FCP devices (hosts) that are not available
Also mark FCP devices with CHPID that is logically varied off,
e.g. after running "chchp -v 0 60".
Such FCP devices can be online, not failed, and are not defunct,
so the other existing markers do not appear.

Shows potential issues with FCP devices at one glance.

Examples:

$ lszfcp -He
0.0.1900 host0 NotAvailable

$ lszfcp -HeV
/sys/devices/css0/0.0.010d/0.0.1900 NotAvailable
/sys/class/fc_host/host0
/sys/class/scsi_host/host0

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Complements: 4036e80b26 ("lszfcp: add new output marker for non-good FCP devices (hosts)")
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-27 14:57:40 +01:00
Jan Höppner
05a0f8e0eb gitignore: Add zcryptstats
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Ingo Franzki
43fcb694bf zcryptstats: add new tool to readme
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Ingo Franzki
8be43a1f16 zcryptstats: Add man page
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Ingo Franzki
7b4a05e5a3 zcryptstats: Add new zcryptstats tool
The zcryptstats tool displays usage statistics of IBM Crypto Express
adapters. It obtains cryptographic performance measurement data
periodically and displays the data for each cryptographic device for
each interval. A cryptographic device can be either a card device or
a queue device (APQN).

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
9911a95144 CHANGELOG: lszfcp: fix regressions
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
9c56255a70 lszfcp: new command line option to show module parameters
I often use "systool -v -m zfcp" but that's a bit longish to type
and contains more output than just the parameters I'm interested in.
"tail /sys/module/zfcp/parameters/*" is also not so nice.
"lszfcp -Z" makes it very easy and can be combined with the other
existing output options of lszfcp.

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
a20cabccc4 lszfcp: sdev attributes for scsi_disk, block, integrity, queue, iosched
Show if command line option for more attribute details specified twice
and depending on existence in sysfs (i.e. not for non-disk such as tape).

Abbreviated examples:

$ lszfcp -DVeamm
/sys/devices/css0/0.0.0019/0.0.1880/0x50050763031bd327/0x4045400300000000
/sys/bus/ccw/drivers/zfcp/0.0.1880/host2/rport-2:0-0/target2:0:0/2:0:0:1073954885
/sys/block/sdd /sys/class/scsi_generic/sg3
Class = "zfcp_unit"
    access_denied       = "0"
    access_readonly     = "0"
    access_shared       = "0"
    failed              = "0"
    in_recovery         = "0"
    status              = "0x54000000"
Class = "scsi_device"
    ...
    modalias            = "scsi:t-0x00"
    model               = "2107900"
    scsi_level          = "6"
    state               = "running"
    type                = "0"
    ...
    zfcp_access_denied  = "0"
    zfcp_failed         = "0"
    zfcp_in_recovery    = "0"
    zfcp_status         = "0x54000000"
Class = "scsi_disk"
    allow_restart       = "0"
    app_tag_own         = "1"
    cache_type          = "write back"
    FUA                 = "0"
    manage_start_stop   = "0"
    max_medium_access_timeouts = "2"
    max_write_same_blocks = "65535"
    protection_mode     = "dix1"
    protection_type     = "1"
    provisioning_mode   = "unmap"
    thin_provisioning   = "1"
    zeroing_mode        = "writesame"
Class = "block"
    alignment_offset    = "0"
    capability          = "50"
    dev                 = "8:48"
    discard_alignment   = "0"
    size                = "2097152"
    ...
    uevent              = "MAJOR=8"
Class = "block_integrity"
    device_is_integrity_capable = "1"
    format              = "T10-DIF-TYPE1-IP"
    protection_interval_bytes = "512"
    read_verify         = "1"
    tag_size            = "2"
    write_generate      = "1"
Class = "block_queue"
    add_random          = "1"
    chunk_sectors       = "0"
    dax                 = "0"
    discard_granularity = "1073741824"
    discard_max_bytes   = "4294966784"
    discard_max_hw_bytes = "4294966784"
    discard_zeroes_data = "0"
    hw_sector_size      = "512"
    io_poll             = "0"
    io_poll_delay       = "0"
    iostats             = "1"
    logical_block_size  = "512"
    max_discard_segments = "1"
    max_hw_sectors_kb   = "1076"
    max_integrity_segments = "269"
    max_sectors_kb      = "1076"
    max_segments        = "269"
    max_segment_size    = "4096"
    minimum_io_size     = "512"
    nomerges            = "0"
    nr_requests         = "128"
    optimal_io_size     = "0"
    physical_block_size = "512"
    read_ahead_kb       = "512"
    rotational          = "1"
    rq_affinity         = "1"
    scheduler           = "noop [deadline] cfq"
    write_cache         = "write back"
    write_same_max_bytes = "33553920"
    write_zeroes_max_bytes = "33553920"
    zoned               = "none"
Class = "block_queue_iosched"
    fifo_batch          = "16"
    front_merges        = "1"
    read_expire         = "500"
    write_expire        = "5000"
    writes_starved      = "2"

/sys/devices/css0/0.0.0222/0.0.3c80/0x2002000e1115c62f/0x0000000000000000
/sys/bus/ccw/drivers/zfcp/0.0.3c80/host4/rport-4:0-2/target4:0:2/4:0:2:0
Class = "zfcp_unit"
    access_denied       = "0"
    access_readonly     = "0"
    access_shared       = "0"
    failed              = "0"
    in_recovery         = "0"
    status              = "0x54000000"
Class = "scsi_device"
    ...
    modalias            = "scsi:t-0x01"
    model               = "ULT3580-TD6"
    scsi_level          = "7"
    state               = "running"
    type                = "1"
    ...
    zfcp_access_denied  = "0"
    zfcp_failed         = "0"
    zfcp_in_recovery    = "0"
    zfcp_status         = "0x54000000"

/sys/devices/css0/0.0.0222/0.0.3c80/0x2002000e1115c62f/0x0001000000000000
/sys/bus/ccw/drivers/zfcp/0.0.3c80/host4/rport-4:0-2/target4:0:2/4:0:2:1
Class = "zfcp_unit"
    access_denied       = "0"
    access_readonly     = "0"
    access_shared       = "0"
    failed              = "0"
    in_recovery         = "0"
    status              = "0x54000000"
Class = "scsi_device"
    ...
    modalias            = "scsi:t-0x08"
    model               = "3573-TL"
    scsi_level          = "6"
    state               = "running"
    type                = "8"
    ...
    zfcp_access_denied  = "0"
    zfcp_failed         = "0"
    zfcp_in_recovery    = "0"
    zfcp_status         = "0x54000000"

/sys/devices/css0/0.0.0222/0.0.3c80/0x500507630313d327/0xffffffffffffffff failed
-
Class = "zfcp_unit"
    access_denied       = "0"
    access_readonly     = "0"
    access_shared       = "0"
    failed              = "1"
    in_recovery         = "0"
    status              = "0x00000000"

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
f67758160e lszfcp: allow to show zfcp_units without associated SCSI device
Useful to detect configuration errors and FCP LUN typos.

Example:

$ lszfcp -De
0.0.3c80/0x500507630313d327/0xffffffffffffffff - failed

$ lszfcp -DeV
/sys/devices/css0/0.0.0222/0.0.3c80/0x500507630313d327/0xffffffffffffffff failed
-

$ lszfcp -Deam
0.0.3c80/0x500507630313d327/0xffffffffffffffff - failed
Class = "zfcp_unit"
    access_denied       = "0"
    access_readonly     = "0"
    access_shared       = "0"
    failed              = "1"
    in_recovery         = "0"
    status              = "0x00000000"

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
e84287e76e lszfcp: attribute details for: css, zfcp_port, zfcp_unit
Consistency with "lszfcp -Ha" which includes zfcp_adapter as class=ccw.
Attribute details are especially useful to show the driver-internal status.

For FCP devices (hosts), "css" shows subchannel details including CHPID.

Abbreviated examples:

$ lszfcp -PVeam -b 0.0.50c0 -p 0x500507680b2481fa
- (NoMoreZfcpPort:0.0.50c0/0x500507680b2481fa)
/sys/class/fc_remote_ports/rport-6:0-2 NotOnline
Class = "fc_remote_ports"
    dev_loss_tmo        = "60"
    fast_io_fail_tmo    = "off"
    maxframe_size       = "2048 bytes"
    node_name           = "0x500507680b0081fa"
    port_id             = "0x242200"
    port_name           = "0x500507680b2481fa"
    port_state          = "Blocked"
    roles               = "FCP Target"
    scsi_target_id      = "2"
    supported_classes   = "Class 2, Class 3"

$ lszfcp -HPDeam
0.0.1900 host0
Bus = "css"
    chpids              = "60 00 00 00 00 00 00 00"
    modalias            = "css:t0"
    pimpampom           = "80 80 ff"
    type                = "0"
    uevent              = "DRIVER=io_subchannel"
    vpm                 = "80"
Bus = "ccw"
    availability        = "good"
    ...
    failed              = "0"
    in_recovery         = "0"
    online              = "1"
    status              = "0x5400040b"
    ...
Class = "fc_host"
    ...
    port_state          = "Online"
    port_type           = "NPIV VPORT"
    ...
Class = "scsi_host"
    ...
    state               = "running"
    ...

0.0.1940 host8 offline
Bus = "css"
    chpids              = "61 00 00 00 00 00 00 00"
    modalias            = "css:t0"
    pimpampom           = "80 80 ff"
    type                = "0"
    uevent              = "DRIVER=io_subchannel"
    vpm                 = "80"
Bus = "ccw"
    availability        = "good"
    ...
    failed              = "0"
    in_recovery         = "0"
    online              = "0"
    status              = "0x00000401"
    ...
Class = "fc_host"
    ...
    port_state          = "Unknown"
    port_type           = "NPIV VPORT"
    ...
Class = "scsi_host"
    ...
    state               = "running"
    ...

0.0.5000 host1 offline
Bus = "css"
    chpids              = "67 00 00 00 00 00 00 00"
    modalias            = "css:t0"
    pimpampom           = "80 80 ff"
    type                = "0"
    uevent              = "DRIVER=io_subchannel"
    vpm                 = "80"
Bus = "ccw"
    availability        = "good"
    ...
    failed              = "0"
    in_recovery         = "0"
    online              = "0"
    status              = "0x00000401"
    uevent              = "DRIVER=zfcp"
    ...
Class = "fc_host"
    ...
    port_state          = "Unknown"
    port_type           = "NPort (fabric via point-to-point)"
    ...
Class = "scsi_host"
    ...
    state               = "running"
    ...

0.0.3c40 host7 defunct
Bus = "css"
    defunct
Bus = "ccw"
    availability        = "no device"
    ...
    failed              = "0"
    in_recovery         = "0"
    online              = "1"
    status              = "0x00000401"
    ...
Class = "fc_host"
    ...
    port_state          = "Unknown"
    port_type           = "NPIV VPORT"
    ...
Class = "scsi_host"
    ...
    state               = "running"
    ...

0.0.1880 - offline
Bus = "css"
    chpids              = "5a 00 00 00 00 00 00 00"
    modalias            = "css:t0"
    pimpampom           = "80 80 ff"
    type                = "0"
    uevent              = "DRIVER=io_subchannel"
    vpm                 = "00"
Bus = "ccw"
    availability        = "good"
    cmb_enable          = "0"
    cutype              = "1731/03"
    devtype             = "1732/03"
    modalias            = "ccw:t1731m03dt1732dm03"
    online              = "0"
    uevent              = "DRIVER=zfcp"

0.0.1900/0x500507630708c5e3 rport-0:0-0
Class = "zfcp_port"
    access_denied       = "0"
    failed              = "0"
    in_recovery         = "0"
    status              = "0x54000001"
Class = "fc_remote_ports"
    dev_loss_tmo        = "2147483647"
    fast_io_fail_tmo    = "5"
    maxframe_size       = "2112 bytes"
    node_name           = "0x5005076307ffc5e3"
    port_id             = "0x675c00"
    port_name           = "0x500507630708c5e3"
    port_state          = "Online"
    roles               = "FCP Target"
    scsi_target_id      = "0"
    supported_classes   = "Class 2, Class 3"

0.0.5000/0x500507680b2381fb rport-1:0-0 NotOnline
Class = "zfcp_port"
    access_denied       = "0"
    failed              = "0"
    in_recovery         = "0"
    status              = "0x00000001"
Class = "fc_remote_ports"
    dev_loss_tmo        = "2147483647"
    fast_io_fail_tmo    = "5"
    maxframe_size       = "2048 bytes"
    node_name           = "0x500507680b0081fb"
    port_id             = "0x24e200"
    port_name           = "0x500507680b2381fb"
    port_state          = "Blocked"
    roles               = "FCP Target"
    scsi_target_id      = "0"
    supported_classes   = "Class 2, Class 3"

0.0.5040/0x500507680b2281fa rport-2:0-0
Class = "zfcp_port"
    access_denied       = "0"
    failed              = "0"
    in_recovery         = "0"
    status              = "0x54000001"
Class = "fc_remote_ports"
    dev_loss_tmo        = "2147483647"
    fast_io_fail_tmo    = "5"
    maxframe_size       = "2048 bytes"
    node_name           = "0x500507680b0081fa"
    port_id             = "0x24a300"
    port_name           = "0x500507680b2281fa"
    port_state          = "Online"
    roles               = "FCP Target"
    scsi_target_id      = "0"
    supported_classes   = "Class 2, Class 3"

0.0.1940/0x500507630718c5e3 rport-8:0-0 NotOnline
Class = "zfcp_port"
    access_denied       = "0"
    failed              = "0"
    in_recovery         = "0"
    status              = "0x00000001"
Class = "fc_remote_ports"
    dev_loss_tmo        = "2147483647"
    fast_io_fail_tmo    = "5"
    maxframe_size       = "2112 bytes"
    node_name           = "0x5005076307ffc5e3"
    port_id             = "0x675e00"
    port_name           = "0x500507630718c5e3"
    port_state          = "Blocked"
    roles               = "FCP Target"
    scsi_target_id      = "0"
    supported_classes   = "Class 2, Class 3"

0.0.1900/0x500507630708c5e3/0x4000408600000000 0:0:0:1082540032 auto
Class = "scsi_device"
    ...
    state               = "running"
    ...
    zfcp_access_denied  = "0"
    zfcp_failed         = "0"
    zfcp_in_recovery    = "0"
    zfcp_status         = "0x54000000"

0.0.1940/0x500507630718c5e3/0x4000408600000000 8:0:0:1082540032 auto NotRunning
Class = "scsi_device"
    ...
    state               = "transport-offline"
    ...
    zfcp_access_denied  = "0"
    zfcp_failed         = "0"
    zfcp_in_recovery    = "0"
    zfcp_status         = "0x00000000"

0.0.5000/0x500507680b2381fb/0x0256000000000000 1:0:0:598 NotRunning
Class = "zfcp_unit"
    access_denied       = "0"
    access_readonly     = "0"
    access_shared       = "0"
    failed              = "0"
    in_recovery         = "0"
    status              = "0x00000000"
Class = "scsi_device"
    ...
    state               = "transport-offline"
    ...
    zfcp_access_denied  = "0"
    zfcp_failed         = "0"
    zfcp_in_recovery    = "0"
    zfcp_status         = "0x00000000"

0.0.5040/0x500507680b2281fa/0x0256000000000000 2:0:0:598
Class = "zfcp_unit"
    access_denied       = "0"
    access_readonly     = "0"
    access_shared       = "0"
    failed              = "0"
    in_recovery         = "0"
    status              = "0x54000000"
Class = "scsi_device"
    ...
    state               = "running"
    ...
    zfcp_access_denied  = "0"
    zfcp_failed         = "0"
    zfcp_in_recovery    = "0"
    zfcp_status         = "0x54000000"

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
0c78add815 lszfcp: add new output marker for non-good SCSI devices (luns)
Shows potential issues with zfcp-attached SCSI devices at one glance.

Example:

$ lszfcp -De
0.0.5000/0x500507680b2181fa/0x027d000000000000 1:0:1:637 NotRunning

$ lszfcp -DeV
/sys/devices/css0/0.0.0223/0.0.5000/0x500507680b2181fa/0x027d000000000000
/sys/bus/ccw/drivers/zfcp/0.0.5000/host1/rport-1:0-1/target1:0:1/1:0:1:637 NotRunning
/sys/block/sdm /sys/class/scsi_generic/sg12

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Fedor Loshakov <loshakov@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
94b7a8f68d lszfcp: allow to also enumerate FCP device that have never been online
Since zfcp lazily allocates Scsi_Host et al. on setting an FCP device
online for the first time since the last driver core bind to zfcp
(such as zfcp kernel module load),
lszfcp has only been showing FCP devices (vHBAs) that have been online
at least once including those that have been set offline again.
This is somewhat confusing.
Also it would be nice if lszfcp could be an easier to type replacement for
"lscss -t 17032/03" to simply show all devices bound to the zfcp device
driver.
Of course those FCP devices that have never been online, won't have any
zfcp-specific attribute details, only CIO attributes from the CCW bus.
They also do not have a Scsi_Host nor fc_host.

In order not to break any scripting or expectations around lszfcp,
make the new feature depend on the extended output command line option.

Example:

$ lszfcp -He
0.0.1880 - offline

$ lszfcp -HeV
/sys/devices/css0/0.0.010b/0.0.1880 offline
-
-

$ lszfcp -Hea
0.0.1880 - offline
Bus = "ccw"
    availability        = "good"
    cmb_enable          = "0"
    cutype              = "1731/03"
    devtype             = "1732/03"
    modalias            = "ccw:t1731m03dt1732dm03"
    online              = "0"
    uevent              = "DRIVER=zfcp"

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Fedor Loshakov <loshakov@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
4036e80b26 lszfcp: add new output marker for non-good FCP devices (hosts)
Shows potential issues with FCP devices at one glance.

Examples:

$ lszfcp -He
0.0.5000 host1 offline
0.0.50c0 host6 failed
0.0.3c40 host7 defunct

$ lszfcp -HeV
/sys/devices/css0/0.0.0223/0.0.5000 offline
/sys/class/fc_host/host1
/sys/class/scsi_host/host1
/sys/devices/css0/0.0.0226/0.0.50c0 failed
/sys/class/fc_host/host6
/sys/class/scsi_host/host6
/sys/devices/css0/defunct/0.0.3c40 defunct
/sys/class/fc_host/host7
/sys/class/scsi_host/host7

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
a236180ad8 lszfcp: add new output marker for non-good fc_rports
$ lszfcp -Pe
0.0.50c0/0x500507680b2481fa rport-6:0-2 NotOnline
$ lszfcp -PeV
- (NoMoreZfcpPort:0.0.50c0/0x500507680b2481fa)
/sys/class/fc_remote_ports/rport-6:0-2 NotOnline

$ lszfcp -Pe
0.0.3c40/0x500507680b2181fb rport-7:0-4 NotOnline
$ lszfcp -PeV
/sys/devices/css0/defunct/0.0.3c40/0x500507680b2181fb
/sys/class/fc_remote_ports/rport-7:0-4 NotOnline

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00
Steffen Maier
a9684b9154 lszfcp: fix error message if no zfcp-attached SCSI device found
s390-tools-1.8.1 introduced a new error message.
It gave the same and thus misleading error message as if no FCP device
(vHBA) found.
In order not to break any scripting built around lszfcp output,
only print the fixed error message depending on the extended output
command line option.

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:40 +01:00
Steffen Maier
6d31760872 lszfcp: fix to show defunct FCP devices again
s390-tools-1.8.0 introduced a regression skipping all FCP devices
that are currently "defunct".

Changing
$SYSFS/devices/css0/*/*/host*
to
$SYSFS/devices/css0/[0-9]*/[0-9]*/host*
was too strict as it won't match
$SYSFS/devices/css0/defunct/[0-9]*/host*
anymore.

Fix:
$SYSFS/devices/css0/[0-9d]*/[0-9]*/host*

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:12:07 +01:00
Steffen Maier
b0dcc61ed5 lszfcp: fix to show non-good target ports again
s390-tools-1.8.1 introduced a regression skipping all fc_rports
with port_state != Online. While we need to skip some output parts
for a zfcp_port which does not exist anymore due to port_remove,
there are other cases with port_state != Online for which we should
not skip an fc_rport.

Such as port_state "Blocked" after a cable pull beyond host-adjacent switch
or port_state "Not Present" after dev_loss_tmo ran out.
This way the user can see the previously discovered ports,
even if they might currently not be usable for traffic.
Non-good ports are marked in the short output with suffix "NotOnline".
In order not to break scripting or expectations around lszfcp, make the new
feature depend on the extended output command line option.

Sysfs path globbing does not work for a removed zfcp_port
to obtain the FCP device bus-ID. Instead, properly walk the sysfs.

Examples with a removed zfcp_port:
$ lszfcp -Pe
0.0.50c0/0x500507680b2481fa rport-6:0-2
$ lszfcp -PeV
- (NoMoreZfcpPort:0.0.50c0/0x500507680b2481fa)
/sys/class/fc_remote_ports/rport-6:0-2

Examples with an existing zfcp_port but pulled fibre:
$ lszfcp -Pe
0.0.3c40/0x500507680b2181fb rport-7:0-4
$ lszfcp -PeV
/sys/devices/css0/defunct/0.0.3c40/0x500507680b2181fb
/sys/class/fc_remote_ports/rport-7:0-4

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:12:07 +01:00
Steffen Maier
a3e37953fe lszfcp: fix missing block & sg device output without CONFIG_SYSFS_DEPRECATED
lszfcp -DVe was missing a 3rd SCSI device header line like:

/sys/devices/css0/0.0.0019/0.0.1880/0x50050763031bd327/0x4045400000000000
/sys/bus/ccw/drivers/zfcp/0.0.1880/host0/rport-0:0-0/target0:0:0/0:0:0:1073758277
/sys/block/sda /sys/class/scsi_generic/sg0

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:12:07 +01:00
Steffen Maier
abf18cb711 lszfcp: new command line option for extended output format
Used in subsequent patches to guard their changes in order not to break
any scripting or expectations around the lszfcp output format.

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:12:07 +01:00
Steffen Maier
22a4d45e3b lszfcp: clean up whitespace (mixed indentation, trailing)
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:12:07 +01:00
Ingo Franzki
e693173eef zkey: Add batch-mode option to zkey-cryptsetup tool
When re-enciphering or setting LUKS2 volume keys using zkey-cryptsetup,
allow to specify the --batch-mode|-q option to suppress confirmation
questions.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-21 12:19:12 +01:00
Ingo Franzki
11bfa1d3c8 zkey: Add open and format options to the cryptsetup command
For LUKS2 volumes the cryptsetup command currently generates
'cryptsetup luksFormat' commands, but for plain mode volumes it
generates 'cryptsetup plainOpen' commands.

With the --open option it can now also generate 'cryptsetup luksOpen'
commands for opening LUKS2 volumes. With the --format option you can
limit the generated commands to only generate 'cryptsetup luksFormat'
commands for LUKS2 volumes, and skip plain mode volumes.
The default behavior (i.e. if none of the two options specified),
remains the same as before.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-21 12:19:12 +01:00
Ingo Franzki
3ed8ab4e2a zkey: Add common passphrase options for crypttab command
When generating crypttab entries for LUKS2 volumes, allow to
specify common passphrase options like --key-file, --keyfile-offset,
--keyfile-size and --tries and pass those to the generated crypttab
entries.

Note that not all distributions support the keyfile-offset and
keyfile-size options in crypttab entries.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-21 12:19:12 +01:00
Ingo Franzki
5a0c93443c zkey: Add batch-mode option to cryptsetup command
When generating cryptsetup commands, allow to specify the
--batch-mode|-q option and pass it to the generated commands.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/59
Fixes: https://github.com/ibm-s390-tools/s390-tools/issues/58

Suggested-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-21 12:19:12 +01:00
Ingo Franzki
b0c7965234 zkey: Add common passphrase options for cryptsetup command
When generating 'cryptsetup luksFormat' or 'zkey-cryptsetup setvp'
commands for LUKS2 volumes, allow to specify common passphrase options
like --key-file, --keyfile-offset, --keyfile-size and --tries and
pass those to the generated commands.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/59
Fixes: https://github.com/ibm-s390-tools/s390-tools/issues/58

Suggested-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-21 12:19:12 +01:00
Dan Horák
cdb23f8d22 zipl: copy new section introduced by GCC 9
GCC 9 is using a new section called .rodata.cst8 for some literals and
it must be included when copying the bootloaders to the bin images.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/60
Signed-off-by: Dan Horák <dan@danny.cz>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-21 12:19:12 +01:00
Sa Liu
60bda7ed0d dbginfo: Added commmands blockdev and lvdisplay
Signed-off-by: Sa Liu <saliu@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-21 12:19:12 +01:00
Peter Oberparleiter
4ff6519961 zdev: Do not export inacceptable attribute values
For some device driver SysFS attributes, values read may not be
acceptable input values for that attribute.

An example would be the group of qeth VNICC attributes that return "n/a"
when VNICC setup is not supported, but only accept "0" and "1" as valid
values that can be written to it.

This leads to errors such as the following when data for such attributes
is imported:

  # chzdev f500 --import test.conf
  Importing configuration data from test.conf
  QETH device 0.0.f500:0.0.f501:0.0.f502 configure failed
      Error: Invalid value for qeth attribute: vnicc/flooding=n/a (*)
      Acceptable values:
      - Integers in the range 0 - 1
      Use 'chzdev qeth --help-attribute vnicc/flooding' for more information
  Note: You can use --force to override safety checks (*)

To fix this, change chzdev's --export function to skip any attribute
value that is not acceptable for that attribute.

Fixes: e831269e74 ("zdev: Add support for VNIC Characteristics")
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-21 12:19:12 +01:00
Ingo Franzki
90dc65659f zkey: Correct crypttab entry generation
Remove 'hash=plain' option for plain type entries, add 'none luks'
for LUKS type entries.

Note that the format of a crypttab entry is distribution specific.
On some distributions only the first 2 fields are required, the
remaining are optional, on other distributions all 4 fields are
required. With this patch correct crypttab entries are generated
for all distributions.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/55
Fixes: https://github.com/ibm-s390-tools/s390-tools/issues/57
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-07 14:02:01 +01:00
Ingo Franzki
ec9c67189e zkey-cryptsetup: Support debug level CRYPT_DEBUG_JSON
With libcryptsetup version 2.1 a new debug level was introduced
to log the JSON structures when adding key slots, digests, etc
into the LUKS2 header.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-07 13:54:43 +01:00
Ingo Franzki
951bd1ae54 zkey-cryptsetup: Fix logging of libcryptsetup debug messages
Messages from libcryptsetup for logging level CRYPT_LOG_DEBUG
do not include an EOL.

Prior to libcryptsetup version 2.1 debug messages were not printed
through the log callback, but using printf directly within
libcryptsetup. Now they are also printed through the log callback,
but without an EOL terminating the text.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-07 13:54:43 +01:00
Ingo Franzki
ed6e3b7270 zkey-cryptsetup: Obtain PBKDF from existing key-slot
For zkey-cryptsetup commands reencipher and setkey, use the
same password-based key derivation function (PBKDF) when
creating unbound key-sots that the key slot uses, which was
unlocked through the specified passphrase. That way the
unlocked key slots created by these commands inherit the
PBKDF from the existing key slot.

This feature requires libcryptsetup version 2.1 or later.
If an older libcryptsetup version is available at compile
time, then PBKDF2 is used for newly created unbound key slots.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-07 13:54:43 +01:00
Ingo Franzki
79ce120553 zkey: Minor correction in man page
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-07 13:54:43 +01:00
Jan Höppner
b45b564681 Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-07 13:54:43 +01:00
106 changed files with 5615 additions and 1013 deletions

1
.gitignore vendored
View File

@@ -69,6 +69,7 @@ zconf/scm/lsscm
zconf/zcrypt/chzcrypt
zconf/zcrypt/lszcrypt
zconf/zcrypt/zcryptctl
zconf/zcrypt/zcryptstats
zdev/src/chzdev
zdev/src/chzdev_usage.c
zdev/src/lszdev

View File

@@ -56,6 +56,7 @@ List of all individuals having contributed content to s390-tools
- Kittipon Meesompop
- Klaus-Dieter Wacker
- Lakhvich Dmitriy
- Marc Hartmayer
- Mark Dettinger
- Martin Kammerer
- Martin Peschke

View File

@@ -1,5 +1,72 @@
Release history for s390-tools (MIT version)
--------------------------------------------
* __v2.11.0 (2019-09-06)__
For Linux kernel version: 5.3
Changes of existing tools:
- dasdfmt: Add support for thin-provisioned volumes
- lsdasd: Add support for thin-provisioned volumes
- libdasd: Provide function to utilise release space ioctl
- libdasd: Provide function to read ese sysfs attribute
- dbginfo: Add lspci (PCI devices) and smc_dbg (SMC sockets)
- dbginfo: Gather ethtool related data
Bug Fixes:
- zipl: Fix freeing of uninitialized pointer
- zipl: Set correct secure IPL default value
* __v2.10.0 (2019-07-31)__
For Linux kernel version: 5.2
Changes of existing tools:
- zdev: Add zfcp dix parameter handling
- cpumf: Add support for CPU-Measurement Facility counters SVN 6
Bug Fixes:
- libutil: Add functions to test path is read/write-only
- zdev: Fix reporting of read-only sysfs attributes
- zdev: Improve handling of invalid udev rules
- zipl: Fix stfle zero padding
- zipl: Fix build issues
- zipl: Remove trailing spaces from the fields defined in BLS files
- zipl: Do not overwrite BOOT_IMAGE entry
- zkey: Fix auto-detection of clear key bitsize for XTS keys
* __v2.9.0 (2019-05-21)__
For Linux kernel version: 5.0 / 5.1
Add new tool:
- zcryptstats: Add zcryptstats to display usage statistics of
IBM Crypto Express adapters
Changes of existing tools:
- lszfcp: New command line option to show module parameters
- lszfcp: Sdev attributes for scsi_disk, block, integrity, queue, iosched
- lszfcp: Add new output marker for non-good SCSI devices (luns)
- lszfcp: Add new output marker for non-good fc_rports
- lszfcp: Clean up whitespace (mixed indentation, trailing)
- lschp: Add support for specifying a CHPID
- zipl: Add secure boot capabilities
- zkey: Add common passphrase options for cryptsetup and crypttab
- zkey: Add batch-mode option to cryptsetup and zkey-cryptsetup
- libu2s: Remove the entire library and provide more robust functionality
in libdasd and libutil instead
Bug Fixes:
- lszfcp: Allow to show zfcp_units without associated SCSI device
- lszfcp: Attribute details for: css, zfcp_port, zfcp_unit
- lszfcp: Allow to also enumerate FCP device that have never been online
- lszfcp: Fix error message if no zfcp-attached SCSI device found
- lszfcp: Fix to show defunct FCP devices again
- lszfcp: Fix to show non-good target ports again
- lszfcp: Fix missing block & sg device output without CONFIG_SYSFS_DEPRECATED
- lszfcp: New command line option for extended output format
- zfcpdbf: Warn about ambiguous payload records with dup reqid & payarea
- zpcictl: Check for regular directory to prevent possible buffer overflow
* __v2.8.0 (2019-02-15)__
For Linux kernel version: 4.20

View File

@@ -3,7 +3,7 @@ ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/ar
# Include common definitions
include common.mak
LIB_DIRS = libvtoc libu2s libutil libzds libdasd libvmdump libccw libvmcp
LIB_DIRS = libvtoc libutil libzds libdasd libvmdump libccw libvmcp
TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \

View File

@@ -129,6 +129,7 @@ Package contents
or show encryption state of attached LUNs.
- lszcrypt: Show Information about zcrypt devices and configuration.
- chzcrypt: Modify the zcrypt configuration.
- zcryptstats: Display usage statistics of IBM Crypto Express adapters.
- znetconf: List and configure network devices for s390 network adapters.
- cio_ignore: Query and modify the contents of the CIO device driver
blacklist.
@@ -284,6 +285,9 @@ Build and runtime requirements for specific tools
In the following more details on the build an runtime requirements of
the different tools are provided:
* dbginfo.sh:
The tar package is required to archive collected data.
* osasnmpd:
You need at least the NET-SNMP 5.1.x package (net-snmp-devel.rpm)
installed, before building the osasnmpd subagent.

View File

@@ -5,7 +5,7 @@ COMMON_INCLUDED = true
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION = 2
RELEASE = 8
RELEASE = 11
PATCHLEVEL = 0
DISTRELEASE = build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
@@ -331,10 +331,6 @@ $(rootdir)/libzds/libzds.a: $(rootdir)/libzds
$(MAKE) -C $(rootdir)/libzds/ libzds.a
.PHONY: $(rootdir)/libzds
$(rootdir)/libu2s/libu2s.a: $(rootdir)/libu2s
$(MAKE) -C $(rootdir)/libu2s/ libu2s.a
.PHONY: $(rootdir)/libu2s
$(rootdir)/libvmdump/libvmdump.a: $(rootdir)/libvmdump
$(MAKE) -C $(rootdir)/libvmdump/ libvmdump.a
.PHONY: $(rootdir)/libvmdump

View File

@@ -6,7 +6,7 @@ include ../common.mak
CPUMF_DATADIR = $(TOOLS_DATADIR)/cpumf
DATA_FILES = cpum-cf-hw-counter.map \
cpum-cf-cfvn-1.ctr cpum-cf-cfvn-3.ctr \
cpum-cf-csvn-generic.ctr \
cpum-cf-csvn-12345.ctr cpum-cf-csvn-6.ctr \
cpum-cf-extended-z10.ctr cpum-cf-extended-z196.ctr \
cpum-cf-extended-zEC12.ctr cpum-sf-modes.ctr \
cpum-cf-extended-z13.ctr cpum-cf-extended-z14.ctr

View File

@@ -267,7 +267,12 @@ sub cpumf_load_ctrdef($;$)
# List of "generic" counter sets
my @def = ();
push @def, "cfvn-" . $version->{cfvn};
push @def, "csvn-generic";
if ($version->{csvn} >= 1 && $version->{csvn} <= 6) {
push @def, "csvn-12345";
}
if ($version->{csvn} == 6) {
push @def, "csvn-6";
}
my $h = {};
# Load counter set definition

View File

@@ -0,0 +1,33 @@
Counter: 80 Name:ECC_FUNCTION_COUNT
Short-Description:ECC Function Count
Description:
This counter counts the
total number of the elliptic-curve cryptography (ECC)
functions issued by the CPU.
.
Counter: 81 Name:ECC_CYCLES_COUNT
Short-Description:ECC Cycles Count
Description:
This counter counts the total
number of CPU cycles when the ECC coprocessor is
busy performing the elliptic-curve cryptography
(ECC) functions issued by the CPU.
.
Counter: 82 Name:ECC_BLOCKED_FUNCTION_COUNT
Short-Description:Ecc Blocked Function Count
Description:
This counter
counts the total number of the elliptic-curve
cryptography (ECC) functions that are issued by the CPU
and are blocked because the ECC coprocessor is
busy performing a function issued by another CPU.
.
Counter: 83 Name:ECC_BLOCKED_CYCLES_COUNT
Short-Description:ECC Blocked Cycles Count
Description:
This counter counts
the total number of CPU cycles blocked for the elliptic-curve
cryptography (ECC) functions issued by the
CPU because the ECC coprocessor is busy perform-
ing a function issued by another CPU.
.

View File

@@ -14,7 +14,8 @@
'cfvn-3' => 'cpum-cf-cfvn-3.ctr',
# CSVN
'csvn-generic' => 'cpum-cf-csvn-generic.ctr',
'csvn-12345' => 'cpum-cf-csvn-12345.ctr',
'csvn-6' => 'cpum-cf-csvn-6.ctr',
# Extended counters
2097 => 'cpum-cf-extended-z10.ctr',
@@ -27,4 +28,7 @@
2965 => 'cpum-cf-extended-z13.ctr',
3906 => 'cpum-cf-extended-z14.ctr',
3907 => 'cpum-cf-extended-z14.ctr',
# Identical with z14
8561 => 'cpum-cf-extended-z14.ctr',
8562 => 'cpum-cf-extended-z14.ctr',
};

View File

@@ -161,8 +161,8 @@ int is_online(int cpuid)
retval = 1;
if (state == 0)
retval = 0;
fclose(filp);
}
fclose(filp);
}
return retval;
}
@@ -220,8 +220,8 @@ int cpu_is_configured(int cpuid)
retval = 1;
if (state == 0)
retval = 0;
fclose(filp);
}
fclose(filp);
}
return retval;
}

View File

@@ -4,7 +4,6 @@ all: dasdfmt
libs = $(rootdir)/libdasd/libdasd.a \
$(rootdir)/libvtoc/libvtoc.a \
$(rootdir)/libu2s/libu2s.a \
$(rootdir)/libutil/libutil.a
dasdfmt: dasdfmt.o $(libs)

View File

@@ -122,6 +122,8 @@ 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).
.br
For thin-provisioned DASD ESE volumes this is the default mode.
.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
@@ -136,6 +138,10 @@ using \fB-b\fR (\fB--blocksize\fR).
Perform a complete format check on a DASD volume. A blocksize can be specified
with \fB-b\fR (\fB--blocksize\fR).
.TP
\fB--no-discard\fR
Omit a full space release when formatting a thin-provisioned DASD ESE volume.
.TP
\fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR
Number of cylinders to be processed in one formatting step.

View File

@@ -53,6 +53,7 @@ static const struct util_prg prg = {
/* Defines for options with no short command */
#define OPT_CHECK 128
#define OPT_NOZERO 129
#define OPT_NODISCARD 130
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("FORMAT ACTIONS"),
@@ -105,6 +106,11 @@ static struct util_opt opt_vec[] = {
.desc = "Prevent storage server from modifying record 0",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "no-discard", no_argument, NULL, OPT_NODISCARD },
.desc = "Do not discard space before formatting",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { NULL, no_argument, NULL, 'y' },
.desc = "Start formatting without further user-confirmation",
@@ -921,6 +927,8 @@ static void dasdfmt_print_info(dasdfmt_info_t *info, char *devname,
printf("Drive Geometry: %d Cylinders * %d Heads = %d Tracks\n",
cylinders, heads, (cylinders * heads));
printf("Device Type: %s Provisioned\n",
info->ese ? "Thinly" : "Fully");
printf("\nI am going to format the device ");
printf("%s in the following way:\n", devname);
printf(" Device number of device : 0x%x\n", info->dasd_info.devno);
@@ -939,7 +947,10 @@ static void dasdfmt_print_info(dasdfmt_info_t *info, char *devname,
(p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
printf(" Blocksize : %d\n", p->blksize);
printf(" Mode : %s\n", mode_str[mode]);
if (info->ese) {
printf(" Full Space Release : %s\n",
(info->no_discard || mode == FULL) ? "no" : "yes");
}
if (info->testmode)
printf("Test mode active, omitting ioctl.\n");
}
@@ -1234,6 +1245,26 @@ static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders,
process_tracks(info, cylinders, heads, format_params);
}
static void dasdfmt_release_space(dasdfmt_info_t *info)
{
format_data_t r = {
.start_unit = 0,
.stop_unit = 0,
.intensity = DASD_FMT_INT_ESE_FULL,
};
int err = 0;
if (!info->ese || info->no_discard)
return;
printf("Releasing space for the entire device...\n");
err = dasd_release_space(dev_filename, &r);
if (err) {
ERRMSG_EXIT(EXIT_FAILURE, "%s: Could not release space (%s)\n",
prog_name, strerror(err));
}
}
static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,
unsigned int cylinders,
unsigned int heads, format_data_t *p)
@@ -1329,6 +1360,8 @@ static void dasdfmt_quick_format(dasdfmt_info_t *info, unsigned int cylinders,
if (info->force) {
printf("Skipping format check due to --force.\n");
} else if (info->ese) {
printf("Skipping format check due to thin-provisioned device.\n");
} else {
check_blocksize(info, p->blksize);
@@ -1394,7 +1427,7 @@ static void do_format_dasd(dasdfmt_info_t *info, char *devname,
if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
dasdfmt_print_info(info, devname, vlabel, cylinders, heads, p);
count = u2s_get_host_access_count(devname);
count = dasd_get_host_access_count(devname);
if (info->force_host) {
if (count > 1) {
ERRMSG_EXIT(EXIT_FAILURE,
@@ -1438,6 +1471,7 @@ static void do_format_dasd(dasdfmt_info_t *info, char *devname,
dasdfmt_prepare_and_format(info, cylinders, heads, p);
break;
case QUICK:
dasdfmt_release_space(info);
dasdfmt_quick_format(info, cylinders, heads, p);
break;
case EXPAND:
@@ -1461,6 +1495,19 @@ static void do_format_dasd(dasdfmt_info_t *info, char *devname,
}
}
static void eval_format_mode(dasdfmt_info_t *info)
{
if (!info->force && info->mode_specified && info->ese && mode == EXPAND) {
ERRMSG_EXIT(EXIT_FAILURE,
"WARNING: The specified device is thin-provisioned\n"
"Format mode 'expand' is not feasible.\n"
"Use --mode=full or --mode=quick to perform a clean format\n");
}
if (!info->mode_specified)
mode = info->ese ? QUICK : FULL;
}
int main(int argc, char *argv[])
{
dasdfmt_info_t info = {
@@ -1496,8 +1543,6 @@ int main(int argc, char *argv[])
format_params.blksize = DEFAULT_BLOCKSIZE;
format_params.intensity = DASD_FMT_INT_COMPAT;
mode = FULL;
/*************** parse parameters **********************/
while (1) {
@@ -1601,6 +1646,10 @@ int main(int argc, char *argv[])
"invalid. Consult the man page for "
"more information.\n",
prog_name, optarg);
info.mode_specified = 1;
break;
case OPT_NODISCARD:
info.no_discard = 1;
break;
case OPT_CHECK:
info.check = 1;
@@ -1645,6 +1694,9 @@ int main(int argc, char *argv[])
"device information failed (%s).\n",
prog_name, strerror(rc));
info.ese = dasd_sys_ese(dev_filename);
eval_format_mode(&info);
/* Either let the user specify the blksize or get it from the kernel */
if (!info.blksize_specified) {
if (!(mode == FULL ||

View File

@@ -27,10 +27,6 @@
#include <sys/types.h>
#include <unistd.h>
/****************************************************************************
* SECTION: Definition needed for DASD-API (see dasd.h) *
****************************************************************************/
/*
* Represents possible format modes that can be specified when formatting
* a DASD.
@@ -45,57 +41,16 @@ static const char mode_str[3][10] = {
"Full", "Quick", "Expand"
};
/*
* values to be used for format_data_t.intensity
* 0/8: normal format
* 1/9: also write record zero
* 3/11: also write home address
* 4/12: invalidate track
*/
#define DASD_FMT_INT_FMT_R0 1 /* write record zero */
#define DASD_FMT_INT_FMT_HA 2 /* write home address, also set FMT_R0 ! */
#define DASD_FMT_INT_INVAL 4 /* invalidate tracks */
#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 */
/*
* 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
/****************************************************************************
* SECTION: DASDFMT internal types *
****************************************************************************/
#define DASD_PARTN_BITS 2
#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
#define EXIT_MISUSE 1
#define EXIT_BUSY 2
#define LABEL_LENGTH 14
#define VLABEL_CHARS 84
#define LINE_LENGTH 80
#define ERR_LENGTH 90
#define DEFAULT_BLOCKSIZE 4096
/* requestsize - number of cylinders in one format step */
#define DEFAULT_REQUESTSIZE 10
#define USABLE_PARTITIONS ((1 << DASD_PARTN_BITS) - 1)
#define ERRMSG(x...) {fflush(stdout);fprintf(stderr,x);}
#define ERRMSG_EXIT(ec,x...) {fflush(stdout);fprintf(stderr,x);exit(ec);}
@@ -137,6 +92,9 @@ typedef struct dasdfmt_info {
int force_host;
int layout_specified;
int check;
int mode_specified;
int ese;
int no_discard;
} dasdfmt_info_t;

View File

@@ -1,7 +1,6 @@
include ../common.mak
libs = $(rootdir)/libu2s/libu2s.a \
$(rootdir)/libutil/libutil.a \
libs = $(rootdir)/libutil/libutil.a \
$(rootdir)/libdasd/libdasd.a
all: dasdinfo

View File

@@ -7,7 +7,6 @@ all: dasdview
libs = $(rootdir)/libdasd/libdasd.a \
$(rootdir)/libzds/libzds.a \
$(rootdir)/libvtoc/libvtoc.a \
$(rootdir)/libu2s/libu2s.a \
$(rootdir)/libutil/libutil.a
dasdview: dasdview.o $(libs)

View File

@@ -28,10 +28,10 @@
#include "lib/dasd_base.h"
#include "lib/dasd_sys.h"
#include "lib/libzds.h"
#include "lib/u2s.h"
#include "lib/util_base.h"
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/util_sys.h"
#include "lib/vtoc.h"
#include "lib/zt_common.h"
@@ -183,7 +183,7 @@ dasdview_get_info(dasdview_info_t *info)
else
info->hw_cylinders = characteristics->no_cyl;
if (u2s_getbusid(info->device, info->busid) == -1)
if (util_sys_get_dev_addr(info->device, info->busid) != 0)
info->busid_valid = 0;
else
info->busid_valid = 1;

View File

@@ -11,7 +11,6 @@
#define DASDVIEW_H
#include <limits.h>
#include "lib/u2s.h"
/********************************************************************************
* SECTION: Definitions needed for DASD-API (see dasd.h)
@@ -109,7 +108,7 @@ typedef struct dasdview_info
int f8c;
int f9c;
char busid[U2S_BUS_ID_SIZE];
char busid[DASD_BUS_ID_SIZE];
int busid_valid;
int raw_track_access;
struct zdsroot *zdsroot;

View File

@@ -3,7 +3,6 @@ include ../common.mak
libs = $(rootdir)/libvtoc/libvtoc.a \
$(rootdir)/libzds/libzds.a \
$(rootdir)/libdasd/libdasd.a \
$(rootdir)/libu2s/libu2s.a \
$(rootdir)/libutil/libutil.a
all: fdasd

View File

@@ -397,7 +397,7 @@ static void fdasd_error(fdasd_anchor_t *anc, enum fdasd_failure why, char *str)
fputc('\n', stderr);
fputs(err_str, stderr);
fdasd_exit(anc, -1);
fdasd_exit(anc, EXIT_FAILURE);
}
/*
@@ -935,7 +935,7 @@ static void fdasd_verify_device(fdasd_anchor_t *anc, char *name)
fdasd_error(anc, device_verification_failed, err_str);
}
count = u2s_get_host_access_count(name);
count = dasd_get_host_access_count(name);
if (anc->force_host) {
if (count > 1) {
snprintf(err_str, ERROR_STRING_SIZE,
@@ -3040,5 +3040,5 @@ int main(int argc, char *argv[])
}
}
return -1;
return EXIT_FAILURE;
}

View File

@@ -20,6 +20,9 @@
#include <stdio.h>
#include <sys/ioctl.h>
/* A bus id of a DASD is 8 characters long. E.g. 0.0.4711 */
#define DASD_BUS_ID_SIZE 9
typedef struct dasd_information2_t {
unsigned int devno; /* S/390 devno */
unsigned int real_devno; /* for aliases */
@@ -51,6 +54,16 @@ typedef struct dasd_information2_t {
unsigned int reserved7; /* reserved for further use ,... */
} dasd_information2_t;
/*
* 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
struct dasd_eckd_characteristics {
unsigned short cu_type;
struct {
@@ -136,6 +149,16 @@ typedef struct format_data_t {
unsigned int intensity;
} format_data_t;
/*
* values to be used for format_data_t.intensity
*/
#define DASD_FMT_INT_FMT_R0 1 /* write record zero */
#define DASD_FMT_INT_FMT_HA 2 /* write home address, also set FMT_R0 ! */
#define DASD_FMT_INT_INVAL 4 /* invalidate tracks */
#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 */
#define DASD_FMT_INT_ESE_FULL 32 /* release space for entire volume */
/*
* struct format_check_t
* represents all data necessary to evaluate the format of
@@ -154,6 +177,16 @@ typedef struct format_check_t {
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
#ifndef __linux__
/* definition from hdreg.h */
struct hd_geometry {
@@ -178,6 +211,8 @@ struct hd_geometry {
#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)
/* Release Allocated Space */
#define BIODASDRAS _IOW(DASD_IOCTL_LETTER, 3, format_data_t)
/* Check device format according to format_data_t */
#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t)
@@ -201,6 +236,7 @@ int dasd_check_format(const char *device, format_check_t *p);
int dasd_format_disk(int fd, format_data_t *p);
int dasd_disk_disable(const char *device, int *fd);
int dasd_disk_enable(int fd);
int dasd_release_space(const char *device, format_data_t *r);
int dasd_get_blocksize(const char *device, unsigned int *blksize);
int dasd_get_blocksize_in_bytes(const char *device, unsigned long long *blksize);
int dasd_get_geo(const char *device, struct hd_geometry *geo);

View File

@@ -13,9 +13,10 @@
#define LIB_DASD_SYS_H
#include <stdio.h>
#include "u2s.h"
int dasd_sys_raw_track_access(char *);
int dasd_sys_ese(char *);
int dasd_reset_chpid(char *, char *);
int dasd_get_host_access_count(char *device);
#endif /* LIB_DASD_SYS_H */

View File

@@ -1,21 +0,0 @@
/*
*
* Copyright IBM Corp. 2004, 2017
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*
* History of changes (starts July 2004)
* 2004-07-02 initial
*/
#ifndef LIB_U2S_H
#define LIB_U2S_H
#define U2S_BUS_ID_SIZE 32
int u2s_getbusid(char *, char *);
int u2s_read_attribute(char *, char *, char *, size_t);
int u2s_get_host_access_count(char *);
#endif /* LIB_U2S_H */

View File

@@ -3,7 +3,7 @@
* @{
* @brief Work with paths
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -21,5 +21,7 @@ bool util_path_is_writable(const char *fmt, ...);
bool util_path_is_dir(const char *fmt, ...);
bool util_path_is_reg_file(const char *fmt, ...);
bool util_path_exists(const char *fmt, ...);
bool util_path_is_readonly_file(const char *fmt, ...);
bool util_path_is_writeonly_file(const char *fmt, ...);
#endif /** LIB_UTIL_PATH_H @} */

17
include/lib/util_sys.h Normal file
View File

@@ -0,0 +1,17 @@
/*
* @defgroup util_sys_h util_sys: SysFS interface
* @{
* @brief Work with SysFS
*
* Copyright IBM Corp. 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIB_UTIL_SYS_H
#define LIB_UTIL_SYS_H
int util_sys_get_dev_addr(const char *dev, char *addr);
#endif /** LIB_UTIL_SYS_H @} */

View File

@@ -228,6 +228,26 @@ int dasd_check_format(const char *device, format_check_t *p)
return 0;
}
/*
* Release Allocated Space
*
* @param[in] fd device node's file descriptor
* @param[in] r format options
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_release_space(const char *device, format_data_t *r)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDRAS, r);
dasd_close_device(fd);
return 0;
}
/*
* Reread partition table
*

View File

@@ -12,7 +12,11 @@
#include <errno.h>
#include <stdlib.h>
#include "lib/dasd_base.h"
#include "lib/dasd_sys.h"
#include "lib/util_file.h"
#include "lib/util_path.h"
#include "lib/util_sys.h"
/**
* Get raw-track access mode status
@@ -31,19 +35,59 @@
*/
int dasd_sys_raw_track_access(char *devnode)
{
char busid[9];
char path[47];
char busid[DASD_BUS_ID_SIZE];
char *path;
FILE *fp;
int rc;
if (u2s_getbusid(devnode, busid))
if (util_sys_get_dev_addr(devnode, busid) != 0)
return 0;
sprintf(path, "/sys/bus/ccw/devices/%s/raw_track_access", busid);
path = util_path_sysfs("bus/ccw/devices/%s/raw_track_access", busid);
fp = fopen(path, "r");
if (!fp)
if (!fp) {
free(path);
return 0;
}
rc = fgetc(fp) - '0';
fclose(fp);
free(path);
return (rc == 1) ? 1 : 0;
}
/**
* Is volume extent space efficient a.k.a. thin-provisioned
*
* 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
*
* @retval 1 Volume is extent space efficient
* @retval 0 Volume is not extent space efficient or
* cannot be determined
*/
int dasd_sys_ese(char *devnode)
{
char busid[DASD_BUS_ID_SIZE];
char *path;
FILE *fp;
int rc;
if (util_sys_get_dev_addr(devnode, busid) != 0)
return 0;
path = util_path_sysfs("bus/ccw/devices/%s/ese", busid);
fp = fopen(path, "r");
if (!fp) {
free(path);
return 0;
}
rc = fgetc(fp) - '0';
fclose(fp);
@@ -51,19 +95,20 @@ int dasd_sys_raw_track_access(char *devnode)
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;
char *path;
FILE *fp;
sprintf(path, "/sys/bus/ccw/devices/%s/../chpids", busid);
path = util_path_sysfs("bus/ccw/devices/%s/../chpids", busid);
*mask = 0;
fp = fopen(path, "r");
if (!fp)
if (!fp) {
free(path);
return ENODEV;
}
for (i = 0; i < 8; i++) {
count = fscanf(fp, " %x", &val);
@@ -75,6 +120,7 @@ int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask)
*mask = 0x80 >> i;
}
fclose(fp);
free(path);
return 0;
}
@@ -102,22 +148,25 @@ int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask)
int dasd_reset_chpid(char *devnode, char *chpid_char)
{
unsigned int chpid;
char path[41];
char busid[9];
char busid[DASD_BUS_ID_SIZE];
int mask, rc;
char *endptr;
char *path;
FILE *fp;
if (u2s_getbusid(devnode, busid))
if (util_sys_get_dev_addr(devnode, busid) != 0)
return ENODEV;
if (!chpid_char) {
sprintf(path, "/sys/bus/ccw/devices/%s/path_reset", busid);
path = util_path_sysfs("bus/ccw/devices/%s/path_reset", busid);
fp = fopen(path, "w");
if (!fp)
if (!fp) {
free(path);
return ENODEV;
}
fprintf(fp, "%s", "all\n");
fclose(fp);
free(path);
return 0;
}
@@ -132,12 +181,45 @@ int dasd_reset_chpid(char *devnode, char *chpid_char)
if (!mask)
return ENOENT;
sprintf(path, "/sys/bus/ccw/devices/%s/path_reset", busid);
path = util_path_sysfs("bus/ccw/devices/%s/path_reset", busid);
fp = fopen(path, "w");
if (!fp)
if (!fp) {
free(path);
return ENODEV;
}
fprintf(fp, "%02x", mask);
fclose(fp);
free(path);
return 0;
}
/**
* Read amount of host with access to \p device
*
* The \p device 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] device Device node of interest
*
* @retval n Number of hosts with access to \p device
* @retval 0 Value could not be determined
*/
int dasd_get_host_access_count(char *device)
{
char busid[9];
char *path;
long value;
if (!util_sys_get_dev_addr(device, busid))
return 0;
path = util_path_sysfs("bus/ccw/devices/%s/host_access_count", busid);
util_file_read_l(&value, 10, path);
free(path);
return value;
}

View File

@@ -1,14 +0,0 @@
include ../common.mak
lib = libu2s.a
all: $(lib)
objects = u2s.o
$(lib): $(objects)
install: all
clean:
rm -f *.o $(lib)

View File

@@ -1,334 +0,0 @@
/*
*
* Copyright IBM Corp. 2004, 2017
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*
*/
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>
#include "lib/u2s.h"
#include "lib/util_libc.h"
#define DEV_BUFFER_LENGTH 20
#define PATH_BUFFER_LENGTH 256
#define BUSIDSIZE 9
#define BLOCKPATH "/sys/block/"
#define DEVICE_LINK "device"
#define DEV_ATTRIBUTE "dev"
/*
* Helper function that expects a file name and returns 1 if this
* is a directory or 0 otherwise.
*/
static int isdir(char *name) {
struct stat statbuf;
if (stat(name, &statbuf) < 0)
return 0;
return S_ISDIR(statbuf.st_mode);
}
/*
* Helper function that expects a directory name in sysfs of the form
* /sys/block/<devname>/ or /sys/block/<devname>/<partname>/.
* It will try to read the file "dev" in this directory and compare
* it's contents with the given dev string of the form <major>:<minor>.
* Trailing white space (newline) is ignored.
* The buffer name is expected to be long enough to hold the additional "dev".
* Returns 1 if the directory matches dev, 0 otherwise.
*/
static int check_directory(char *name, char *dev) {
char buffer[DEV_BUFFER_LENGTH];
char *end;
int fd;
ssize_t count;
int dev_attr_len, dev_parm_len;
unsigned int namelen;
namelen = strlen(name);
if ((PATH_BUFFER_LENGTH - namelen) < sizeof(DEV_ATTRIBUTE))
return 0;
end = name + namelen;
strcpy(end, DEV_ATTRIBUTE);
fd = open(name, O_RDONLY);
*end = 0;
if (fd < 0)
return 0;
count = read(fd, buffer, DEV_BUFFER_LENGTH);
close(fd);
if (count < 0)
return 0;
dev_attr_len = strspn(buffer, "1234567890:");
dev_parm_len = strlen(dev);
if (dev_attr_len != dev_parm_len )
return 0;
return (strncmp(dev, buffer, dev_parm_len) == 0);
}
/*
* Helper function that expects a directory name in sysfs of the form
* /sys/block/<devname>/. It will try to read a link "device"
* in this directory and extract the busid, which is the last part
* of that link. The buffer name is expected to be long enough
* to hold the additional "device".
* name: block device path in sysfs.
* busid: buffer in which the busid string will be returned
* returns 0 for successful operation and -1 in case of an error.
*/
static int extract_busid(char *name, char *busid) {
int count;
unsigned int namelen;
char linkbuffer[PATH_BUFFER_LENGTH];
char *start, *end;
size_t len;
namelen = strlen(name);
if ((PATH_BUFFER_LENGTH - namelen) < sizeof(DEVICE_LINK))
return 0;
end = name + namelen;
strcpy(end, DEVICE_LINK);
count = readlink(name, linkbuffer, PATH_BUFFER_LENGTH - 1);
if (count < 0)
return -1;
linkbuffer[count] = 0;
start = strrchr(linkbuffer, '/');
if (!start)
return -1;
start++;
len = util_strlcpy(busid, start, BUSIDSIZE);
if (len >= BUSIDSIZE)
return -1;
return 0;
};
/*
* Helper function that makes some basic checks on a directory entry.
* The function checks if there is still enough space left in the buffer
* for the new string, excludes '.' and '..', and verifies that the entry
* is actually a directory.
* buffer: the beginning of the name buffer
* oldend: the current end of the string in the name buffer
* dir: the dirent in question
* returns: a pointer to the new end of the string in buffer or NULL if
* one of the checks failed
*/
static char *append_if_directory(char *buffer, char *oldend, struct dirent *dir) {
char *newend;
int oldlength, dirlength;
if (strcmp(dir->d_name, ".") == 0 ||
strcmp(dir->d_name, "..") == 0)
return NULL;
oldlength = strlen(buffer);
dirlength = strlen(dir->d_name);
if (PATH_BUFFER_LENGTH < oldlength + dirlength + 2)
return NULL;
strcpy(oldend, dir->d_name);
if (!isdir(buffer)) {
*oldend = 0;
return NULL;
}
newend = oldend + dirlength;
strcpy(newend, "/");
newend++;
return newend;
}
/*
* helper function that searches for a specific block device and returns
* it's busid
* dev: <major>:<minor> of the device
* busid: buffer in which the busid string will be returned
* returns 0 for successful operation and -1 in case of an error.
*/
static int find_busid_in_sysfs(char *dev, char *busid) {
DIR *blockdir, *diskdir;
struct dirent *blockde, *diskde;
int found = 0;
char namebuffer[PATH_BUFFER_LENGTH];
char *blockend, *diskend = NULL, *partend;
/* everything, including the other helper functions, works on the
* same buffer area 'namebuffer'. The pointers blockend, diskend
* and partend point to the end of the various names.
* Example:
* "/sys/block/dasda/dasda1/"
* ^ blockend
* ^ diskend
* ^ partend
*/
strcpy(namebuffer,BLOCKPATH);
blockdir = opendir(namebuffer);
if (!blockdir)
return -1;
blockend = namebuffer + strlen(namebuffer);
/* check each entry in /sys/block */
while ((blockde = readdir(blockdir))) {
diskend = append_if_directory(namebuffer, blockend, blockde);
if (!diskend)
continue;
found = check_directory(namebuffer, dev);
if (found)
break;
diskdir = opendir(namebuffer);
if (!diskdir)
continue;
/* check each entry in /sys/block/<disk name> */
while ((diskde = readdir(diskdir))) {
partend = append_if_directory(
namebuffer, diskend, diskde);
if (!partend)
continue;
found = check_directory(namebuffer, dev);
if (found)
break;
}
closedir(diskdir);
if (found)
break;
}
closedir(blockdir);
if (found) {
*diskend = 0; /* remove partition directory from name */
return extract_busid(namebuffer, busid);
} else
return -1;
}
/*
* helper function that searches for a specific block device in
* /proc/dasd/devices and returns it's bus-ID
* maja, mina: <major>, <minor> of the device
* busid: buffer in which the bus-ID string will be returned
* returns 0 for successful operation and -1 in case of an error
* e.g. /proc/dasd/devices does not exist.
*
* An entry looks like:
* 0.0.XXXX(DISCIPLINE) at ( MAJ: MIN) is dasdX :
* active at blocksize: BLOCKSIZE, BLOCKS blocks, SIZE MB
*/
static int find_busid_in_proc(int maja, int mina, char *busid)
{
FILE *filp;
char bus[BUSIDSIZE];
int majb, minb, rc;
size_t len;
rc = -1;
filp = fopen("/proc/dasd/devices", "r");
if (!filp)
return rc;
while (fscanf(filp, "%[^(] %*[^)] ) at ( %d : %d %*[^\n]\n",
bus, &majb, &minb) != EOF) {
if ((maja == majb) && (mina == minb)) {
len = util_strlcpy(busid, bus, BUSIDSIZE);
if (len < BUSIDSIZE)
rc = 0;
break;
}
}
fclose(filp);
return rc;
}
/*
* Return the busid of a given device node.
* Works only for block devices.
* devicenode: path to the device node
* busid: buffer in which the busid string will be returned
* returns 0 for successful operation and -1 in case of an error.
*/
int u2s_getbusid(char *devicenode, char *busid)
{
int maj, min, rc;
struct stat stat_buf;
char dev_string[DEV_BUFFER_LENGTH];
/*
* Get major and minor information of the device special file
* and combine them to a <maj>:<min> string, as returned by
* the dev attributes in sysfs
*/
if (stat(devicenode, &stat_buf))
return -1;
if (!S_ISBLK(stat_buf.st_mode))
return -1;
maj = major(stat_buf.st_rdev);
min = minor(stat_buf.st_rdev);
rc = find_busid_in_proc(maj, min, busid);
if (rc) {
snprintf(dev_string, DEV_BUFFER_LENGTH, "%u:%u", maj, min);
rc = find_busid_in_sysfs(dev_string, busid);
}
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;
}

View File

@@ -27,7 +27,8 @@ objects = util_base.o \
util_part.o \
util_prg.o \
util_proc.o \
util_rec.o
util_rec.o \
util_sys.o
util_base_example: util_base_example.o $(lib)
util_panic_example: util_panic_example.o $(lib)

View File

@@ -112,6 +112,12 @@ int main(int argc, char *argv[])
case OPT_NOSHORT:
printf("Specified: --noshort\n");
break;
case 'l':
printf("Specified: -l\n");
break;
case 'm':
printf("Specified: --manual\n");
break;
default:
util_opt_print_parse_error(c, argv);
return EXIT_FAILURE;

View File

@@ -3,7 +3,7 @@
*
* Work with paths
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -107,7 +107,7 @@ bool util_path_is_readable(const char *fmt, ...)
bool rc;
UTIL_VASPRINTF(&path, fmt, ap);
rc = access(path, R_OK) == 0 ? true : false;
rc = access(path, R_OK) == 0;
free(path);
return rc;
@@ -131,7 +131,7 @@ bool util_path_is_writable(const char *fmt, ...)
bool rc;
UTIL_VASPRINTF(&path, fmt, ap);
rc = access(path, W_OK) == 0 ? true : false;
rc = access(path, W_OK) == 0;
free(path);
return rc;
@@ -150,18 +150,14 @@ bool util_path_is_writable(const char *fmt, ...)
*/
bool util_path_is_reg_file(const char *fmt, ...)
{
bool rc = false;
struct stat sb;
va_list ap;
char *path;
bool rc;
UTIL_VASPRINTF(&path, fmt, ap);
if (stat(path, &sb)) {
rc = false;
goto free_str;
}
rc = (sb.st_mode & S_IFREG) ? true : false;
free_str:
if (stat(path, &sb) == 0)
rc = S_ISREG(sb.st_mode);
free(path);
return rc;
}
@@ -179,18 +175,14 @@ free_str:
*/
bool util_path_is_dir(const char *fmt, ...)
{
bool rc = false;
struct stat sb;
va_list ap;
char *path;
bool rc;
UTIL_VASPRINTF(&path, fmt, ap);
if (stat(path, &sb)) {
rc = false;
goto free_str;
}
rc = (sb.st_mode & S_IFDIR) ? true : false;
free_str:
if (stat(path, &sb) == 0)
rc = S_ISDIR(sb.st_mode);
free(path);
return rc;
}
@@ -213,7 +205,62 @@ bool util_path_exists(const char *fmt, ...)
bool rc;
UTIL_VASPRINTF(&path, fmt, ap);
rc = access(path, F_OK) == 0 ? true : false;
rc = access(path, F_OK) == 0;
free(path);
return rc;
}
/**
* Test if path exists, is a regular file, and permission is read-only
*
* @param[in] fmt Format string for path to test
* @param[in] ... Variable arguments for format string
*
* @returns true Path exists, is a regular file, and permission does
* not allow any write but allows read
* false Otherwise
*/
bool util_path_is_readonly_file(const char *fmt, ...)
{
bool rc = false;
struct stat sb;
va_list ap;
char *path;
UTIL_VASPRINTF(&path, fmt, ap);
if (stat(path, &sb) == 0) {
rc = S_ISREG(sb.st_mode) &&
(sb.st_mode & 0222) == 0 &&
(sb.st_mode & 0444) != 0;
}
free(path);
return rc;
}
/**
* Test if path exists, is a regular file, and permission is write-only
*
* @param[in] fmt Format string for path to test
* @param[in] ... Variable arguments for format string
*
* @returns true Path exists, is a regular file, and permission does
* not allow any read but allows write
* false Otherwise
*/
bool util_path_is_writeonly_file(const char *fmt, ...)
{
bool rc = false;
struct stat sb;
va_list ap;
char *path;
UTIL_VASPRINTF(&path, fmt, ap);
if (stat(path, &sb) == 0) {
rc = S_ISREG(sb.st_mode) &&
(sb.st_mode & 0222) != 0 &&
(sb.st_mode & 0444) == 0;
}
free(path);
return rc;
}

View File

@@ -1,7 +1,7 @@
/**
* util_path_example - Example program for util_path
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -13,6 +13,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "lib/util_path.h"
#include "lib/util_prg.h"
@@ -26,7 +27,7 @@ const struct util_prg prg = {
{
.owner = "IBM Corp.",
.pub_first = 2001,
.pub_last = 2017,
.pub_last = 2019,
},
UTIL_PRG_COPYRIGHT_END
}
@@ -72,9 +73,17 @@ static void test_path(const char *path)
else
printf("reg_file=no ");
if (util_path_is_dir(path))
printf("dir=yes");
printf("dir=yes ");
else
printf("dir=no ");
printf("dir=no ");
if (util_path_is_readonly_file(path))
printf("read-only_file=yes ");
else
printf("read-only_file=no ");
if (util_path_is_writeonly_file(path))
printf("write-only_file=yes");
else
printf("write-only_file=no ");
printf("\n");
}

77
libutil/util_sys.c Normal file
View File

@@ -0,0 +1,77 @@
/*
* util - Utility function library
*
* SysFS helper functions
*
* Copyright IBM Corp. 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h>
#include "lib/util_path.h"
#include "lib/util_sys.h"
/* lstat() doesn't work for sysfs files, a fixed size is therefore inevitable */
#define READLINK_SIZE 256
/**
* Identify device address
*
* Identifying the device address with this function works for almost any
* character and block device (e.g. NVMe, SCSI, DASD, etc).
* The user must provide a buffer that is large enough for the desired device
* address to be read into \p addr.
*
* @param[in] dev Device node of interest
* @param[out] addr Identified device address
*
* @retval 0 Success
* @retval -1 Error while reading device information or
* constructed path
*/
int util_sys_get_dev_addr(const char *dev, char *addr)
{
char device[READLINK_SIZE], *result;
unsigned int maj, min;
struct stat s;
ssize_t len;
char *path;
if (stat(dev, &s) != 0)
return -1;
maj = major(s.st_rdev);
min = minor(s.st_rdev);
if (S_ISBLK(s.st_mode))
path = util_path_sysfs("dev/block/%u:%u/device", maj, min);
else if (S_ISCHR(s.st_mode))
path = util_path_sysfs("dev/char/%u:%u/device", maj, min);
else
return -1;
len = readlink(path, device, READLINK_SIZE - 1);
free(path);
if (len != -1)
device[len] = '\0';
else
return -1;
result = strrchr(device, '/');
if (result)
result++;
else
result = device;
strcpy(addr, result);
return 0;
}

View File

@@ -20,8 +20,8 @@
#include <stdlib.h>
#include "lib/dasd_base.h"
#include "lib/dasd_sys.h"
#include "lib/libzds.h"
#include "lib/u2s.h"
#include "lib/vtoc.h"
/** @cond PRIVATE */
@@ -3701,7 +3701,7 @@ int lzds_analyse_open_count(struct zdsroot *root, int warn)
int rc = 0;
util_list_iterate(root->dasdlist, dasd) {
value = u2s_get_host_access_count(dasd->device);
value = dasd_get_host_access_count(dasd->device);
if (value < 0) {
fprintf(stderr,

View File

@@ -173,6 +173,9 @@ readonly OUTPUT_FILE_LSOF="${WORKPATH}open_files.out"
# File that includes content of OSA OAT
readonly OUTPUT_FILE_OSAOAT="${WORKPATH}osa_oat"
# File that includes content of Ethtool commands
readonly OUTPUT_FILE_ETHTOOL="${WORKPATH}ethtool.out"
# File that includes the output of journalctl
readonly OUTPUT_FILE_JOURNALCTL="${WORKPATH}journalctl.out"
@@ -192,7 +195,7 @@ readonly OUTPUT_FILE_NVME="${WORKPATH}nvme.out"
readonly MOUNT_POINT_DEBUGFS="/sys/kernel/debug"
# The amount of steps running the whole collections
readonly COLLECTION_COUNT=12
readonly COLLECTION_COUNT=13
# The kernel version (e.g. '2' from 2.6.32 or '3' from 3.2.1)
readonly KERNEL_VERSION=$(uname -r 2>/dev/null | cut -d'.' -f1)
@@ -470,6 +473,10 @@ CMDS="uname -a\
:docker version\
:docker stats --no-stream\
:systemctl status docker.service\
:blockdev --report\
:lvdisplay\
:lspci -vv\
:smc_dbg\
"
########################################
@@ -748,6 +755,37 @@ collect_osaoat() {
pr_log_stdout " "
}
########################################
collect_ethtool() {
local network_devices
local network_device
network_devices=$(ls /sys/class/net 2>/dev/null)
if which ethtool >/dev/null 2>&1; then
if test -n "${network_devices}"; then
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting ethtool output"
for network_device in ${network_devices}; do
call_run_command "ethtool ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -k ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -a ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -c ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -g ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -i ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -l ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -P ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -S ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -T ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
done
else
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting ethtool output skipped - no devices"
fi
else
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting ethtool output skipped - not available"
fi
pr_log_stdout " "
}
########################################
# OpenVSwitch
collect_ovs() {
@@ -764,7 +802,7 @@ collect_ovs() {
:ovsdb-client dump\
"
if test -n "${br_list}"; then
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting OpenVSwitch output"
pr_syslog_stdout "9 of ${COLLECTION_COUNT}: Collecting OpenVSwitch output"
IFS=:
for ovscmd in ${ovscmds}; do
IFS=${ifs_orig} call_run_command "${ovscmd}" "${OUTPUT_FILE_OVS}.out"
@@ -783,7 +821,7 @@ collect_ovs() {
IFS="${ifs_orig}"
done
else
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting OpenVSwitch output skipped"
pr_syslog_stdout "9 of ${COLLECTION_COUNT}: Collecting OpenVSwitch output skipped"
fi
pr_log_stdout " "
@@ -796,12 +834,12 @@ collect_domain_xml() {
domain_list=$(virsh list --all --name)
if test -n "${domain_list}"; then
pr_syslog_stdout "9 of ${COLLECTION_COUNT}: Collecting domain xml files"
pr_syslog_stdout "10 of ${COLLECTION_COUNT}: Collecting domain xml files"
for domain in ${domain_list}; do
call_run_command "virsh dumpxml ${domain}" "${OUTPUT_FILE_XML}_${domain}.xml"
done
else
pr_syslog_stdout "9 of ${COLLECTION_COUNT}: Collecting domain xml files skipped"
pr_syslog_stdout "10 of ${COLLECTION_COUNT}: Collecting domain xml files skipped"
fi
pr_log_stdout " "
@@ -815,23 +853,23 @@ collect_docker() {
# 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"
pr_syslog_stdout "11a 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"
pr_syslog_stdout "11a 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"
pr_syslog_stdout "11b 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"
pr_syslog_stdout "11b of ${COLLECTION_COUNT}: Collecting docker network output skipped"
fi
pr_log_stdout " "
@@ -841,7 +879,7 @@ collect_docker() {
collect_nvme() {
local NVME
pr_syslog_stdout "11 of ${COLLECTION_COUNT}: Collecting nvme output"
pr_syslog_stdout "12 of ${COLLECTION_COUNT}: Collecting nvme output"
call_run_command "nvme list" "${OUTPUT_FILE_NVME}"
for NVME in /dev/nvme[0-9]*; do
@@ -1148,6 +1186,8 @@ collect_configfiles
collect_osaoat
collect_ethtool
collect_ovs
collect_domain_xml

View File

@@ -52,7 +52,7 @@ Sample invocation:
.br
dbginfo.sh: Debug information script version %S390_TOOLS_VERSION%
.br
Copyright IBM Corp. 2002, 2017
Copyright IBM Corp. 2002, 2019
.PP
Hardware platform = s390x
.br
@@ -60,34 +60,40 @@ Kernel version = <kernel\-version>
.br
Runtime environment = z/VM
.PP
1 of 11: Collecting command output
1 of 13: Collecting command output
.PP
2 of 11: Collecting z/VM command output
2 of 13: Collecting z/VM command output
.PP
3 of 11: Collecting procfs
3 of 13: Collecting procfs
.PP
4 of 11: Collecting sysfs
4 of 13: Collecting sysfs
.PP
5 of 11: Collecting log files
5 of 13: Collecting log files
.PP
6 of 11: Collecting config files
6 of 13: Collecting config files
.PP
7 of 11: Collecting osa oat output skipped \- not available
7 of 13: Collecting osa oat output skipped \- not available
.PP
8 of 11: Collecting OpenVSwitch output
8 of 13: Collecting ethtool output
.PP
9 of 11: Collecting domain xml files
9 of 13: Collecting OpenVSwitch output
.PP
10a of 11: Collecting docker container output
10b of 11: Collecting docker network output
10 of 13: Collecting domain xml files
.PP
11 of 11: Postprocessing
11a of 13: Collecting docker container output
11b of 13: Collecting docker network output
.PP
12 of 13: Collecting nvme output
.PP
13 of 13: Postprocessing
.PP
Finalizing: Creating archive with collected data
.PP
Collected data was saved to:
.br
>> /data\-collection/DBGINFO\-2015\-02\-26\-21\-39\-16\-host\-012345.tgz <<
>> /data\-collection/DBGINFO\-2019\-08\-19\-21\-39\-16\-host\-012345.tgz <<
.br
Review the collected data before sending to your service organization.
.SH HINTS
Run the script with root authority.
.br

View File

@@ -291,6 +291,13 @@ sub get_payload_records
my $area = str_from_hex(substr($record[2], 2, 14));
my $counter = hex(substr($record[2], 0, 2));
my $fsf_req_id = substr($record[2], 16, 16);
# ($counter == 0) is just a simple heuristic which can fail if
# there are missing payload record junks due to PAY area wrap!
if ($counter == 0 &&
defined($PAYLOAD_RECORDS{$fsf_req_id}{$area})) {
print "Warning: Ambiguous PAYload records. reqid:" .
$fsf_req_id . " area:" . $area . "\n";
}
$PAYLOAD_RECORDS{$fsf_req_id}{$area}[$counter] = [@record];
if ($def_error && ($area =~ /def_err/)) {
$def_error{$fsf_req_id}[$counter] = [@record];
@@ -515,11 +522,16 @@ sub print_payload
my $field_name = shift();
my $tmp_str;
if ($payload) {
# workaround to let user determine ambiguous PAYload records
printf "%-14s : %s\n", "Payload time", $payload->[0]->[0];
}
printf "%-14s : ", $field_name;
if (!$payload) {
print "record not available anymore.\n";
return;
}
# TODO: iterate with $counter loop and notify user about missing junks
foreach my $cc (@$payload) {
$tmp_str .= substr($cc->[2], 32);
}

View File

@@ -3,7 +3,6 @@ include ../../common.mak
ALL_CPPFLAGS += -I../include -I../boot
libs = $(rootdir)/libdasd/libdasd.a \
$(rootdir)/libu2s/libu2s.a \
$(rootdir)/libutil/libutil.a
all: tunedasd

View File

@@ -3,7 +3,7 @@
*
* Provide main function and command line parsing.
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -57,7 +57,7 @@ const struct util_prg prg = {
{
.owner = "IBM Corp.",
.pub_first = 2016,
.pub_last = 2017,
.pub_last = 2019,
},
UTIL_PRG_COPYRIGHT_END
}
@@ -236,7 +236,7 @@ static char *get_chp_dir(int css, int id)
char *path;
path = util_path_sysfs("devices/css%x/chp%x.%x", css, css, id);
if ((stat(path, &sb) == 0) && (sb.st_mode == S_IFDIR))
if ((stat(path, &sb) == 0) && S_ISDIR(sb.st_mode))
return path;
free(path);
return util_path_sysfs("devices/css%x/chp%x.%02x", css, css, id);
@@ -296,7 +296,7 @@ static void perform_command(int css, int id)
char *path;
path = get_chp_dir(css, id);
if ((stat(path, &sb) != 0) || ((sb.st_mode & S_IFMT) != S_IFDIR)) {
if ((stat(path, &sb) != 0) || !S_ISDIR(sb.st_mode)) {
printf("Skipping unknown channel-path %x.%02x\n", css, id);
goto out_free_path;
}

View File

@@ -11,10 +11,24 @@ lschp \- list information about available channel\-paths.
.B lschp
.RB [ \-h|\-\-help ]
.RB [ \-v|\-\-version ]
.RB [
.I CHPID
]
.SH DESCRIPTION
The lschp command lists status and type information about available
channel\-paths.
channel\-paths. A
.I CHPID
argument can be specified to return the information for the respective
channel-path identifier only.
Channel\-path identifiers are specified in hexadecimal notation either simply
as the CHPID\-number (e.g. e0) or in the form
.RS
<cssid>.<id>
.RE
where <cssid> is the channel\-subsystem identifier and <id> is the CHPID\-number (e.g. 0.7e).
.B Column description:

View File

@@ -3,7 +3,7 @@
*
* Provide main function and command line parsing.
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -12,6 +12,7 @@
#include <err.h>
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
#include "lib/util_base.h"
#include "lib/util_file.h"
@@ -31,7 +32,7 @@ static const struct util_prg prg = {
{
.owner = "IBM Corp.",
.pub_first = 2016,
.pub_last = 2017,
.pub_last = 2019,
},
UTIL_PRG_COPYRIGHT_END
}
@@ -55,9 +56,10 @@ static struct util_opt opt_vec[] = {
* @param[in] dir Path of the desired directory
* @param[in] css_id ID for device identification
* @param[in] rec The buffer structure, where results are written to
* @param[in] chp If set: CHPID to filter by
*/
static void print_chpid(const char *chp_dir, unsigned int css_id,
struct util_rec *rec)
struct util_rec *rec, char *chp)
{
unsigned int css_id_tmp, chp_id;
bool chid_external;
@@ -123,7 +125,8 @@ static void print_chpid(const char *chp_dir, unsigned int css_id,
} else {
util_rec_set(rec, "pchid", "%s", "-");
}
util_rec_print(rec);
if (!strlen(chp) || strcmp(util_rec_get(rec, "chpid"), chp) == 0)
util_rec_print(rec);
free(path);
}
@@ -153,8 +156,9 @@ static int chpsort(const struct dirent **de1, const struct dirent **de2)
*
* @param[in] css_dir The desired directory
* @param[in] rec The buffer structure, where results are written to
* @param[in] chp If set: CHPID to filter by
*/
static void print_css(const char *css_dir, struct util_rec *rec)
static void print_css(const char *css_dir, struct util_rec *rec, char *chp)
{
struct dirent **de_vec;
unsigned int css_id;
@@ -167,15 +171,17 @@ static void print_css(const char *css_dir, struct util_rec *rec)
path = util_path_sysfs("devices/css%d", css_id);
count = util_scandir(&de_vec, chpsort, path, "chp%x.*", css_id);
for (i = 0; i < count; i++)
print_chpid(de_vec[i]->d_name, css_id, rec);
print_chpid(de_vec[i]->d_name, css_id, rec, chp);
util_scandir_free(de_vec, count);
free(path);
}
/*
* Print chpid table
*
* @param[in] chp If set: CHPID to filter by
*/
static void cmd_lschp(void)
static void cmd_lschp(char *chp)
{
struct dirent **de_vec;
struct util_rec *rec;
@@ -198,17 +204,19 @@ static void cmd_lschp(void)
path = util_path_sysfs("devices");
count = util_scandir(&de_vec, alphasort, path, "^css[[:xdigit:]]{1,2}$");
for (i = 0; i < count; i++)
print_css(de_vec[i]->d_name, rec);
print_css(de_vec[i]->d_name, rec, chp);
util_ptr_vec_free((void **) de_vec, count);
free(path);
util_rec_free(rec);
}
#define CHP_LEN 4
/*
* Parse options and execute the command
*/
int main(int argc, char *argv[])
{
char chp[CHP_LEN + 1] = "";
int c;
util_prg_init(&prg);
@@ -231,10 +239,30 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
}
if (argc > optind) {
util_prg_print_arg_error(argv[optind]);
return EXIT_FAILURE;
if (argc > optind + 1)
errx(EXIT_FAILURE, "Too many arguments specified");
if (argc == optind + 1) {
/* we take a single argument only */
switch (strlen(argv[optind])) {
case 1:
sprintf(chp, "0.0%s", argv[optind]);
break;
case 2:
sprintf(chp, "0.%s", argv[optind]);
break;
case CHP_LEN:
strcpy(chp, argv[optind]);
break;
default:
errx(EXIT_FAILURE, "%s is not a valid channel-path ID",
argv[optind]);
}
if (!isdigit(chp[0]) || chp[1] != '.' || !isxdigit(chp[2]) ||
!isxdigit(chp[3]))
errx(EXIT_FAILURE, "%s is not a valid channel-path ID",
chp);
}
cmd_lschp();
cmd_lschp(chp);
return EXIT_SUCCESS;
}

View File

@@ -164,6 +164,7 @@ function gatherDeviceData() {
read DEV_UID 2> /dev/null < $DEVPATH/uid || continue
read READONLY 2> /dev/null < $DEVPATH/readonly || continue
read DISCIPLINE 2> /dev/null < $DEVPATH/discipline || continue
read ESE 2> /dev/null < $DEVPATH/ese
# Block device specific information is only available for
# devices that are online and not a PAV alias
@@ -244,7 +245,7 @@ function newoutput()
#-------------------------------------------#
if [[ "$ONLINE" == 0 ]]; then
printf "%s:%s:%-8s offline\n" \
printf "%s:%s:%-8s offline\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" ;
return
@@ -252,7 +253,7 @@ function newoutput()
if [[ "$ALIAS" == 1 ]]; then
if [[ "$BASEONLY" == "false" ]]; then
printf "%s:%s:%-8s alias %28s\n" \
printf "%s:%s:%-8s alias %26s\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$DISCIPLINE"
@@ -286,7 +287,11 @@ function newoutput()
ACTIVE="active"
fi
printf "%s:%s:%-8s %-6s%-4s %-8s %-2s:%-2s %-4s %-4s %-8s %s\n" \
if [[ "$ESE" == 1 ]]; then
DISCIPLINE="${DISCIPLINE} (ESE)"
fi
printf "%s:%s:%-8s %-6s%-2s %-8s %-2s:%-2s %-11s %-4s %-8s %s\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$ACTIVE" \
@@ -378,6 +383,10 @@ function extended()
read OPM NPPM CABLEPM CUIRPM HPFPM IFCCPM 2> /dev/null < $DEVPATH/path_masks
read -a C 2> /dev/null < $DEVPATH/../chpids
read PIM PAM POM 2> /dev/null < $DEVPATH/../pimpampom
read ESE 2> /dev/null < $DEVPATH/ese
read EXTSZ 2> /dev/null < $DEVPATH/extent_pool/extent_size
read CAPACITY 2> /dev/null < $DEVPATH/capacity/logical_capacity
read ALLOCATED 2> /dev/null < $DEVPATH/capacity/space_allocated
# convert to hexadecimal values
PIM=0x$PIM
@@ -550,7 +559,11 @@ 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# 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" \
if [[ "$ESE" == 1 ]]; then
DISCIPLINE="${DISCIPLINE} (ESE)"
fi
printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# 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" \
@@ -562,6 +575,9 @@ function extended()
"$SSIZE" \
"$MBSIZE" \
"$BLOCKCOUNT" \
"$EXTSZ" \
"$CAPACITY" \
"$ALLOCATED" \
"$DIAG" \
"$READONLY" \
"$EER" \
@@ -787,10 +803,10 @@ fi
if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then
printf "Bus-ID Name UID\n"
printf "==============================================================================\n"
printf "================================================================================\n"
elif [[ "$OUTPUT" == "new" ]]; then
printf "Bus-ID Status Name Device Type BlkSz Size Blocks\n"
printf "==============================================================================\n"
printf "Bus-ID Status Name Device Type BlkSz Size Blocks\n"
printf "================================================================================\n"
elif [[ "$OUTPUT" == "extended" ]]; then
PROCESSING=" $PROCESSING | sed 's/#/\n/g' "
fi

View File

@@ -2,7 +2,7 @@
#
# lszfcp - Tool to display information about zfcp devices (adapters/ports/units)
#
# Copyright IBM Corp. 2006, 2017
# Copyright IBM Corp. 2006, 2019
#
# s390-tools is free software; you can redistribute it and/or modify
# it under the terms of the MIT license. See LICENSE for details.
@@ -14,10 +14,13 @@ FC_CLASS=false
# Command line parameters
VERBOSITY=0
SHOW_MODPARMS=0
SHOW_HOSTS=0
SHOW_PORTS=0
SHOW_DEVICES=0
SHOW_ATTRIBUTES=false
SHOW_MORE_ATTRS=0
SHOW_EXTENDED=false
unset PAR_BUSID PAR_WWPN PAR_LUN
@@ -26,8 +29,8 @@ unset PAR_BUSID PAR_WWPN PAR_LUN
check_sysfs()
{
if [ -z $SYSFS -o ! -d $SYSFS -o ! -r $SYSFS ]; then
echo "Error: sysfs not available."
exit 1
echo "Error: sysfs not available."
exit 1
fi
}
@@ -43,13 +46,36 @@ check_zfcp_support()
check_fcp_devs()
{
local found=0
if $FC_CLASS; then
# theoretically this includes "defunct" (and thus online) devs
ignore=`ls $SYSFS/class/fc_host/host* 2>&1`
else
ignore=`ls $SYSFS/devices/css0/[0-9]*/[0-9]*/host[0-9]* 2>&1`
fi
[ $? -eq 0 ] && found=1
if [ $? -ne 0 ]; then
if [ $found -eq 0 ] && $SHOW_EXTENDED; then
# nothing found yet so search for "defunct" FCP devices
ignore=$(ls -dX $SYSFS/devices/css[0-9]*/defunct/[0-9]*/host[0-9]* 2>&1)
[ $? -eq 0 ] && found=1
fi
if [ $found -eq 0 ] && $SHOW_EXTENDED; then
local mypath mylist=""
# nothing found yet so search for FCP devices never been online
for mypath in $SYSFS/bus/ccw/drivers/zfcp/*.*.*; do
if [ "$mypath" = "$SYSFS/bus/ccw/drivers/zfcp/*.*.*" ];
then
break # glob did not match anything
fi
[ -d $mypath/host[0-9]* ] && continue # is/was online
mylist="$mylist $(readlink -e $mypath)/-"
done
[ -n "$mylist" ] && found=1
fi
if [ $found -eq 0 ]; then
echo "Error: No fcp devices found."
exit 1
fi
@@ -57,7 +83,7 @@ check_fcp_devs()
check_fc_class()
{
if [ -d "$SYSFS/class/fc_host" ]; then
if [ -d "$SYSFS/class/fc_host" ]; then
FC_CLASS=true
fi
}
@@ -66,7 +92,7 @@ print_version()
{
cat <<EOF
$SCRIPTNAME: version %S390_TOOLS_VERSION%
Copyright IBM Corp. 2006, 2017
Copyright IBM Corp. 2006, 2019
EOF
}
@@ -84,18 +110,24 @@ OPTIONS:
-H, --hosts show host information (default)
-P, --ports show remote port information
-D, --devices show SCSI device information
-Z, --modparms show zfcp (module) parameters
-b, --busid=BUSID select specific busid
-p, --wwpn=WWPN select specific port name
-l, --lun=LUN select specific LUN
-a, --attributes show all attributes
-a, --attributes show attributes
-m, --moreattrs show more attributes
(host: css; port: zfcp_port; SCSI device: zfcp_unit)
specify twice to show more attributes for SCSI devices
(scsi_disk,block,integrity,queue,iosched)
-V, --verbose show sysfs paths of associated class
and bus devices
-e, --extended extended output format
-s, --sysfs=PATH use path as sysfs (for dbginfo archives)
-h, --help print this help
-v, --version print version information
EXAMPLE:
List for all zfcp adapters, ports and units the names of their
EXAMPLE:
List for all zfcp adapters, ports and units the names of their
associated SCSI hosts, FC remote ports and SCSI devices.
#> lszfcp -P -H -D
@@ -129,29 +161,95 @@ show_attributes()
}
show_modparms()
{
local modparmdir=$SYSFS/module/zfcp/parameters
[ -d "$modparmdir" ] || return
if [ $VERBOSITY -ne 0 ]; then
echo "$modparmdir"
fi
echo 'Module = "zfcp"'
show_attributes "$modparmdir"
echo
}
show_hosts()
{
HOST_LIST=`ls -dX $SYSFS/devices/css0/[0-9]*/[0-9]*/host[0-9]*`
HOST_LIST=`ls -dX $SYSFS/devices/css0/[0-9]*/[0-9]*/host[0-9]* \
2> /dev/null`
if $SHOW_EXTENDED; then
# add all "defunct" FCP devices
HOST_LIST="$HOST_LIST
$(ls -dX $SYSFS/devices/css[0-9]*/defunct/[0-9]*/host[0-9]* 2>/dev/null)"
# add all FCP devices that have never been online
for HOST_PATH in $SYSFS/bus/ccw/drivers/zfcp/*.*.*; do
[ -d $HOST_PATH/host[0-9]* ] && continue # is/was online
HOST_LIST="$HOST_LIST
$(readlink -e $HOST_PATH)/-"
done
fi
for HOST_PATH in $HOST_LIST; do
SCSI_HOST=`basename $HOST_PATH`
ADAPTER_PATH=`dirname $HOST_PATH`
ADAPTER=`basename $ADAPTER_PATH`
[ $ADAPTER != ${PAR_BUSID:-$ADAPTER} ] && continue
read ONLINE < $ADAPTER_PATH/online
read AVAILABILITY < $ADAPTER_PATH/availability
[ -r $ADAPTER_PATH/failed ] && read FAILED < $ADAPTER_PATH/failed
DEFUNCT=${ADAPTER_PATH%/*} # strip devbusid
DEFUNCT=${DEFUNCT##*/} # basename
HOSTMARKER=""
if $SHOW_EXTENDED; then
if [ "$DEFUNCT" = "defunct" ]; then
HOSTMARKER=" defunct"
elif [ "$ONLINE" = "0" ]; then
HOSTMARKER=" offline"
elif [ "$FAILED" = "1" ]; then
HOSTMARKER=" failed"
elif [ "$AVAILABILITY" != "good" ]; then
HOSTMARKER=" NotAvailable"
fi
fi
if [ $VERBOSITY -eq 0 ]; then
echo $ADAPTER $SCSI_HOST
echo $ADAPTER $SCSI_HOST$HOSTMARKER
else
echo $ADAPTER_PATH
$FC_CLASS && echo "$SYSFS/class/fc_host/$SCSI_HOST"
echo "$SYSFS/class/scsi_host/$SCSI_HOST"
echo $ADAPTER_PATH$HOSTMARKER
if [ "$SCSI_HOST" != "-" ]; then
$FC_CLASS && echo "$SYSFS/class/fc_host/$SCSI_HOST"
echo "$SYSFS/class/scsi_host/$SCSI_HOST"
else
echo "-"
echo "-"
fi
fi
if $SHOW_ATTRIBUTES; then
if [ $SHOW_MORE_ATTRS -ge 1 ]; then
echo 'Bus = "css"'
if [ "$DEFUNCT" = "defunct" ]; then
printf " %-19s\n" "defunct"
else
show_attributes ${ADAPTER_PATH%/*}
fi
fi
echo 'Bus = "ccw"'
show_attributes $ADAPTER_PATH
if [ "$SCSI_HOST" = "-" ]; then
# skip output of non-existent fc_host & scsi_host
echo
continue
fi
if $FC_CLASS; then
echo 'Class = "fc_host"'
show_attributes \
@@ -175,7 +273,7 @@ show_ports()
for PORT_PATH in $PORT_LIST; do
WWPN=`basename $PORT_PATH`
ADAPTER=`basename \`dirname $PORT_PATH\``
[ $WWPN != ${PAR_WWPN:-$WWPN} ] && continue
[ $ADAPTER != ${PAR_BUSID:-$ADAPTER} ] && continue
@@ -196,30 +294,60 @@ show_ports()
for FC_PORT_PATH in $PORT_LIST; do
PORT=`basename $FC_PORT_PATH`
read PORT_STATE < $FC_PORT_PATH/port_state
if [ "$PORT_STATE" == "Online" ];
then
if [ "$PORT_STATE" == "Online" ] || $SHOW_EXTENDED; then
read WWPN < $FC_PORT_PATH/port_name
else
continue
fi
PORTSTATEMARKER=""
$SHOW_EXTENDED && [ "$PORT_STATE" != "Online" ] \
&& PORTSTATEMARKER=" NotOnline"
[ $WWPN != ${PAR_WWPN:-$WWPN} ] && continue
ADAPTER_PORT_PATH=`ls -d \
$SYSFS/devices/css0/*/*/$WWPN/../host[0-9]*/$PORT |\
awk -F "/../host" '{ print $1 }'`
ADAPTER=`basename \`dirname $ADAPTER_PORT_PATH\``
local sysreal=$(readlink -e "$FC_PORT_PATH")
local ADAPTER=""
while [ -n "$sysreal" ]; do
# ascend to parent: strip last path part
sysreal=${sysreal%/*}
[ -h $sysreal/subsystem ] || continue
local subsystem=$(readlink -e $sysreal/subsystem)
if [ "${subsystem##*/}" = "ccw" ]; then
ADAPTER=${sysreal##*/}
break
fi
done
[ -z "$ADAPTER" ] && continue # skip not zfcp-attached ones
if [ -d $SYSFS/devices/css[0-9]*/[0-9d]*/[0-9]*/$WWPN/../host[0-9]*/$PORT ];
then
ADAPTER_PORT_PATH=$SYSFS/devices/css[0-9]*/[0-9d]*/$ADAPTER/$WWPN
else
ADAPTER_PORT_PATH="-"
fi
[ $ADAPTER != ${PAR_BUSID:-$ADAPTER} ] && continue
if [ $VERBOSITY -eq 0 ]; then
echo "$ADAPTER/$WWPN $PORT"
echo "$ADAPTER/$WWPN $PORT$PORTSTATEMARKER"
else
echo $ADAPTER_PORT_PATH
echo $FC_PORT_PATH
if [ "$ADAPTER_PORT_PATH" != "-" ]; then
echo $ADAPTER_PORT_PATH
else
echo "- (NoMoreZfcpPort:$ADAPTER/$WWPN)"
fi
echo $FC_PORT_PATH$PORTSTATEMARKER
fi
if $SHOW_ATTRIBUTES; then
if [ $SHOW_MORE_ATTRS -ge 1 ] \
&& [ "$ADAPTER_PORT_PATH" != "-" ] \
&& [ -d $ADAPTER_PORT_PATH ];
then
# fc_rport can exist without zfcp_port
# (e.g. after port_remove)
echo 'Class = "zfcp_port"'
show_attributes "$ADAPTER_PORT_PATH"
fi
echo 'Class = "fc_remote_ports"'
show_attributes "$FC_PORT_PATH"
echo
@@ -234,54 +362,166 @@ show_devices()
if $FC_CLASS; then
SCSI_DEVICE_LIST=`ls -d \
$SYSFS/bus/ccw/drivers/zfcp/*/host*/rport*/target*/*/ \
2>/dev/null |grep -P '\d+:\d+:\d+:\d+'`
2>/dev/null |grep -P '\d+:\d+:\d+:\d+'`
else
SCSI_DEVICE_LIST=`ls -d $SYSFS/devices/css0/*/*/host[0-9]*/*/`
fi
if [ -z "$SCSI_DEVICE_LIST" ]; then
echo "Error: No fcp devices found."
if $SHOW_EXTENDED; then
ZFCP_UNIT_LIST=$(ls -d \
$SYSFS/devices/css[0-9]*/[0-9d]*/[0-9]*/0x*/0x* \
2> /dev/null)
else
ZFCP_UNIT_LIST=""
fi
if [ -z "$SCSI_DEVICE_LIST" ] && [ -z "$ZFCP_UNIT_LIST" ]; then
if $SHOW_EXTENDED; then
echo "Error: No zfcp-attached SCSI devices found."
else
echo "Error: No fcp devices found."
fi
fi
for SCSI_DEVICE_PATH in $SCSI_DEVICE_LIST; do
read ADAPTER < $SCSI_DEVICE_PATH/hba_id
read WWPN < $SCSI_DEVICE_PATH/wwpn
read LUN < $SCSI_DEVICE_PATH/fcp_lun
# remove from ZFCP_UNIT_LIST if SCSI device exists
REDUCED_LIST=""
for UNIT_PATH in $ZFCP_UNIT_LIST; do
STRIPPED_PATH=$UNIT_PATH
L=${UNIT_PATH##*/}
STRIPPED_PATH=${STRIPPED_PATH%/*}
W=${STRIPPED_PATH##*/}
STRIPPED_PATH=${STRIPPED_PATH%/*}
A=${STRIPPED_PATH##*/}
[ "$A/$W/$L" = "$ADAPTER/$WWPN/$LUN" ] && continue
REDUCED_LIST="$REDUCED_LIST $UNIT_PATH"
done
ZFCP_UNIT_LIST="$REDUCED_LIST"
[ $LUN != ${PAR_LUN:-$LUN} ] && continue
[ $WWPN != ${PAR_WWPN:-$WWPN} ] && continue
[ $ADAPTER != ${PAR_BUSID:-$ADAPTER} ] && continue
ZFCP_UNIT_PATH=$SYSFS/devices/css[0-9]*/[0-9d]*/$ADAPTER/$WWPN/$LUN
SDEVMARKER=""
if $SHOW_EXTENDED; then
[ -d $ZFCP_UNIT_PATH ] || SDEVMARKER="$SDEVMARKER auto"
[ -r $SCSI_DEVICE_PATH/state ] \
&& read SDEVSTATE < $SCSI_DEVICE_PATH/state
[ "$SDEVSTATE" != "running" ] \
&& SDEVMARKER="$SDEVMARKER NotRunning"
fi
if [ $VERBOSITY -eq 0 ]; then
echo "$ADAPTER/$WWPN/$LUN `basename $SCSI_DEVICE_PATH`$SDEVMARKER"
else
echo "`ls -d $SYSFS/devices/css0/[0-9d]*/$ADAPTER`/$WWPN/$LUN"
echo ${SCSI_DEVICE_PATH%*/}$SDEVMARKER # without trailing slash
# On live systems, there are links to the block and
# generic devices. In a dbginfo archive, these links
# are not present. Therefore, fall back to reading
# the runtime.out log file.
if [ `ls $SCSI_DEVICE_PATH | grep -c block:` -eq 1 ]
then
BLOCK_DEV=`ls $SCSI_DEVICE_PATH | grep block:`
GEN_DEV=`ls $SCSI_DEVICE_PATH |\
grep scsi_generic:`
echo -n "$SYSFS/block/${BLOCK_DEV#*:} "
echo "$SYSFS/class/scsi_generic/${GEN_DEV#*:}"
elif [ -d $SCSI_DEVICE_PATH/block ] && $SHOW_EXTENDED
then
# case without CONFIG_SYSFS_DEPRECATED
BLOCK_DEV=$(echo $SCSI_DEVICE_PATH/block/*)
BLOCK_DEV=${BLOCK_DEV##*/}
echo -n "$SYSFS/block/$BLOCK_DEV "
local SGPATH=$SCSI_DEVICE_PATH/scsi_generic
if [ -d $SGPATH ]; then
GEN_DEV=$(echo $SGPATH/*)
GEN_DEV=${GEN_DEV##*/}
echo "$SYSFS/class/scsi_generic/$GEN_DEV"
else
echo "-"
fi
# FIXME Find a way to assign the generic devices.
elif [ -r $SYSFS/../runtime.out ]; then
SCSI_DEV=`basename $SCSI_DEVICE_PATH`
echo "$SYSFS/block/"`grep -r "\[$SCSI_DEV\]"\
$SYSFS/../runtime.out |\
awk -F "/dev/" '{print $2}'`
fi
fi
if $SHOW_ATTRIBUTES && [ $SHOW_MORE_ATTRS -ge 1 ]; then
# auto scan LUNs not necessarily have a zfcp_unit
if [ -d $ZFCP_UNIT_PATH ]; then
echo 'Class = "zfcp_unit"'
show_attributes "$ZFCP_UNIT_PATH"
fi
fi
if $SHOW_ATTRIBUTES; then
echo 'Class = "scsi_device"'
show_attributes "$SCSI_DEVICE_PATH"
fi
if $SHOW_ATTRIBUTES && [ $SHOW_MORE_ATTRS -ge 2 ]; then
if [ -d $SCSI_DEVICE_PATH/scsi_disk ]; then
echo 'Class = "scsi_disk"'
show_attributes "$SCSI_DEVICE_PATH/scsi_disk/$(basename $SCSI_DEVICE_PATH)"
fi
if [ -d $SCSI_DEVICE_PATH/block ]; then
echo 'Class = "block"'
show_attributes "$SCSI_DEVICE_PATH/block/*/"
fi
if [ -d $SCSI_DEVICE_PATH/block/*/integrity ]; then
echo 'Class = "block_integrity"'
show_attributes "$SCSI_DEVICE_PATH/block/*/integrity"
fi
if [ -d $SCSI_DEVICE_PATH/block/*/queue ]; then
echo 'Class = "block_queue"'
show_attributes "$SCSI_DEVICE_PATH/block/*/queue"
fi
if [ -d $SCSI_DEVICE_PATH/block/*/queue/iosched ]; then
echo 'Class = "block_queue_iosched"'
show_attributes "$SCSI_DEVICE_PATH/block/*/queue/iosched"
fi
fi
if $SHOW_ATTRIBUTES; then
echo
fi
done
# what's left in ZFCP_UNIT_LIST are now units without SCSI device
for UNIT_PATH in $ZFCP_UNIT_LIST; do
STRIPPED_PATH=$UNIT_PATH
LUN=${UNIT_PATH##*/}
STRIPPED_PATH=${STRIPPED_PATH%/*}
WWPN=${STRIPPED_PATH##*/}
STRIPPED_PATH=${STRIPPED_PATH%/*}
ADAPTER=${STRIPPED_PATH##*/}
[ $LUN != ${PAR_LUN:-$LUN} ] && continue
[ $WWPN != ${PAR_WWPN:-$WWPN} ] && continue
[ $ADAPTER != ${PAR_BUSID:-$ADAPTER} ] && continue
if [ $VERBOSITY -eq 0 ]; then
echo "$ADAPTER/$WWPN/$LUN `basename $SCSI_DEVICE_PATH`"
echo "$ADAPTER/$WWPN/$LUN - failed"
else
echo "`ls -d $SYSFS/devices/css0/*/$ADAPTER`/$WWPN/$LUN"
echo ${SCSI_DEVICE_PATH%*/} # without trailing slash
echo "$UNIT_PATH failed"
echo "-"
fi
# On live systems, there are links to the block and
# generic devices. In a dbginfo archive, these links
# are not present. Therefore, fall back to reading
# the runtime.out log file.
if [ `ls $SCSI_DEVICE_PATH | grep -c block:` -eq 1 ]
then
BLOCK_DEV=`ls $SCSI_DEVICE_PATH | grep block:`
GEN_DEV=`ls $SCSI_DEVICE_PATH |\
grep scsi_generic:`
echo -n "$SYSFS/block/${BLOCK_DEV#*:} "
echo "$SYSFS/class/scsi_generic/${GEN_DEV#*:}"
# FIXME Find a way to assign the generic devices.
elif [ -r $SYSFS/../runtime.out ]; then
SCSI_DEV=`basename $SCSI_DEVICE_PATH`
echo "$SYSFS/block/"`grep -r "\[$SCSI_DEV\]"\
$SYSFS/../runtime.out |\
awk -F "/dev/" '{print $2}'`
fi
if $SHOW_ATTRIBUTES && [ $SHOW_MORE_ATTRS -ge 1 ]; then
echo 'Class = "zfcp_unit"'
show_attributes "$UNIT_PATH"
fi
if $SHOW_ATTRIBUTES; then
echo 'Class = "scsi_device"'
show_attributes "$SCSI_DEVICE_PATH"
echo
fi
done
@@ -290,8 +530,8 @@ show_devices()
##############################################################################
ARGS=`getopt --options ahvHPDVb:p:l:s: --longoptions \
attributes,help,version,hosts,ports,devices,verbose,busid:,wwpn:,lun:,sysfs: \
ARGS=`getopt --options ahvHPDVb:p:l:s:emZ --longoptions \
attributes,help,version,hosts,ports,devices,verbose,busid:,wwpn:,lun:,sysfs:,extended,moreattrs,modparms \
-n "$SCRIPTNAME" -- "$@"`
if [ $? -ne 0 ]; then
@@ -305,6 +545,8 @@ eval set -- "$ARGS"
for ARG; do
case "$ARG" in
-a|--attributes) SHOW_ATTRIBUTES=true; shift 1;;
-m|--moreattrs) ((SHOW_MORE_ATTRS++)); shift 1;;
-e|--extended) SHOW_EXTENDED=true; shift 1;;
-b|--busid) PAR_BUSID=$2; shift 2;;
-h|--help) print_help; exit 0;;
-l|--lun) PAR_LUN=$2; shift 2;;
@@ -314,6 +556,7 @@ for ARG; do
-D|--devices) SHOW_DEVICES=1; shift 1;;
-P|--ports) SHOW_PORTS=1; shift 1;;
-V|--verbose) VERBOSITY=1; shift 1;;
-Z|--modparms) SHOW_MODPARMS=1; shift 1;;
-s|--sysfs) SYSFS=$2; shift 2;;
--) shift; break;;
esac
@@ -325,6 +568,10 @@ check_fc_class
check_fcp_devs
default=1
if [ $SHOW_MODPARMS -eq 1 ]; then
default=0; show_modparms
fi
if [ $SHOW_HOSTS -eq 1 ]; then
default=0; show_hosts
elif [ $SHOW_PORTS -eq 0 -a $SHOW_DEVICES -eq 0 -a -n "$PAR_BUSID" ]; then

View File

@@ -1,14 +1,14 @@
.\" Copyright IBM Corp. 2006, 2017
.\" Copyright IBM Corp. 2006, 2019
.\" s390-tools is free software; you can redistribute it and/or modify
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH LSZFCP 8 "Mar 2008" "s390-tools"
.TH LSZFCP 8 "Feb 2019" "s390-tools"
.SH NAME
lszfcp \- list information about zfcp adapters, ports, and units
.SH SYNOPSIS
.B lszfcp
.RB [ \-hvVaHDP ]
.RB [ \-hvVaZHDPem ]
.RB [ \-b
.IR busid ]
.RB [ \-l
@@ -28,8 +28,10 @@ scsi_devices.
The default is to list busids of all zfcp adapters and their corresponding
SCSI host names.
There are three output variants. Default (without options "-a" or
"-V") is one line for each object. For adapters the busid and their
There are four output variants. Default (without options "-a" or
"-V" or "-Z") is one line for each object.
For the zfcp device driver (module), its parameters are listed.
For adapters the busid and their
corresponding SCSI host names are listed. For ports the pair
"busid"/"wwpn" and their corresponding FC-remote-port names are listed.
For units the triple "busid"/"wwpn"/"lun" and their corresponding SCSI
@@ -37,20 +39,53 @@ device names are listed.
Option "-V" additionally shows the sysfs paths of interest for the
listed object.
If a SCSI device has an associated block device (disk)
and SCSI generic (sg) device, show their sysfs paths in a 3rd line.
Option "-a" additionally shows all attributes of interest found in
Option "-a" additionally shows attributes of interest found in
sysfs for the listed object.
Option "-m" together with option "-a" shows sysfs attributes if available for:
host: css (subchannel); port: zfcp_port; lun: zfcp_unit.
Specifying option "-m" twice together with option "-a"
additionally shows SCSI device sysfs attributes
if available for:
scsi_disk, block, block_integrity, block_queue, block_queue_iosched.
Option "-e" enables an extended output format.
It enumerates all hosts/ports/luns independent of their state.
It also produces some improved error messages.
The extended output format can help determining problems.
Since a long time, without option "-e", lszfcp has
.I
not
enumerated:
hosts that have never been online (since last bind to zfcp device driver),
hosts that are defunct (CHPID configured off, or z/VM detach),
ports with fc_rport port_state unequal to "Online" (such as fibres pulled),
zfcp units without associated SCSI device (unit_add of non-existent LUN).
.SH OPTIONS
.TP
.B -a, --attributes
Show all attributes of the specified objects.
Show the most interesting attributes of the specified objects.
.TP
.B -m, --moreattrs
Show more attributes of the specified objects.
Host: css (subchannel). Port: zfcp_port. Lun: zfcp_unit.
If specified twice,
show additional attributes of the specified SCSI device objects:
scsi_disk, block, block_integrity, block_queue, block_queue_iosched.
.TP
.B -Z, --modparms
List zfcp (module) parameters with a scope of the device driver.
.TP
.B -D, --devices
List zfcp units and SCSI devices.
.TP
.B -H, --hosts
List zfcp adapters and fc-hosts (default). Information is given only
List zfcp adapters, fc-hosts, and scsi-hosts (default).
Without option "-e", information is given only
for adapters that are online (registered at the SCSI stack).
.TP
.B -P, --ports
@@ -69,9 +104,14 @@ List zfcp port(s) and FC remote port(s) selected by wwpn. (Information
for several ports might be shown if a remote port is configured for
different adapters.)
.TP
.B -e, --extended
Generate extended output.
.TP
.B -V, --verbose
Generate verbose output. Display sysfs path names of class and bus
devices that are of interest for this object.
If a SCSI device has an associated block device (disk)
and SCSI generic (sg) device, show their sysfs paths in a 3rd line.
.TP
.B -s, --sysfs /path/to/sys
Use path as sysfs (for dbginfo archives).
@@ -86,7 +126,7 @@ Display version info and exit.
.PP
Options "-b", "-p" or "-l" are of restricting nature. They limit the output
to those adapters, ports or units that match the specified busid, wwpn and lun.
If none of the options "-H", "-P" and "-D" are specified, "-b" implies "-H",
If none of the options "-Z", "-H", "-P" and "-D" are specified, "-b" implies "-H",
"-p" implies "-P" and "-l" implies "-D".
.SH EXAMPLES
@@ -105,6 +145,8 @@ Show all adapters that match the given busid, all ports that match the given
busid and wwpnn and show all units that match the given busid, wwpn and lun.
.IP "lszfcp -b 0.0.0815 -p 0x5005123456789000 -l 0x0000000000000000 -H -P -D"
Generates same output as previous example.
.IP "lszfcp -ZHPDVeamm"
Generates the fullest output in the extended format.
.SH "SEE ALSO"
.BR lscss (8)

View File

@@ -1,24 +1,27 @@
include ../../common.mak
all: chzcrypt lszcrypt zcryptctl
all: chzcrypt lszcrypt zcryptctl zcryptstats
libs = $(rootdir)/libutil/libutil.a
chzcrypt: chzcrypt.o misc.o $(libs)
lszcrypt: lszcrypt.o misc.o $(libs)
zcryptctl: zcryptctl.o misc.o $(libs)
zcryptstats: zcryptstats.o $(libs)
install: all
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 chzcrypt $(DESTDIR)$(BINDIR)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 lszcrypt $(DESTDIR)$(BINDIR)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 zcryptctl $(DESTDIR)$(BINDIR)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 zcryptstats $(DESTDIR)$(BINDIR)
$(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 644 -c chzcrypt.8 $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 644 -c lszcrypt.8 $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 644 -c zcryptctl.8 $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 644 -c zcryptstats.8 $(DESTDIR)$(MANDIR)/man8
clean:
rm -f *.o chzcrypt lszcrypt zcryptctl
rm -f *.o chzcrypt lszcrypt zcryptctl zcryptstats
.PHONY: all install clean

252
zconf/zcrypt/zcryptstats.8 Normal file
View File

@@ -0,0 +1,252 @@
.\" Copyright IBM Corp. 2019
.\" s390-tools is free software; you can redistribute it and/or modify
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH ZCRYPTSTATS 1 "January 2019" "s390-tools"
.SH NAME
zcryptstats \- Display usage statistics of IBM Crypto Express adapters
.
.
.SH SYNOPSIS
.B zcryptstats
.RI [ OPTIONS ]
.RI [ DEVICE_ID
[...] ]
.
.PP
.B zcryptstats
.BR \-\-help | \-h
.br
.B zcryptstats
.BR \-\-version | \-v
.
.
.
.SH DESCRIPTION
.
Use \fBzcryptstats\fP to display usage statistics of IBM Crypto Express
adapters.
.PP
\fBzcryptstats\fP obtains cryptographic performance measurement data
periodically and displays the data for each cryptographic device for each
interval.
A cryptographic device can be either a card device or a queue device (APQN).
\fBzcryptstats\fP runs forever unless you limit the number of intervals with
the \fB\-\-count\fP option. The default interval time is 10 seconds.
Use the \fB\-\-interval\fP option to specify a different interval time.
.PP
By default, all available cryptographic devices are monitored.
You can optionally specify the device IDs of the devices to be monitored.
The card device representation and the queue device are both in hexadecimal
notation.
.PP
Use the \fB\-\-no-apqn\fP option to omit the performance measurement data of
the queues. If the system does not support obtaining cryptographic
performance measurement data on the queue devices, only the card devices
are monitored.
.PP
For each device, a set of counters is displayed. The amount and meaning of the
counters are dependent on the device type and mode, see the COUNTERS section.
For each counter and interval, the following values are displayed:
.RS 2
.IP "\(bu" 2
Number of measured operations.
.IP "\(bu" 2
Rate of the measured operation in operations per second.
.IP "\(bu" 2
Utilization of the device in percent.
.IP "\(bu" 2
Average duration of the operations.
.RE
.PP
The sum of all operations is displayed in a separate \fBtotals\fP line.
Use the \fB\-\-only-totals\fP option to omit the individual counters and
display the totals only. Use the \fB\-\-no\-totals\fP option to omit the
totals.
.PP
.B Note:
The utilization value of a counter can exceed 100%. This value is caused by
the parallel execution of cryptographic operations.
.PP
Cryptographic performance measurement data might not be available when Linux
is running as guest under z/VM or under KVM. \fBzcryptstats\fP then displays an
error message and exits.
.PP
.B Note:
\fBzcryptstats\fP utilizes the device node \fB/dev/chsc\fP. When this device
node is not available, you might have to load kernel module \fBchsc_sch\fP using
\fBmodprobe chsc_sch\fP to make it available.
.
.
.
.SH OPTIONS
.
.TP
.BR DEVICE_ID
Specifies a cryptographic device for which statistics are displayed.
A device ID can either be a card device ID
(\fI<card-id>\fP) or a queue device (APQN) ID (\fI<card-id>.<domain-id>\fP).
To filter all devices by domain, provide \fI.<domain-id>\fP.
If no IDs are given, statistics are displayed for all available devices.
.
.TP
.BR \-i ", " \-\-interval\~\fIINTERVAL\fP
Specifies the interval time in seconds. If this option is omitted, then the
default interval time of 10 seconds is used.
.
.TP
.BR \-c ", " \-\-count\~\fICOUNT\fP
Specifies the number of reports that are generated at \fIINTERVAL\fP seconds
apart. If this option is omitted, the \fBzcryptstats\fP command generates
reports continuously, until it is stopped with control-C.
.
.TP
.BR \-o ", " \-\-output\~\fIJSON\fP|\fITABLE\fP|\fICSV\fP
Displays the statistics in the specified format. If this option is omitted, a
comprehensive report is displayed. Supported output formats are:
.RS 8
.IP "\(bu" 2
\fBJSON:\fP Displays the statistics in Javascript Object Notation (JSON) format.
JSON output field order is undefined, and new fields might be added in the
future.
.IP "\(bu" 2
\fBTABLE:\fP Displays the statistics in a human readable simple table format.
The individual counters are omitted, and only the totals are displayed.
This output format implies option \fB\-\-only-totals\fP.
.IP "\(bu" 2
\fBCSV:\fP Displays the statistics in comma-separated values format. The values
are separated with a semicolon. The individual counters are omitted, and only
the totals are displayed. This output format implies option
\fB\-\-only-totals\fP.
.RE
.
.TP
.BR \-t ", " \-\-no\-totals
Excludes the totals of all counters of a card device or queue device
(APQN). This option cannot be specified together with option
\fB\-\-only\-totals\fP or option \fB\-\-output\fP \fITABLE\fP|\fICSV\fP.
.
.TP
.BR \-T ", " \-\-only\-totals
Displays only the totals of all counters of a card device or a queue device
(APQN), but not the individual counters. This option is implied with
option \fB\-\-output\fP \fITABLE\fP|\fICSV\fP.
.
.TP
.BR \-a ", " \-\-no\-apqn
Displays only the counters of the card device, but omits the counters of the
queue device (APQN). If the system does not support obtaining cryptographic
performance measurement data on the queue devices, this option is implied.
.
.TP
.BR \-M ", " \-\-map\-type\~\fIMAPPING\fP
Maps unknown cryptographic device types and modes to known types and modes.
This option should only be used when new, so far unknown cryptographic devices
are found. You can then map them to known devices and modes, provided that the
new cryptographic devices report the same counters as the known cryptographic
device to which it is mapped.
The mapping specification consists of a comma-separated list of
\fIFROM\-TYPE\fP:\fIFROM\-MODE\fP=\fITO\-TYPE\fP:\fITO\-MODE\fP specifications.
The type and mode values must be specified in decimal notation.
.
.TP
.BR \-A ", " \-\-all
Displays all cards devices and queue devices (APQNs), not only those that are
available to the Linux instance. Using this option additional cryptographic
devices that are available in the CEC, but not available to the Linux system
are also monitored.
This option cannot be specified together with option \fB\-\-only-online\fP.
.
.TP
.BR \-O ", " \-\-only\-online
Displays only online cards devices and queue devices (APQNs). This option
cannot be specified together with option \fB\-\-all\fP.
.
.TP
.BR \-V ", " \-\-verbose
Displays additional information messages during processing.
.TP
.BR \-h ", " \-\-help
Displays help text and exits.
.TP
.BR \-v ", " \-\-version
Displays version information and exits.
.
.
.
.SH COUNTERS
.
.PP
.B IBM Crypto Express adapter in accelerator mode:
.RS 4
.TP
.B All
All operations on the adapter
.TP
.B RSA Key-gen
RSA-key-generation operations (also included in \fBAll\fP).
.RE
.PP
.B IBM Crypto Express adapter in CCA co-processor mode:
.RS 4
.TP
.B RSA 1024 ME
1024-bit ME-format RSA operations.
.TP
.B RSA 2048 ME
2048-bit ME-format RSA operations.
.TP
.B RSA 1024 CRT
1024-bit CRT-format RSA operations.
.TP
.B RSA 2048 CRT
2048-bit CRT-format RSA operations.
.TP
.B RSA 4096 ME
4096-bit ME-format RSA operations.
.TP
.B RSA 4096 CTR
4096-bit CRT-format RSA operations.
.RE
.PP
.B IBM Crypto Express adapter in EP11 co-processor mode:
.RS 4
.TP
.B Asym. Slow
Slow asymmetric-key functions.
.TP
.B Asym. Fast
Fast asymmetric-key functions.
.TP
.B Symm. Partial
Symmetric-key functions that return partial or incremental results.
.TP
.B Symm. Complete
Symmetric-key functions that return a complete or final result.
.TP
.B Asym. Key-gen
asymmetric-key generation function.
.RE
.PP
.
.
.
.SH EXAMPLES
.TP
.B zcryptstats 02
Display statistics for all cryptographic devices with card ID \fB02\fP.
.TP
.B zcryptstats 02.0005 --interval 5
Display statistics for cryptographic devices with card ID \fB02\fP and domain
ID \fB0005\fP in a 5 second interval.
.TP
.B zcryptstats .0005 --count 10
Display statistics for cryptographic devices with domain ID \fB0005\fP with the
default interval time of 10 seconds, for 10 intervals.
.TP
.B zcryptstats 02 --output JSON
Display statistics for all cryptographic devices with card ID \fB02\fP in
\fBJSON\fP output format.
.TP

2422
zconf/zcrypt/zcryptstats.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1128,12 +1128,6 @@ then
exit 1
fi
# check existence of ccwgroup devices
if ! [ -d $CCWGROUPBUS_DIR ]; then
print_error "There are no ccwgroup devices"
exit $RC_NO_CCWGROUP
fi
# determine environment
check_vm_env
@@ -1298,6 +1292,12 @@ then
exit $RC_TOO_MUCH_ARGUMENTS
fi
# check existence of ccwgroup devices
if ! [ -d $CCWGROUPBUS_DIR ]; then
print_error "There are no ccwgroup devices"
exit $RC_NO_CCWGROUP
fi
# react to parsed options
if [ $DO_ADD -eq 1 ]
then

View File

@@ -136,6 +136,12 @@ void _warn(const char *, ...);
fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \
_warn(__VA_ARGS__); \
} while (0)
void _warn_once(const char *, ...);
#define warn_once(...) do { \
if (debug_enabled) \
fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \
_warn_once(__VA_ARGS__); \
} while (0)
#define info(...) do { if (!quiet) fprintf(stdout_data ? stderr : stdout, \
__VA_ARGS__); } while (0)
#define verb(...) do { if (verbose) fprintf(stdout_data ? stderr : stdout, \

View File

@@ -40,6 +40,7 @@ struct udev_file {
};
exit_code_t udev_read_file(const char *, struct udev_file **);
bool udev_file_is_empty(struct udev_file *file);
void udev_free_file(struct udev_file *);
void udev_file_print(struct udev_file *);

View File

@@ -1,7 +1,7 @@
/*
* zdev - Modify and display the persistent configuration of devices
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -12,6 +12,8 @@
#include <stdint.h>
#include "ccw.h"
#include "exit_code.h"
#include "misc.h"
#define ZFCP_LUN_NAME "zfcp-lun"
#define SCSI_ATTR_PREFIX "scsi_dev"

View File

@@ -3,7 +3,7 @@
*
* chzdev: Configure z Systems specific devices
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -2573,7 +2573,7 @@ static exit_code_t do_export(struct options *opts)
info("Exporting data to standard output\n");
} else {
info("Exporting data to %s\n", opts->export);
if (!util_path_exists(opts->export)) {
if (!util_path_exists("%s", opts->export)) {
rc = path_create(opts->export);
if (rc)
return rc;

View File

@@ -1,7 +1,7 @@
/*
* zdev - Modify and display the persistent configuration of devices
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -10,6 +10,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "lib/util_path.h"
@@ -521,7 +522,7 @@ void device_read_active_settings(struct device *dev, read_scope_t scope)
s = setting_list_apply_actual(dev->active.settings, a, name,
value);
if (link || (scope == scope_all &&
!util_path_is_writable(path)))
util_path_is_readonly_file("%s", path)))
s->readonly = 1;
if (link)
free(link);

View File

@@ -78,6 +78,10 @@ static bool is_exportable(struct setting *s, config_t config)
/* Skip values that cannot be determined. */
return false;
}
if (!attrib_check_value(a, s->value)) {
/* Skip values that are not acceptable input values. */
return false;
}
if (!attrib_match_default(s->attrib, s->value)) {
/* All non-default values should be exported. */
return true;

View File

@@ -57,6 +57,7 @@ unsigned long longrun_total;
unsigned long longrun_current;
static struct util_list *delayed_messages;
static struct util_list *warn_once_messages;
static FILE *dryrun_file;
static FILE *dryrun_get_file(void)
@@ -245,6 +246,7 @@ static void dryrun_print(void)
void misc_exit(void)
{
strlist_free(delayed_messages);
strlist_free(warn_once_messages);
if (dryrun_file) {
if (verbose)
dryrun_print();
@@ -362,6 +364,29 @@ void _warn(const char *format, ...)
va_end(args);
}
/* Report a warning: print an error message to standard error. Only print each
* warning once. */
void _warn_once(const char *format, ...)
{
va_list args;
char *str;
va_start(args, format);
if (vasprintf(&str, format, args) == -1)
oom();
va_end(args);
/* Check if message was printed before. */
if (!warn_once_messages)
warn_once_messages = strlist_new();
if (!strlist_find(warn_once_messages, str)) {
fprintf(stderr, "%s", str);
strlist_add(warn_once_messages, "%s", str);
}
free(str);
}
/* Print an error message indicating an out-of-memory situation and exit. */
void oom(void)
{

View File

@@ -10,6 +10,7 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "lib/util_path.h"
@@ -259,7 +260,7 @@ bool module_set_params(const char *mod, struct setting_list *settings)
struct setting *s;
char *path;
const char *value;
bool result;
bool readonly;
exit_code_t rc;
/* First check if all modified settings can be applied this way. */
@@ -277,9 +278,9 @@ bool module_set_params(const char *mod, struct setting_list *settings)
return false;
}
path = path_get_sys_module_param(mod, s->name);
result = util_path_is_writable(path);
readonly = util_path_is_readonly_file("%s", path);
free(path);
if (!result) {
if (readonly) {
/* Sysfs file is not writable. */
return false;
}

View File

@@ -346,6 +346,21 @@ exit_code_t udev_read_file(const char *path, struct udev_file **file_ptr)
return EXIT_OK;
}
/* Check if a udev file does not contain any statements. */
bool udev_file_is_empty(struct udev_file *file)
{
struct udev_line_node *l;
if (!file)
return true;
util_list_iterate(&file->lines, l) {
if (l->line[0])
return false;
}
return true;
}
static bool get_ids_cb(const char *filename, void *data)
{
char *prefix = data;

View File

@@ -108,8 +108,13 @@ exit_code_t udev_ccw_read_device(struct device *dev, bool autoconf)
rc = udev_read_file(path, &file);
if (rc)
goto out;
udev_file_get_settings(file, st->dev_attribs, state->settings);
state->exists = 1;
if (udev_file_is_empty(file)) {
warn_once("Warning: Invalid udev rule: %s\n", path);
state->exists = 0;
} else {
udev_file_get_settings(file, st->dev_attribs, state->settings);
state->exists = 1;
}
udev_free_file(file);
out:

View File

@@ -163,9 +163,14 @@ exit_code_t udev_ccwgroup_read_device(struct device *dev, bool autoconf)
rc = udev_read_file(path, &file);
if (rc)
goto out;
udev_file_get_settings(file, st->dev_attribs, state->settings);
expand_id(dev, file);
state->exists = 1;
if (udev_file_is_empty(file)) {
warn_once("Warning: Invalid udev rule: %s\n", path);
state->exists = 0;
} else {
udev_file_get_settings(file, st->dev_attribs, state->settings);
expand_id(dev, file);
state->exists = 1;
}
udev_free_file(file);
out:
@@ -344,6 +349,9 @@ static char *read_full_id(const char *path)
out:
free(text);
if (!id)
warn_once("Warning: Invalid udev rule: %s\n", path);
return id;
}

View File

@@ -345,6 +345,7 @@ static exit_code_t udev_read_zfcp_lun_rule(const char *filename,
in_fc,
in_scsi,
} state = none;
bool empty_rule = true;
rc = udev_read_file(filename, &file);
if (rc)
@@ -374,16 +375,22 @@ static exit_code_t udev_read_zfcp_lun_rule(const char *filename,
state = in_scsi;
node = zfcp_lun_node_from_entry(entry, node,
list);
if (node)
empty_rule = false;
}
break;
case in_fc:
node = zfcp_lun_node_from_entry(entry, node, list);
if (node)
if (node) {
add_fc_setting_from_entry(entry, node);
empty_rule = false;
}
break;
case in_scsi:
if (node)
if (node) {
add_scsi_setting_from_entry(entry, node);
empty_rule = false;
}
break;
}
}
@@ -393,6 +400,9 @@ static exit_code_t udev_read_zfcp_lun_rule(const char *filename,
out:
udev_free_file(file);
if (empty_rule)
warn_once("Warning: Invalid udev rule: %s\n", filename);
return rc;
}
@@ -475,11 +485,17 @@ static void zfcp_lun_node_to_state(struct zfcp_lun_node *node,
struct attrib *a;
char *name;
state->exists = 1;
state->modified = 0;
state->deconfigured = 0;
state->definable = 0;
if (!node) {
state->exists = 0;
return;
}
state->exists = 1;
util_list_iterate(&node->fc_settings->list, s) {
a = attrib_find(attribs, s->name);
setting_list_add(state->settings,
@@ -519,10 +535,7 @@ exit_code_t udev_zfcp_lun_read_device(struct device *dev, bool autoconf)
goto out;
node = zfcp_lun_node_find(luns, dev->devid);
if (node)
zfcp_lun_node_to_state(node, st->dev_attribs, state);
else
rc = EXIT_DEVICE_NOT_FOUND;
zfcp_lun_node_to_state(node, st->dev_attribs, state);
out:
zfcp_lun_node_list_free(luns);

View File

@@ -1,7 +1,7 @@
/*
* zdev - Modify and display the persistent configuration of devices
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -67,7 +67,7 @@ static struct attrib zfcp_tattr_allow_lun_scan = {
"Control the use of the automatic LUN scanning feature for FCP\n"
"devices that are configured in N_PORT ID Virtualization mode.\n"
" 0: Automatic LUN scanning is disabled\n"
" 1: Automatic LUN scanning is enabled\n\n",
" 1: Automatic LUN scanning is enabled\n",
.nounload = 1,
.defval = "1",
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
@@ -75,16 +75,28 @@ static struct attrib zfcp_tattr_allow_lun_scan = {
static struct attrib zfcp_tattr_dif = {
.name = "dif",
.title = "Enable DIF/DIX data consistency checking",
.title = "Enable DIF data consistency checking",
.desc =
"Control the use of the end-to-end data consistency checking\n"
"mechanism (DIF/DIX):\n"
"Control the use of the DIF data consistency checking\n"
"mechanism:\n"
" 0: DIF is disabled\n"
" 1: DIF is enabled when supported by the FCP device hardware\n",
.defval = "0",
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
};
static struct attrib zfcp_tattr_dix = {
.name = "dix",
.title = "Enable DIF&DIX data consistency checking",
.desc =
"Control the use of the end-to-end data consistency checking\n"
"mechanism (DIF&DIX):\n"
" 0: DIF&DIX is disabled\n"
" 1: DIF&DIX is enabled when supported by the FCP device hardware\n",
.defval = "0",
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
};
static struct attrib zfcp_tattr_datarouter = {
.name = "datarouter",
.title = "Enable hardware data routing",
@@ -160,6 +172,7 @@ static void all_bools_to_num(struct setting_list *list)
util_list_iterate(&list->list, s) {
if (s->attrib == &zfcp_tattr_allow_lun_scan ||
s->attrib == &zfcp_tattr_dif ||
s->attrib == &zfcp_tattr_dix ||
s->attrib == &zfcp_tattr_datarouter ||
s->attrib == &zfcp_tattr_no_auto_port_rescan) {
/* Convert Y to 1 and N to 0. */
@@ -295,6 +308,7 @@ struct devtype zfcp_devtype = {
&zfcp_tattr_queue_depth,
&zfcp_tattr_allow_lun_scan,
&zfcp_tattr_dif,
&zfcp_tattr_dix,
&zfcp_tattr_datarouter,
&zfcp_tattr_no_auto_port_rescan,
&zfcp_tattr_port_scan_ratelimit,

View File

@@ -1,7 +1,7 @@
/*
* zdev - Modify and display the persistent configuration of devices
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -64,7 +64,7 @@ static struct attrib zfcp_host_attr_port_rescan = {
.title = "Trigger a port rescan for the FCP device",
.desc =
"Rescan FCP device for available remote ports by writing the value 1\n"
"to this attribute\n",
"to this attribute.\n",
.activeonly = 1,
.writeonly = 1,
.accept = ACCEPT_ARRAY(ACCEPT_NUM(1)),

View File

@@ -1,7 +1,7 @@
/*
* zdev - Modify and display the persistent configuration of devices
*
* Copyright IBM Corp. 2016, 2017
* Copyright IBM Corp. 2016, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -246,6 +246,7 @@ static unsigned long zfcp_lun_num_ids_in_range(const char *range)
static bool zfcp_lun_is_id_in_range(const char *id, const char *range)
{
/* No ranges are supported on zfcp lun IDs. */
return false;
}
@@ -317,6 +318,7 @@ struct namespace zfcp_lun_namespace = {
/*
* zfcp lun device attributes.
*/
static struct attrib zfcp_lun_attr_failed = {
.name = "failed",
.title = "Check and restart FCP SCSI device recovery",
@@ -1080,6 +1082,7 @@ static exit_code_t zfcp_lun_st_detect_definable(struct subtype *st,
/*
* zfcp lun subtype.
*/
struct subtype zfcp_lun_subtype = {
.super = &subtype_base,

View File

@@ -2,9 +2,8 @@ include ../common.mak
libs = $(rootdir)/libzds/libzds.a \
$(rootdir)/libvtoc/libvtoc.a \
$(rootdir)/libu2s/libu2s.a \
$(rootdir)/libutil/libutil.a \
$(rootdir)/libdasd/libdasd.a
$(rootdir)/libdasd/libdasd.a \
$(rootdir)/libutil/libutil.a
ifeq (${HAVE_FUSE},0)

View File

@@ -514,7 +514,7 @@ function check_for_multipath_devices() {
(( i+=2 ));
while [[ `echo "${mp_arr[$i]:0:1}" | grep -ve "[0-9a-zA-Z]"` ]] && [ $i -lt ${#mp_arr[@]} ]; do
if [ `echo ${mp_arr[$i]} | grep -e "[0-9]\{1,\}:[0-9]\{1,\}:[0-9]\{1,\}:[0-9]\{1,\}" | wc -l` -ne 0 ]; then
line="`echo ${mp_arr[$i]} | sed 's/.*\([0-9]\{1,\}:[0-9]\{1,\}:[0-9]\{1,\}:[0-9]\{1,\}\)/\1/'`";
line="`echo ${mp_arr[$i]} | sed 's/[^0-9]*\([0-9]\{1,\}:[0-9]\{1,\}:[0-9]\{1,\}:[0-9]\{1,\}\)/\1/'`";
checked_devs[${#checked_devs[@]}]=`echo $line | awk '{print "/dev/"$2}'`;
ddebug " adding ${checked_devs[${#checked_devs[@]}-1]}";
WRP_HOST_ADAPTERS[${#WRP_HOST_ADAPTERS[@]}]="host${line%%:*}";

View File

@@ -6,17 +6,16 @@ CFLAGS_BOOT = $(NO_PIE_CFLAGS) -Os -g -I../include -D__ASSEMBLY__ \
-fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \
-fno-delete-null-pointer-checks \
-fexec-charset=IBM1047 -m64 -mpacked-stack \
-mstack-size=8192 -mstack-guard=128 -msoft-float \
-mstack-size=4096 -mstack-guard=128 -msoft-float \
-W -Wall -Wformat-security
FILES = fba0.bin fba1b.bin fba2.bin \
eckd0_ldl.bin eckd0_cdl.bin \
eckd1.bin eckd1b.bin eckd2.bin \
tape0.bin \
eckd2dump_sv.bin tape2dump.bin fba2dump.bin eckd2dump_mv.bin \
stage3.bin
eckd2dump_sv.bin tape2dump.bin fba2dump.bin eckd2dump_mv.bin
all: data.o data.h tape0.bin
all: data.o data.h tape0.bin stage3.bin
# Prevent make from using some default rules...
%: %.S
@@ -44,10 +43,10 @@ eckd2.exec: head.o stage2.o cio.o eckd2.o libc.o menu.o sclp.o \
fba2.exec: head.o stage2.o cio.o fba2.o libc.o menu.o sclp.o \
kdump2.o kdump.o entry.o
stage3.exec: head.o stage3.o kdump3.o libc.o sclp.o sclp_stage3.o \
kdump.o entry.o
kdump.o entry.o stage3.lds
%.exec: %.o
@STAGE=$$( \
STAGE=$$( \
echo $@ | awk ' \
match($$0,/[0-9]+b*/){ \
print substr($$0,RSTART,RLENGTH) \
@@ -60,7 +59,7 @@ stage3.exec: head.o stage3.o kdump3.o libc.o sclp.o sclp_stage3.o \
2) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage2.lds";; \
3) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3.lds";; \
esac; \
$(LINK) $$SFLAGS -m64 $^ -o $@
$(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@
%.bin: %.exec
$(OBJCOPY) -O binary \
@@ -71,12 +70,30 @@ stage3.exec: head.o stage3.o kdump3.o libc.o sclp.o sclp_stage3.o \
--only-section=.ex_table \
--only-section=.data \
--only-section=.rodata.str1.2 \
--only-section=.rodata.cst8 \
--only-section=.rodata \
--only-section=.stage2dump.tail \
--only-section=.eckd2dump_mv.tail \
--only-section=.fixup \
$< $@
stage3.bin: stage3.exec
$(OBJCOPY) -O binary \
--only-section=.stage2.head \
--only-section=.text.dummy \
--only-section=.text.start \
--only-section=.text \
--only-section=.ex_table \
--only-section=.data \
--only-section=.rodata.str1.2 \
--only-section=.rodata.cst8 \
--only-section=.rodata \
--only-section=.stage2dump.tail \
--only-section=.eckd2dump_mv.tail \
--only-section=.fixup \
--pad-to=0xe000 \
$< $@
data.o: $(FILES)
$(LD) $(NO_PIE_LDFLAGS) -r -b binary -o data.o $(FILES)
@@ -86,6 +103,7 @@ data.h: data.o
echo "extern char $$SYMBOL;" >>data.h; done
clean:
rm -f *.o *.exec *.bin $(FILES) data.o data.h tape0.bin *.xxx *.yyy
rm -f *.o *.exec *.bin $(FILES) data.o data.h tape0.bin *.xxx *.yyy \
stage3.bin
.PHONY: all clean

View File

@@ -31,6 +31,9 @@
/* Internal error */
#define EINTERNAL 0x00004511
/* Secure IPL error */
#define ESECUREBOOT 0x00004512
/* kdump: No operating system information was found */
#define EOS_INFO_MISSING 0x00004520

View File

@@ -58,6 +58,26 @@ void *memcpy(void *dest, const void *src, unsigned long n)
return dest;
}
/*
* Move @n bytes of memory from @src to @dest. The memory regions may overlap.
*/
void *memmove(void *dest, const void *src, unsigned long n)
{
const char *s = src;
char *d = dest;
if (s < d) {
d += n;
s += n;
while (n--)
*--d = *--s;
} else {
while (n--)
*d++ = *s++;
}
return dest;
}
/*
* Copy string
*/

View File

@@ -49,6 +49,7 @@ typedef unsigned char uint8_t;
void printf(const char *, ...);
void sprintf(char *, const char *, ...);
void *memcpy(void *, const void *, unsigned long);
void *memmove(void *, const void *, unsigned long);
void *memset(void *, int c, unsigned long);
char *strcat(char *, const char *);
int strncmp(const char *, const char *, unsigned long);

View File

@@ -15,7 +15,7 @@
#include "stage2.h"
/* address of extra command line */
#define COMMAND_LINE_EXTRA (0xA000-0x400)
#define COMMAND_LINE_EXTRA 0xE000
/* max command line length */
#define COMMAND_LINE_SIZE 896

View File

@@ -35,6 +35,11 @@ struct psw_t {
uint64_t addr;
} __aligned(8);
struct psw32_t {
uint32_t mask;
uint32_t addr;
} __aligned(8);
void load_wait_psw(uint64_t, struct psw_t *);
struct _lowcore {
@@ -447,6 +452,18 @@ static inline int test_facility(unsigned long nr)
return __test_facility(nr, &S390_lowcore.stfle_fac_list);
}
static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size)
{
register unsigned long reg0 asm("0") = size - 1;
asm volatile(
".insn s,0xb2b00000,0(%1)" /* stfle */
: "+d" (reg0)
: "a" (stfle_fac_list)
: "memory", "cc");
return reg0;
}
/**
* stfle - Store facility list extended
* @stfle_fac_list: array where facility list can be stored
@@ -465,13 +482,8 @@ static inline void stfle(u64 *stfle_fac_list, int size)
memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
if (S390_lowcore.stfl_fac_list & 0x01000000) {
/* More facility bits available with stfle */
register unsigned long reg0 asm("0") = size - 1;
asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */
: "+d" (reg0)
: "a" (stfle_fac_list)
: "memory", "cc");
nr = (reg0 + 1) * 8; /* # bytes stored by stfle */
nr = __stfle_asm(stfle_fac_list, size);
nr = MIN((nr + 1) * 8, size * 8UL);
}
memset((char *) stfle_fac_list + nr, 0, size * 8 - nr);
}

View File

@@ -115,8 +115,13 @@ void start(void)
/* skip header */
entry = (struct component_entry *)
(load_address + sizeof(struct component_header));
while (entry->type == COMPONENT_LOAD) {
while (entry->type == COMPONENT_LOAD ||
entry->type == COMPONENT_SIGNATURE) {
if (entry->type == COMPONENT_SIGNATURE) {
/* Skip unhandled signature components */
entry++;
continue;
}
load_address = (void *)(unsigned long)
entry->address.load_address[1];
load_blocklist(entry, subchannel_id, load_address);

View File

@@ -61,7 +61,8 @@ struct component_entry {
typedef enum {
COMPONENT_EXECUTE = 0x01,
COMPONENT_LOAD = 0x02
COMPONENT_LOAD = 0x02,
COMPONENT_SIGNATURE = 0x03
} component_type;
struct stage2_descr {

View File

@@ -9,9 +9,11 @@
* 0x2000-0x4fff Sections (load): head, text, data, rodata, rodata.str
* 0x5000-0x51ff eckd2dump_mv parameter block (426 bytes)
* 0x5200-0x5fff Sections: bss
* 0x6000-0x9fff Memory allocation (heap)
* 0x6000-0x8fff Memory allocation (heap)
* 0x9000-0x9fff Memory to load stage3 parameter to
* 0xa000-0xdfff Memory to load stage3 to
* 0xe000-0xffff Stack
* 0xe000-0xe3ff command line extra
* 0xe400-0xffff Stack
*
* Special memory locations
* ------------------------
@@ -52,7 +54,7 @@ SECTIONS
. = 0x6000;
__heap_start = .;
. = 0xa000;
. = 0x9000;
__heap_stop = .;
. = 0xf000;

View File

@@ -12,35 +12,15 @@
#include "libc.h"
#include "s390.h"
#include "stage3.h"
#include "error.h"
/*
* 48 Byte dummy space for external symbols
* _parm_addr; address of parmline
* _initrd_addr; address of initrd
* _initrd_len; length of initrd
* _load_psw; load psw of kernel
* _extra_parm; use extra parm line mechanism?
* stage3_flags; flags (e.g. STAGE3_FLAG_KDUMP)
*
* needed to blow up the binary and leave room
*/
__attribute__ ((section(".text.dummy"))) void _dummy(void)
{
asm volatile(
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
".long 0x00000000\n"
);
}
#define for_each_rb_entry(entry, rb) \
for (entry = rb->entries; \
(void *) entry + sizeof(*entry) <= (void *) rb + rb->len; \
entry++)
static const char *msg_sipl_inval = "Secure boot failure: invalid load address";
static const char *msg_sipl_unverified = "Secure boot failure: unverified load address";
static unsigned char ebc_037[256] = {
/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */
@@ -221,6 +201,64 @@ start_kernel(void)
: [psw] "a" (psw) );
}
unsigned int
is_verified_address(unsigned long image_addr)
{
struct ipl_rb_component_entry *comp;
struct ipl_rb_components *comps;
struct ipl_pl_hdr *pl_hdr;
struct ipl_rl_hdr *rl_hdr;
struct ipl_rb_hdr *rb_hdr;
unsigned long tmp;
void *rl_end;
/*
* There is an IPL report, to find it load the pointer to the
* IPL parameter information block from lowcore and skip past
* the IPL parameter list, then align the address to a double
* word boundary.
*/
tmp = (unsigned long) S390_lowcore.ipl_parmblock_ptr;
pl_hdr = (struct ipl_pl_hdr *) tmp;
tmp = (tmp + pl_hdr->len + 7) & -8UL;
rl_hdr = (struct ipl_rl_hdr *) tmp;
/* Walk through the IPL report blocks in the IPL Report list */
comps = NULL;
rl_end = (void *) rl_hdr + rl_hdr->len;
rb_hdr = (void *) rl_hdr + sizeof(*rl_hdr);
while ((void *) rb_hdr + sizeof(*rb_hdr) < rl_end &&
(void *) rb_hdr + rb_hdr->len <= rl_end) {
switch (rb_hdr->rbt) {
case IPL_RBT_COMPONENTS:
comps = (struct ipl_rb_components *) rb_hdr;
break;
default:
break;
}
rb_hdr = (void *) rb_hdr + rb_hdr->len;
}
for_each_rb_entry(comp, comps) {
if (image_addr == comp->addr &&
comp->flags & IPL_RB_COMPONENT_FLAG_SIGNED &&
comp->flags & IPL_RB_COMPONENT_FLAG_VERIFIED)
return 1;
}
return 0;
}
unsigned int
secure_boot_enabled()
{
struct ipl_pl_hdr *pl_hdr;
unsigned long tmp;
tmp = (unsigned long) S390_lowcore.ipl_parmblock_ptr;
pl_hdr = (struct ipl_pl_hdr *) tmp;
return pl_hdr->flags & IPL_FLAG_SECURE;
}
void start(void)
{
unsigned int subchannel_id;
@@ -228,6 +266,26 @@ void start(void)
unsigned char *command_line = (unsigned char *)COMMAND_LINE;
unsigned int begin = 0, end = 0, length = 0;
/*
* IPL process is secure we have to use default IPL values and
* check if the psw jump address is within at the start of a
* verified component. If it is not IPL is aborted.
*/
if (secure_boot_enabled()) {
if (_image_addr != DEFAULT_IMAGE_ADDR ||
_load_psw != DEFAULT_PSW_LOAD)
panic(ESECUREBOOT, "%s", msg_sipl_inval);
if (!is_verified_address(_load_psw & PSW_ADDR_MASK))
panic(ESECUREBOOT, "%s", msg_sipl_unverified);
}
/*
* cut the kernel header
*/
memmove((void *)_image_addr,
(void *)_image_addr + KERNEL_HEADER_SIZE,
_image_len - KERNEL_HEADER_SIZE);
/* store subchannel ID into low core and into new kernel space */
subchannel_id = S390_lowcore.subchannel_id;
*(unsigned int *)__LC_IPLDEV = subchannel_id;

View File

@@ -22,19 +22,161 @@
#define OLDMEM_SIZE 0x10420
#define COMMAND_LINE 0x10480
#define COMMAND_LINE_SIZE 896
#define COMMAND_LINE_EXTRA (0xA000-0x400)
#define COMMAND_LINE_EXTRA 0xE000
#define STAGE3_FLAG_SCSI 0x0001000000000000ULL
#define STAGE3_FLAG_KDUMP 0x0002000000000000ULL
#define IPL_FLAG_SECURE 0x40
#define DEFAULT_IMAGE_ADDR 0x10000
#define DEFAULT_PSW_LOAD 0x0008000080010000L
#define PSW_ADDR_MASK 0x000000007FFFFFFFL
#define KERNEL_HEADER_SIZE 65536
#define UNSPECIFIED_ADDRESS -1ULL
/* IPL Parameter List header */
struct ipl_pl_hdr {
uint32_t len;
uint8_t flags;
uint8_t reserved1[2];
uint8_t version;
} __packed;
/* IPL Parameter Block header */
struct ipl_pb_hdr {
uint32_t len;
uint8_t pbt;
} __packed;
/* IPL Parameter Block 0 with common fields */
struct ipl_pb0_common {
uint32_t len;
uint8_t pbt;
uint8_t flags;
uint8_t reserved1[2];
uint8_t loadparm[8];
uint8_t reserved2[84];
} __packed;
/* IPL Parameter Block 0 for FCP */
struct ipl_pb0_fcp {
uint32_t len;
uint8_t pbt;
uint8_t reserved1[3];
uint8_t loadparm[8];
uint8_t reserved2[304];
uint8_t opt;
uint8_t reserved3[3];
uint8_t cssid;
uint8_t reserved4[1];
uint8_t devno;
uint8_t reserved5[4];
uint64_t wwpn;
uint64_t lun;
uint32_t bootprog;
uint8_t reserved6[12];
uint64_t br_lba;
uint32_t scp_data_len;
uint8_t reserved7[260];
uint8_t scp_data[];
} __packed;
/* IPL Parameter Block 0 for CCW */
struct ipl_pb0_ccw {
uint32_t len;
uint8_t pbt;
uint8_t flags;
uint8_t reserved1[2];
uint8_t loadparm[8];
uint8_t reserved2[84];
uint16_t reserved3 : 13;
uint8_t ssid : 3;
uint16_t devno;
uint8_t vm_flags;
uint8_t reserved4[3];
uint32_t vm_parm_len;
uint8_t nss_name[8];
uint8_t vm_parm[64];
uint8_t reserved5[8];
} __packed;
struct ipl_parameter_block {
struct ipl_pl_hdr hdr;
union {
struct ipl_pb_hdr pb0_hdr;
struct ipl_pb0_common common;
struct ipl_pb0_fcp fcp;
struct ipl_pb0_ccw ccw;
char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)];
};
} __packed __aligned(PAGE_SIZE);
/* IPL Report List header */
struct ipl_rl_hdr {
uint32_t len;
uint8_t flags;
uint8_t reserved1[2];
uint8_t version;
uint8_t reserved2[8];
} __packed;
/* IPL Report Block header */
struct ipl_rb_hdr {
uint32_t len;
uint8_t rbt;
uint8_t reserved1[11];
} __packed;
/* IPL Report Block types */
enum ipl_rbt {
IPL_RBT_CERTIFICATES = 1,
IPL_RBT_COMPONENTS = 2,
};
/* IPL Report Block for the certificate list */
struct ipl_rb_certificate_entry {
uint64_t addr;
uint64_t len;
} __packed;
struct ipl_rb_certificates {
uint32_t len;
uint8_t rbt;
uint8_t reserved1[11];
struct ipl_rb_certificate_entry entries[];
} __packed;
/* IPL Report Block for the component list */
struct ipl_rb_component_entry {
uint64_t addr;
uint64_t len;
uint8_t flags;
uint8_t reserved1[5];
uint16_t certificate_index;
uint8_t reserved2[8];
};
#define IPL_RB_COMPONENT_FLAG_SIGNED 0x80
#define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40
struct ipl_rb_components {
uint32_t len;
uint8_t rbt;
uint8_t reserved1[11];
struct ipl_rb_component_entry entries[];
} __packed;
extern unsigned long long _parm_addr; /* address of parmline */
extern unsigned long long _initrd_addr; /* address of initrd */
extern unsigned long long _initrd_len; /* length of initrd */
extern unsigned long long _load_psw; /* load psw of kernel */
extern unsigned long long _extra_parm; /* use extra parm line mechanism? */
extern unsigned long long stage3_flags; /* flags (e.g. STAGE3_FLAG_KDUMP) */
extern unsigned long long _image_len; /* length of kernel */
extern unsigned long long _image_addr; /* target address of kernel */
extern void kdump_stage3();
#endif /* STAGE3_H */

View File

@@ -1,33 +1,47 @@
/*
* Memory layout for stage 3
* =========================
*
* General memory layout
* ---------------------
*
* 0x0000-0x1fff Lowcore
* 0x2000-0x5fff Memory allocation (heap)
* 0x6000-0x8fff free
* 0x9000-0x9fff Stage3 parameter
* 0xa000-0xdfff Stage3 code + data
* 0xe000-0xffff Stack
*/
SECTIONS
{
. = 0x0;
. = 0x7000;
. = 0x2000;
__heap_start = .;
. = 0xa000;
. = 0x6000;
__heap_stop = .;
. = 0xa000;
/* stage 3 parameter */
. = 0x9000;
_parm_addr = .;
. = 0xa008;
. = 0x9008;
_initrd_addr = .;
. = 0xa010;
. = 0x9010;
_initrd_len = .;
. = 0xa018;
. = 0x9018;
_load_psw = .;
. = 0xa020;
. = 0x9020;
_extra_parm = .;
. = 0xa028;
. = 0x9028;
stage3_flags =.;
. = 0x9030;
_image_len = .;
. = 0x9038;
_image_addr = .;
. = 0xa000;
.text.dummy : { *(.text.dummy) }
. = 0xa050;
.text.start : { *(.text.start) }
.text : { *(.text) }
__ex_table_start = .;
@@ -35,11 +49,9 @@ SECTIONS
__ex_table_stop = .;
.eh_frame : { *(.eh_frame) }
. = 0xc000;
__bss_start = .;
.bss : { *(.bss) }
__bss_stop = .;
.rodata : {*(.rodata) }
.data : { *(.data) }
}

View File

@@ -248,6 +248,9 @@ struct boot_stage3_params {
uint64_t load_psw;
uint64_t extra_parm;
uint16_t flags;
uint16_t reserved[3];
uint64_t image_len;
uint64_t image_addr;
} __attribute__ ((packed));
#define STAGE3_FLAG_SCSI 0x0001
@@ -305,10 +308,10 @@ int boot_init_fba_stage1b(struct boot_fba_stage1b *stage1b,
disk_blockptr_t *stage2_list,
blocknum_t stage2_count);
int boot_get_eckd_stage2(void** data, size_t* size, struct job_data* job);
size_t get_stage3_size();
int boot_get_stage3(void** buffer, size_t* bytecount, address_t parm_addr,
address_t initrd_addr, size_t initrd_len,
address_t image_addr, int extra_parm, uint16_t flags);
int boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
address_t initrd_addr, size_t initrd_len,
address_t load_addr, int extra_parm, uint16_t flags,
size_t image_len);
int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr,
address_t initrd_addr, address_t image_addr);
int boot_get_tape_dump(void** data, size_t* size, uint64_t mem);

View File

@@ -16,6 +16,37 @@
#include "job.h"
#include "zipl.h"
#define SIGNATURE_MAGIC "~Module signature appended~\n"
#define PKCS7_FORMAT 0x01
struct signature_header {
uint8_t format;
uint8_t reserved[3];
uint32_t length;
} __attribute((packed));
typedef union {
uint64_t load_address;
uint64_t load_psw;
struct signature_header sig_head;
} component_data;
/*
* The file_signature structure and the PKEY_ID definition
* are based on linux/scripts/sign-file.c
*/
struct file_signature {
u8 algorithm;
u8 hash;
u8 id_type;
u8 signer_len;
u8 key_id_len;
u8 __pad[3];
u32 sig_len;
char magic[28];
};
#define PKEY_ID_PKCS7 0x02
int bootmap_create(struct job_data* job, disk_blockptr_t* program_table,
disk_blockptr_t *scsi_dump_sb_blockptr,

View File

@@ -121,6 +121,7 @@ struct job_data {
int add_files;
int dry_run;
int command_line;
int is_secure;
};

View File

@@ -51,6 +51,7 @@ int misc_check_readable_file(const char* filename);
int misc_check_writable_device(const char* devno, int blockdev, int chardev);
void misc_ebcdic_to_ascii(unsigned char *from, unsigned char *to);
void misc_ascii_to_ebcdic(unsigned char *from, unsigned char *to);
unsigned int misc_check_secure_boot(void);
#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))

View File

@@ -16,7 +16,7 @@
#define SCAN_SECTION_NUM 9
#define SCAN_KEYWORD_NUM 21
#define SCAN_KEYWORD_NUM 22
#define SCAN_KEYWORD_ONLY_NUM 1
#define SCAN_AUTOMENU_NAME "zipl-automatic-menu"
@@ -51,6 +51,7 @@ enum scan_keyword_id {
scan_keyword_targetoffset = 18,
scan_keyword_defaultauto = 19,
scan_keyword_kdump = 20,
scan_keyword_secure = 21,
};
enum scan_section_type {

View File

@@ -20,10 +20,11 @@
#define DISK_LAYOUT_ID 0x00000001
#define ZIPL_STAGE2_LOAD_ADDRESS 0x2000
#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa050LL
#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000LL
#define DEFAULT_IMAGE_ADDRESS 0x10000LL
#define KDUMP_IMAGE_ADDRESS 0x10010LL
#define DEFAULT_STAGE3_ADDRESS 0xa000LL
#define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000LL
#define MINIMUM_ADDRESS 0x10000LL
#define ADDRESS_LIMIT 0x80000000LL
#define ADDRESS_LIMIT_KDUMP 0x2000000UL /* HSA size: 32 MiB */
@@ -31,25 +32,35 @@
#define MAXIMUM_PARMLINE_SIZE 0x380
#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000
#define STAGE3_HEAP_SIZE 0x4000
#define STAGE3_HEAP_ADDRESS 0x2000
#define STAGE3_STACK_SIZE 0x1000
#define STAGE3_STACK_ADDRESS 0xF000
#define PSW_ADDRESS_MASK 0x000000007fffffffLL
#define PSW_LOAD 0x0008000080000000LL
#define PSW_DISABLED_WAIT 0x000a000000000000LL
#define KERNEL_HEADER_SIZE 65536
#define BOOTMAP_FILENAME "bootmap"
#define BOOTMAP_TEMPLATE_FILENAME "bootmap_temp.XXXXXX"
#define DEFAULTBOOT_SECTION "defaultboot"
#define ZIPL_CONF_VAR "ZIPLCONF"
#define ZIPL_DEFAULT_CONF "/etc/zipl.conf"
#define ZIPL_DEFAULT_CONF TOOLS_SYSCONFDIR "/zipl.conf"
#define ZIPL_DEFAULT_BLSDIR "/boot/loader/entries"
#define ZIPL_STAGE3_PATH TOOLS_LIBDIR "/stage3.bin"
#define ZIPL_SIPL_PATH "/sys/firmware/ipl/has_secure"
#define MENU_DEFAULT_PROMPT 0
#define MENU_DEFAULT_TIMEOUT 0
#define MAX_DUMP_VOLUMES 32
#define SECURE_BOOT_DISABLED 0
#define SECURE_BOOT_ENABLED 1
#define SECURE_BOOT_AUTO 2
/* Internal component load address type */
typedef uint64_t address_t;

View File

@@ -352,6 +352,21 @@ whether they contain a dump signature or not.
This option can only be used together with
.BR \-\-mvdump .
.TP
.BR "\-S <SWITCH>" " or " "\-\-secure <SWITCH>"
Control the zIPL secure boot support.
<SWITCH> can take one of three values:
auto (default)
Write signatures if available and supported by the system.
1
Write signatures regardless of support indicated by the local
system. Missing signatures for stage 3 and kernel IPL files
will result in an error.
0
Do not write signatures.
.SH EXAMPLE
1. Scenario: prepare disk for booting a Linux kernel image using the
following parameters:

View File

@@ -82,6 +82,8 @@ below).
.br
defaultmenu = menu1
.br
secure = auto
.br
[linux]
.br
@@ -517,6 +519,31 @@ An optional hexadecimal address may be provided to load the kernel to a
non-default memory location.
.PP
.B secure
=
.IR auto / 1 / 0
(configuration only)
.IP
.B Configuration section:
.br
Control the zIPL secure boot support.
Set this option to one of the following values:
.IP " - " 12
.BR auto:
Write signatures if available and supported by the system.
.IP " - " 12
.BR 1:
Write signatures regardless of support indicated by the local system.
Missing signatures for stage 3 and kernel IPL files will result in an error.
.IP " - " 12
.BR 0:
Do not write signatures.
The default value for
.B 'secure'
is auto.
.PP
.B segment
=
.IR segment\-file , address

View File

@@ -7,16 +7,16 @@ ALL_CPPFLAGS += -I../include -I../boot \
-D_FILE_OFFSET_BITS=64 $(NO_PIE_CFLAGS)
ALL_LDFLAGS += -Wl,-z,noexecstack $(NO_PIE_LDFLAGS)
libs = $(rootdir)/libu2s/libu2s.a \
$(rootdir)/libutil/libutil.a
libs = $(rootdir)/libutil/libutil.a
objects = misc.o error.o scan.o job.o boot.o bootmap.o disk.o \
install.o zipl.o $(rootdir)/zipl/boot/data.o
zipl_helpers = $(basename $(wildcard zipl_helper.*.c))
chreipl_helpers = $(subst zipl_,chreipl_, $(zipl_helpers))
zipl_stage3 = ../boot/stage3.bin
all: zipl $(chreipl_helpers)
all: zipl $(chreipl_helpers) $(zipl_stage3)
zipl: $(objects) $(libs)
@@ -33,6 +33,7 @@ install: all
$(INSTALL) -m 755 $(zipl_helpers) $(chreipl_helpers) \
$(DESTDIR)$(TOOLS_LIBDIR)
$(CP) --no-dereference $(chreipl_helpers) $(DESTDIR)$(TOOLS_LIBDIR)
$(CP) --no-dereference $(zipl_stage3) $(DESTDIR)$(TOOLS_LIBDIR)
clean:
rm -f *.o $(zipl_helpers) $(chreipl_helpers) zipl
@@ -48,3 +49,6 @@ clean:
../boot/data.o:
make -C ../boot data.o
../boot/stage3.bin:
make -C ../boot stage3.bin

View File

@@ -14,6 +14,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "../boot/data.h"
#include "boot.h"
@@ -68,20 +70,17 @@ boot_check_data(void)
return 0;
}
/* Export stage 3 size for partition dump with dump kernel */
size_t
get_stage3_size()
{
return DATA_SIZE(stage3);
}
/* Create a stage 3 loader in memory.
/*
* Create a stage 3 parameter block in memory.
* Upon success, return 0 and set BUFFER to point to the data buffer and set
* BYTECOUNT to contain the loader size in bytes. Return non-zero otherwise. */
* BYTECOUNT to contain the parameter block size in bytes.
* Return non-zero otherwise.
*/
int
boot_get_stage3(void** buffer, size_t* bytecount, address_t parm_addr,
address_t initrd_addr, size_t initrd_len, address_t image_addr,
int extra_parm, uint16_t flags)
boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
address_t initrd_addr, size_t initrd_len,
address_t image_addr, int extra_parm, uint16_t flags,
size_t image_len)
{
struct boot_stage3_params params;
void* data;
@@ -92,9 +91,10 @@ boot_get_stage3(void** buffer, size_t* bytecount, address_t parm_addr,
return -1;
}
/* Get memory */
data = misc_malloc(DATA_SIZE(stage3));
data = misc_malloc(sizeof(params));
if (data == NULL)
return -1;
memset(data, 0, sizeof(params));
/* Prepare params section */
params.parm_addr = (uint64_t) parm_addr;
params.initrd_addr = (uint64_t) initrd_addr;
@@ -102,11 +102,12 @@ boot_get_stage3(void** buffer, size_t* bytecount, address_t parm_addr,
params.load_psw = (uint64_t)(image_addr | PSW_LOAD);
params.extra_parm = (uint64_t) extra_parm;
params.flags = flags;
params.image_len = (uint64_t) image_len;
params.image_addr = (uint64_t) image_addr;
/* Initialize buffer */
memcpy(data, DATA_ADDR(stage3), DATA_SIZE(stage3));
memcpy(data, &params, sizeof(struct boot_stage3_params));
memcpy(data, &params, sizeof(params));
*buffer = data;
*bytecount = DATA_SIZE(stage3);
*bytecount = sizeof(params);
return 0;
}

View File

@@ -19,6 +19,7 @@
#include <sys/types.h>
#include "lib/util_part.h"
#include "lib/util_path.h"
#include "boot.h"
#include "bootmap.h"
@@ -117,6 +118,25 @@ check_menu_positions(struct job_menu_data* menu, char* name,
return 0;
}
static bool
check_secure_boot_support(void)
{
unsigned int val;
FILE *fp;
fp = fopen(ZIPL_SIPL_PATH, "r");
if (!fp)
return false;
if (fscanf(fp, "%d", &val) != 1) {
fclose(fp);
return false;
}
fclose(fp);
return val ? true : false;
}
/* Write COUNT elements of the blocklist specified by LIST as a linked list
* of segment table blocks to the file identified by file descriptor FD. Upon
@@ -199,24 +219,21 @@ add_program_table(int fd, disk_blockptr_t* table, int entries,
return rc;
}
struct component_entry {
uint8_t data[23];
uint8_t type;
union {
uint64_t load_address;
uint64_t load_psw;
} address;
component_data compdat;
} __attribute((packed));
typedef enum {
component_execute = 0x01,
component_load = 0x02
component_load = 0x02,
component_signature = 0x03
} component_type;
static void
create_component_entry(void* buffer, disk_blockptr_t* pointer,
component_type type, uint64_t address,
component_type type, component_data data,
struct disk_info* info)
{
struct component_entry* entry;
@@ -228,10 +245,15 @@ create_component_entry(void* buffer, disk_blockptr_t* pointer,
case component_load:
bootmap_store_blockptr(&entry->data, pointer,
info);
entry->address.load_address = address;
entry->compdat.load_address = data.load_address;
break;
case component_execute:
entry->address.load_psw = address;
entry->compdat.load_psw = data.load_psw;
break;
case component_signature:
bootmap_store_blockptr(&entry->data, pointer,
info);
entry->compdat.sig_head = data.sig_head;
break;
}
}
@@ -267,7 +289,7 @@ struct component_loc {
static int
add_component_file(int fd, const char* filename, address_t load_address,
off_t offset, void* component, int add_files,
size_t trailer, void *component, int add_files,
struct disk_info* info, struct job_target_data* target,
struct component_loc *location)
{
@@ -279,8 +301,6 @@ add_component_file(int fd, const char* filename, address_t load_address,
size_t size;
blocknum_t count;
int rc;
int from;
unsigned int to;
if (add_files) {
/* Read file to buffer */
@@ -289,17 +309,10 @@ add_component_file(int fd, const char* filename, address_t load_address,
error_text("Could not read file '%s'", filename);
return rc;
}
/* Ensure minimum size */
if (size <= (size_t) offset) {
error_reason("File '%s' is too small (has to be "
"greater than %ld bytes)", filename,
(long) offset);
free(buffer);
return -1;
}
size -= trailer;
/* Write buffer */
count = disk_write_block_buffer(fd, 0, buffer + offset,
size - offset, &list, info);
count = disk_write_block_buffer(fd, 0, buffer,
size, &list, info);
free(buffer);
if (count == 0) {
error_text("Could not write to bootmap file");
@@ -321,20 +334,7 @@ add_component_file(int fd, const char* filename, address_t load_address,
disk_free_info(file_info);
if (count == 0)
return -1;
if (count * info->phy_block_size <= (size_t) offset) {
error_reason("File '%s' is too small (has to be "
"greater than %ld bytes)", filename,
(long) offset);
free(list);
return -1;
}
if (offset > 0) {
/* Shorten list by offset */
from = offset / info->phy_block_size;
count -= from;
for (to=0; to < count; to++, from++)
list[to] = list[from];
}
count -= DIV_ROUND_UP(trailer, info->phy_block_size);
}
/* Fill in component location */
loc.addr = load_address;
@@ -346,7 +346,7 @@ add_component_file(int fd, const char* filename, address_t load_address,
free(list);
if (rc == 0) {
create_component_entry(component, &segment, component_load,
load_address, info);
(component_data) load_address, info);
/* Return location if requested */
if (location != NULL)
*location = loc;
@@ -354,11 +354,10 @@ add_component_file(int fd, const char* filename, address_t load_address,
return rc;
}
static int
add_component_buffer(int fd, void* buffer, size_t size, address_t load_address,
add_component_buffer(int fd, void* buffer, size_t size, component_data data,
void* component, struct disk_info* info,
struct component_loc *location)
struct component_loc *location, int type)
{
struct component_loc loc;
disk_blockptr_t segment;
@@ -372,17 +371,21 @@ add_component_buffer(int fd, void* buffer, size_t size, address_t load_address,
error_text("Could not write to bootmap file");
return -1;
}
/* Fill in component location */
loc.addr = load_address;
loc.size = count * info->phy_block_size;
if (type == component_load) {
/* Fill in component location */
loc.addr = data.load_address;
loc.size = count * info->phy_block_size;
} else {
loc.addr = 0;
loc.size = 0;
}
/* Try to compact list */
count = disk_compact_blocklist(list, count, info);
/* Write segment table */
rc = add_segment_table(fd, list, count, &segment, info);
free(list);
if (rc == 0) {
create_component_entry(component, &segment, component_load,
load_address, info);
create_component_entry(component, &segment, type, data, info);
/* Return location if requested */
if (location != NULL)
*location = loc;
@@ -391,6 +394,30 @@ add_component_buffer(int fd, void* buffer, size_t size, address_t load_address,
}
static int
add_dummy_buffer(int fd, size_t size, address_t addr, void *component,
struct disk_info *info, struct component_loc *comp_loc)
{
char *buffer;
int rc;
buffer = misc_malloc(size);
if (buffer == NULL)
return -1;
memset(buffer, 0, size);
rc = add_component_buffer(fd, buffer, size,
(component_data) (uint64_t) addr,
component, info, comp_loc, component_load);
if (rc) {
free(buffer);
return rc;
}
free(buffer);
return 0;
}
static void
print_components(const char *name[], struct component_loc *loc, int num)
{
@@ -409,23 +436,86 @@ print_components(const char *name[], struct component_loc *loc, int num)
}
}
static int
extract_signature(char *filename, void **ret_signature,
struct signature_header *sig_head)
{
struct file_signature *file_sig;
size_t signature_size = 0;
void *signature;
char *buffer;
size_t size;
if (misc_read_file(filename, &buffer, &size, 0))
return 0;
file_sig = (void *) buffer + size - sizeof(*file_sig);
if (memcmp(file_sig->magic, SIGNATURE_MAGIC, sizeof(file_sig->magic))
!= 0)
goto out;
signature = misc_malloc(file_sig->sig_len);
if (signature == NULL)
goto out;
signature_size = file_sig->sig_len;
memcpy(signature, buffer + size - signature_size - sizeof(*file_sig),
signature_size);
*ret_signature = signature;
sig_head->length = signature_size;
switch (file_sig->id_type) {
case PKEY_ID_PKCS7:
sig_head->format = PKCS7_FORMAT;
break;
default:
error_text("Unsupported signature type %02x",
file_sig->id_type);
signature_size = 0;
goto out;
}
/* return size of signature and corresponding header */
signature_size += sizeof(*file_sig);
out:
free(buffer);
return signature_size;
}
static void
check_remaining_filesize(size_t filesize, size_t signature_size,
struct disk_info *info, char *filename)
{
if ((filesize - signature_size) % info->phy_block_size) {
fprintf(stderr,
"Warning: Size of signed file %s is not a multiple of the disk block size\n",
filename);
}
}
static int
add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
int verbose, int add_files, component_header_type type,
struct disk_info* info, struct job_target_data* target)
struct disk_info* info, struct job_target_data* target,
int is_secure)
{
struct stat stats;
void* table;
void* stage3;
size_t stage3_size;
const char *comp_name[4] = {"kernel image", "parmline",
"initial ramdisk", "internal loader"};
struct component_loc comp_loc[4];
int rc;
struct component_loc comp_loc[10];
struct signature_header sig_head;
size_t ramdisk_size, image_size;
bool secure_boot_supported;
size_t stage3_params_size;
const char *comp_name[10];
size_t signature_size;
int offset, flags = 0;
void *stage3_params;
struct stat stats;
void *signature;
int comp_nr = 0;
void *table;
int rc;
memset(comp_loc, 0, sizeof(comp_loc));
memset(&sig_head, 0, sizeof(sig_head));
table = misc_malloc(info->phy_block_size);
if (table == NULL)
return -1;
@@ -456,55 +546,189 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
return -1;
}
}
if (info->type == disk_type_scsi)
ramdisk_size = stats.st_size;
if (info->type == disk_type_scsi) {
flags |= STAGE3_FLAG_SCSI;
/*
* Add dummy components for stage 3 heap and stack to block the
* associated memory areas against firmware use.
*/
rc = add_dummy_buffer(fd, STAGE3_HEAP_SIZE, STAGE3_HEAP_ADDRESS,
VOID_ADD(table, offset), info,
&comp_loc[comp_nr]);
if (rc) {
error_text("Could not add stage3 HEAP dummy");
free(table);
return rc;
}
comp_name[comp_nr] = "heap area";
offset += sizeof(struct component_entry);
comp_nr++;
rc = add_dummy_buffer(fd, STAGE3_STACK_SIZE,
STAGE3_STACK_ADDRESS,
VOID_ADD(table, offset), info,
&comp_loc[comp_nr]);
if (rc) {
error_text("Could not add stage3 STACK dummy");
free(table);
return rc;
}
comp_name[comp_nr] = "stack area";
offset += sizeof(struct component_entry);
comp_nr++;
}
if (ipl->is_kdump)
flags |= STAGE3_FLAG_KDUMP;
/* Get kernel file size */
if (stat(ipl->image, &stats)) {
error_reason(strerror(errno));
error_text("Could not get information for file '%s'",
ipl->image);
free(table);
return -1;
}
image_size = stats.st_size;
secure_boot_supported = check_secure_boot_support();
signature_size = extract_signature(ZIPL_STAGE3_PATH, &signature,
&sig_head);
if (signature_size &&
(is_secure == SECURE_BOOT_ENABLED ||
(is_secure == SECURE_BOOT_AUTO && secure_boot_supported))) {
if (verbose)
printf(" signature for.....: %s\n", ZIPL_STAGE3_PATH);
rc = add_component_buffer(fd, signature, sig_head.length,
(component_data)sig_head,
VOID_ADD(table, offset), info,
&comp_loc[comp_nr],
component_signature);
if (rc) {
error_text("Could not add stage3 signature");
free(table);
return rc;
}
comp_name[comp_nr] = "loader signature";
offset += sizeof(struct component_entry);
comp_nr++;
free(signature);
} else if (is_secure == SECURE_BOOT_ENABLED) {
/*
* If secure boot is forced and we have failed to extract a
* signature for the stage 3 loader zipl will abort with an
* error message
*/
error_text("Could not install Secure Boot IPL records");
error_reason("Missing signature in internal loader file %s",
ZIPL_STAGE3_PATH);
free(table);
return -1;
}
/* Add stage 3 loader to bootmap */
rc = boot_get_stage3(&stage3, &stage3_size, ipl->parm_addr,
ipl->ramdisk_addr, (size_t) stats.st_size,
ipl->is_kdump ? ipl->image_addr + 0x10 :
ipl->image_addr,
(info->type == disk_type_scsi) ? 0 : 1,
flags);
rc = add_component_file(fd, ZIPL_STAGE3_PATH, DEFAULT_STAGE3_ADDRESS,
signature_size, VOID_ADD(table, offset), 1,
info, target, &comp_loc[comp_nr]);
if (rc) {
error_text("Could not add internal loader file '%s'",
ZIPL_STAGE3_PATH);
free(table);
return rc;
}
offset += sizeof(struct component_entry);
comp_name[comp_nr] = "internal loader";
comp_nr++;
/* Add stage 3 parameter to bootmap */
rc = boot_get_stage3_parms(&stage3_params, &stage3_params_size,
ipl->parm_addr, ipl->ramdisk_addr,
ramdisk_size,
ipl->is_kdump ? ipl->image_addr + 0x10 :
ipl->image_addr,
(info->type == disk_type_scsi) ? 0 : 1,
flags, image_size);
if (rc) {
free(table);
return rc;
}
rc = add_component_buffer(fd, stage3, stage3_size,
DEFAULT_STAGE3_ADDRESS,
VOID_ADD(table, offset), info, &comp_loc[3]);
free(stage3);
rc = add_component_buffer(fd, stage3_params, stage3_params_size,
(component_data) (uint64_t)
DEFAULT_STAGE3_PARAMS_ADDRESS,
VOID_ADD(table, offset), info,
&comp_loc[comp_nr], component_load);
free(stage3_params);
if (rc) {
error_text("Could not add stage 3 boot loader");
error_text("Could not add parameters");
free(table);
return -1;
}
offset += sizeof(struct component_entry);
comp_name[comp_nr] = "parameters";
comp_nr++;
/* Add kernel image */
if (verbose) {
printf(" kernel image......: %s\n", ipl->image);
}
signature_size = extract_signature(ipl->image, &signature, &sig_head);
if (signature_size &&
(is_secure == SECURE_BOOT_ENABLED ||
(is_secure == SECURE_BOOT_AUTO && secure_boot_supported))) {
if (verbose)
printf(" signature for.....: %s\n", ipl->image);
rc = add_component_buffer(fd, signature, sig_head.length,
(component_data)sig_head,
VOID_ADD(table, offset), info,
&comp_loc[comp_nr],
component_signature);
if (rc) {
error_text("Could not add image signature");
free(table);
return rc;
}
comp_name[comp_nr] = "image signature";
offset += sizeof(struct component_entry);
comp_nr++;
free(signature);
check_remaining_filesize(image_size, signature_size, info,
ipl->image);
} else if (is_secure == SECURE_BOOT_ENABLED) {
/*
* If secure boot is forced and we have failed to extract a
* signature for the kernel image zipl will abort with an
* error message
*/
error_text("Could not install Secure Boot IPL records");
error_reason("Missing signature in image file %s",
ipl->image);
free(table);
return -1;
}
rc = add_component_file(fd, ipl->image, ipl->image_addr,
KERNEL_HEADER_SIZE, VOID_ADD(table, offset),
add_files, info, target, &comp_loc[0]);
signature_size, VOID_ADD(table, offset),
add_files, info, target, &comp_loc[comp_nr]);
if (rc) {
error_text("Could not add image file '%s'", ipl->image);
free(table);
return rc;
}
offset += sizeof(struct component_entry);
comp_name[comp_nr] = "kernel image";
comp_nr++;
/* Add kernel parmline */
if (ipl->parmline != NULL) {
/* Add kernel parmline */
if (verbose) {
printf(" kernel parmline...: '%s'\n", ipl->parmline);
}
rc = add_component_buffer(fd, ipl->parmline,
strlen(ipl->parmline) + 1,
ipl->parm_addr,
(component_data) ipl->parm_addr,
VOID_ADD(table, offset),
info, &comp_loc[1]);
info, &comp_loc[comp_nr],
component_load);
if (rc) {
error_text("Could not add parmline '%s'",
ipl->parmline);
@@ -512,14 +736,45 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
return -1;
}
offset += sizeof(struct component_entry);
comp_name[comp_nr] = "parmline";
comp_nr++;
}
/* finally add ramdisk */
if (ipl->ramdisk != NULL) {
signature_size = extract_signature(ipl->ramdisk, &signature,
&sig_head);
if (signature_size &&
(is_secure == SECURE_BOOT_ENABLED ||
(is_secure == SECURE_BOOT_AUTO &&
secure_boot_supported))) {
if (verbose) {
printf(" signature for.....: %s\n",
ipl->ramdisk);
}
rc = add_component_buffer(fd, signature,
sig_head.length,
(component_data)sig_head,
VOID_ADD(table, offset), info,
&comp_loc[comp_nr],
component_signature);
if (rc) {
error_text("Could not add ramdisk signature");
free(table);
return rc;
}
comp_name[comp_nr] = "ramdisk signature";
offset += sizeof(struct component_entry);
comp_nr++;
free(signature);
check_remaining_filesize(ramdisk_size, signature_size,
info, ipl->ramdisk);
}
rc = add_component_file(fd, ipl->ramdisk,
ipl->ramdisk_addr, 0,
ipl->ramdisk_addr, signature_size,
VOID_ADD(table, offset),
add_files, info, target, &comp_loc[2]);
add_files, info, target,
&comp_loc[comp_nr]);
if (rc) {
error_text("Could not add ramdisk '%s'",
ipl->ramdisk);
@@ -527,13 +782,16 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
return -1;
}
offset += sizeof(struct component_entry);
comp_name[comp_nr] = "initial ramdisk";
comp_nr++;
}
if (verbose)
print_components(comp_name, comp_loc, 4);
print_components(comp_name, comp_loc, comp_nr);
/* Terminate component table */
create_component_entry(VOID_ADD(table, offset), NULL,
component_execute,
ZIPL_STAGE3_ENTRY_ADDRESS | PSW_LOAD,
(component_data) (uint64_t)
(ZIPL_STAGE3_ENTRY_ADDRESS | PSW_LOAD),
info);
/* Write component table */
rc = disk_write_block_aligned(fd, table, info->phy_block_size,
@@ -584,7 +842,8 @@ if (rc) {
print_components(comp_name, comp_loc, 1);
/* Terminate component table */
create_component_entry(VOID_ADD(table, offset), NULL,
component_execute, PSW_DISABLED_WAIT, info);
component_execute, (component_data) (uint64_t)
PSW_DISABLED_WAIT, info);
/* Write component table */
rc = disk_write_block_aligned(fd, table, info->phy_block_size,
program, info);
@@ -674,7 +933,7 @@ add_dump_program(int fd, struct job_dump_data* dump,
return rc;
ipl.parm_addr = dump->parm_addr;
return add_ipl_program(fd, &ipl, program, verbose, 1,
type, info, target);
type, info, target, SECURE_BOOT_DISABLED);
}
@@ -711,7 +970,7 @@ build_program_table(int fd, struct job_data* job, disk_blockptr_t* pointer,
rc = add_ipl_program(fd, &job->data.ipl, &table[0],
verbose || job->command_line,
job->add_files, component_header,
info, &job->target);
info, &job->target, job->is_secure);
break;
case job_segment:
if (job->command_line)
@@ -762,7 +1021,8 @@ build_program_table(int fd, struct job_data* job, disk_blockptr_t* pointer,
&table[job->data.menu.entry[i].pos],
verbose || job->command_line,
job->add_files, component_header,
info, &job->target);
info, &job->target,
job->is_secure);
break;
case job_print_usage:
case job_print_version:
@@ -913,7 +1173,9 @@ bootmap_create(struct job_data *job, disk_blockptr_t *program_table,
ulong size;
ulong unused_size;
size = DIV_ROUND_UP(get_stage3_size(), info->phy_block_size);
/* Use approximated stage 3 size as starting point */
size = MINIMUM_ADDRESS;
/* Ramdisk */
if (job->data.dump.ramdisk != NULL) {
if (stat(job->data.dump.ramdisk, &st))

View File

@@ -198,8 +198,8 @@ disk_get_info(const char* device, struct job_target_data* target,
long devsize;
FILE *fh;
char *script_pre = TOOLS_LIBDIR "/zipl_helper.";
char *script_file;
char *ppn_cmd;
char *script_file = NULL;
char *ppn_cmd = NULL;
char buffer[80];
char value[40];
int majnum, minnum;
@@ -443,10 +443,12 @@ type_determined:
data->fs_block_size = -1;
close(fd);
*info = data;
free(script_file);
return 0;
out_close:
close(fd);
free(ppn_cmd);
free(script_file);
free(data);
return -1;

View File

@@ -23,7 +23,7 @@
#include <syslog.h>
#include <unistd.h>
#include "lib/u2s.h"
#include "lib/util_sys.h"
#include "boot.h"
#include "bootmap.h"
@@ -1132,7 +1132,7 @@ install_mvdump(char* const device[], struct job_target_data* target, int count,
parm.param[i].num_heads = info[i]->geo.heads;
parm.param[i].blocksize = info[i]->phy_block_size >> 8;
parm.param[i].devno = info[i]->devno;
if (u2s_getbusid(device[i], busid)) {
if (util_sys_get_dev_addr(device[i], busid) != 0) {
error_text("Could not find bus-ID for '%s'", device[i]);
rc = -1;
goto out;

View File

@@ -52,11 +52,12 @@ static struct option options[] = {
{ "dry-run", no_argument, NULL, '0'},
{ "force", no_argument, NULL, 'f'},
{ "kdump", required_argument, NULL, 'k'},
{ "secure", required_argument, NULL, 'S'},
{ NULL, 0, NULL, 0 }
};
/* Command line option abbreviations */
static const char option_string[] = "-c:b:t:i:r:p:P:d:D:M:s:m:hHnVvaT:fk:";
static const char option_string[] = "-c:b:t:i:r:p:P:d:D:M:s:S:m:hHnVvaT:fk:";
struct command_line {
char* data[SCAN_KEYWORD_NUM];
@@ -113,7 +114,7 @@ get_command_line(int argc, char* argv[], struct command_line* line)
break;
case 'D':
error_reason("dumptofs has been deprecated, use "
"--dump instead");
"--dumpto instead");
rc = -1;
break;
case 'M':
@@ -215,6 +216,11 @@ get_command_line(int argc, char* argv[], struct command_line* line)
} else
cmdline.menu = optarg;
break;
case 'S':
is_keyword = 1;
rc = store_option(&cmdline, scan_keyword_secure,
optarg);
break;
case 'h':
cmdline.help = 1;
break;
@@ -511,7 +517,7 @@ get_ipl_components(struct job_ipl_data *ipl, struct component_loc **clp,
/* Fill in component data */
num = 0;
rc = set_cl_element(&cl[num++], "kernel image", ipl->image,
&ipl->image_addr, 0, 0x10000,
&ipl->image_addr, 0, 0,
MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc)
goto error;
@@ -553,7 +559,7 @@ get_dump_components(struct job_dump_data *dump,
/* Fill in component data */
num = 0;
rc = set_cl_element(&cl[num++], "kernel image", dump->image,
&dump->image_addr, 0, 0x10000,
&dump->image_addr, 0, 0x0,
MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc)
goto error;
@@ -1263,6 +1269,26 @@ type_from_target(char *target, disk_type_t *type)
}
}
static int
set_secure_ipl(char *keyword, struct job_data *job)
{
if (strcmp(keyword, "auto") == 0) {
job->is_secure = SECURE_BOOT_AUTO;
} else if (strcmp(keyword, "0") == 0) {
job->is_secure = SECURE_BOOT_DISABLED;
} else if (strcmp(keyword, "1") == 0) {
if (job->target.targettype != disk_type_scsi) {
error_reason("Secure boot forced for non-SCSI disk type");
return -1;
}
job->is_secure = SECURE_BOOT_ENABLED;
} else {
error_reason("Invalid secure boot setting '%s'",
keyword);
return -1;
}
return 0;
}
static int
get_job_from_section_data(char* data[], struct job_data* job, char* section)
@@ -1345,6 +1371,13 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
return -1;
}
}
/* Fill in secure boot */
if (data[(int) scan_keyword_secure] != NULL) {
rc = set_secure_ipl(data[(int) scan_keyword_secure],
job);
if (rc)
return rc;
}
break;
case section_ipl_tape:
/* Tape IPL job */
@@ -1502,6 +1535,13 @@ get_menu_job(struct scan_token* scan, char* menu, struct job_data* job)
job->data.menu.timeout =
atol(scan[i].content.keyword.value);
break;
case scan_keyword_secure:
rc = set_secure_ipl(
scan[i].content.keyword.value,
job);
if (rc)
return rc;
break;
case scan_keyword_target:
job->target.bootmap_dir = misc_strdup(
scan[i].content.keyword.value);
@@ -1840,6 +1880,7 @@ job_get(int argc, char* argv[], struct job_data** data)
job->add_files = cmdline.add_files;
job->data.mvdump.force = cmdline.force;
job->dry_run = cmdline.dry_run;
job->is_secure = SECURE_BOOT_AUTO;
/* Get job data from user input */
if (cmdline.help) {
job->command_line = 1;

View File

@@ -22,7 +22,6 @@
#include "error.h"
#include "misc.h"
/* Allocate SIZE bytes of memory. Upon success, return pointer to memory.
* Return NULL otherwise. */
void *

View File

@@ -45,45 +45,45 @@ enum scan_key_state scan_key_table[SCAN_SECTION_NUM][SCAN_KEYWORD_NUM] = {
* ult to tofs e mete file isk ent et pt out ultm dump
* rs enu
*
* targ targ targ targ targ defa kdum
* etba etty etge etbl etof ulta p
* targ targ targ targ targ defa kdum secu
* etba etty etge etbl etof ulta p re
* se pe omet ocks fset uto
* ry ize
*/
/* default auto */
{opt, inv, inv, inv, inv, inv, inv, inv, req, opt, opt, inv, inv, inv,
opt, opt, opt, opt, opt, opt, inv},
opt, opt, opt, opt, opt, opt, inv, opt},
/* default menu */
{inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv,
inv, inv, inv, inv, inv, inv, inv},
inv, inv, inv, inv, inv, inv, inv, opt},
/* default section */
{req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv,
inv, inv, inv, inv, inv, inv, inv},
inv, inv, inv, inv, inv, inv, inv, opt},
/* ipl */
{inv, inv, inv, req, opt, opt, opt, inv, req, inv, inv, inv, inv, inv,
opt, opt, opt, opt, opt, inv, opt},
opt, opt, opt, opt, opt, inv, opt, opt},
/* segment load */
{inv, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv, inv,
inv, inv, inv, inv, inv, inv, inv},
inv, inv, inv, inv, inv, inv, inv, inv},
/* part dump */
{inv, req, inv, inv, inv, inv, inv, inv, opt, inv, inv, inv, inv, inv,
inv, inv, inv, inv, inv, inv, inv},
inv, inv, inv, inv, inv, inv, inv, inv},
/* fs dump */
{inv, inv, req, inv, opt, opt, inv, inv, req, inv, inv, inv, inv, inv,
inv, inv, inv, inv, inv, inv, inv},
inv, inv, inv, inv, inv, inv, inv, inv},
/* ipl tape */
{inv, inv, inv, req, opt, opt, opt, inv, inv, inv, inv, inv, req, inv,
inv, inv, inv, inv, inv, inv, inv},
inv, inv, inv, inv, inv, inv, inv, inv},
/* multi volume dump */
{inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req,
inv, inv, inv, inv, inv, inv, inv}
inv, inv, inv, inv, inv, inv, inv, inv}
};
/* Determines which keyword may be present in a menu section */
enum scan_key_state scan_menu_key_table[SCAN_KEYWORD_NUM] = {
/* menu section */
opt, inv, inv, inv, inv, inv, inv, inv, req, opt, opt, inv, inv, inv,
opt, opt, opt, opt, opt, inv, inv
opt, opt, opt, opt, opt, inv, inv, opt
};
/* Mapping of keyword IDs to strings */
@@ -111,6 +111,7 @@ static const struct {
{ "timeout", scan_keyword_timeout},
{ "tape", scan_keyword_tape},
{ "kdump", scan_keyword_kdump},
{ "secure", scan_keyword_secure},
};
/* List of keywords that are used without an assignment */
@@ -698,6 +699,10 @@ scan_bls_field(struct misc_file_buffer *file, struct scan_token* scan,
}
val_end = file->pos;
while (val_end > val_start && isblank(file->buffer[val_end - 1]))
val_end--;
file->buffer[key_end] = '\0';
file->buffer[val_end] = '\0';
@@ -779,6 +784,7 @@ scan_bls(const char* blsdir, struct scan_token** token, int scan_size)
case EOF:
break;
case '\t':
case '\n':
case '\0':
case ' ':
file.pos++;
@@ -1863,6 +1869,7 @@ scan_build_automenu(struct scan_token* scan)
/* defaultmenu */ 1 +
/* menu heading */ 1 +
/* keyword default,prompt,timeout */ 3 +
/* keyword secure */ 1 +
/* target keywords*/ num_targets +
/* missing target definitions */ num_sections * num_targets +
/* number assigment */ num_sections;
@@ -1978,6 +1985,14 @@ scan_build_automenu(struct scan_token* scan)
db_keyword[i]))
goto err;
}
/* secure= */
i = (int) scan_keyword_secure;
if (db_keyword[i]) {
if (scan_append_keyword_assignment(new_scan, &i_new,
scan_keyword_secure,
db_keyword[i]))
goto err;
}
/* target= */
/* targetbase= */
/* targetgeometry= */

View File

@@ -3,7 +3,7 @@
*
* Keystore handling functions
*
* Copyright IBM Corp. 2018
* Copyright IBM Corp. 2018, 2019
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -133,14 +133,7 @@ static int _keystore_get_key_filenames(struct keystore *keystore,
*/
static int _keystore_reencipher_key_exists(struct key_filenames *file_names)
{
struct stat sb;
int rc;
rc = stat(file_names->renc_filename, &sb);
if (rc == 0 && !S_ISREG(sb.st_mode))
rc = 1;
return !rc;
return util_path_is_reg_file("%s", file_names->renc_filename);
}
/**
@@ -153,20 +146,14 @@ static int _keystore_reencipher_key_exists(struct key_filenames *file_names)
*/
static int _keystore_exists_keyfiles(struct key_filenames *file_names)
{
struct stat sb_skey, sb_info;
int rc_skey, rc_info;
bool rc_skey, rc_info;
rc_skey = stat(file_names->skey_filename, &sb_skey);
if (rc_skey == 0 && !S_ISREG(sb_skey.st_mode))
rc_skey = 1;
rc_skey = util_path_is_reg_file("%s", file_names->skey_filename);
rc_info = util_path_is_reg_file("%s", file_names->info_filename);
rc_info = stat(file_names->info_filename, &sb_info);
if (rc_info == 0 && !S_ISREG(sb_info.st_mode))
rc_info = 1;
if (rc_skey == 0 && rc_info == 0)
if (rc_skey && rc_info)
return 1;
if (rc_skey != 0 && rc_info != 0 &&
if (!rc_skey && !rc_info &&
_keystore_reencipher_key_exists(file_names) == 0)
return 0;
return -1;
@@ -369,7 +356,7 @@ out:
return 0;
}
typedef int (*check_association_t)(const char *value, bool remove,
typedef int (*check_association_t)(const char *value, bool remove, bool set,
char **normalized, void *private);
/**
@@ -407,7 +394,7 @@ static int _keystore_set_association(struct properties *key_props,
for (i = 0; newvals[i] != NULL; i++) {
if (check_func != NULL) {
rc = check_func(newvals[i], 0, &normalized,
rc = check_func(newvals[i], 0, 1, &normalized,
check_private);
if (rc != 0)
goto out;
@@ -488,7 +475,7 @@ static int _keystore_add_association(struct properties *key_props,
for (i = 0; newvals[i] != NULL; i++) {
if (check_func != NULL) {
rc = check_func(newvals[i], 0, &normalized,
rc = check_func(newvals[i], 0, 0, &normalized,
check_private);
if (rc != 0)
goto out;
@@ -567,7 +554,7 @@ static int _keystore_remove_association(struct properties *key_props,
for (i = 0; delvals[i] != NULL; i++) {
if (check_func != NULL) {
rc = check_func(delvals[i], 1, &normalized,
rc = check_func(delvals[i], 1, 0, &normalized,
check_private);
if (rc != 0)
goto out;
@@ -1085,20 +1072,27 @@ out:
return rc;
}
struct apqn_check {
bool noonlinecheck;
bool nomsg;
};
/**
* Checks an APQN value for its syntax. This is a callback function for
* function _keystore_change_association().
*
* @param[in] apqn the APQN value to check
* @param[in] remove if true the apqn is removed
* @param[in] set if true the apqn is set (not used here)
* @param[out] normalized normalized value on return or NULL if no change
* @param[in] private private data (not used here)
* @param[in] private private data (struct apqn_check)
*
* @returns 0 if successful, a negative errno value otherwise
*/
static int _keystore_apqn_check(const char *apqn, bool remove,
char **normalized, void *UNUSED(private))
static int _keystore_apqn_check(const char *apqn, bool remove, bool UNUSED(set),
char **normalized, void *private)
{
struct apqn_check *info = (struct apqn_check *)private;
int rc, card, domain;
regmatch_t pmatch[1];
regex_t reg_buf;
@@ -1124,15 +1118,16 @@ static int _keystore_apqn_check(const char *apqn, bool remove,
util_asprintf(normalized, "%02x.%04x", card, domain);
if (remove) {
if (remove || info->noonlinecheck) {
rc = 0;
goto out;
}
rc = _keystore_is_apqn_online(card, domain);
if (rc != 1) {
warnx("The APQN %02x.%04x is %s", card, domain,
rc == -1 ? "not a CCA card" : "not online");
if (info->nomsg == 0)
warnx("The APQN %02x.%04x is %s", card, domain,
rc == -1 ? "not a CCA card" : "not online");
rc = -EIO;
goto out;
} else {
@@ -1149,6 +1144,7 @@ struct volume_check {
struct keystore *keystore;
const char *name;
const char *volume;
bool set;
};
/**
@@ -1173,6 +1169,11 @@ static int _keystore_volume_check_process(struct keystore *UNUSED(keystore),
{
struct volume_check *info = (struct volume_check *)private;
if (info->set) {
if (strcmp(name, info->name) == 0)
return 0;
}
warnx("Key '%s' is already associated with volume '%s'", name,
info->volume);
return -EINVAL;
@@ -1204,12 +1205,13 @@ static int _keystore_is_block_device(const char *volume)
*
* @param[in] volume the Volume value to check
* @param[in] remove if true the volume is removed
* @param[in] set if true the volume is set
* @param[out] normalized normalized value on return or NULL if no change
* @param[in] private private data: struct volume_check
*
* @returns 0 if successful, a negative errno value otherwise
*/
static int _keystore_volume_check(const char *volume, bool remove,
static int _keystore_volume_check(const char *volume, bool remove, bool set,
char **normalized, void *private)
{
struct volume_check *info = (struct volume_check *)private;
@@ -1250,6 +1252,7 @@ static int _keystore_volume_check(const char *volume, bool remove,
goto out;
}
info->set = set;
rc = _keystore_process_filtered(info->keystore, NULL, info->volume,
NULL, NULL,
_keystore_volume_check_process, info);
@@ -1362,7 +1365,7 @@ struct keystore *keystore_new(const char *directory, bool verbose)
warnx("Can not access '%s': %s", directory, strerror(errno));
return NULL;
}
if (!(sb.st_mode & S_IFDIR)) {
if (!S_ISDIR(sb.st_mode)) {
warnx("'%s' is not a directory", directory);
return NULL;
}
@@ -1543,6 +1546,8 @@ static int _keystore_set_default_properties(struct properties *key_props)
* key (optional, can be NULL)
* @param[in] apqns a comma separated list of APQNs associated with this
* key (optional, can be NULL)
* @param[in] noapqncheck if true, the specified APQN(s) are not checked for
* existence and type.
* @param[in] sector_size the sector size to use with dm-crypt. It must be power
* of two and in range 512 - 4096 bytes. 0 means that
* the sector size is not specified and the system
@@ -1554,10 +1559,14 @@ static int _keystore_create_info_file(struct keystore *keystore,
const struct key_filenames *filenames,
const char *description,
const char *volumes, const char *apqns,
bool noapqncheck,
size_t sector_size,
const char *volume_type)
{
struct volume_check vol_check = { .keystore = keystore, .name = name };
struct volume_check vol_check = { .keystore = keystore, .name = name,
.set = 0 };
struct apqn_check apqn_check = { .noonlinecheck = noapqncheck,
.nomsg = 0 };
struct properties *key_props;
char temp[10];
int rc;
@@ -1583,7 +1592,8 @@ static int _keystore_create_info_file(struct keystore *keystore,
rc = _keystore_change_association(key_props, PROP_NAME_APQNS,
apqns != NULL ? apqns : "",
"APQN", _keystore_apqn_check, NULL);
"APQN", _keystore_apqn_check,
&apqn_check);
if (rc != 0)
goto out;
@@ -1607,7 +1617,8 @@ static int _keystore_create_info_file(struct keystore *keystore,
rc = -EINVAL;
goto out;
}
rc = properties_set(key_props, PROP_NAME_VOLUME_TYPE, volume_type);
rc = properties_set2(key_props, PROP_NAME_VOLUME_TYPE, volume_type,
true);
if (rc != 0) {
warnx("Invalid characters in volume-type");
goto out;
@@ -1642,15 +1653,18 @@ out:
}
/**
* Extracts a card/domain pair from the specified APQns, or uses AUTOSELECT
* if no APQNs are specified.
* Extracts an online card/domain pair from the specified APQns. If none of the
* specified APQNs are online, then -ENODEV is returned.
* If no APQNs are specified at all, then it uses AUTOSELECT and returns zero.
*/
static int _keystore_get_card_domain(const char *apqns, unsigned int *card,
unsigned int *domain)
{
struct apqn_check apqn_check = { .noonlinecheck = 0, .nomsg = 1 };
char **apqn_list;
char *normalized = NULL;
int rc = 0;
int i;
*card = AUTOSELECT;
*domain = AUTOSELECT;
@@ -1662,17 +1676,23 @@ static int _keystore_get_card_domain(const char *apqns, unsigned int *card,
if (apqn_list[0] == NULL)
goto out;
rc = _keystore_apqn_check(apqn_list[0], 0, &normalized, NULL);
if (normalized != NULL)
free(normalized);
if (rc != 0)
goto out;
for (i = 0; apqn_list[i] != NULL; i++) {
rc = _keystore_apqn_check(apqn_list[i], 0, 0, &normalized,
&apqn_check);
if (normalized != NULL)
free(normalized);
if (rc == -EINVAL)
goto out;
if (rc != 0)
continue;
if (sscanf(apqn_list[0], "%x.%x", card, domain) != 2) {
rc = -EINVAL;
goto out;
if (sscanf(apqn_list[i], "%x.%x", card, domain) == 2)
goto found;
}
warnx("None of the specified APQNs is online or of type CCA");
rc = -ENODEV;
found:
out:
str_list_free_string_array(apqn_list);
return rc;
@@ -1688,6 +1708,8 @@ out:
* key (optional, can be NULL)
* @param[in] apqns a comma separated list of APQNs associated with this
* key (optional, can be NULL)
* @param[in] noapqncheck if true, the specified APQN(s) are not checked for
* existence and type.
* @param[in] sector_size the sector size to use with dm-crypt. It must be power
* of two and in range 512 - 4096 bytes. 0 means that
* the sector size is not specified and the system
@@ -1704,9 +1726,10 @@ out:
*/
int keystore_generate_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
const char *apqns, size_t sector_size,
size_t keybits, bool xts, const char *clear_key_file,
const char *volume_type, int pkey_fd)
const char *apqns, bool noapqncheck,
size_t sector_size, size_t keybits, bool xts,
const char *clear_key_file, const char *volume_type,
int pkey_fd)
{
struct key_filenames file_names = { NULL, NULL, NULL };
struct properties *key_props = NULL;
@@ -1748,7 +1771,7 @@ int keystore_generate_key(struct keystore *keystore, const char *name,
rc = _keystore_create_info_file(keystore, name, &file_names,
description, volumes, apqns,
sector_size, volume_type);
noapqncheck, sector_size, volume_type);
if (rc != 0)
goto out_free_props;
@@ -1781,6 +1804,8 @@ out_free_key_filenames:
* key (optional, can be NULL)
* @param[in] apqns a comma separated list of APQNs associated with this
* key (optional, can be NULL)
* @param[in] noapqncheck if true, the specified APQN(s) are not checked for
* existence and type.
* @param[in] sector_size the sector size to use with dm-crypt. It must be power
* of two and in range 512 - 4096 bytes. 0 means that
* the sector size is not specified and the system
@@ -1792,7 +1817,7 @@ out_free_key_filenames:
*/
int keystore_import_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
const char *apqns, size_t sector_size,
const char *apqns, bool noapqncheck, size_t sector_size,
const char *import_file, const char *volume_type)
{
struct key_filenames file_names = { NULL, NULL, NULL };
@@ -1832,7 +1857,7 @@ int keystore_import_key(struct keystore *keystore, const char *name,
rc = _keystore_create_info_file(keystore, name, &file_names,
description, volumes, apqns,
sector_size, volume_type);
noapqncheck, sector_size, volume_type);
if (rc != 0)
goto out_free_props;
@@ -1870,6 +1895,8 @@ out_free_key_filenames:
* key, or an APQN prefixed with '+' or '-' to add or
* remove that APQN respectively. If NULL then the APQNs
* are not changed.
* @param[in] noapqncheck if true, the specified APQN(s) are not checked for
* existence and type.
* @param[in] sector_size the sector size to use with dm-crypt. It must be power
* of two and in range 512 - 4096 bytes. 0 means that
* the sector size is not specified and the system
@@ -1883,10 +1910,13 @@ out_free_key_filenames:
*/
int keystore_change_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
const char *apqns, long int sector_size,
const char *volume_type)
const char *apqns, bool noapqncheck,
long int sector_size, const char *volume_type)
{
struct volume_check vol_check = { .keystore = keystore, .name = name };
struct volume_check vol_check = { .keystore = keystore, .name = name,
.set = 0 };
struct apqn_check apqn_check = { .noonlinecheck = noapqncheck,
.nomsg = 0 };
struct key_filenames file_names = { NULL, NULL, NULL };
struct properties *key_props = NULL;
char temp[30];
@@ -1931,7 +1961,8 @@ int keystore_change_key(struct keystore *keystore, const char *name,
if (apqns != NULL) {
rc = _keystore_change_association(key_props, PROP_NAME_APQNS,
apqns, "APQN",
_keystore_apqn_check, NULL);
_keystore_apqn_check,
&apqn_check);
if (rc != 0)
goto out;
}
@@ -1959,8 +1990,8 @@ int keystore_change_key(struct keystore *keystore, const char *name,
goto out;
}
rc = properties_set(key_props, PROP_NAME_VOLUME_TYPE,
volume_type);
rc = properties_set2(key_props, PROP_NAME_VOLUME_TYPE,
volume_type, true);
if (rc != 0) {
warnx("Invalid characters in volume-type");
goto out;
@@ -2265,6 +2296,7 @@ static void _keystore_print_record(struct util_rec *rec,
struct validate_info {
struct util_rec *rec;
int pkey_fd;
bool noapqncheck;
unsigned long int num_valid;
unsigned long int num_invalid;
unsigned long int num_warnings;
@@ -2418,8 +2450,9 @@ static int _keystore_process_validate(struct keystore *keystore,
"master key\n", 0);
info->num_warnings++;
}
if (_keystore_display_apqn_status(properties, name) != 0)
info->num_warnings++;
if (info->noapqncheck == 0)
if (_keystore_display_apqn_status(properties, name) != 0)
info->num_warnings++;
if (_keystore_display_volume_status(properties, name) != 0)
info->num_warnings++;
@@ -2435,11 +2468,16 @@ out:
*
* @param[in] keystore the key store
* @param[in] name_filter the name filter to select the key (can be NULL)
* @param[in] apqn_filter the APQN filter to select the key (can be NULL)
* @param[in] noapqncheck if true, the specified APQN(s) are not checked for
* existence and type.
* @param[in] pkey_fd the file descriptor of /dev/pkey
*
* @returns 0 for success or a negative errno in case of an error
*/
int keystore_validate_key(struct keystore *keystore, const char *name_filter,
const char *apqn_filter, int pkey_fd)
const char *apqn_filter, bool noapqncheck,
int pkey_fd)
{
struct validate_info info;
struct util_rec *rec;
@@ -2450,6 +2488,7 @@ int keystore_validate_key(struct keystore *keystore, const char *name_filter,
rec = _keystore_setup_record(1);
info.pkey_fd = pkey_fd;
info.noapqncheck = noapqncheck;
info.rec = rec;
info.num_valid = 0;
info.num_invalid = 0;
@@ -2833,7 +2872,7 @@ int keystore_copy_key(struct keystore *keystore, const char *name,
const char *newname, const char *volumes)
{
struct volume_check vol_check = { .keystore = keystore,
.name = newname };
.name = newname, .set = 0 };
struct key_filenames file_names = { NULL, NULL, NULL };
struct key_filenames new_names = { NULL, NULL, NULL };
struct properties *key_prop = NULL;
@@ -3012,7 +3051,7 @@ out:
* @returnd 0 if the user confirmed the deletion, a negative errno value
* otherwise
*/
static int _keystore_propmp_for_remove(struct keystore *keystore,
static int _keystore_prompt_for_remove(struct keystore *keystore,
const char *name,
struct key_filenames *file_names)
{
@@ -3033,7 +3072,8 @@ static int _keystore_propmp_for_remove(struct keystore *keystore,
_keystore_msg_for_volumes(msg, key_prop, VOLUME_TYPE_PLAIN);
free(msg);
printf("%s: Remove key '%s'? ", program_invocation_short_name, name);
printf("%s: Remove key '%s' [y/N]? ", program_invocation_short_name,
name);
if (fgets(str, sizeof(str), stdin) == NULL) {
rc = -EIO;
goto out;
@@ -3042,6 +3082,7 @@ static int _keystore_propmp_for_remove(struct keystore *keystore,
str[strlen(str) - 1] = '\0';
pr_verbose(keystore, "Prompt reply: '%s'", str);
if (strcasecmp(str, "y") != 0 && strcasecmp(str, "yes") != 0) {
warnx("Operation aborted");
rc = -ECANCELED;
goto out;
}
@@ -3078,7 +3119,7 @@ int keystore_remove_key(struct keystore *keystore, const char *name,
goto out;
if (!quiet) {
if (_keystore_propmp_for_remove(keystore, name,
if (_keystore_prompt_for_remove(keystore, name,
&file_names) != 0)
goto out;
}
@@ -3242,6 +3283,13 @@ static int _keystore_execute_cmd(const char *cmd,
struct crypt_info {
bool execute;
bool batch_mode;
const char *keyfile;
size_t keyfile_offset;
size_t keyfile_size;
size_t tries;
bool open;
bool format;
char **volume_filter;
int (*process_func)(struct keystore *keystore,
const char *volume,
@@ -3280,16 +3328,46 @@ static int _keystore_process_cryptsetup(struct keystore *keystore,
const char *volume_type,
struct crypt_info *info)
{
char *keyfile_opt = NULL, *offset_opt = NULL;
char *size_opt = NULL, *tries_opt = NULL;
char *common_passphrase_options;
size_t common_len;
char temp[100];
int rc = 0;
char *cmd;
sprintf(temp, "--sector-size %lu ", sector_size);
if (info->keyfile) {
util_asprintf(&keyfile_opt, "--key-file '%s' ", info->keyfile);
if (info->keyfile_offset > 0)
util_asprintf(&offset_opt, "--keyfile-offset %lu ",
info->keyfile_offset);
if (info->keyfile_size > 0)
util_asprintf(&size_opt, "--keyfile-size %lu ",
info->keyfile_size);
}
if (info->tries > 0)
util_asprintf(&tries_opt, "--tries %lu ", info->tries);
util_asprintf(&common_passphrase_options, "%s%s%s%s",
keyfile_opt != NULL ? keyfile_opt : "",
offset_opt != NULL ? offset_opt : "",
size_opt != NULL ? size_opt : "",
tries_opt != NULL ? tries_opt : "");
common_len = strlen(common_passphrase_options);
free(keyfile_opt);
free(offset_opt);
free(size_opt);
free(tries_opt);
if (strcasecmp(volume_type, VOLUME_TYPE_PLAIN) == 0) {
if (info->format)
return 0;
util_asprintf(&cmd,
"cryptsetup plainOpen %s--key-file '%s' "
"cryptsetup plainOpen %s%s--key-file '%s' "
"--key-size %lu --cipher %s %s%s %s",
info->batch_mode ? "-q " : "",
keystore->verbose ? "-v " : "", key_file_name,
key_file_size * 8, cipher_spec,
sector_size > 0 ? temp : "", volume, dmname);
@@ -3301,45 +3379,69 @@ static int _keystore_process_cryptsetup(struct keystore *keystore,
printf("%s\n", cmd);
}
} else if (strcasecmp(volume_type, VOLUME_TYPE_LUKS2) == 0) {
/*
* Use PBKDF2 as key derivation function for LUKS2 volumes.
* LUKS2 uses Argon2i as default, but this might cause
* out-of-memory errors when multiple LUKS2 volumes are opened
* automatically via /etc/crypttab
*/
util_asprintf(&cmd,
"cryptsetup luksFormat %s--type luks2 "
"--master-key-file '%s' --key-size %lu "
"--cipher %s --pbkdf pbkdf2 %s%s",
keystore->verbose ? "-v " : "", key_file_name,
key_file_size * 8, cipher_spec,
sector_size > 0 ? temp : "", volume);
if (info->open) {
util_asprintf(&cmd,
"cryptsetup luksOpen %s%s%s%s %s",
info->batch_mode ? "-q " : "",
keystore->verbose ? "-v " : "",
common_len > 0 ?
common_passphrase_options : "",
volume, dmname);
if (info->execute) {
printf("Executing: %s\n", cmd);
rc = _keystore_execute_cmd(cmd, "cryptsetup");
if (info->execute) {
printf("Executing: %s\n", cmd);
rc = _keystore_execute_cmd(cmd, "cryptsetup");
} else {
printf("%s\n", cmd);
}
} else {
printf("%s\n", cmd);
}
/*
* Use PBKDF2 as key derivation function for LUKS2
* volumes. LUKS2 uses Argon2i as default, but this
* might cause out-of-memory errors when multiple LUKS2
* volumes are opened automatically via /etc/crypttab
*/
util_asprintf(&cmd,
"cryptsetup luksFormat %s%s--type luks2 "
"--master-key-file '%s' --key-size %lu "
"--cipher %s --pbkdf pbkdf2 %s%s%s",
info->batch_mode ? "-q " : "",
keystore->verbose ? "-v " : "",
key_file_name, key_file_size * 8,
cipher_spec, common_len > 0 ?
common_passphrase_options : "",
sector_size > 0 ? temp : "", volume);
free(cmd);
if (rc != 0)
return rc;
if (info->execute) {
printf("Executing: %s\n", cmd);
rc = _keystore_execute_cmd(cmd, "cryptsetup");
} else {
printf("%s\n", cmd);
}
util_asprintf(&cmd,
"zkey-cryptsetup setvp %s%s", volume,
keystore->verbose ? " -V " : "");
free(cmd);
if (rc != 0)
return rc;
if (info->execute) {
printf("Executing: %s\n", cmd);
rc = _keystore_execute_cmd(cmd, "zkey-cryptsetup");
} else {
printf("%s\n", cmd);
util_asprintf(&cmd,
"zkey-cryptsetup setvp %s %s%s", volume,
common_len > 0 ?
common_passphrase_options : "",
keystore->verbose ? "-V" : "");
if (info->execute) {
printf("Executing: %s\n", cmd);
rc = _keystore_execute_cmd(cmd,
"zkey-cryptsetup");
} else {
printf("%s\n", cmd);
}
}
} else {
return -EINVAL;
}
free(common_passphrase_options);
free(cmd);
return rc;
}
@@ -3369,7 +3471,7 @@ static int _keystore_process_crypttab(struct keystore *UNUSED(keystore),
size_t key_file_size,
size_t sector_size,
const char *volume_type,
struct crypt_info *UNUSED(info))
struct crypt_info *info)
{
char temp[1000];
@@ -3388,11 +3490,22 @@ static int _keystore_process_crypttab(struct keystore *UNUSED(keystore),
}
sprintf(temp, ",sector-size=%lu", sector_size);
printf("%s\t%s\t%s\tplain,cipher=%s,size=%lu,hash=plain%s\n",
printf("%s\t%s\t%s\tplain,cipher=%s,size=%lu%s\n",
dmname, volume, key_file_name, cipher_spec,
key_file_size * 8, sector_size > 0 ? temp : "");
} else if (strcasecmp(volume_type, VOLUME_TYPE_LUKS2) == 0) {
printf("%s\t%s\n", dmname, volume);
printf("%s\t%s\t%s\tluks", dmname, volume,
info->keyfile != NULL ? info->keyfile : "none");
if (info->keyfile != NULL) {
if (info->keyfile_offset > 0)
printf(",keyfile-offset=%lu",
info->keyfile_offset);
if (info->keyfile_size > 0)
printf(",keyfile-size=%lu", info->keyfile_size);
}
if (info->tries > 0)
printf(",tries=%lu", info->tries);
printf("\n");
} else {
return -EINVAL;
}
@@ -3577,11 +3690,21 @@ out:
* @param[in] execute If TRUE the cryptsetup command is executed,
* otherwise it is printed to stdout
* @param[in] volume_type the type of volume to generate cryptsetup cmds for
* *
* @param[in] keyfile If non-NULL, specifies the name of the file to
* read the passphrase from.
* @param[in] keyfile_offset the offset in bytes for reading from keyfile
* @param[in] keyfile_size the size in bytes for reading from keyfile
* @param[in] tries the number of tries for passphrase entry
* @param[in] batch_mode If TRUE, suppress cryptsetup confirmation questions
* @param[in] open If TRUE, generate luksOpen/plainOpen commands
* @param[in] format If TRUE, generate luksFormat commands
* @returns 0 for success or a negative errno in case of an error
*/
int keystore_cryptsetup(struct keystore *keystore, const char *volume_filter,
bool execute, const char *volume_type)
bool execute, const char *volume_type,
const char *keyfile, size_t keyfile_offset,
size_t keyfile_size, size_t tries, bool batch_mode,
bool open, bool format)
{
struct crypt_info info = { 0 };
int rc;
@@ -3598,6 +3721,13 @@ int keystore_cryptsetup(struct keystore *keystore, const char *volume_filter,
}
info.execute = execute;
info.open = open;
info.format = format;
info.batch_mode = batch_mode;
info.keyfile = keyfile;
info.keyfile_offset = keyfile_offset;
info.keyfile_size = keyfile_size;
info.tries = tries;
info.volume_filter = str_list_split(volume_filter);
info.process_func = _keystore_process_cryptsetup;
@@ -3629,11 +3759,17 @@ int keystore_cryptsetup(struct keystore *keystore, const char *volume_filter,
* for the volume filter. If not specified, the filter
* checks the volume part only.
* @param[in] volume_type the type of volume to generate crypttab entries for
* @param[in] keyfile If non-NULL, specifies the name of the file to
* read the passphrase from.
* @param[in] keyfile_offset the offset in bytes for reading from keyfile
* @param[in] keyfile_size the size in bytes for reading from keyfile
* @param[in] tries the number of tries for passphrase entry
*
* @returns 0 for success or a negative errno in case of an error
*/
int keystore_crypttab(struct keystore *keystore, const char *volume_filter,
const char *volume_type)
const char *volume_type, const char *keyfile,
size_t keyfile_offset, size_t keyfile_size, size_t tries)
{
struct crypt_info info = { 0 };
int rc;
@@ -3649,6 +3785,10 @@ int keystore_crypttab(struct keystore *keystore, const char *volume_filter,
return -EINVAL;
}
info.keyfile = keyfile;
info.keyfile_offset = keyfile_offset;
info.keyfile_size = keyfile_size;
info.tries = tries;
info.volume_filter = str_list_split(volume_filter);
info.process_func = _keystore_process_crypttab;

View File

@@ -28,25 +28,27 @@ struct keystore *keystore_new(const char *directory, bool verbose);
int keystore_generate_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
const char *apqns, size_t sector_size,
size_t keybits, bool xts, const char *clear_key_file,
const char *volume_type, int pkey_fd);
const char *apqns, bool noapqncheck,
size_t sector_size, size_t keybits, bool xts,
const char *clear_key_file, const char *volume_type,
int pkey_fd);
int keystore_import_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
const char *apqns, size_t sector_size,
const char *apqns, bool noapqncheck, size_t sector_size,
const char *import_file, const char *volume_type);
int keystore_change_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
const char *apqns, long int sector_size,
const char *volume_type);
const char *apqns, bool noapqncheck,
long int sector_size, const char *volume_type);
int keystore_rename_key(struct keystore *keystore, const char *name,
const char *newname);
int keystore_validate_key(struct keystore *keystore, const char *name_filter,
const char *apqn_filter, int pkey_fd);
const char *apqn_filter, bool noapqncheck,
int pkey_fd);
int keystore_reencipher_key(struct keystore *keystore, const char *name_filter,
const char *apqn_filter,
@@ -68,10 +70,14 @@ int keystore_list_keys(struct keystore *keystore, const char *name_filter,
const char *volume_type);
int keystore_cryptsetup(struct keystore *keystore, const char *volume_filter,
bool execute, const char *volume_type);
bool execute, const char *volume_type,
const char *keyfile, size_t keyfile_offset,
size_t keyfile_size, size_t tries, bool batch_mode,
bool open, bool format);
int keystore_crypttab(struct keystore *keystore, const char *volume_filter,
const char *volume_type);
const char *volume_type, const char *keyfile,
size_t keyfile_offset, size_t keyfile_size, size_t tries);
void keystore_free(struct keystore *keystore);

View File

@@ -267,7 +267,7 @@ static u8 *read_clear_key(const char *keyfile, size_t keybits, bool xts,
return NULL;
}
} else {
keybits = DOUBLE_KEYSIZE_FOR_XTS(size * 8, xts);
keybits = HALF_KEYSIZE_FOR_XTS(size * 8, xts);
}
switch (keybits) {

View File

@@ -9,6 +9,7 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -183,14 +184,16 @@ static struct property *properties_find(struct properties *properties,
* @param[in] properties the properties object
* @param[in] name the name of the property
* @param[in] value the value of the property
* @param[in] uppercase if true the value is set all uppercase
*
* @returns 0 on success,
* -EINVAL if the name or value contains invalid characters
*/
int properties_set(struct properties *properties,
const char *name, const char *value)
int properties_set2(struct properties *properties,
const char *name, const char *value, bool uppercase)
{
struct property *property;
int i;
util_assert(properties != NULL, "Internal error: properties is NULL");
util_assert(name != NULL, "Internal error: name is NULL");
@@ -211,9 +214,30 @@ int properties_set(struct properties *properties,
property->value = util_strdup(value);
util_list_add_tail(&properties->list, property);
}
if (uppercase) {
for (i = 0; property->value[i] != '\0'; i++)
property->value[i] = toupper(property->value[i]);
}
return 0;
}
/**
* Adds or updates a property
*
* @param[in] properties the properties object
* @param[in] name the name of the property
* @param[in] value the value of the property
*
* @returns 0 on success,
* -EINVAL if the name or value contains invalid characters
*/
int properties_set(struct properties *properties,
const char *name, const char *value)
{
return properties_set2(properties, name, value, false);
}
/**
* Gets a property
*

Some files were not shown because too many files have changed in this diff Show More