mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
188 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aca6704cfa | ||
|
|
3a85d1ebe6 | ||
|
|
e8f9244224 | ||
|
|
a49887de1f | ||
|
|
4e61b4c9f4 | ||
|
|
d884cc27c1 | ||
|
|
bf3810ea6a | ||
|
|
99d7ec51a7 | ||
|
|
327d132aac | ||
|
|
fcb89662e0 | ||
|
|
a52243ea04 | ||
|
|
805a4d4408 | ||
|
|
b1e4f6f331 | ||
|
|
10d72caac0 | ||
|
|
0ea693d95c | ||
|
|
0ff130ed84 | ||
|
|
8a57017af3 | ||
|
|
41ec030db1 | ||
|
|
34aff761d0 | ||
|
|
01cb8c4085 | ||
|
|
8d58a9abb0 | ||
|
|
ce82010827 | ||
|
|
c0d8034962 | ||
|
|
95290562e0 | ||
|
|
638cbbe332 | ||
|
|
70157462d8 | ||
|
|
40bc181f31 | ||
|
|
a2eb03660d | ||
|
|
f4c4c40b78 | ||
|
|
fe78faa8ae | ||
|
|
617a8248e8 | ||
|
|
c5695e43c4 | ||
|
|
7b3add9389 | ||
|
|
44fdf586e1 | ||
|
|
0d6e63abdc | ||
|
|
1771e7f2f3 | ||
|
|
c403208332 | ||
|
|
2a99007a6e | ||
|
|
994269c278 | ||
|
|
ae5687f1d1 | ||
|
|
b856ae62a7 | ||
|
|
7b4be02441 | ||
|
|
2403d1e166 | ||
|
|
3f03ceb007 | ||
|
|
150ae08678 | ||
|
|
43a10f4806 | ||
|
|
4e08c5fcd8 | ||
|
|
6532bf02c2 | ||
|
|
3f7b459606 | ||
|
|
14830b1ead | ||
|
|
1dae9b4f49 | ||
|
|
b58414d7dc | ||
|
|
64524f17fa | ||
|
|
1b87b016d4 | ||
|
|
94bdb17d01 | ||
|
|
2625cd704f | ||
|
|
59df2c6d02 | ||
|
|
8ba03642b7 | ||
|
|
1956e7abc5 | ||
|
|
d76cb1d53a | ||
|
|
7d5f2ba038 | ||
|
|
8bbf1d5bea | ||
|
|
b2fcb608d5 | ||
|
|
76b7928592 | ||
|
|
339b69cf3b | ||
|
|
419f042f55 | ||
|
|
128e5f86fe | ||
|
|
b29e824923 | ||
|
|
3175d52ce7 | ||
|
|
17024c02af | ||
|
|
5cd680c0be | ||
|
|
c333f91d4c | ||
|
|
095e5ee226 | ||
|
|
6ee5ffef91 | ||
|
|
82f8c137e1 | ||
|
|
b21a824fda | ||
|
|
f74b8d7d6f | ||
|
|
b766d4a53c | ||
|
|
a1126352ec | ||
|
|
35e539a428 | ||
|
|
99100b3f99 | ||
|
|
49faa1d7fd | ||
|
|
86ce85b3a6 | ||
|
|
b1c1bea4e2 | ||
|
|
e68547f06f | ||
|
|
95d784d866 | ||
|
|
783ae9735e | ||
|
|
5a78c7f45d | ||
|
|
586040a0ad | ||
|
|
deb61b5cd9 | ||
|
|
8be51ad454 | ||
|
|
cef50c2140 | ||
|
|
33bd112e2f | ||
|
|
2c31ed6f14 | ||
|
|
771623832b | ||
|
|
b8060baf44 | ||
|
|
76a0401deb | ||
|
|
e6ac87d7a2 | ||
|
|
0a711d4934 | ||
|
|
f90e913806 | ||
|
|
94a7ec22f2 | ||
|
|
940ce67900 | ||
|
|
c12faf0128 | ||
|
|
a3d50487ed | ||
|
|
b1d8e40bfe | ||
|
|
8d3949f77b | ||
|
|
2f49025d49 | ||
|
|
4c9ceeeb64 | ||
|
|
3a0c394fa2 | ||
|
|
20a4ebd83c | ||
|
|
4a9f66fc31 | ||
|
|
35d68b2101 | ||
|
|
522c67a2c3 | ||
|
|
f4ee6c2c8d | ||
|
|
377f2a59f5 | ||
|
|
176f0405b8 | ||
|
|
839d34e758 | ||
|
|
a68d1e323b | ||
|
|
549c7ef9e7 | ||
|
|
103c9444c9 | ||
|
|
fe7bef3f09 | ||
|
|
8a88ada9c5 | ||
|
|
538bc7b4e8 | ||
|
|
b56451e5a4 | ||
|
|
63f9a672d0 | ||
|
|
2c5c5ef4b4 | ||
|
|
5a3ffc2036 | ||
|
|
e576443859 | ||
|
|
43067df78e | ||
|
|
973059438f | ||
|
|
9d3567d9ce | ||
|
|
7687b0fcda | ||
|
|
6f70f34b79 | ||
|
|
37aed81745 | ||
|
|
5aa1824eef | ||
|
|
82603e589a | ||
|
|
3ba897a1be | ||
|
|
fa92a7f7c9 | ||
|
|
f569849e57 | ||
|
|
458c27a0e1 | ||
|
|
e4dcf084c5 | ||
|
|
bed1bc8676 | ||
|
|
8e315c4401 | ||
|
|
ae8fa4371f | ||
|
|
29ff9408e0 | ||
|
|
a24be25779 | ||
|
|
58337d7f90 | ||
|
|
fcaad5a8e2 | ||
|
|
4d598ade86 | ||
|
|
b455ee9a31 | ||
|
|
82b9328e48 | ||
|
|
f45a45c38c | ||
|
|
d1bf9e68c6 | ||
|
|
0356d78bc2 | ||
|
|
a4f48415a0 | ||
|
|
c9f0e3accf | ||
|
|
9dd432ca94 | ||
|
|
179bc57cdf | ||
|
|
e1d1c6df9c | ||
|
|
e894fb61d8 | ||
|
|
c3a84109b7 | ||
|
|
1ca5f63dee | ||
|
|
60bc1e38d0 | ||
|
|
431e4542ca | ||
|
|
731f00202c | ||
|
|
2945593991 | ||
|
|
f375327085 | ||
|
|
338bea49c2 | ||
|
|
d15e36cf24 | ||
|
|
4b76530788 | ||
|
|
cb1c002bed | ||
|
|
d6f7eff5b5 | ||
|
|
e1692b7079 | ||
|
|
54b3c9ef24 | ||
|
|
48743aa28b | ||
|
|
7ce988ac59 | ||
|
|
f4fec5f120 | ||
|
|
2739b8a488 | ||
|
|
ce9c518b97 | ||
|
|
bd2a2cc6a1 | ||
|
|
6547d1ae4c | ||
|
|
650265e296 | ||
|
|
b122acb422 | ||
|
|
9710f29770 | ||
|
|
ed01bac8e2 | ||
|
|
66d3aa849a | ||
|
|
95e4b3413a | ||
|
|
06e0d569f1 |
@@ -10,3 +10,4 @@
|
||||
--ignore FILE_PATH_CHANGES
|
||||
--ignore NEW_TYPEDEFS
|
||||
--ignore SPDX_LICENSE_TAG
|
||||
--ignore STRNCPY
|
||||
|
||||
37
.clang-tidy
Normal file
37
.clang-tidy
Normal file
@@ -0,0 +1,37 @@
|
||||
Checks: >
|
||||
bugprone-*,
|
||||
clang-analyzer-*,
|
||||
misc-*,
|
||||
performance-*,
|
||||
portability-*,
|
||||
readability-*,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-misc-include-cleaner,
|
||||
-readability-braces-around-statements,
|
||||
-readability-identifier-length,
|
||||
-readability-isolate-declaration,
|
||||
-modernize-*,
|
||||
-performance-*,
|
||||
-portability-*,
|
||||
-readability-implicit-bool-conversion
|
||||
|
||||
CheckOptions:
|
||||
- key: readability-identifier-naming.VariableCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.FunctionCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.StructCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.EnumCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.EnumConstantCase
|
||||
value: UPPER_CASE
|
||||
- key: readability-identifier-naming.MacroDefinitionCase
|
||||
value: UPPER_CASE
|
||||
- key: bugprone-sizeof-expression.WarnOnSizeOfPointer
|
||||
value: true
|
||||
- key: misc-unused-parameters.StrictMode
|
||||
value: true
|
||||
|
||||
FormatStyle: file
|
||||
UseColor: true
|
||||
17
.gitignore
vendored
17
.gitignore
vendored
@@ -25,6 +25,7 @@ compile_commands.json
|
||||
#
|
||||
**/.detect-openssl.dep.c
|
||||
*.debug
|
||||
*/autocompletion_generator_host
|
||||
ap_tools/ap-check
|
||||
cmsfs-fuse/cmsfs-fuse
|
||||
cpacfstats/cpacfstats
|
||||
@@ -34,8 +35,20 @@ cpumf/lscpumf
|
||||
cpumf/lshwc
|
||||
cpumf/lspai
|
||||
cpumf/pai
|
||||
cpumf/_chcpumf
|
||||
cpumf/_lscpumf
|
||||
cpumf/_lshwc
|
||||
cpumf/_lspai
|
||||
cpumf/_pai
|
||||
cpumf/chcpumf.bash
|
||||
cpumf/lscpumf.bash
|
||||
cpumf/lshwc.bash
|
||||
cpumf/lspai.bash
|
||||
cpumf/pai.bash
|
||||
cpuplugd/cpuplugd
|
||||
dasdfmt/dasdfmt
|
||||
dasdfmt/_dasdfmt
|
||||
dasdfmt/dasdfmt.bash
|
||||
dasdinfo/dasdinfo
|
||||
dasdview/dasdview
|
||||
dump2tar/src/dump2tar
|
||||
@@ -63,7 +76,7 @@ libekmfweb/check-dep-libekmfweb
|
||||
libekmfweb/detect-openssl-version.dep
|
||||
libekmfweb/libekmfweb.so
|
||||
libekmfweb/libekmfweb.so.1
|
||||
libekmfweb/libekmfweb.so.1.0
|
||||
libekmfweb/libekmfweb.so.1.1
|
||||
libkmipclient/check-dep-libkmipclient
|
||||
libkmipclient/detect-openssl-version.dep
|
||||
libkmipclient/libkmipclient.so
|
||||
@@ -119,7 +132,7 @@ ziomon/ziomon_zfcpdd
|
||||
ziomon/ziorep_traffic
|
||||
ziomon/ziorep_utilization
|
||||
zipl/boot/*.bin
|
||||
zipl/boot/*.exec
|
||||
zipl/boot/*.elf
|
||||
zipl/boot/.loaders
|
||||
zipl/boot/data.h
|
||||
zipl/src/chreipl_helper.device-mapper
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
exclude: \.(bin|crl|crt|key)$
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.1.0
|
||||
rev: v6.0.0
|
||||
hooks:
|
||||
- id: check-merge-conflict
|
||||
- id: end-of-file-fixer
|
||||
@@ -11,6 +11,9 @@ repos:
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-shebang-scripts-are-executable
|
||||
exclude_types: ['rust']
|
||||
- id: check-yaml
|
||||
- id: check-json
|
||||
- id: check-toml
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: git-clang-format
|
||||
@@ -24,7 +27,7 @@ repos:
|
||||
minimum_pre_commit_version: "2.9.0"
|
||||
types_or: [c++, c]
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.2.1
|
||||
rev: v2.4.1
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude_types: ['rust']
|
||||
|
||||
10
AUTHORS.md
10
AUTHORS.md
@@ -1,11 +1,13 @@
|
||||
List of all individuals having contributed content to s390-tools
|
||||
----------------------------------------------------------------
|
||||
|
||||
- Ajaykumar Rajappa
|
||||
- Alexander Egorenkov
|
||||
- Alexandra Winter
|
||||
- Alexey Ishchuk
|
||||
- Andreas Herrmann
|
||||
- André Wild
|
||||
- Annu Sharma
|
||||
- Antoinette Kaschner
|
||||
- Arnd Bergmann
|
||||
- Axel Wirbser
|
||||
@@ -28,6 +30,7 @@ List of all individuals having contributed content to s390-tools
|
||||
- Eberhard Pasch
|
||||
- Eduard Shishkin
|
||||
- Einar Lueck
|
||||
- Ellen McIntyre
|
||||
- Eric Farman
|
||||
- Eric Sandeen
|
||||
- Erwin Vicari
|
||||
@@ -49,8 +52,8 @@ List of all individuals having contributed content to s390-tools
|
||||
- Graham Inggs
|
||||
- Guevenc Guelce
|
||||
- Hannes Reinecke
|
||||
- Hans-Joachim Picht
|
||||
- Hans Wippel
|
||||
- Hans-Joachim Picht
|
||||
- Harald Freudenberger
|
||||
- Heiko Carstens
|
||||
- Hendrik Brueckner
|
||||
@@ -72,12 +75,13 @@ List of all individuals having contributed content to s390-tools
|
||||
- Jens Remus
|
||||
- Jochen Roehrig
|
||||
- Joern Siglen
|
||||
- Jörn Siglen
|
||||
- Juergen Christ
|
||||
- Julian Wiedmann
|
||||
- Jörn Siglen
|
||||
- Karsten Graul
|
||||
- Kittipon Meesompop
|
||||
- Klaus-Dieter Wacker
|
||||
- L. E. Segovia
|
||||
- Lakhvich Dmitriy
|
||||
- Marc Hartmayer
|
||||
- Mario Held
|
||||
@@ -110,6 +114,7 @@ List of all individuals having contributed content to s390-tools
|
||||
- Raimund Schroeder
|
||||
- Ralph Wuerthner
|
||||
- Rene Trumpp
|
||||
- Richie Buturla
|
||||
- Rolf Schaefer
|
||||
- Sa Liu
|
||||
- Sascha Silbe
|
||||
@@ -132,6 +137,7 @@ List of all individuals having contributed content to s390-tools
|
||||
- Sven Schnelle
|
||||
- Sven Schuetz
|
||||
- Swen Schillig
|
||||
- Szabina Korbai
|
||||
- Taraka R. Bodireddy
|
||||
- Thomas Heidrich
|
||||
- Thomas Huth
|
||||
|
||||
69
CHANGELOG.md
69
CHANGELOG.md
@@ -1,6 +1,75 @@
|
||||
Release history for s390-tools (MIT version)
|
||||
--------------------------------------------
|
||||
|
||||
* __v2.40.0 (2025-12-11)__
|
||||
|
||||
For Linux kernel version: 6.18
|
||||
|
||||
Add new tools / libraries:
|
||||
- Add project-wide .clang-tidy configuration
|
||||
- libutil: Introduce util_time for time related functionality
|
||||
- libutil: Introduce zsh/bash autocompletion tooling based on util_opt
|
||||
- pvinfo: Tool to display Secure Execution system information
|
||||
- pvverify: Tool to verify host-key documents
|
||||
|
||||
Changes of existing tools:
|
||||
- cpumf: Implement zsh and bash autocompletion
|
||||
- dasdfmt: Implement zsh and bash autocompletion
|
||||
- dbginfo.sh: Add NetworkManager and netplan
|
||||
- dbginfo.sh: Add kvm_stat
|
||||
- dbginfo.sh: Adding stp time information
|
||||
- dbginfo.sh: Simplify procfs collection
|
||||
- hyptop: Add physical information row
|
||||
- hyptop: Calculate sample time delta for physical partition
|
||||
- hyptop: Replace long option names using _ with - for consistency
|
||||
For example: --cpu_types -> --cpu-types
|
||||
(Options with _ are still supported for backward compatibility)
|
||||
- libekmfweb: Add function to validate a certificate against the identity key
|
||||
- netboot: Add longer kernel command lines support
|
||||
- udev/rules.d: Make virtio-blk devices non-rotational
|
||||
- udev/rules.d: Set default io scheduler to 'none' for virtio-blk
|
||||
- ziomon: Add support to sample device symlinks (/dev/disk/...)
|
||||
- ziorep_config: Add fcp-lun details to -M option output
|
||||
- ziorep_config: Add port_id and failed attributes to -A option output
|
||||
- netboot: Install on non-s390 architectures
|
||||
|
||||
Bug Fixes:
|
||||
- lib(ekmfweb|kmipclient): Use ln without -r
|
||||
- s390-tools: Fix various compilation issues with musl libc
|
||||
- zipl/boot: Fix unused loadparm when SCLP line-mode console is absent
|
||||
|
||||
* __v2.39.0 (2025-10-14)__
|
||||
|
||||
For Linux kernel version: 6.16 / 6.17
|
||||
|
||||
Changes of existing tools:
|
||||
- chpstat: Add options to select IEC units for scaling (SI units are default)
|
||||
- chzdev: Introduce --no-module-load option
|
||||
- cpi: Disable CPI for SEL guests by default
|
||||
- dbginfo.sh: Enhance logging on timeout triggered
|
||||
- iucvterm: Install symlink for lsiucvallow.8 man page
|
||||
- lshwc: Add command line flag to specify individual counters
|
||||
- lspai: Add command line flag for delta values
|
||||
- lspai: Add command line flag for short counter names
|
||||
- lspai: Add command line flag to specify individual counters
|
||||
- lspai: Add command line flags for all cpus
|
||||
- lspai: Add command line flags for hexadecimal output
|
||||
- man: Use CR for constant width font
|
||||
- pvimg: Add '--image-key' option
|
||||
- zdev: Allow dynamic control of module load
|
||||
- zipl/boot: Fix EBCDIC code page 500 conversion and decrease size by 200 bytes
|
||||
- zipl: Add support of heterogeneous mirrors (remove technical limitations
|
||||
on mirrored targets, thus allowing mirrored devices consist of partitions
|
||||
at different offsets on disks of different types and geometry).
|
||||
- zkey: Add support for generating and importing exportable secure keys
|
||||
|
||||
Bug Fixes:
|
||||
- chpstat: Fix scaling of DPU utilization calculation
|
||||
- zdev/dracut: Prevent loading of unused kernel modules
|
||||
- zdev: Fix double device configuration on DPM systems
|
||||
- zdev: Fix double device configuration with rd.dasd
|
||||
- zipl_helper.device-mapper: Fix segfault in an error path
|
||||
|
||||
* __v2.38.0 (2025-06-25)__
|
||||
|
||||
For Linux kernel version: 6.14 / 6.15
|
||||
|
||||
2
Makefile
2
Makefile
@@ -21,7 +21,7 @@ TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
|
||||
else
|
||||
BASELIB_DIRS =
|
||||
LIB_DIRS = libpv
|
||||
TOOL_DIRS = rust
|
||||
TOOL_DIRS = netboot rust
|
||||
endif
|
||||
|
||||
SUB_DIRS = $(BASELIB_DIRS) $(LIB_DIRS) $(TOOL_DIRS)
|
||||
|
||||
12
README.md
12
README.md
@@ -414,6 +414,18 @@ the different tools are provided:
|
||||
dumping).
|
||||
Removing the inflate modules and function prototypes are the only major
|
||||
modifications made to the kernel version of zlib.
|
||||
For stand-alone NVMe and list-directed DASD dump, the following tools/packages
|
||||
are required to populate dumper's initramfs:
|
||||
- cat
|
||||
- cut
|
||||
- findmnt
|
||||
- logsave
|
||||
- makedumpfile
|
||||
- mount
|
||||
- poweroff
|
||||
- sha256sum
|
||||
- sync
|
||||
- umount
|
||||
|
||||
* zgetdump
|
||||
For building zgetdump you need OpenSSL version 1.1.0 or newer
|
||||
|
||||
@@ -129,7 +129,7 @@ else # $(ENABLE_DOC) != 1
|
||||
# freshness of the man page can be checked, even if `pandoc` is not available,
|
||||
# or ENABLE_DOC disabled.
|
||||
|
||||
MANPAGE_FRESH := $(shell sha256sum --check .chreipl-fcp-mpath.7.cksum >/dev/null && echo 1 || echo 0)
|
||||
MANPAGE_FRESH := $(shell sha256sum -c .chreipl-fcp-mpath.7.cksum >/dev/null && echo 1 || echo 0)
|
||||
ifeq ($(MANPAGE_FRESH),0)
|
||||
$(warning chreipl-fcp-mpath.7 is outdated, please regenerate it by calling `make ENABLE_DOC=1`)
|
||||
endif
|
||||
|
||||
18
common.mak
18
common.mak
@@ -32,7 +32,7 @@ endif
|
||||
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
|
||||
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
|
||||
VERSION := 2
|
||||
RELEASE := 38
|
||||
RELEASE := 40
|
||||
PATCHLEVEL := 0
|
||||
DISTRELEASE := build-$(shell date +%Y%m%d)
|
||||
S390_TOOLS_RELEASE := $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
||||
@@ -119,6 +119,10 @@ ifneq ($(HOST_ARCH),$(BUILD_ARCH))
|
||||
endif
|
||||
endif
|
||||
|
||||
# *_FOR_BUILD variables define compilation configurations for binaries used
|
||||
# during the build process (e.g. autocompleteion script generators). This
|
||||
# is especially important for cross-compilation where these binaries need to
|
||||
# be executed on the build system.
|
||||
$(eval $(call define_toolchain_variables,_FOR_BUILD,))
|
||||
$(eval $(call define_toolchain_variables,,$(CROSS_COMPILE)))
|
||||
|
||||
@@ -165,7 +169,7 @@ ifeq ("${ENABLE_WERROR}", "1")
|
||||
endif
|
||||
|
||||
DEFAULT_CPPFLAGS = -D_GNU_SOURCE
|
||||
DEFAULT_LDFLAGS = -rdynamic
|
||||
DEFAULT_LDFLAGS = -rdynamic -Wl,--as-needed
|
||||
|
||||
ifeq ("${ASAN}","1")
|
||||
DEFAULT_CFLAGS += -fsanitize=address -fno-omit-frame-pointer
|
||||
@@ -201,7 +205,7 @@ endef
|
||||
# $5: Additional compiler & linker options (optional)
|
||||
#
|
||||
check_dep=\
|
||||
printf "\#include <%s>\n int main(void) {return 0;}\n" $2 | ( $(CC) $(filter-out --coverage, $(ALL_CFLAGS)) $(ALL_CPPFLAGS) $5 -o /dev/null -x c - ) > /dev/null 2>&1; \
|
||||
printf "\#include <%s>\n int main(void) {return 0;}\n" $2 | ( $(CC) $(filter-out --coverage, $(ALL_CFLAGS)) $(ALL_CPPFLAGS) -Wl,--no-as-needed $5 -o /dev/null -x c - ) > /dev/null 2>&1; \
|
||||
if [ $$? != 0 ]; \
|
||||
then \
|
||||
printf " REQCHK %s (%s)\n" $1 $2; \
|
||||
@@ -340,14 +344,6 @@ endif
|
||||
export INSTALL CFLAGS CXXFLAGS \
|
||||
LDFLAGS CPPFLAGS ALL_CFLAGS ALL_CXXFLAGS ALL_LDFLAGS ALL_CPPFLAGS
|
||||
|
||||
ifneq ($(shell $(CC_SILENT) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),)
|
||||
NO_PIE_CFLAGS := -fno-pie
|
||||
NO_PIE_LDFLAGS := -no-pie
|
||||
else
|
||||
NO_PIE_CFLAGS :=
|
||||
NO_PIE_LDFLAGS :=
|
||||
endif
|
||||
|
||||
# Overwrite implicit makefile rules for having nice compile output
|
||||
%.o: %.c
|
||||
ifeq ("${C}","1")
|
||||
|
||||
81
common_autocomp.mak
Normal file
81
common_autocomp.mak
Normal file
@@ -0,0 +1,81 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright IBM Corp. 2025
|
||||
|
||||
|
||||
# This file defines the build process for shell autocompletion binaries
|
||||
#
|
||||
# How to incorporate it into tool Makefiles:
|
||||
#
|
||||
# 0. The file with the autocompletion script generation code should be named
|
||||
# 'autocompletion_generator_host.c'
|
||||
#
|
||||
# 1. Define the 'bash-completions' and 'zsh-completions' variables: both must be a list
|
||||
# of the names of all the shell completion scripts that belong to the tools the Makefile
|
||||
# is responsible for building.
|
||||
#
|
||||
# (The name of a zsh completion script is the same as the name of the tool,
|
||||
# prefixed by an underscore)
|
||||
#
|
||||
# (The name of a bash completion script is the same as the name of the tool,
|
||||
# suffixed by '.bash')
|
||||
#
|
||||
# 2. include this file
|
||||
#
|
||||
# +1: Add the autocompletion scripts to the .gitignore file
|
||||
#
|
||||
# (See cpumf or dasdfmt as example)
|
||||
|
||||
|
||||
autocomplete-bin := autocompletion_generator_host
|
||||
|
||||
autocomp-object := $(rootdir)/libutil/util_autocomp_host.o
|
||||
|
||||
$(autocomp-object): $(rootdir)/libutil
|
||||
$(MAKE) -C $(rootdir)/libutil/ $(notdir $@)
|
||||
|
||||
$(autocomplete-bin).o: $(autocomplete-bin).c
|
||||
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -I $(rootdir)/include -c $< -o $@
|
||||
|
||||
$(autocomplete-bin): $(autocomplete-bin).o $(autocomp-object)
|
||||
$(LINK_FOR_BUILD) $^ -o $@
|
||||
|
||||
$(bash-completions) $(zsh-completions) &: $(autocomplete-bin)
|
||||
./$(autocomplete-bin)
|
||||
|
||||
install-shell-completions: $(bash-completions) $(zsh-completions)
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(ZSHCOMPLETIONDIR)
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(BASHCOMPLETIONDIR)
|
||||
for completion in $(bash-completions); do \
|
||||
$(INSTALL) -m 644 $$completion $(DESTDIR)$(BASHCOMPLETIONDIR); \
|
||||
done
|
||||
for completion in $(zsh-completions); do \
|
||||
$(INSTALL) -m 644 $$completion $(DESTDIR)$(ZSHCOMPLETIONDIR); \
|
||||
done
|
||||
|
||||
all: $(zsh-completions) $(bash-completions)
|
||||
|
||||
install: install-shell-completions
|
||||
|
||||
.PHONY: install-shell-completions $(rootdir)/libutil
|
||||
|
||||
clean-autocomplete-bin:
|
||||
$(RM) -- $(autocomplete-bin)
|
||||
|
||||
clean: clean-autocomplete-bin
|
||||
|
||||
ifdef bash-completions
|
||||
clean-bash-completions:
|
||||
$(RM) -- $(bash-completions)
|
||||
|
||||
clean: clean-bash-completions
|
||||
endif
|
||||
|
||||
|
||||
ifdef zsh-completions
|
||||
clean-zsh-completions:
|
||||
$(RM) -- $(zsh-completions)
|
||||
|
||||
clean: clean-zsh-completions
|
||||
endif
|
||||
|
||||
.PHONY: clean-autocomplete-bin clean-bash-completions clean-zsh-completions
|
||||
@@ -22,7 +22,7 @@ ALL_CPPFLAGS += -DVERSION=$(VERSION)
|
||||
all: check_dep cpacfstats cpacfstatsd
|
||||
|
||||
cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o cpacfstats_common.o \
|
||||
$(rootdir)/libutil/libutil.a
|
||||
$(rootdir)/libcpumf/libcpumf.a $(rootdir)/libutil/libutil.a
|
||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -ludev -lpthread -o $@
|
||||
|
||||
cpacfstats: cpacfstats.o stats_sock.o cpacfstats_common.o
|
||||
|
||||
@@ -79,9 +79,11 @@ the cpacfstats client application.
|
||||
|
||||
Example usage scenario:
|
||||
.P
|
||||
1. Start the cpacfstatsd daemon with root privileges.
|
||||
1. Start the cpacfstatsd daemon with root privileges using 'systemctl start
|
||||
cpacfstatsd'.
|
||||
.P
|
||||
2. Check for successful startup by using the ps and syslog commands.
|
||||
2. Check for successful startup by using the 'systemctl status cpacfstatsd'
|
||||
command.
|
||||
.P
|
||||
3. Enable the CPACF counters of interest. For example, enable all counters
|
||||
by issuing cpacfstats -e.
|
||||
@@ -95,7 +97,7 @@ cryptographic counters as required. To reset, use, for example, cpacfstats
|
||||
6. Disable all the CPACF measurements, for example, by using cpacfstats
|
||||
-d.
|
||||
.P
|
||||
7. Shutdown the cpacfstatsd daemon by using killall cpacfstatsd.
|
||||
7. Shutdown the cpacfstatsd daemon by using 'systemctl stop cpacfstatsd'.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <libudev.h>
|
||||
|
||||
#include "cpacfstats.h"
|
||||
#include "lib/libcpumf.h"
|
||||
#include "../include/lib/zt_common.h"
|
||||
|
||||
/* correlation between counter and perf counter string */
|
||||
@@ -123,16 +124,6 @@ static struct percpucounter *findcpu(unsigned int cpunum, int unlinkflag)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
|
||||
int cpu, int group_fd, unsigned long flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
|
||||
group_fd, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int perf_supported(void)
|
||||
{
|
||||
return !access("/proc/sys/kernel/perf_event_paranoid", R_OK);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <poll.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -3,6 +3,11 @@ include ../common.mak
|
||||
BIN_FILES = lscpumf chcpumf lshwc pai lspai
|
||||
MAN_FILES = lscpumf.8 chcpumf.8 lshwc.8 pai.8 lspai.8
|
||||
|
||||
zsh-completions := $(addprefix _,$(BIN_FILES))
|
||||
bash-completions := $(addsuffix .bash,$(BIN_FILES))
|
||||
|
||||
include ../common_autocomp.mak
|
||||
|
||||
all: $(BIN_FILES)
|
||||
|
||||
libs = $(rootdir)/libcpumf/libcpumf.a $(rootdir)/libutil/libutil.a
|
||||
|
||||
28
cpumf/autocompletion_generator_host.c
Normal file
28
cpumf/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Autocompletion generation - for cpumf family of tools
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 "lib/util_autocomp.h"
|
||||
|
||||
#include "chcpumf_cli.h"
|
||||
#include "lscpumf_cli.h"
|
||||
#include "lshwc_cli.h"
|
||||
#include "lspai_cli.h"
|
||||
#include "pai_cli.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
generate_autocomp(chcpumf_opt_vec, "chcpumf");
|
||||
generate_autocomp(lscpumf_opt_vec, "lscpumf");
|
||||
generate_autocomp(lshwc_opt_vec, "lshwc");
|
||||
generate_autocomp(lspai_opt_vec, "lspai");
|
||||
generate_autocomp(pai_opt_vec, "pai");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
@@ -17,37 +17,15 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "lib/libcpumf.h"
|
||||
#include "lib/util_base.h"
|
||||
#include "lib/util_opt.h"
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_prg.h"
|
||||
|
||||
#include "chcpumf_cli.h"
|
||||
|
||||
static unsigned int verbose;
|
||||
static unsigned long min_sdb, max_sdb;
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "min", required_argument, NULL, 'm' },
|
||||
.argument = "num_sdb",
|
||||
.desc = "Specifies the initial size of the sampling buffer.\n"
|
||||
"A sample-data-block (SDB) consumes about 4 kilobytes.",
|
||||
},
|
||||
{
|
||||
.option = { "max", required_argument, NULL, 'x' },
|
||||
.argument = "num_sdb",
|
||||
.desc = "Specifies the maximum size of the sampling buffer.\n"
|
||||
"A sample-data-block (SDB) consumes about 4 kilobytes.",
|
||||
},
|
||||
{
|
||||
.option = { "verbose", no_argument, NULL, 'V' },
|
||||
.desc = "Verbose, display new sample-data-block values.",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
static const struct util_prg prg = {
|
||||
.desc = "Change CPU Measurement facility charactertics",
|
||||
.copyright_vec = {
|
||||
@@ -163,7 +141,7 @@ int main(int argc, char **argv)
|
||||
unsigned long my_min, my_max;
|
||||
|
||||
util_prg_init(&prg);
|
||||
util_opt_init(opt_vec, NULL);
|
||||
util_opt_init(chcpumf_opt_vec, NULL);
|
||||
|
||||
parse_args(argc, argv);
|
||||
if (geteuid())
|
||||
|
||||
40
cpumf/chcpumf_cli.h
Normal file
40
cpumf/chcpumf_cli.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for chcpumf
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 CHCPUMF_CLI_H
|
||||
#define CHCPUMF_CLI_H
|
||||
|
||||
#include "lib/util_fmt.h"
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static struct util_opt chcpumf_opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "min", required_argument, NULL, 'm' },
|
||||
.argument = "num_sdb",
|
||||
.desc = "Specifies the initial size of the sampling buffer.\n"
|
||||
"A sample-data-block (SDB) consumes about 4 kilobytes.",
|
||||
},
|
||||
{
|
||||
.option = { "max", required_argument, NULL, 'x' },
|
||||
.argument = "num_sdb",
|
||||
.desc = "Specifies the maximum size of the sampling buffer.\n"
|
||||
"A sample-data-block (SDB) consumes about 4 kilobytes.",
|
||||
},
|
||||
{
|
||||
.option = { "verbose", no_argument, NULL, 'V' },
|
||||
.desc = "Verbose, display new sample-data-block values.",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -7,8 +7,7 @@
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
@@ -31,6 +30,8 @@
|
||||
|
||||
#include "lib/libcpumf.h"
|
||||
|
||||
#include "lscpumf_cli.h"
|
||||
|
||||
#define ACTION_NONE 0
|
||||
#define ACTION_INFO 1
|
||||
#define ACTION_CNT 2
|
||||
@@ -39,7 +40,7 @@
|
||||
static bool actions[ACTION_SAMPLE + 1]; /* Specified command line options */
|
||||
|
||||
/* This defines the number of pages a Sample Data Buffer Table (SDBT) can hold
|
||||
* as payload data. Each SDBT is one PAGE (4096 bytes) and continas 512 eight
|
||||
* as payload data. Each SDBT is one PAGE (4096 bytes) and contains 512 eight
|
||||
* byte data pointers to Sample Data Buffers (SDB). The last entry of a SDBT
|
||||
* points to another SDBT and can not store payload.
|
||||
*/
|
||||
@@ -47,33 +48,6 @@ static bool actions[ACTION_SAMPLE + 1]; /* Specified command line options */
|
||||
|
||||
/* File names to read data from */
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "list-counters", no_argument, NULL, 'c' },
|
||||
.desc = "Lists counters for which the LPAR is authorized.",
|
||||
},
|
||||
{
|
||||
.option = { "list-all-counters", no_argument, NULL, 'C' },
|
||||
.desc = "Lists counters regardless of LPAR authorization.",
|
||||
},
|
||||
{
|
||||
.option = { "name", no_argument, NULL, 'n' },
|
||||
.desc = "Displays counter names.",
|
||||
},
|
||||
{
|
||||
.option = { "info", no_argument, NULL, 'i' },
|
||||
.desc = "Displays detailed information.",
|
||||
},
|
||||
{
|
||||
.option = { "list-sampling-events", no_argument, NULL, 's' },
|
||||
.desc = "Lists sampling events for which the LPAR is authorized.",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
static const struct util_prg prg = {
|
||||
.desc = "List CPU Measurement facility charactertics",
|
||||
.copyright_vec = {
|
||||
@@ -139,7 +113,7 @@ static struct samples { /* Sample definition for all machines */
|
||||
* The CPU Measurement facility has a first and second version number.
|
||||
*
|
||||
* The first version number governs basic counter set and the
|
||||
* problem state counter set. Currently used are first verion numbers 1 and 3.
|
||||
* problem state counter set. Currently used are first version numbers 1 and 3.
|
||||
* The counter numbers are identifical for version number 1 and 3, but
|
||||
* have different purpose and description.
|
||||
*
|
||||
@@ -627,7 +601,7 @@ static struct counters cpumcf_z10_counters[] = {
|
||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||
.name = "L1D_L3_LOCAL_WRITES",
|
||||
.desc = "A directory write to the Level-1 D-Cache directory"
|
||||
"\n\t\twhere the installtion cache line was source from"
|
||||
"\n\t\twhere the installation cache line was source from"
|
||||
"\n\t\tthe Level-3 cache that is on the same book as the"
|
||||
"\n\t\tData cache (Local L2 cache)",
|
||||
},
|
||||
@@ -1916,7 +1890,7 @@ static struct counters cpumcf_z14_counters[] = {
|
||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||
.name = "L1I_ONCHIP_L3_SOURCED_WRITES",
|
||||
.desc = "A directory write to the Level-1 Instruction cache"
|
||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
||||
"\n\t\tdirectory where the returned cache line was sourced"
|
||||
"\n\t\tfrom an On-Chip Level-3 cache without intervention",
|
||||
},
|
||||
{
|
||||
@@ -1924,7 +1898,7 @@ static struct counters cpumcf_z14_counters[] = {
|
||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||
.name = "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
|
||||
.desc = "A directory write to the Level-1 Instruction cache"
|
||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
||||
"\n\t\tdirectory where the returned cache line was sourced"
|
||||
"\n\t\tfrom On-Chip memory",
|
||||
},
|
||||
{
|
||||
@@ -1932,7 +1906,7 @@ static struct counters cpumcf_z14_counters[] = {
|
||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||
.name = "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
|
||||
.desc = "A directory write to the Level-1 Instruction cache"
|
||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
||||
"\n\t\tdirectory where the returned cache line was sourced"
|
||||
"\n\t\tfrom an On-Chip Level-3 cache with intervention",
|
||||
},
|
||||
{
|
||||
@@ -2342,7 +2316,7 @@ static struct counters cpumcf_z15_counters[] = {
|
||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||
.name = "L1I_ONCHIP_L3_SOURCED_WRITES",
|
||||
.desc = "A directory write to the Level-1 Instruction cache"
|
||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
||||
"\n\t\tdirectory where the returned cache line was sourced"
|
||||
"\n\t\tfrom an On-Chip Level-3 cache without intervention",
|
||||
},
|
||||
{
|
||||
@@ -2350,7 +2324,7 @@ static struct counters cpumcf_z15_counters[] = {
|
||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||
.name = "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
|
||||
.desc = "A directory write to the Level-1 Instruction cache"
|
||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
||||
"\n\t\tdirectory where the returned cache line was sourced"
|
||||
"\n\t\tfrom On-Chip memory",
|
||||
},
|
||||
{
|
||||
@@ -2358,7 +2332,7 @@ static struct counters cpumcf_z15_counters[] = {
|
||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||
.name = "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
|
||||
.desc = "A directory write to the Level-1 Instruction cache"
|
||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
||||
"\n\t\tdirectory where the returned cache line was sourced"
|
||||
"\n\t\tfrom an On-Chip Level-3 cache with intervention",
|
||||
},
|
||||
{
|
||||
@@ -4160,7 +4134,7 @@ int main(int argc, char **argv)
|
||||
int ret;
|
||||
|
||||
util_prg_init(&prg);
|
||||
util_opt_init(opt_vec, NULL);
|
||||
util_opt_init(lscpumf_opt_vec, NULL);
|
||||
|
||||
ret = parse_args(argc, argv);
|
||||
if (read_info() == EXIT_FAILURE)
|
||||
|
||||
44
cpumf/lscpumf_cli.h
Normal file
44
cpumf/lscpumf_cli.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for lscpumf
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 LSCPUMF_CLI_H
|
||||
#define LSCPUMF_CLI_H
|
||||
|
||||
#include "lib/util_fmt.h"
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static struct util_opt lscpumf_opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "list-counters", no_argument, NULL, 'c' },
|
||||
.desc = "Lists counters for which the LPAR is authorized.",
|
||||
},
|
||||
{
|
||||
.option = { "list-all-counters", no_argument, NULL, 'C' },
|
||||
.desc = "Lists counters regardless of LPAR authorization.",
|
||||
},
|
||||
{
|
||||
.option = { "name", no_argument, NULL, 'n' },
|
||||
.desc = "Displays counter names.",
|
||||
},
|
||||
{
|
||||
.option = { "info", no_argument, NULL, 'i' },
|
||||
.desc = "Displays detailed information.",
|
||||
},
|
||||
{
|
||||
.option = { "list-sampling-events", no_argument, NULL, 's' },
|
||||
.desc = "Lists sampling events for which the LPAR is authorized.",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -37,12 +37,13 @@
|
||||
#include "lib/util_base.h"
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_scandir.h"
|
||||
#include "lib/util_libc.h"
|
||||
#include "lib/util_str.h"
|
||||
#include "lib/util_file.h"
|
||||
#include "lib/util_fmt.h"
|
||||
#include "lib/libcpumf.h"
|
||||
|
||||
#include "lshwc.h"
|
||||
#include "lshwc_cli.h"
|
||||
|
||||
#define CPUS_ONLINE "/sys/devices/system/cpu/online"
|
||||
#define CPUS_POSSIBLE "/sys/devices/system/cpu/possible"
|
||||
@@ -61,6 +62,7 @@ static bool hideundef;
|
||||
static bool delta, firstread;
|
||||
static int output_format = FMT_CSV;
|
||||
static bool quote_all;
|
||||
static char *ctrlist; /* Comma separated list of counter to extract */
|
||||
|
||||
static unsigned int max_possible_cpus; /* No of possible CPUs */
|
||||
static struct ctrname { /* List of defined counters */
|
||||
@@ -151,6 +153,8 @@ static bool read_counternames(void)
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < count && ctr >= 0; i++) {
|
||||
if (!ctr_in_list(namelist[i]->d_name, ctrlist))
|
||||
continue;
|
||||
util_asprintf(&ctrpath, "%s/%s", path, namelist[i]->d_name);
|
||||
if (util_file_read_va(ctrpath, "event=%x", &ctr) == 1)
|
||||
ctrname[ctr].name = mk_name(ctr, namelist[i]->d_name);
|
||||
@@ -729,61 +733,6 @@ static int do_it(char *s)
|
||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "all", no_argument, NULL, 'a' },
|
||||
.desc = "Displays all CPUs in output"
|
||||
},
|
||||
{
|
||||
.option = { "loop", required_argument, NULL, 'l' },
|
||||
.argument = "NUMBER",
|
||||
.desc = "Specifies loop count for next read"
|
||||
},
|
||||
{
|
||||
.option = { "interval", required_argument, NULL, 'i' },
|
||||
.argument = "NUMBER",
|
||||
.desc = "Specifies interval between read operations (seconds)"
|
||||
},
|
||||
{
|
||||
.option = { "short", no_argument, NULL, 's' },
|
||||
.desc = "Abbreviate counter name with counter set letter and number"
|
||||
},
|
||||
{
|
||||
.option = { "hex0x", no_argument, NULL, 'X' },
|
||||
.desc = "Counter values in hexadecimal format with leading 0x"
|
||||
},
|
||||
{
|
||||
.option = { "hex", no_argument, NULL, 'x' },
|
||||
.desc = "Counter values in hexadecimal format"
|
||||
},
|
||||
{
|
||||
.option = { "hide", no_argument, NULL, 'H' },
|
||||
.desc = "Do not display undefined counters of a counter set"
|
||||
},
|
||||
{
|
||||
.option = { "delta", no_argument, NULL, 'd' },
|
||||
.desc = "Display delta counter values"
|
||||
},
|
||||
{
|
||||
.option = { "timeout", required_argument, NULL, 't' },
|
||||
.argument = "NUMBER",
|
||||
.desc = "run time in s (seconds) m (minutes) h (hours) and d (days)"
|
||||
},
|
||||
{
|
||||
.option = { "quote-all", no_argument, NULL, 'q' },
|
||||
.desc = "Apply quoting to all output elements"
|
||||
},
|
||||
{
|
||||
.option = { "format", required_argument, NULL, 'f' },
|
||||
.argument = "FORMAT",
|
||||
.desc = "List counters in specified FORMAT (" FMT_TYPE_NAMES ")"
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
static const struct util_prg prg = {
|
||||
.desc = "Read CPU Measurement facility counter sets",
|
||||
.copyright_vec = {
|
||||
@@ -814,7 +763,7 @@ int main(int argc, char **argv)
|
||||
int ch;
|
||||
|
||||
util_prg_init(&prg);
|
||||
util_opt_init(opt_vec, NULL);
|
||||
util_opt_init(lshwc_opt_vec, NULL);
|
||||
|
||||
while ((ch = util_opt_getopt_long(argc, argv)) != -1) {
|
||||
switch (ch) {
|
||||
@@ -892,6 +841,12 @@ int main(int argc, char **argv)
|
||||
errx(EXIT_FAILURE, "Supported formats:" FMT_TYPE_NAMES);
|
||||
output_format = fmt;
|
||||
break;
|
||||
case 'c':
|
||||
hideundef = true;
|
||||
ctrlist = util_strdup(optarg);
|
||||
util_str_rm_whitespace(optarg, ctrlist);
|
||||
util_str_toupper(ctrlist);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,5 +882,6 @@ int main(int argc, char **argv)
|
||||
free_counternames();
|
||||
free(check);
|
||||
free(ioctlbuffer);
|
||||
free(ctrlist);
|
||||
return ch;
|
||||
}
|
||||
|
||||
78
cpumf/lshwc_cli.h
Normal file
78
cpumf/lshwc_cli.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for lshwc
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 LSHWC_CLI_H
|
||||
#define LSHWC_CLI_H
|
||||
|
||||
#include "lib/util_fmt.h"
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static struct util_opt lshwc_opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "all", no_argument, NULL, 'a' },
|
||||
.desc = "Displays all CPUs in output"
|
||||
},
|
||||
{
|
||||
.option = { "loop", required_argument, NULL, 'l' },
|
||||
.argument = "NUMBER",
|
||||
.desc = "Specifies loop count for next read"
|
||||
},
|
||||
{
|
||||
.option = { "interval", required_argument, NULL, 'i' },
|
||||
.argument = "NUMBER",
|
||||
.desc = "Specifies interval between read operations (seconds)"
|
||||
},
|
||||
{
|
||||
.option = { "short", no_argument, NULL, 's' },
|
||||
.desc = "Abbreviate counter name with counter set letter and number"
|
||||
},
|
||||
{
|
||||
.option = { "hex0x", no_argument, NULL, 'X' },
|
||||
.desc = "Counter values in hexadecimal format with leading 0x"
|
||||
},
|
||||
{
|
||||
.option = { "hex", no_argument, NULL, 'x' },
|
||||
.desc = "Counter values in hexadecimal format"
|
||||
},
|
||||
{
|
||||
.option = { "hide", no_argument, NULL, 'H' },
|
||||
.desc = "Do not display undefined counters of a counter set"
|
||||
},
|
||||
{
|
||||
.option = { "delta", no_argument, NULL, 'd' },
|
||||
.desc = "Display delta counter values"
|
||||
},
|
||||
{
|
||||
.option = { "timeout", required_argument, NULL, 't' },
|
||||
.argument = "NUMBER",
|
||||
.desc = "run time in s (seconds) m (minutes) h (hours) and d (days)"
|
||||
},
|
||||
{
|
||||
.option = { "quote-all", no_argument, NULL, 'q' },
|
||||
.desc = "Apply quoting to all output elements"
|
||||
},
|
||||
{
|
||||
.option = { "format", required_argument, NULL, 'f' },
|
||||
.argument = "FORMAT",
|
||||
.desc = "List counters in specified FORMAT (" FMT_TYPE_NAMES ")"
|
||||
},
|
||||
{
|
||||
.option = { "counters", required_argument, NULL, 'c' },
|
||||
.argument = "LIST",
|
||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||
.desc = "Specify comma separated list of counters to display"
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
477
cpumf/lspai.c
477
cpumf/lspai.c
@@ -6,7 +6,6 @@
|
||||
|
||||
/* List available Processor Assist Instrumentation (PAI) counters. */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
@@ -17,7 +16,12 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/time.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include "lib/util_base.h"
|
||||
#include "lib/util_file.h"
|
||||
@@ -28,30 +32,10 @@
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_prg.h"
|
||||
#include "lib/util_scandir.h"
|
||||
#include "lib/util_str.h"
|
||||
#include "lib/libcpumf.h"
|
||||
|
||||
#define OPT_FORMAT 256 /* --format XXX option */
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "format", required_argument, NULL, OPT_FORMAT },
|
||||
.argument = "FORMAT",
|
||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||
.desc = "List counters in specified FORMAT (" FMT_TYPE_NAMES ")"
|
||||
},
|
||||
{
|
||||
.option = { "numeric", no_argument, NULL, 'n' },
|
||||
.desc = "Sort PAI counters by counter number"
|
||||
},
|
||||
{
|
||||
.option = { "type", required_argument, NULL, 't' },
|
||||
.argument = "TYPE",
|
||||
.desc = "Type of PAI counters to show: crypto, nnpa"
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
#include "lspai_cli.h"
|
||||
|
||||
static const struct util_prg prg = {
|
||||
.desc = "List Processor Assist Information counter sets",
|
||||
@@ -59,14 +43,24 @@ static const struct util_prg prg = {
|
||||
{
|
||||
.owner = "IBM Corp.",
|
||||
.pub_first = 2023,
|
||||
.pub_last = 2023,
|
||||
.pub_last = 2025,
|
||||
},
|
||||
UTIL_PRG_COPYRIGHT_END
|
||||
}
|
||||
};
|
||||
|
||||
static bool allcpu; /* Show counter values per CPU */
|
||||
static bool numsort; /* If true sort counter numerically */
|
||||
static bool shortname; /* Use abbreviated counter names */
|
||||
static bool delta, firstread; /* Display delta values */
|
||||
static int output_format = -1; /* Generate style if >= 0 */
|
||||
static unsigned int max_cpus; /* # of CPUs to read counter values from */
|
||||
static unsigned int max_fds; /* # of file descriptor to read counter values */
|
||||
static unsigned long loops; /* # loops */
|
||||
static unsigned long read_interval = DEFAULT_LOOP_INTERVAL;
|
||||
static cpu_set_t cpu_online_mask;
|
||||
static char *ctrformat = "%ld"; /* Default counter output format */
|
||||
static char *ctrlist; /* Comma separated list of counter to extract */
|
||||
|
||||
#define PAI_PATH "/bus/event_source/devices/%s"
|
||||
|
||||
@@ -78,9 +72,18 @@ enum pai_types { /* Bit mask for supported PAI counters */
|
||||
|
||||
static int pai_types_show;
|
||||
|
||||
struct pai_cpudata { /* Event data per CPU */
|
||||
int fd; /* Event file descriptor */
|
||||
int cpu; /* CPU number */
|
||||
unsigned long value; /* Event value */
|
||||
unsigned long prev_value; /* Previous value for deltas */
|
||||
};
|
||||
|
||||
struct pai_ctrname { /* List of defined counters */
|
||||
char *name; /* Counter name */
|
||||
unsigned long nr; /* Counter number */
|
||||
unsigned long total; /* Total count on all CPus */
|
||||
struct pai_cpudata *data; /* Counter data per CPU */
|
||||
};
|
||||
|
||||
struct pai_node { /* Head for PAI counter sets */
|
||||
@@ -113,6 +116,20 @@ static unsigned long pai_type_base(enum pai_types t)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return character for this counter set. */
|
||||
static char pai_type_char(enum pai_types t)
|
||||
{
|
||||
switch (t) {
|
||||
case pai_type_crypto:
|
||||
return 'C';
|
||||
case pai_type_nnpa:
|
||||
return 'N';
|
||||
case pai_type_max:
|
||||
break;
|
||||
}
|
||||
return 'U';
|
||||
}
|
||||
|
||||
/* Test PAI counter name from command line option. */
|
||||
static const char *pai_type_name(enum pai_types t)
|
||||
{
|
||||
@@ -154,16 +171,6 @@ static int pai_ctrcmp(const void *p1, const void *p2)
|
||||
return l->nr > r->nr ? 1 : -1;
|
||||
}
|
||||
|
||||
/* Convert string to upper case. */
|
||||
static char *str2uc(const char *s)
|
||||
{
|
||||
char *uc = util_strdup(s), *old_uc = uc;
|
||||
|
||||
for (; *uc; ++uc)
|
||||
*uc = toupper(*uc);
|
||||
return old_uc;
|
||||
}
|
||||
|
||||
/* Read counter names and assigned event number from sysfs file tree.
|
||||
* Exit when sysfs directory can not be scanned.
|
||||
*/
|
||||
@@ -171,7 +178,7 @@ static void read_counternames(struct pai_node *node)
|
||||
{
|
||||
int i, more = 0, ctr = 0, count = 0;
|
||||
struct dirent **namelist = NULL;
|
||||
char *path, *ctrpath;
|
||||
char *path, *ctrpath, sname[128];
|
||||
|
||||
/* Read counter names and assigned event number. */
|
||||
path = util_path_sysfs(PAI_PATH "/events", node->sysfs_name);
|
||||
@@ -184,9 +191,18 @@ static void read_counternames(struct pai_node *node)
|
||||
for (i = 0; i < count && ctr >= 0; i++) {
|
||||
util_asprintf(&ctrpath, "%s/%s", path, namelist[i]->d_name);
|
||||
if (util_file_read_va(ctrpath, "event=%x", &ctr) == 1) {
|
||||
snprintf(sname, sizeof(sname), "%c%ld",
|
||||
pai_type_char(node->type), ctr - node->base);
|
||||
if (!ctr_in_list(sname, ctrlist) &&
|
||||
!ctr_in_list(namelist[i]->d_name, ctrlist)) {
|
||||
/* Counter not listed in --counters option */
|
||||
continue;
|
||||
}
|
||||
node->ctrlist[node->ctridx].data = NULL;
|
||||
node->ctrlist[node->ctridx].name = util_strdup(namelist[i]->d_name);
|
||||
node->ctrlist[node->ctridx++].nr = ctr;
|
||||
more++;
|
||||
max_fds++;
|
||||
} else {
|
||||
warnx("Cannot parse %s", ctrpath);
|
||||
}
|
||||
@@ -199,7 +215,7 @@ static void read_counternames(struct pai_node *node)
|
||||
qsort(node->ctrlist, more, sizeof(*node->ctrlist), pai_ctrcmp);
|
||||
}
|
||||
|
||||
static void show_format(enum util_fmt_t fmt)
|
||||
static void format_painode(enum util_fmt_t fmt)
|
||||
{
|
||||
struct pai_node *node;
|
||||
|
||||
@@ -214,9 +230,12 @@ static void show_format(enum util_fmt_t fmt)
|
||||
for (int i = 0; i < node->ctridx; ++i) {
|
||||
util_fmt_obj_start(FMT_ROW, "counter");
|
||||
util_fmt_pair(FMT_QUOTE, "name", "%s", node->ctrlist[i].name);
|
||||
if (shortname)
|
||||
util_fmt_pair(FMT_QUOTE, "name", "%c%d",
|
||||
pai_type_char(node->type),
|
||||
node->ctrlist[i].nr - node->base);
|
||||
util_fmt_pair(FMT_DEFAULT, "config", "%d", node->ctrlist[i].nr);
|
||||
util_fmt_pair(FMT_DEFAULT, "number", "%d",
|
||||
node->ctrlist[i].nr - node->base);
|
||||
util_fmt_pair(FMT_DEFAULT, "id", "%d", node->ctrlist[i].nr - node->base);
|
||||
util_fmt_obj_end();
|
||||
}
|
||||
util_fmt_obj_end(); /* Counters */
|
||||
@@ -226,14 +245,14 @@ static void show_format(enum util_fmt_t fmt)
|
||||
util_fmt_exit();
|
||||
}
|
||||
|
||||
static void show_painode(void)
|
||||
static void list_painode(void)
|
||||
{
|
||||
struct pai_node *node;
|
||||
int indent = 0;
|
||||
int offset = 0;
|
||||
|
||||
if (output_format != -1) {
|
||||
show_format(output_format);
|
||||
format_painode(output_format);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -264,8 +283,10 @@ static void free_painode(void)
|
||||
|
||||
util_list_iterate_safe(&pai_list, node, next) {
|
||||
free(node->name_uc);
|
||||
for (int i = 0; i < node->ctridx; ++i)
|
||||
for (int i = 0; i < node->ctridx; ++i) {
|
||||
free(node->ctrlist[i].name);
|
||||
free(node->ctrlist[i].data);
|
||||
}
|
||||
free(node->ctrlist);
|
||||
free(node);
|
||||
}
|
||||
@@ -279,7 +300,8 @@ static void make_painode(enum pai_types t)
|
||||
node->type = t;
|
||||
node->sysfs_name = pai_type_sysfs(t);
|
||||
node->name = pai_type_name(t);
|
||||
node->name_uc = str2uc(node->name);
|
||||
node->name_uc = util_strdup(node->name);
|
||||
util_str_toupper(node->name_uc);
|
||||
node->filter_name = pai_type_filter(t);
|
||||
node->base = pai_type_base(t);
|
||||
|
||||
@@ -308,6 +330,267 @@ static void sort_painode(void)
|
||||
util_list_sort(&pai_list, painode_cmp, NULL);
|
||||
}
|
||||
|
||||
/* Read counter value. */
|
||||
static unsigned long event_read(int fd)
|
||||
{
|
||||
unsigned long count;
|
||||
int rc;
|
||||
|
||||
rc = read(fd, &count, sizeof(count));
|
||||
if (rc != sizeof(count))
|
||||
err(EXIT_FAILURE, "Failed to read counter value");
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Write header. */
|
||||
static void line_header(void)
|
||||
{
|
||||
struct pai_node *node;
|
||||
static bool header;
|
||||
bool comma = false;
|
||||
|
||||
if (header)
|
||||
return; /* Printed already */
|
||||
printf("Date,Time,CPU,"); /* Print counter name and number */
|
||||
util_list_iterate(&pai_list, node) {
|
||||
for (int i = 0; i < node->ctridx; ++i) {
|
||||
if (comma)
|
||||
putchar(',');
|
||||
if (shortname) {
|
||||
printf("%c%ld", pai_type_char(node->type),
|
||||
node->ctrlist[i].nr - node->base);
|
||||
} else {
|
||||
printf("%s(%ld)", node->ctrlist[i].name ?: node->name_uc,
|
||||
node->ctrlist[i].nr - node->base);
|
||||
}
|
||||
comma = true;
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
header = true;
|
||||
}
|
||||
|
||||
/* Print CPU specific counter values. */
|
||||
static void line_cpu(char *header)
|
||||
{
|
||||
struct pai_cpudata *data;
|
||||
struct pai_node *node;
|
||||
bool comma;
|
||||
char txt[16];
|
||||
|
||||
for (unsigned int h = 0; h < max_cpus; ++h) {
|
||||
comma = false;
|
||||
util_list_iterate(&pai_list, node) {
|
||||
for (int i = 0; i < node->ctridx; ++i) {
|
||||
data = &node->ctrlist[i].data[h];
|
||||
if (!comma) {
|
||||
snprintf(txt, sizeof(txt), "CPU%d,", data->cpu);
|
||||
printf("%s,%s", header, txt);
|
||||
} else {
|
||||
putchar(',');
|
||||
}
|
||||
printf(ctrformat, data->value);
|
||||
comma = true;
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
/* Write an output line. */
|
||||
static void line_out(char *header)
|
||||
{
|
||||
struct pai_node *node;
|
||||
bool comma;
|
||||
|
||||
line_header();
|
||||
if (allcpu)
|
||||
line_cpu(header);
|
||||
|
||||
/* Print total count of all CPUs */
|
||||
printf("%s,%s,", header, delta && !firstread ? "Delta" : "Total");
|
||||
comma = false;
|
||||
util_list_iterate(&pai_list, node) {
|
||||
for (int i = 0; i < node->ctridx; ++i) {
|
||||
if (comma)
|
||||
putchar(',');
|
||||
printf(ctrformat, node->ctrlist[i].total);
|
||||
comma = true;
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/* Write a formatted line. */
|
||||
static void format_line_out(time_t now, char *now_text)
|
||||
{
|
||||
static unsigned int called;
|
||||
struct pai_node *node;
|
||||
char cpuid[16];
|
||||
|
||||
if (!called) {
|
||||
util_fmt_init(stdout, output_format, FMT_DEFAULT | FMT_HANDLEINT, 1);
|
||||
util_fmt_obj_start(FMT_DEFAULT, NULL);
|
||||
util_fmt_obj_start(FMT_LIST, "measurements");
|
||||
}
|
||||
util_list_iterate(&pai_list, node) {
|
||||
if (!node->ctridx) /* Counter set not selected */
|
||||
continue;
|
||||
util_fmt_obj_start(FMT_DEFAULT, "entry");
|
||||
util_fmt_pair(FMT_PERSIST, "iteration", "%d", called++);
|
||||
util_fmt_pair(FMT_PERSIST, "time_epoch", "%d", now);
|
||||
util_fmt_pair(FMT_QUOTE | FMT_PERSIST, "time", "%s", now_text);
|
||||
util_fmt_pair(FMT_QUOTE | FMT_PERSIST, "valuetype",
|
||||
(delta && !firstread) ? "delta" : "total");
|
||||
util_fmt_obj_start(FMT_LIST, "counters");
|
||||
for (int i = 0; i < node->ctridx; ++i) {
|
||||
util_fmt_obj_start(FMT_ROW, "counter");
|
||||
util_fmt_pair(FMT_QUOTE, "name", "%s", node->ctrlist[i].name);
|
||||
if (shortname)
|
||||
util_fmt_pair(FMT_QUOTE, "shortname", "%c%d",
|
||||
pai_type_char(node->type),
|
||||
node->ctrlist[i].nr - node->base);
|
||||
util_fmt_pair(FMT_DEFAULT, "config", "%d", node->ctrlist[i].nr);
|
||||
util_fmt_pair(FMT_DEFAULT, "id", "%d", node->ctrlist[i].nr - node->base);
|
||||
util_fmt_pair(FMT_DEFAULT, "value", ctrformat, node->ctrlist[i].total);
|
||||
if (allcpu) {
|
||||
for (unsigned int j = 0; j < max_cpus; ++j) {
|
||||
snprintf(cpuid, sizeof(cpuid), "cpu%d", j);
|
||||
util_fmt_pair(FMT_DEFAULT, cpuid, ctrformat,
|
||||
node->ctrlist[i].data[j].value);
|
||||
}
|
||||
}
|
||||
util_fmt_obj_end();
|
||||
}
|
||||
util_fmt_obj_end(); /* Counters */
|
||||
util_fmt_obj_end(); /* Entry */
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate formatted output. */
|
||||
static void format_line_end(void)
|
||||
{
|
||||
util_fmt_obj_end(); /* Iteration */
|
||||
util_fmt_obj_end(); /* Default */
|
||||
util_fmt_exit();
|
||||
}
|
||||
|
||||
/* Display counter values. */
|
||||
static void show_values(void)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
struct tm *now_tm;
|
||||
char now_text[32];
|
||||
|
||||
now_tm = localtime(&now);
|
||||
if (output_format != -1) {
|
||||
strftime(now_text, sizeof(now_text), "%F %T%z", now_tm);
|
||||
format_line_out(now, now_text);
|
||||
} else {
|
||||
strftime(now_text, sizeof(now_text), "%F,%T", now_tm);
|
||||
line_out(now_text);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read each counter value. */
|
||||
static void read_painode(void)
|
||||
{
|
||||
struct pai_cpudata *data;
|
||||
struct pai_node *node;
|
||||
unsigned long value;
|
||||
|
||||
util_list_iterate(&pai_list, node) {
|
||||
for (int i = 0; i < node->ctridx; ++i) {
|
||||
node->ctrlist[i].total = 0;
|
||||
for (size_t j = 0; j < max_cpus; ++j) {
|
||||
data = &node->ctrlist[i].data[j];
|
||||
value = event_read(data->fd);
|
||||
if (delta) {
|
||||
data->value = value - data->prev_value;
|
||||
data->prev_value = value;
|
||||
} else {
|
||||
data->value = value;
|
||||
}
|
||||
node->ctrlist[i].total += data->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wait_painode(void)
|
||||
{
|
||||
for (unsigned long i = 0; i < loops; ++i) {
|
||||
read_painode();
|
||||
show_values();
|
||||
if (i + 1 < loops)
|
||||
sleep(read_interval);
|
||||
firstread = false;
|
||||
}
|
||||
format_line_end();
|
||||
}
|
||||
|
||||
/* Install one event. */
|
||||
static int event_add(int cpu, int idx, struct pai_node *node)
|
||||
{
|
||||
struct perf_event_attr attr;
|
||||
int fd;
|
||||
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
attr.size = sizeof(attr);
|
||||
attr.config = node->ctrlist[idx].nr;
|
||||
attr.type = node->pmu;
|
||||
fd = perf_event_open(&attr, -1, cpu, -1, 0);
|
||||
if (fd == -1)
|
||||
err(EXIT_FAILURE, "Failed to open perf event: file descriptor not available");
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Increase number of file descriptors this process can open. */
|
||||
static void event_fdlimit(void)
|
||||
{
|
||||
unsigned int needed = 3 + max_fds * max_cpus;
|
||||
struct rlimit rlimit;
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlimit) == -1)
|
||||
err(EXIT_FAILURE, "Failed to read RLIMIT_NOFILE");
|
||||
if (needed > rlimit.rlim_cur)
|
||||
rlimit.rlim_cur = needed;
|
||||
if (setrlimit(RLIMIT_NOFILE, &rlimit) == -1)
|
||||
err(EXIT_FAILURE, "Failed to set RLIMIT_NOFILE");
|
||||
}
|
||||
|
||||
/* Install all events and iterate over requested read operations. */
|
||||
static void event_painode(void)
|
||||
{
|
||||
size_t pai_cpudata_sz = sizeof(struct pai_cpudata) * max_cpus;
|
||||
struct pai_cpudata *data;
|
||||
struct pai_node *node;
|
||||
|
||||
event_fdlimit();
|
||||
util_list_iterate(&pai_list, node) {
|
||||
for (int i = 0; i < node->ctridx; ++i) {
|
||||
node->ctrlist[i].data = util_malloc(pai_cpudata_sz);
|
||||
data = node->ctrlist[i].data;
|
||||
for (unsigned int j = 0; j < CPU_SETSIZE; ++j) {
|
||||
if (CPU_ISSET(j, &cpu_online_mask)) {
|
||||
data->cpu = j;
|
||||
data->fd = event_add(j, i, node);
|
||||
data->value = 0;
|
||||
data->prev_value = 0;
|
||||
++data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wait_painode();
|
||||
util_list_iterate(&pai_list, node) {
|
||||
for (int i = 0; i < node->ctridx; ++i) {
|
||||
for (unsigned int j = 0; j < max_cpus; ++j)
|
||||
close(node->ctrlist[i].data[j].fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for hardware support and return false if not available. */
|
||||
static bool have_support(enum pai_types t)
|
||||
{
|
||||
@@ -344,20 +627,60 @@ static void check_type_name(const char *type)
|
||||
errx(EXIT_FAILURE, "Invalid argument for -t %s", type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get list of specified CPUs from command line. Check if these CPUs
|
||||
* exist and are online. Ignore those CPUs which are not available and
|
||||
* issue one warning when CPUs have been specified but are not online.
|
||||
*/
|
||||
static void get_cpulist(char *parm)
|
||||
{
|
||||
bool warned = false;
|
||||
cpu_set_t cpulist;
|
||||
int i, rc;
|
||||
|
||||
CPU_ZERO(&cpulist);
|
||||
rc = libcpumf_cpuset(parm, &cpulist);
|
||||
if (rc)
|
||||
err(EXIT_FAILURE, "Cannot parse cpulist %s", parm);
|
||||
for (i = 0; i < CPU_SETSIZE; ++i) {
|
||||
if (CPU_ISSET(i, &cpulist) && !CPU_ISSET(i, &cpu_online_mask)) {
|
||||
if (!warned) {
|
||||
warnx("some CPU(s) are offline, ignored");
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
if (!CPU_ISSET(i, &cpulist) && CPU_ISSET(i, &cpu_online_mask))
|
||||
CPU_CLR(i, &cpu_online_mask);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
bool list_only = true;
|
||||
enum util_fmt_t fmt;
|
||||
bool i_flag = false;
|
||||
bool l_flag = false;
|
||||
char *endchar;
|
||||
int ch;
|
||||
|
||||
util_list_init(&pai_list, struct pai_node, node);
|
||||
util_prg_init(&prg);
|
||||
util_opt_init(opt_vec, NULL);
|
||||
util_opt_init(lspai_opt_vec, NULL);
|
||||
|
||||
while ((ch = util_opt_getopt_long(argc, argv)) != -1) {
|
||||
switch (ch) {
|
||||
default:
|
||||
util_opt_print_parse_error(ch, argv);
|
||||
return EXIT_FAILURE;
|
||||
case 'a':
|
||||
allcpu = true;
|
||||
list_only = false;
|
||||
break;
|
||||
case 'd':
|
||||
delta = true;
|
||||
firstread = true;
|
||||
list_only = false;
|
||||
break;
|
||||
case 'h':
|
||||
util_prg_print_help();
|
||||
util_opt_print_help();
|
||||
@@ -365,21 +688,80 @@ int main(int argc, char **argv)
|
||||
case 'v':
|
||||
util_prg_print_version();
|
||||
return EXIT_SUCCESS;
|
||||
case 'i':
|
||||
i_flag = true;
|
||||
list_only = false;
|
||||
errno = 0;
|
||||
read_interval = strtoul(optarg, &endchar, 0);
|
||||
if (errno || *endchar)
|
||||
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
||||
break;
|
||||
case 'l':
|
||||
l_flag = true;
|
||||
list_only = false;
|
||||
errno = 0;
|
||||
loops = strtoul(optarg, &endchar, 0);
|
||||
if (errno || *endchar)
|
||||
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
||||
break;
|
||||
case 'n':
|
||||
numsort = true;
|
||||
break;
|
||||
case 's':
|
||||
list_only = false;
|
||||
shortname = true;
|
||||
break;
|
||||
case 't':
|
||||
check_type_name(optarg);
|
||||
break;
|
||||
case 'x':
|
||||
list_only = false;
|
||||
ctrformat = "%lx";
|
||||
break;
|
||||
case 'X':
|
||||
list_only = false;
|
||||
ctrformat = "%#lx";
|
||||
break;
|
||||
case OPT_FORMAT:
|
||||
if (!util_fmt_name_to_type(optarg, &fmt))
|
||||
errx(EXIT_FAILURE, "Supported formats:" FMT_TYPE_NAMES);
|
||||
output_format = fmt;
|
||||
break;
|
||||
case 'c':
|
||||
ctrlist = util_strdup(optarg);
|
||||
util_str_rm_whitespace(optarg, ctrlist);
|
||||
util_str_toupper(ctrlist);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing specified, show all PAI counters */
|
||||
if (i_flag && !l_flag) {
|
||||
util_prg_print_help();
|
||||
util_opt_print_help();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read currently online CPUs and create a bit mask.
|
||||
* This bitmap of online CPUs is used to check command line parameter
|
||||
* for valid CPUs
|
||||
* When any of the flags which set variable list_only to false have
|
||||
* be specified, lets also show the counter value, not just list them.
|
||||
*/
|
||||
if (optind < argc) /* List of CPUs on command line */
|
||||
list_only = false;
|
||||
if (!list_only) { /* Show counter values */
|
||||
ch = libcpumf_cpuset_fn(S390_CPUS_ONLINE, &cpu_online_mask);
|
||||
if (ch)
|
||||
err(EXIT_FAILURE, "Cannot read file /sys/" S390_CPUS_ONLINE);
|
||||
while (optind < argc)
|
||||
get_cpulist(argv[optind++]);
|
||||
max_cpus = CPU_COUNT(&cpu_online_mask);
|
||||
if (!loops)
|
||||
loops = 1;
|
||||
}
|
||||
|
||||
/* Nothing specified, use all PAI counters */
|
||||
if (!pai_types_show)
|
||||
pai_types_show = (1 << pai_type_crypto) | (1 << pai_type_nnpa);
|
||||
|
||||
@@ -393,7 +775,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
sort_painode();
|
||||
show_painode();
|
||||
ch = EXIT_SUCCESS;
|
||||
if (!list_only)
|
||||
event_painode();
|
||||
else
|
||||
list_painode();
|
||||
free_painode();
|
||||
free(ctrlist);
|
||||
return ch;
|
||||
}
|
||||
|
||||
81
cpumf/lspai_cli.h
Normal file
81
cpumf/lspai_cli.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for lspai
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 LSPAI_CLI_H
|
||||
#define LSPAI_CLI_H
|
||||
|
||||
#include "lib/util_fmt.h"
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
#define STR_SUB(x) #x
|
||||
#define STR(x) STR_SUB(x)
|
||||
|
||||
#define OPT_FORMAT 256 /* --format XXX option */
|
||||
#define DEFAULT_LOOP_INTERVAL 60 /* loop interval in seconds */
|
||||
|
||||
static struct util_opt lspai_opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "all", no_argument, NULL, 'a' },
|
||||
.desc = "Displays all CPUs in output"
|
||||
},
|
||||
{
|
||||
.option = { "delta", no_argument, NULL, 'd' },
|
||||
.desc = "Display delta counter values"
|
||||
},
|
||||
{
|
||||
.option = { "counters", required_argument, NULL, 'c' },
|
||||
.argument = "LIST",
|
||||
.desc = "Specify comma separated list of counters to display"
|
||||
},
|
||||
{
|
||||
.option = { "format", required_argument, NULL, OPT_FORMAT },
|
||||
.argument = "FORMAT",
|
||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||
.desc = "List counters in specified FORMAT (" FMT_TYPE_NAMES ")"
|
||||
},
|
||||
{
|
||||
.option = { "loops", required_argument, NULL, 'l' },
|
||||
.argument = "COUNT",
|
||||
.desc = "Number of read operations"
|
||||
},
|
||||
{
|
||||
.option = { "interval", required_argument, NULL, 'i' },
|
||||
.argument = "SECONDS",
|
||||
.desc = "Time to wait between loop iterations (default "
|
||||
STR(DEFAULT_LOOP_INTERVAL) "s)"
|
||||
},
|
||||
{
|
||||
.option = { "numeric", no_argument, NULL, 'n' },
|
||||
.desc = "Sort PAI counters by counter number"
|
||||
},
|
||||
{
|
||||
.option = { "short", no_argument, NULL, 's' },
|
||||
.desc = "Abbreviate counter name with counter set letter and number"
|
||||
},
|
||||
{
|
||||
.option = { "type", required_argument, NULL, 't' },
|
||||
.argument = "TYPE",
|
||||
.desc = "Type of PAI counters to show: crypto, nnpa"
|
||||
},
|
||||
{
|
||||
.option = { "hex0x", no_argument, NULL, 'X' },
|
||||
.desc = "Counter values in hexadecimal format with leading 0x"
|
||||
},
|
||||
{
|
||||
.option = { "hex", no_argument, NULL, 'x' },
|
||||
.desc = "Counter values in hexadecimal format"
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,9 +17,9 @@ chcpumf \- manage the CPU-measurement facilities support
|
||||
.SH SYNOPSIS
|
||||
.B chcpumf
|
||||
.RB [ \-m | \-\-min
|
||||
.IR num_sdb ]
|
||||
.IR NUM_SDB ]
|
||||
.RB [ \-x | \-\-max
|
||||
.IR num_sdb ]
|
||||
.IR NUM_SDB ]
|
||||
.RB [ \-V | \-\-verbose ]
|
||||
.br
|
||||
.B chcpumf
|
||||
@@ -36,14 +36,14 @@ facilities for Linux on System z.
|
||||
.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR \-m ", " \-\-min " \fInum_sdb\fP"
|
||||
.BR \-m ", " \-\-min " \fINUM_SDB\fP"
|
||||
Specifies the minimum sampling facility buffer size in sample-data-blocks
|
||||
(SDB). A sample-data-block consumes about 4 kilobytes.
|
||||
|
||||
This is the initial buffer size when you start the sampling facility.
|
||||
.
|
||||
.TP
|
||||
.BR \-x ", " \-\-max " \fInum_sdb\fP"
|
||||
.BR \-x ", " \-\-max " \fINUM_SDB\fP"
|
||||
Specifies the maximum sampling facility buffer size in sample-data-blocks
|
||||
(SDB). A sample-data-block consumes about 4 kilobytes.
|
||||
|
||||
|
||||
@@ -16,14 +16,16 @@ lshwc \- extract CPU Measurement Facilities counter sets
|
||||
\*c
|
||||
.RB [ \-a ][ \-d ][ \-H ][ \-s ][ \-x ][ \-X ][ \-q ]
|
||||
.RB [ \-l
|
||||
.IR count ]
|
||||
.IR COUNT ]
|
||||
.RB [ \-i
|
||||
.IR interval ]
|
||||
.IR INTERVAL ]
|
||||
.RB [ \-t
|
||||
.IR time ]
|
||||
.IR TIME ]
|
||||
.RB [ \-f
|
||||
.IR format ]
|
||||
\fR[\fIcpulist\fR][:\fIsets\fR]\fP
|
||||
.IR FORMAT ]
|
||||
.RB [ \-c
|
||||
.IR LIST ]
|
||||
\fR[\fICPULIST\fR][:\fISETS\fR]\fP
|
||||
.br
|
||||
\*c
|
||||
.BR \-h | \-\-help
|
||||
@@ -62,13 +64,13 @@ Without this flag the total value of each counter is displayed.
|
||||
See Examples.
|
||||
.
|
||||
.TP
|
||||
.BR \-i ", " \-\-interval \fI\ seconds\fP
|
||||
.BR \-i ", " \-\-interval \fI\ SECONDS\fP
|
||||
Specifies a time interval, in seconds,
|
||||
that the command waits between read operations.
|
||||
The default is 60 seconds.
|
||||
.
|
||||
.TP
|
||||
.BR \-l ", " \-\-loop \fI\ count\fP
|
||||
.BR \-l ", " \-\-loop \fI\ COUNT\fP
|
||||
Performs the specified number of read operations.
|
||||
.
|
||||
.TP
|
||||
@@ -134,7 +136,7 @@ Displays counter values as hexadecimal values with a leading 0x prefix.
|
||||
Apply quoting to every output element, regardless of content or format.
|
||||
.
|
||||
.TP
|
||||
.BR \-f ", " \-\-format \fI\ format\fP
|
||||
.BR \-f ", " \-\-format \fI\ FORMAT\fP
|
||||
Retrieve output in one of the following formats:
|
||||
JSON, CSV, JSON-SEQ or PAIRS.
|
||||
If no format is specified, the output defaults to CSV.
|
||||
@@ -173,7 +175,12 @@ and \fBvalue\fP.
|
||||
.RE
|
||||
.
|
||||
.TP
|
||||
\fR[\fIcpulist\fR][:\fIsets\fR]\fP
|
||||
.BR \-c ", " \-\-counters \fI\ LIST\fP
|
||||
Specify a comma-separated list of counter names to be printed.
|
||||
If a counter name does not match any valid counter name, it is omitted. (Implies -H)
|
||||
.
|
||||
.TP
|
||||
\fR[\fICPULIST\fR][:\fISETS\fR]\fP
|
||||
A comma-separated list of CPUs.
|
||||
Each CPU can optionally be followed by characters that specify the counter set.
|
||||
See below for details.
|
||||
@@ -206,7 +213,7 @@ Two read operations are performed and a summary line is printed for each
|
||||
read operation.
|
||||
.sp 1
|
||||
.nf
|
||||
.ft CW
|
||||
.ft CR
|
||||
# lshwc -l2 0-1:BP
|
||||
Date,Time,CPU,CPU_CYCLES(0),INSTRUCTIONS(1),L1I_DIR_WRITES(2),L1I_PENALTY_CYCLES(3),L1D_DIR_WRITES(4),
|
||||
L1D_PENALTY_CYCLES(5),PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
|
||||
@@ -220,7 +227,7 @@ Date,Time,CPU,CPU_CYCLES(0),INSTRUCTIONS(1),L1I_DIR_WRITES(2),L1I_PENALTY_CYCLES
|
||||
This example shows the counter values of the problem state counter set per CPU.
|
||||
CPU 0 and CPU 1 are selected.
|
||||
.nf
|
||||
.ft CW
|
||||
.ft CR
|
||||
.sp 1
|
||||
# lshwc -l3 -a 0-1:P
|
||||
Date,Time,CPU,PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
|
||||
@@ -239,7 +246,7 @@ Date,Time,CPU,PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
|
||||
This example shows the counter values of the basic counter set
|
||||
using delta output format.
|
||||
.nf
|
||||
.ft CW
|
||||
.ft CR
|
||||
.sp 1
|
||||
# lshwc -d -l 10 -i 5 -s :b
|
||||
Date,Time,CPU,B0,B1,B2,B3,B4,B5
|
||||
@@ -259,7 +266,7 @@ Date,Time,CPU,B0,B1,B2,B3,B4,B5
|
||||
This example shows the counter values of the problem state counter set with
|
||||
CPU 3 selected.
|
||||
.nf
|
||||
.ft CW
|
||||
.ft CR
|
||||
.sp 1
|
||||
# lshwc -l2 -a 3:P -H --format json
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
.TH \*c "8" "August 2023" "s390-tools" "CPU-MF management programs"
|
||||
.
|
||||
.SH NAME
|
||||
lspai \- list Processor Activity Instrumentation (PAI) counters
|
||||
\*c \- list Processor Activity Instrumentation (PAI) counters and values
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
\*c
|
||||
@@ -18,7 +18,22 @@ lspai \- list Processor Activity Instrumentation (PAI) counters
|
||||
.IR FORMAT ]
|
||||
.RB [ \-n ]
|
||||
.RB [ \-t
|
||||
.IR TYPE ]
|
||||
.br
|
||||
\*c
|
||||
.RB [ \-\-format
|
||||
.IR FORMAT ]
|
||||
.RB [ \-n ]
|
||||
.RB [ \-t
|
||||
.IR "\ TYPE" ]
|
||||
.RB [ \-a ][ \-d ][ \-i
|
||||
.IR SECONDS ]
|
||||
.RB [ \-l
|
||||
.IR COUNT ]
|
||||
.RB [ \-s ][ \-x ][ \-x ]
|
||||
.RB [ \-c
|
||||
.IR LIST ]
|
||||
.RI [ CPULIST ]
|
||||
.br
|
||||
\*c
|
||||
.BR \-h | \-\-help
|
||||
@@ -28,10 +43,34 @@ lspai \- list Processor Activity Instrumentation (PAI) counters
|
||||
.
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
On the first line
|
||||
\*c displays the Processor Activity Instrumentation (PAI) counters
|
||||
for Linux on IBM Z.
|
||||
The output is a human-readable list of available PAI counter
|
||||
names and numbers.
|
||||
The output lists the available PAI counter names
|
||||
and numbers in various formats.
|
||||
If
|
||||
.I CPULIST
|
||||
is specified or any of the options
|
||||
.BR \-a ,
|
||||
.BR \-d ,
|
||||
.BR \-s ,
|
||||
.BR \-x ,
|
||||
.BR \-X ,
|
||||
.B \-l
|
||||
or
|
||||
.BR \-i,
|
||||
are present on the command line,
|
||||
\*c command extracts counter values from the
|
||||
specified PAI counter sets.
|
||||
Counter sets can be specified and extracted for individual CPUs.
|
||||
By default the output is a comma-separated list of values.
|
||||
Each line starts with a timestamp
|
||||
followed by the extracted counter values.
|
||||
A header line shows each counter name and the
|
||||
counter number in parenthesis.
|
||||
For other formats, use the
|
||||
.B \-\-format
|
||||
option.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR \-h ", " \-\-help
|
||||
@@ -42,7 +81,44 @@ Displays help information, then exits.
|
||||
Displays version information, then exits.
|
||||
.
|
||||
.TP
|
||||
.BR \-t ", " \-\-type "\ TYPE"
|
||||
.BR \-a ", " \-\-allcpu
|
||||
Displays counter values from each CPU.
|
||||
The default is a total summary line of all counters from all CPUs.
|
||||
.
|
||||
.TP
|
||||
.BR \-d ", " \-\-delta
|
||||
Displays counter values in form of deltas.
|
||||
Each counter value shows the increment to the previous output line.
|
||||
Without this flag the total value of each counter is displayed.
|
||||
.
|
||||
.TP
|
||||
.BR \-c ", " \-\-counters \fI\ LIST\fP
|
||||
Specify a comma separated list of counter names to
|
||||
be printed.
|
||||
If a counter name does not match any valid counter
|
||||
name, it is omitted.
|
||||
.
|
||||
.TP
|
||||
.BR \-s ", " \-\-short
|
||||
Displays counter names as short names in the heading.
|
||||
A short name consists of
|
||||
a letter for the counter set followed by a number.
|
||||
For example,
|
||||
this flag displays counter number 0 in the PAI crypto counter
|
||||
set as
|
||||
.B C0
|
||||
instead of
|
||||
.BR CRYPTO_ALL .
|
||||
Valid counter set letters are:
|
||||
.RS
|
||||
.IP C
|
||||
PAI crypto counter set
|
||||
.IP N
|
||||
PAI NNPA counter set
|
||||
.RE
|
||||
.
|
||||
.TP
|
||||
.BR \-t ", " \-\-type "\ \fITYPE\fP"
|
||||
Specifies the PAI counter set to list.
|
||||
Valid counter set values are
|
||||
.I crypto
|
||||
@@ -63,6 +139,26 @@ Retrieve output in one of the following formats:
|
||||
JSON, csv, json-seq or pairs.
|
||||
If no format is specified,
|
||||
the output defaults to a human-readable format.
|
||||
.
|
||||
.TP
|
||||
.BR \-i ", " \-\-interval \fI\ SECONDS\fP
|
||||
Specifies a time interval, in seconds,
|
||||
that the command waits between read operations.
|
||||
The default is 60 seconds.
|
||||
.
|
||||
.TP
|
||||
.BR \-l ", " \-\-loop \fI\ COUNT\fP
|
||||
Performs the specified number of read operations.
|
||||
The default is one.
|
||||
.
|
||||
.TP
|
||||
.BR \-x ", " \-\-hex
|
||||
Displays counter values as hexadecimal values.
|
||||
.
|
||||
.TP
|
||||
.BR \-X ", " \-\-hex0x
|
||||
Displays counter values as hexadecimal values with a leading 0x prefix.
|
||||
.
|
||||
.SH "EXAMPLE"
|
||||
The \*c invocation lists all PAI Neural Network Processing Assist Facility
|
||||
(NNPA) counters in numeric order:
|
||||
@@ -83,6 +179,58 @@ suitable for
|
||||
.IR perf "(8)"
|
||||
event specification by name.
|
||||
The third gives a short explanation, if available.
|
||||
.sp 1
|
||||
The \*c invocation displays all PAI Neural Network Processing Assist Facility
|
||||
(NNPA) counters values.
|
||||
Ten iterations with a two second delay in between
|
||||
is printed on the screen.
|
||||
.nf
|
||||
# lspai -i 2 -l 10 -t nnpa -n
|
||||
Date,Time,CPU,NNPA_ALL(0),NNPA_ADD(1),NNPA_SUB(2),NNPA_MUL(3),NNPA_DIV(4),
|
||||
NNPA_MIN(5),NNPA_MAX(6),NNPA_LOG(7),NNPA_EXP(8),NNPA_IBM_RESERVED_9(9),
|
||||
NNPA_RELU(10),NNPA_TANH(11),NNPA_SIGMOID(12),NNPA_SOFTMAX(13),NNPA_BATCHNORM(14),
|
||||
NNPA_MAXPOOL2D(15),NNPA_AVGPOOL2D(16),NNPA_LSTMACT(17),NNPA_GRUACT(18),
|
||||
NNPA_CONVOLUTION(19),NNPA_MATMUL_OP(20),NNPA_MATMUL_OP_BCAST23(21),
|
||||
NNPA_SMALLBATCH(22),NNPA_LARGEDIM(23),NNPA_SMALLTENSOR(24),NNPA_1MFRAME(25),
|
||||
NNPA_2GFRAME(26),NNPA_ACCESSEXCEPT(27)
|
||||
2025-05-13,08:18:27,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
2025-05-13,08:18:29,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
2025-05-13,08:18:31,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
2025-05-13,08:18:33,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
2025-05-13,08:18:35,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
2025-05-13,08:18:37,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
2025-05-13,08:18:39,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
2025-05-13,08:18:41,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
2025-05-13,08:18:43,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
2025-05-13,08:18:45,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
#
|
||||
.fi
|
||||
.sp 1
|
||||
This \*c example displays the value of PAI crypto counter number 7.
|
||||
It is field number 116 in the output.
|
||||
This counter is incremented after \*c is started and
|
||||
the table shows the delta values for PAI crypto counter 7.
|
||||
.nf
|
||||
# lspai -d -s -i 5 -l3 -t crypto | \
|
||||
awk -F , '{ print $1 "," $2 "," $3 "," $4 "," $116; }'
|
||||
Date,Time,CPU,C0,C7
|
||||
2025-06-24,13:02:24,Total,0,0
|
||||
2025-06-24,13:02:29,Delta,77122286,77122284
|
||||
2025-06-24,13:02:34,Delta,92574403,92574403
|
||||
#
|
||||
.fi
|
||||
.sp 1
|
||||
The following table shows the total value for PAI crypto counter 7
|
||||
after \*c is started.
|
||||
.nf
|
||||
# lspai -s -i 5 -l3 -t crypto | \
|
||||
awk -F , '{ print $1 "," $2 "," $3 "," $4 "," $116; }'
|
||||
Date,Time,CPU,C0,C7
|
||||
2025-06-24,13:03:01,Total,0,0
|
||||
2025-06-24,13:03:06,Total,72550754,72566121
|
||||
2025-06-24,13:03:11,Total,164633982,164650377
|
||||
#
|
||||
.fi
|
||||
.SH "SEE ALSO"
|
||||
.BR pai (8)
|
||||
.BR lscpumf (8)
|
||||
|
||||
@@ -15,24 +15,24 @@ pai \- record and report Processor Activity Instrumentation (PAI) counters
|
||||
.SH SYNOPSIS
|
||||
\*c
|
||||
.RB [ \-V ][ \-m | \-\-mapsize
|
||||
.IR size ]
|
||||
.IR SIZE ]
|
||||
.RB [ \-i | \-\-interval
|
||||
.IR ms ]
|
||||
.IR MS ]
|
||||
.RB [ \-R | \-\-realtime
|
||||
.IR prio ]
|
||||
.BR \-c | \-\-crypto [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
|
||||
.IR PRIO ]
|
||||
.BR \-c | \-\-crypto [ \fICPULIST ][: \fIDATA\fR "] [" \fILOOPS\fP ]
|
||||
.br
|
||||
\*c
|
||||
.RB [ \-V ][ \-m | \-\-mapsize
|
||||
.IR size ]
|
||||
.IR SIZE ]
|
||||
.RB [ \-i | \-\-interval
|
||||
.IR ms ]
|
||||
.IR MS ]
|
||||
.RB [ \-R | \-\-realtime
|
||||
.IR prio ]
|
||||
.BR \-n | \-\-nnpa [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
|
||||
.IR PRIO ]
|
||||
.BR \-n | \-\-nnpa [ \fICPULIST ][: \fIDATA\fR "] [" \fILOOPS\fP ]
|
||||
.br
|
||||
\*c
|
||||
.RB [ \-V ][ \-H | \-\-humantime ][ \-S | \-\-summary "] " \-r | \-\-report " [" \fIfiles\fP ]
|
||||
.RB [ \-V ][ \-H | \-\-humantime ][ \-S | \-\-summary "] " \-r | \-\-report " [" \fIFILES\fP ]
|
||||
.br
|
||||
\*c
|
||||
.BR \-h | \-\-help
|
||||
@@ -73,7 +73,7 @@ Reporting evaluates files that are created by recording.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR \-c ", " \-\-crypto "\fR[\fIcpulist\fR][:\fIdata\fR]"
|
||||
.BR \-c ", " \-\-crypto "\fR[\fICPULIST\fR][:\fIDATA\fR]"
|
||||
Records data for all (default) or a specified list of CPUs.
|
||||
The CPU list is a comma-separated list of CPU numbers and ranges.
|
||||
In a range, a hyphen separates the first CPU number
|
||||
@@ -106,7 +106,7 @@ execution.
|
||||
.RE
|
||||
.
|
||||
.TP
|
||||
.BR \-n ", " \-\-nnpa "\fR[\fIcpulist\fR][:\fIdata\fR]"
|
||||
.BR \-n ", " \-\-nnpa "\fR[\fICPULIST\fR][:\fIDATA\fR]"
|
||||
Records data for all (default) or a specified list of CPUs.
|
||||
The CPU list is a comma-separated list of CPU numbers and ranges.
|
||||
In a range, a hyphen separates the first CPU number
|
||||
@@ -241,7 +241,7 @@ The program runs for 10 seconds
|
||||
(10 intervals of 1000 milliseconds).
|
||||
.sp 1
|
||||
.nf
|
||||
.ft CW
|
||||
.ft CR
|
||||
# \*c -c0 10
|
||||
.ft R
|
||||
.fi
|
||||
@@ -256,7 +256,7 @@ and a comma-separated list of counter number, colon (:),
|
||||
and the counter value n hexadecimal notation.
|
||||
.sp 1
|
||||
.nf
|
||||
.ft CW
|
||||
.ft CR
|
||||
# \*c -r
|
||||
0x62a668f2fa 0 event 4096 sample pid 4956/4956 9:0xa7,73:0x8,74:0x18
|
||||
0x6319c75653 0 event 4096 sample pid 4972/4972 32:0x1
|
||||
|
||||
62
cpumf/pai.c
62
cpumf/pai.c
@@ -40,7 +40,9 @@
|
||||
#include "lib/util_prg.h"
|
||||
#include "lib/util_scandir.h"
|
||||
#include "lib/libcpumf.h"
|
||||
|
||||
#include "pai.h"
|
||||
#include "pai_cli.h"
|
||||
|
||||
#define S390_EVT_PAI_CRYPTO 0x1000
|
||||
#define S390_EVT_PAI_NNPA 0x1800
|
||||
@@ -59,14 +61,6 @@ static struct util_list list_pai_event;
|
||||
static struct util_list list_pmu_event;
|
||||
static bool summary;
|
||||
|
||||
/* System call to perf_event_open(2) */
|
||||
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
|
||||
int cpu, int group_fd, unsigned long flags)
|
||||
{
|
||||
return syscall(__NR_perf_event_open, hw_event, pid, cpu,
|
||||
group_fd, flags);
|
||||
}
|
||||
|
||||
static void ev_dealloc(void)
|
||||
{
|
||||
struct pai_event *next, *p;
|
||||
@@ -743,8 +737,8 @@ static int add_events(int type)
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
free(pmuname);
|
||||
warnx("failed building event list for %s", pmuname);
|
||||
free(pmuname);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -933,54 +927,6 @@ static void parse_cpulist(int enr, const char *parm)
|
||||
}
|
||||
}
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "crypto", optional_argument, NULL, 'c' },
|
||||
.argument = "CPULIST[:DATA]",
|
||||
.desc = "Collect PAI crypto counters"
|
||||
},
|
||||
{
|
||||
.option = { "nnpa", optional_argument, NULL, 'n' },
|
||||
.argument = "CPULIST[:DATA]",
|
||||
.desc = "Collect PAI nnpa counters"
|
||||
},
|
||||
{
|
||||
.option = { "mapsize", required_argument, NULL, 'm' },
|
||||
.argument = "SIZE",
|
||||
.desc = "Specifies number of 4KB pages for event ring buffer"
|
||||
},
|
||||
{
|
||||
.option = { "report", no_argument, NULL, 'r' },
|
||||
.desc = "Report file contents"
|
||||
},
|
||||
{
|
||||
.option = { "realtime", required_argument, NULL, 'R' },
|
||||
.argument = "PRIO",
|
||||
.desc = "Collect data with this RT SCHED_FIFO priority"
|
||||
},
|
||||
{
|
||||
.option = { "interval", required_argument, NULL, 'i' },
|
||||
.argument = "NUMBER",
|
||||
.desc = "Specifies interval between read operations in milliseconds"
|
||||
},
|
||||
{
|
||||
.option = { "verbose", no_argument, NULL, 'V' },
|
||||
.desc = "Verbose output"
|
||||
},
|
||||
{
|
||||
.option = { "humantime", no_argument, NULL, 'H' },
|
||||
.desc = "Human readable timestamp in seconds.nanoseconds"
|
||||
},
|
||||
{
|
||||
.option = { "summary", no_argument, NULL, 'S' },
|
||||
.desc = "Print summary of all non-zero counter values"
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
static const struct util_prg prg = {
|
||||
.desc = "Record and report Processor Activity Instrumentation Facility Counters.",
|
||||
.copyright_vec = {
|
||||
@@ -1046,7 +992,7 @@ int main(int argc, char **argv)
|
||||
util_list_init(&list_pai_event, struct pai_event, node);
|
||||
util_list_init(&list_pmu_event, struct pmu_events, node);
|
||||
util_prg_init(&prg);
|
||||
util_opt_init(opt_vec, NULL);
|
||||
util_opt_init(pai_opt_vec, NULL);
|
||||
|
||||
/* Read currently online CPUs and create a bit mask.
|
||||
* This bitmap of online CPUs is used to check command line parameter
|
||||
|
||||
65
cpumf/pai_cli.h
Normal file
65
cpumf/pai_cli.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for pai
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 PAI_CLI_H
|
||||
#define PAI_CLI_H
|
||||
|
||||
#include "lib/util_fmt.h"
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static struct util_opt pai_opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "crypto", optional_argument, NULL, 'c' },
|
||||
.argument = "CPULIST[:DATA]",
|
||||
.desc = "Collect PAI crypto counters"
|
||||
},
|
||||
{
|
||||
.option = { "nnpa", optional_argument, NULL, 'n' },
|
||||
.argument = "CPULIST[:DATA]",
|
||||
.desc = "Collect PAI nnpa counters"
|
||||
},
|
||||
{
|
||||
.option = { "mapsize", required_argument, NULL, 'm' },
|
||||
.argument = "SIZE",
|
||||
.desc = "Specifies number of 4KB pages for event ring buffer"
|
||||
},
|
||||
{
|
||||
.option = { "report", no_argument, NULL, 'r' },
|
||||
.desc = "Report file contents"
|
||||
},
|
||||
{
|
||||
.option = { "realtime", required_argument, NULL, 'R' },
|
||||
.argument = "PRIO",
|
||||
.desc = "Collect data with this RT SCHED_FIFO priority"
|
||||
},
|
||||
{
|
||||
.option = { "interval", required_argument, NULL, 'i' },
|
||||
.argument = "NUMBER",
|
||||
.desc = "Specifies interval between read operations in milliseconds"
|
||||
},
|
||||
{
|
||||
.option = { "verbose", no_argument, NULL, 'V' },
|
||||
.desc = "Verbose output"
|
||||
},
|
||||
{
|
||||
.option = { "humantime", no_argument, NULL, 'H' },
|
||||
.desc = "Human readable timestamp in seconds.nanoseconds"
|
||||
},
|
||||
{
|
||||
.option = { "summary", no_argument, NULL, 'S' },
|
||||
.desc = "Print summary of all non-zero counter values"
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,10 @@
|
||||
include ../common.mak
|
||||
|
||||
zsh-completions = _dasdfmt
|
||||
bash-completions = dasdfmt.bash
|
||||
|
||||
include ../common_autocomp.mak
|
||||
|
||||
all: dasdfmt
|
||||
|
||||
libs = $(rootdir)/libdasd/libdasd.a \
|
||||
|
||||
20
dasdfmt/autocompletion_generator_host.c
Normal file
20
dasdfmt/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Autocompletion generation - for dasdfmt tool
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 "lib/util_autocomp.h"
|
||||
|
||||
#include "dasdfmt_cli.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
generate_autocomp(opt_vec, "dasdfmt");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "lib/zt_common.h"
|
||||
|
||||
#include "dasdfmt.h"
|
||||
#include "dasdfmt_cli.h"
|
||||
|
||||
#define BUSIDSIZE 8
|
||||
#define SEC_PER_DAY (60 * 60 * 24)
|
||||
@@ -81,112 +82,6 @@ static struct dasdfmt_globals {
|
||||
.dasd_info = { 0 },
|
||||
};
|
||||
|
||||
/* 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"),
|
||||
{
|
||||
.option = { "mode", required_argument, NULL, 'M' },
|
||||
.argument = "MODE",
|
||||
.desc = "Specify scope of operation using MODE:\n"
|
||||
" full: Full device (default)\n"
|
||||
" quick: Only the first two tracks\n"
|
||||
" expand: Unformatted tracks at device end",
|
||||
},
|
||||
{
|
||||
.option = { "check", no_argument, NULL, OPT_CHECK },
|
||||
.desc = "Perform complete format check on device",
|
||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||
},
|
||||
UTIL_OPT_SECTION("FORMAT OPTIONS"),
|
||||
{
|
||||
.option = { "blocksize", required_argument, NULL, 'b' },
|
||||
.argument = "SIZE",
|
||||
.desc = "Format blocks to SIZE bytes (default 4096)",
|
||||
},
|
||||
{
|
||||
.option = { "disk_layout", required_argument, NULL, 'd' },
|
||||
.argument = "LAYOUT",
|
||||
.desc = "Specify the disk layout:\n"
|
||||
" cdl: Compatible Disk Layout (default)\n"
|
||||
" ldl: Linux Disk Layout",
|
||||
},
|
||||
{
|
||||
.option = { "keep_volser", no_argument, NULL, 'k' },
|
||||
.desc = "Do not change the current volume serial",
|
||||
},
|
||||
{
|
||||
.option = { "label", required_argument, NULL, 'l' },
|
||||
.argument = "VOLSER",
|
||||
.desc = "Specify volume serial number",
|
||||
},
|
||||
{
|
||||
.option = { "no_label", no_argument, NULL, 'L' },
|
||||
.desc = "Don't write a disk label",
|
||||
},
|
||||
{
|
||||
.option = { "requestsize", required_argument, NULL, 'r' },
|
||||
.argument = "NUM",
|
||||
.desc = "Process NUM cylinders in one formatting step",
|
||||
},
|
||||
{
|
||||
.option = { "norecordzero", no_argument, NULL, OPT_NOZERO },
|
||||
.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",
|
||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||
},
|
||||
UTIL_OPT_SECTION("DISPLAY PROGRESS"),
|
||||
{
|
||||
.option = { "hashmarks", required_argument, NULL, 'm' },
|
||||
.argument = "NUM",
|
||||
.desc = "Show a hashmark every NUM cylinders",
|
||||
},
|
||||
{
|
||||
.option = { "progressbar", no_argument, NULL, 'p' },
|
||||
.desc = "Show a progressbar",
|
||||
},
|
||||
{
|
||||
.option = { "percentage", no_argument, NULL, 'P' },
|
||||
.desc = "Show progress in percent",
|
||||
},
|
||||
UTIL_OPT_SECTION("MISC"),
|
||||
{
|
||||
.option = { "check_host_count", no_argument, NULL, 'C' },
|
||||
.desc = "Check if device is in use by other hosts",
|
||||
},
|
||||
{
|
||||
.option = { "force", no_argument, NULL, 'F' },
|
||||
.desc = "Format without performing sanity checking",
|
||||
},
|
||||
{
|
||||
.option = { "test", no_argument, NULL, 't' },
|
||||
.desc = "Run in dry-run mode without modifying the DASD",
|
||||
},
|
||||
{
|
||||
.option = { NULL, no_argument, NULL, 'v' },
|
||||
.desc = "Print verbose messages when executing",
|
||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
{
|
||||
.option = { "version", no_argument, NULL, 'V' },
|
||||
.desc = "Print version information, then exit",
|
||||
},
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
/* Report error, free memory, and exit */
|
||||
static void error(const char *format, ...)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <limits.h>
|
||||
#include <mntent.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -69,13 +70,13 @@ static void error(const char *format, ...)
|
||||
"is in invalid format\n",prog_name);}
|
||||
|
||||
typedef struct bootstrap1 {
|
||||
u_int32_t key;
|
||||
u_int32_t data[6];
|
||||
uint32_t key;
|
||||
uint32_t data[6];
|
||||
} __attribute__ ((packed)) bootstrap1_t;
|
||||
|
||||
typedef struct bootstrap2 {
|
||||
u_int32_t key;
|
||||
u_int32_t data[36];
|
||||
uint32_t key;
|
||||
uint32_t data[36];
|
||||
} __attribute__ ((packed)) bootstrap2_t;
|
||||
|
||||
|
||||
|
||||
123
dasdfmt/dasdfmt_cli.h
Normal file
123
dasdfmt/dasdfmt_cli.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for dasdfmt
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 DASDFMT_CLI_H
|
||||
#define DASDFMT_CLI_H
|
||||
|
||||
#include "lib/util_fmt.h"
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
/* 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"),
|
||||
{
|
||||
.option = { "mode", required_argument, NULL, 'M' },
|
||||
.argument = "MODE",
|
||||
.desc = "Specify scope of operation using MODE:\n"
|
||||
" full: Full device (default)\n"
|
||||
" quick: Only the first two tracks\n"
|
||||
" expand: Unformatted tracks at device end",
|
||||
},
|
||||
{
|
||||
.option = { "check", no_argument, NULL, OPT_CHECK },
|
||||
.desc = "Perform complete format check on device",
|
||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||
},
|
||||
UTIL_OPT_SECTION("FORMAT OPTIONS"),
|
||||
{
|
||||
.option = { "blocksize", required_argument, NULL, 'b' },
|
||||
.argument = "SIZE",
|
||||
.desc = "Format blocks to SIZE bytes (default 4096)",
|
||||
},
|
||||
{
|
||||
.option = { "disk_layout", required_argument, NULL, 'd' },
|
||||
.argument = "LAYOUT",
|
||||
.desc = "Specify the disk layout:\n"
|
||||
" cdl: Compatible Disk Layout (default)\n"
|
||||
" ldl: Linux Disk Layout",
|
||||
},
|
||||
{
|
||||
.option = { "keep_volser", no_argument, NULL, 'k' },
|
||||
.desc = "Do not change the current volume serial",
|
||||
},
|
||||
{
|
||||
.option = { "label", required_argument, NULL, 'l' },
|
||||
.argument = "VOLSER",
|
||||
.desc = "Specify volume serial number",
|
||||
},
|
||||
{
|
||||
.option = { "no_label", no_argument, NULL, 'L' },
|
||||
.desc = "Don't write a disk label",
|
||||
},
|
||||
{
|
||||
.option = { "requestsize", required_argument, NULL, 'r' },
|
||||
.argument = "NUM",
|
||||
.desc = "Process NUM cylinders in one formatting step",
|
||||
},
|
||||
{
|
||||
.option = { "norecordzero", no_argument, NULL, OPT_NOZERO },
|
||||
.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",
|
||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||
},
|
||||
UTIL_OPT_SECTION("DISPLAY PROGRESS"),
|
||||
{
|
||||
.option = { "hashmarks", required_argument, NULL, 'm' },
|
||||
.argument = "NUM",
|
||||
.desc = "Show a hashmark every NUM cylinders",
|
||||
},
|
||||
{
|
||||
.option = { "progressbar", no_argument, NULL, 'p' },
|
||||
.desc = "Show a progressbar",
|
||||
},
|
||||
{
|
||||
.option = { "percentage", no_argument, NULL, 'P' },
|
||||
.desc = "Show progress in percent",
|
||||
},
|
||||
UTIL_OPT_SECTION("MISC"),
|
||||
{
|
||||
.option = { "check_host_count", no_argument, NULL, 'C' },
|
||||
.desc = "Check if device is in use by other hosts",
|
||||
},
|
||||
{
|
||||
.option = { "force", no_argument, NULL, 'F' },
|
||||
.desc = "Format without performing sanity checking",
|
||||
},
|
||||
{
|
||||
.option = { "test", no_argument, NULL, 't' },
|
||||
.desc = "Run in dry-run mode without modifying the DASD",
|
||||
},
|
||||
{
|
||||
.option = { NULL, no_argument, NULL, 'v' },
|
||||
.desc = "Print verbose messages when executing",
|
||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
{
|
||||
.option = { "version", no_argument, NULL, 'V' },
|
||||
.desc = "Print version information, then exit",
|
||||
},
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -23,16 +23,21 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lib/dasd_base.h"
|
||||
#include "lib/util_base.h"
|
||||
#include "lib/util_file.h"
|
||||
#include "lib/util_libc.h"
|
||||
#include "lib/util_opt.h"
|
||||
#include "lib/util_prg.h"
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/zt_common.h"
|
||||
|
||||
#define RD_BUFFER_SIZE 80
|
||||
#define TEMP_DEV_MAX_RETRIES 1000
|
||||
|
||||
#ifndef FTW_CONTINUE
|
||||
#define FTW_CONTINUE 0
|
||||
#define FTW_STOP 1
|
||||
#endif
|
||||
|
||||
static const struct util_prg prg = {
|
||||
.desc = "Display DASD volume serial number and ID information",
|
||||
.args = "-i BUSID | -b BLOCKDEV | -d DEVNODE",
|
||||
@@ -212,7 +217,7 @@ static int dinfo_read_dasd_vlabel(char *device, struct volume_label *vlabel,
|
||||
if (lseek(f, vlabel_start, SEEK_SET) < 0)
|
||||
goto error_close;
|
||||
|
||||
bzero(vlabel, vlsize);
|
||||
memset(vlabel, 0, vlsize);
|
||||
|
||||
if (read(f, vlabel, vlsize) != vlsize) {
|
||||
warnx("Could not read volume label");
|
||||
@@ -220,15 +225,15 @@ static int dinfo_read_dasd_vlabel(char *device, struct volume_label *vlabel,
|
||||
}
|
||||
|
||||
if (dasd_info.FBA_layout) {
|
||||
bzero(&tmp, vlsize);
|
||||
memset(&tmp, 0, vlsize);
|
||||
memcpy(&tmp, vlabel, vlsize);
|
||||
memcpy(vlabel->vollbl, &tmp, vlsize - 4);
|
||||
}
|
||||
|
||||
close(f);
|
||||
|
||||
bzero(readbuf, 7);
|
||||
bzero(vollbl, 5);
|
||||
memset(readbuf, 0, 7);
|
||||
memset(vollbl, 0, 5);
|
||||
strncpy(vollbl, vlabel->vollbl, 4);
|
||||
dinfo_ebcdic_dec(vollbl, vollbl, 4);
|
||||
|
||||
@@ -283,7 +288,7 @@ static int dinfo_create_devnode(dev_t dev, char **devno)
|
||||
char filename[] = "dasdinfo0000";
|
||||
mode_t mode;
|
||||
unsigned int path;
|
||||
int retry;
|
||||
unsigned int retry;
|
||||
int rc;
|
||||
int fd;
|
||||
|
||||
@@ -294,7 +299,7 @@ static int dinfo_create_devnode(dev_t dev, char **devno)
|
||||
if (pathname[path] == NULL)
|
||||
continue;
|
||||
for (retry = 0; retry < TEMP_DEV_MAX_RETRIES; retry++) {
|
||||
sprintf(filename, "dasdinfo%04d", retry);
|
||||
snprintf(filename, sizeof(filename), "dasdinfo%04d", retry);
|
||||
result = dinfo_make_path(pathname[path], filename);
|
||||
if (result == NULL)
|
||||
return -1;
|
||||
@@ -334,7 +339,7 @@ static int dinfo_extract_dev(dev_t *dev, char *str)
|
||||
char *p = NULL;
|
||||
int ma, mi;
|
||||
|
||||
bzero(tmp, RD_BUFFER_SIZE);
|
||||
memset(tmp, 0, RD_BUFFER_SIZE);
|
||||
util_strlcpy(tmp, str, RD_BUFFER_SIZE);
|
||||
p = strchr(tmp, ':');
|
||||
if (p == NULL) {
|
||||
@@ -354,18 +359,26 @@ static int dinfo_extract_dev(dev_t *dev, char *str)
|
||||
static int dinfo_get_dev_from_blockdev(char *blockdev, dev_t *dev)
|
||||
{
|
||||
char *readbuf = NULL;
|
||||
char *path;
|
||||
|
||||
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||
if (!readbuf) {
|
||||
warnx("Error: Not enough memory to allocate readbuffer");
|
||||
return -1;
|
||||
}
|
||||
if (util_file_read_line(readbuf, RD_BUFFER_SIZE,
|
||||
"/sys/block/%s/dev", blockdev) < 0)
|
||||
path = util_path_sysfs("block/%s/dev", blockdev);
|
||||
if (util_file_read_line(readbuf, RD_BUFFER_SIZE, path) < 0) {
|
||||
free(path);
|
||||
free(readbuf);
|
||||
return -1;
|
||||
if (dinfo_extract_dev(dev, readbuf) != 0)
|
||||
}
|
||||
free(path);
|
||||
if (dinfo_extract_dev(dev, readbuf) != 0) {
|
||||
free(readbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(readbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -373,8 +386,9 @@ static int
|
||||
dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
|
||||
int tflag, struct FTW *ftwbuf)
|
||||
{
|
||||
enum { LINK_DIR_SIZE = 128 };
|
||||
char linkdir[LINK_DIR_SIZE];
|
||||
char *tempdir;
|
||||
char linkdir[128];
|
||||
ssize_t i;
|
||||
|
||||
if (tflag != FTW_D || (strncmp((fpath + ftwbuf->base), searchbusid,
|
||||
@@ -387,12 +401,12 @@ dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
|
||||
*/
|
||||
if (asprintf(&tempdir, "%s/driver", fpath) < 0)
|
||||
return -1;
|
||||
i = readlink(tempdir, linkdir, 128);
|
||||
i = readlink(tempdir, linkdir, LINK_DIR_SIZE);
|
||||
free(tempdir);
|
||||
if ((i < 0) || (i >= 128))
|
||||
if (i < 0 || i >= LINK_DIR_SIZE)
|
||||
return -1;
|
||||
/* append '\0' because readlink returns non zero terminated string */
|
||||
tempdir[i + 1] = '\0';
|
||||
linkdir[i] = '\0';
|
||||
if (strstr(linkdir, "dasd") == NULL)
|
||||
return FTW_CONTINUE;
|
||||
free(busiddir);
|
||||
@@ -439,7 +453,7 @@ dinfo_get_blockdev_from_busid(char *busid, char **blkdev)
|
||||
|
||||
char *tempdir = NULL;
|
||||
char *result = NULL;
|
||||
char *sysfsdir = "/sys/devices/";
|
||||
char *sysfsdir = util_path_sysfs("devices/");
|
||||
|
||||
/* dinfo_is_devnode needs to know the busid */
|
||||
searchbusid = busid;
|
||||
@@ -475,6 +489,7 @@ out:
|
||||
out2:
|
||||
free(busiddir);
|
||||
free(result);
|
||||
free(sysfsdir);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -486,6 +501,7 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
||||
DIR *directory = NULL;
|
||||
struct dirent *dir_entry = NULL;
|
||||
int rc = 0;
|
||||
char *path;
|
||||
|
||||
if (stat(devnode, &stat_buffer) != 0) {
|
||||
warnx("Error: could not stat %s", devnode);
|
||||
@@ -495,32 +511,34 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
||||
sprintf(stat_dev, "%d:%d", major(stat_buffer.st_rdev),
|
||||
minor(stat_buffer.st_rdev));
|
||||
|
||||
directory = opendir("/sys/block/");
|
||||
path = util_path_sysfs("block/");
|
||||
directory = opendir(path);
|
||||
if (directory == NULL) {
|
||||
warnx("Error: could not open directory /sys/block");
|
||||
warnx("Error: could not open directory %s", path);
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||
if (!readbuf) {
|
||||
warnx("Error: Not enough memory to allocate readbuffer");
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((dir_entry = readdir(directory)) != NULL) {
|
||||
if (util_file_read_line(readbuf, RD_BUFFER_SIZE,
|
||||
"/sys/block/%s/dev",
|
||||
if (util_file_read_line(readbuf, RD_BUFFER_SIZE, "%s%s/dev", path,
|
||||
dir_entry->d_name) < 0)
|
||||
continue;
|
||||
|
||||
if (strncmp(stat_dev, readbuf,
|
||||
MAX(strlen(stat_dev), strlen(readbuf) - 1)) == 0) {
|
||||
rc = snprintf(*uidfile, RD_BUFFER_SIZE,
|
||||
"/sys/block/%s/device/uid",
|
||||
rc = snprintf(*uidfile, RD_BUFFER_SIZE, "%s%s/device/uid", path,
|
||||
dir_entry->d_name);
|
||||
if (rc >= RD_BUFFER_SIZE) {
|
||||
fprintf(stderr,
|
||||
"Error: Device name was truncated\n");
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -529,6 +547,7 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
||||
}
|
||||
|
||||
closedir(directory);
|
||||
free(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -626,16 +645,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||
uidfile = dinfo_malloc(RD_BUFFER_SIZE);
|
||||
if (!(readbuf && uidfile))
|
||||
if (!readbuf)
|
||||
exit(1);
|
||||
|
||||
/* try to read the uid attribute */
|
||||
if (busid) {
|
||||
sprintf(uidfile, "/sys/bus/ccw/devices/%s/uid", busid);
|
||||
uidfile = util_path_sysfs("bus/ccw/devices/%s/uid", busid);
|
||||
} else if (blockdev) {
|
||||
sprintf(uidfile, "/sys/block/%s/device/uid", blockdev);
|
||||
uidfile = util_path_sysfs("block/%s/device/uid", blockdev);
|
||||
} else if (devnode) {
|
||||
uidfile = dinfo_malloc(RD_BUFFER_SIZE);
|
||||
if (!uidfile)
|
||||
exit(1);
|
||||
if (dinfo_get_uid_from_devnode(&uidfile, devnode) != 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#define _LARGEFILE64_SOURCE /* needed for unistd.h */
|
||||
#define _FILE_OFFSET_BITS 64 /* needed for unistd.h */
|
||||
|
||||
#include <ctype.h>
|
||||
@@ -17,6 +16,7 @@
|
||||
#include <linux/version.h>
|
||||
#include <malloc.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -428,7 +428,7 @@ dasdview_read_vlabel(dasdview_info_t *info, volume_label_t *vlabel)
|
||||
|
||||
pos = info->dasd_info.label_block * info->blksize;
|
||||
|
||||
bzero(vlabel, sizeof(volume_label_t));
|
||||
memset(vlabel, 0, sizeof(volume_label_t));
|
||||
if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
|
||||
!info->dasd_info.FBA_layout) {
|
||||
/* OS/390 and zOS compatible disk layout */
|
||||
@@ -466,7 +466,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
printf("\n--- volume label -----------------------------"
|
||||
"---------------------------------\n");
|
||||
|
||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.volkey, 4);
|
||||
memset(s4, 0, 5);
|
||||
memset(t4, 0, 5);
|
||||
strncpy((char *)s4, vlabel.volkey, 4);
|
||||
printf("volume label key : ascii '%4s'\n", s4);
|
||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||
printf(" : ebcdic '%4s'\n", t4);
|
||||
@@ -474,7 +476,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("%02x", s4[i]);
|
||||
|
||||
bzero(s4, 5); bzero(s4, 5); strncpy((char *)s4, vlabel.vollbl, 4);
|
||||
memset(s4, 0, 5);
|
||||
memset(t4, 0, 5);
|
||||
strncpy((char *)s4, vlabel.vollbl, 4);
|
||||
printf("\n\nvolume label identifier : ascii '%4s'\n", s4);
|
||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||
printf(" : ebcdic '%4s'\n", t4);
|
||||
@@ -482,7 +486,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("%02x", s4[i]);
|
||||
|
||||
bzero(s6, 7); bzero(t6, 7); strncpy((char *)s6, vlabel.volid, 6);
|
||||
memset(s6, 0, 7);
|
||||
memset(t6, 0, 7);
|
||||
strncpy((char *)s6, vlabel.volid, 6);
|
||||
printf("\n\nvolume identifier : ascii '%6s'\n", s6);
|
||||
vtoc_ebcdic_dec((char *)s6, (char *)t6, 6);
|
||||
printf(" : ebcdic '%6s'\n", t6);
|
||||
@@ -503,7 +509,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
vtoc_get_cyl_from_cchhb(&vlabel.vtoc),
|
||||
vtoc_get_head_from_cchhb(&vlabel.vtoc), vlabel.vtoc.b);
|
||||
|
||||
bzero(s5, 6); bzero(t5, 6); strncpy((char *)s5, vlabel.res1, 5);
|
||||
memset(s5, 0, 6);
|
||||
memset(t5, 0, 6);
|
||||
strncpy((char *)s5, vlabel.res1, 5);
|
||||
printf("reserved : ascii '%5s'\n", s5);
|
||||
vtoc_ebcdic_dec((char *)s5, (char *)t5, 5);
|
||||
printf(" : ebcdic '%5s'\n", t5);
|
||||
@@ -511,7 +519,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
for (i = 0; i < 5; i++)
|
||||
printf("%02x", s5[i]);
|
||||
|
||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.cisize, 4);
|
||||
memset(s4, 0, 5);
|
||||
memset(t4, 0, 5);
|
||||
strncpy((char *)s4, vlabel.cisize, 4);
|
||||
printf("\n\nCI size for FBA : ascii '%4s'\n", s4);
|
||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||
printf(" : ebcdic '%4s'\n", t4);
|
||||
@@ -519,7 +529,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("%02x", s4[i]);
|
||||
|
||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.blkperci, 4);
|
||||
memset(s4, 0, 5);
|
||||
memset(t4, 0, 5);
|
||||
strncpy((char *)s4, vlabel.blkperci, 4);
|
||||
printf("\n\nblocks per CI (FBA) : ascii '%4s'\n", s4);
|
||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||
printf(" : ebcdic '%4s'\n", t4);
|
||||
@@ -527,7 +539,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("%02x", s4[i]);
|
||||
|
||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.labperci, 4);
|
||||
memset(s4, 0, 5);
|
||||
memset(t4, 0, 5);
|
||||
strncpy((char *)s4, vlabel.labperci, 4);
|
||||
printf("\n\nlabels per CI (FBA) : ascii '%4s'\n", s4);
|
||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||
printf(" : ebcdic '%4s'\n", t4);
|
||||
@@ -535,7 +549,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("%02x", s4[i]);
|
||||
|
||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.res2, 4);
|
||||
memset(s4, 0, 5);
|
||||
memset(t4, 0, 5);
|
||||
strncpy((char *)s4, vlabel.res2, 4);
|
||||
printf("\n\nreserved : ascii '%4s'\n", s4);
|
||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||
printf(" : ebcdic '%4s'\n", t4);
|
||||
@@ -543,7 +559,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("%02x", s4[i]);
|
||||
|
||||
bzero(s14, 15); bzero(t14, 15); strncpy(s14, vlabel.lvtoc, 14);
|
||||
memset(s14, 0, 15);
|
||||
memset(t14, 0, 15);
|
||||
strncpy(s14, vlabel.lvtoc, 14);
|
||||
printf("\n\nowner code for VTOC : ascii '%14s'\n", s14);
|
||||
vtoc_ebcdic_dec(s14, t14, 14);
|
||||
printf(" ebcdic '%14s'\n", t14);
|
||||
@@ -556,9 +574,10 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
bzero(s29, 30); strncpy(s29, vlabel.res3, 28);
|
||||
memset(s29, 0, 30);
|
||||
strncpy(s29, vlabel.res3, 28);
|
||||
printf("\n\nreserved : ascii '%28s'\n", s29);
|
||||
bzero(t29, 30);
|
||||
memset(t29, 0, 30);
|
||||
vtoc_ebcdic_dec(s29, t29, 28);
|
||||
printf(" ebcdic '%28s'\n", t29);
|
||||
printf(" hex ");
|
||||
@@ -573,7 +592,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
||||
" ");
|
||||
}
|
||||
|
||||
bzero(s4, 5); bzero(t4, 5); s4[0] = vlabel.ldl_version;
|
||||
memset(s4, 0, 5);
|
||||
memset(t4, 0, 5);
|
||||
s4[0] = vlabel.ldl_version;
|
||||
printf("\n\nldl_version : ascii '%1s'\n", s4);
|
||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 1);
|
||||
printf(" : ebcdic '%1s'\n", t4);
|
||||
@@ -609,8 +630,8 @@ dasdview_print_volser(dasdview_info_t *info)
|
||||
dasdview_read_vlabel(info, &vlabel);
|
||||
}
|
||||
|
||||
bzero(vollbl, 5);
|
||||
bzero(volser, 7);
|
||||
memset(vollbl, 0, 5);
|
||||
memset(volser, 0, 7);
|
||||
strncpy(vollbl, vlabel.vollbl, 4);
|
||||
vtoc_ebcdic_dec(vollbl, vollbl, 4);
|
||||
|
||||
@@ -631,12 +652,12 @@ dasdview_read_vtoc(dasdview_info_t *info)
|
||||
volume_label_t vlabel;
|
||||
format1_label_t tmp;
|
||||
unsigned long maxblk, pos;
|
||||
u_int64_t vtocblk;
|
||||
uint64_t vtocblk;
|
||||
int i;
|
||||
|
||||
pos = info->dasd_info.label_block * info->blksize;
|
||||
|
||||
bzero(&vlabel, sizeof(vlabel));
|
||||
memset(&vlabel, 0, sizeof(vlabel));
|
||||
if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
|
||||
!info->dasd_info.FBA_layout) {
|
||||
/* OS/390 and zOS compatible disk layout */
|
||||
@@ -648,7 +669,7 @@ dasdview_read_vtoc(dasdview_info_t *info)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
vtocblk = (u_int64_t)vtoc_get_cyl_from_cchhb(&vlabel.vtoc) *
|
||||
vtocblk = (uint64_t)vtoc_get_cyl_from_cchhb(&vlabel.vtoc) *
|
||||
info->geo.heads * info->geo.sectors +
|
||||
vtoc_get_head_from_cchhb(&vlabel.vtoc) * info->geo.sectors +
|
||||
vlabel.vtoc.b;
|
||||
@@ -747,13 +768,13 @@ static void dasdview_print_format1_8_short_info(format1_label_t *f1,
|
||||
char s6[7], s13[14], s44[45];
|
||||
unsigned long track_low, track_up;
|
||||
|
||||
bzero(s44, 45);
|
||||
memset(s44, 0, 45);
|
||||
strncpy(s44, f1->DS1DSNAM, 44);
|
||||
vtoc_ebcdic_dec(s44, s44, 44);
|
||||
bzero(s6, 7);
|
||||
memset(s6, 0, 7);
|
||||
strncpy(s6, (char *)f1->DS1DSSN, 6);
|
||||
vtoc_ebcdic_dec(s6, s6, 6);
|
||||
bzero(s13, 14);
|
||||
memset(s13, 0, 14);
|
||||
strncpy(s13, (char *)f1->DS1SYSCD, 13);
|
||||
vtoc_ebcdic_dec(s13, s13, 13);
|
||||
|
||||
@@ -837,13 +858,13 @@ static void dasdview_print_format1_8_short_info_raw(format1_label_t *f1,
|
||||
struct dscb *dscb;
|
||||
int rc;
|
||||
|
||||
bzero(s44, 45);
|
||||
memset(s44, 0, 45);
|
||||
strncpy(s44, f1->DS1DSNAM, 44);
|
||||
vtoc_ebcdic_dec(s44, s44, 44);
|
||||
bzero(s6, 7);
|
||||
memset(s6, 0, 7);
|
||||
strncpy(s6, (char *)f1->DS1DSSN, 6);
|
||||
vtoc_ebcdic_dec(s6, s6, 6);
|
||||
bzero(s13, 14);
|
||||
memset(s13, 0, 14);
|
||||
strncpy(s13, (char *)f1->DS1SYSCD, 13);
|
||||
vtoc_ebcdic_dec(s13, s13, 13);
|
||||
|
||||
@@ -1071,7 +1092,7 @@ static void dasdview_print_vtoc_info_raw(dasdview_info_t *info)
|
||||
|
||||
/*
|
||||
* Note: the explicit cylinder/head conversion for large volume
|
||||
* adresses should not be necessary for entries that point to
|
||||
* addresses should not be necessary for entries that point to
|
||||
* vtoc labels, as those must be located in the first 65K-1 tracks,
|
||||
* but we do it anyway to be on the safe side.
|
||||
*/
|
||||
@@ -1080,9 +1101,9 @@ static void dasdview_print_format1_8_no_head(format1_label_t *f1)
|
||||
char s6[7], s13[14], s44[45];
|
||||
int i;
|
||||
|
||||
bzero(s6, 7);
|
||||
bzero(s13, 14);
|
||||
bzero(s44, 45);
|
||||
memset(s6, 0, 7);
|
||||
memset(s13, 0, 14);
|
||||
memset(s44, 0, 45);
|
||||
|
||||
strncpy(s44, f1->DS1DSNAM, 44);
|
||||
printf("DS1DSNAM : ascii '%44s'\n", s44);
|
||||
@@ -1865,7 +1886,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
||||
|
||||
/* seek in SEEK_STEP steps */
|
||||
for (i = 1; i <= j; i++) {
|
||||
rc = lseek64(fd, SEEK_STEP, SEEK_CUR);
|
||||
rc = lseek(fd, SEEK_STEP, SEEK_CUR);
|
||||
if (rc == -1) {
|
||||
printf("*** rc: %d (%d) ***\n", rc, errno);
|
||||
printf("*** j: %llu ***\n", j);
|
||||
@@ -1918,7 +1939,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
||||
|
||||
count = info->begin;
|
||||
for (i = 1; i <= j; i++) {
|
||||
bzero(dumpstr, DUMP_STRING_SIZE);
|
||||
memset(dumpstr, 0, DUMP_STRING_SIZE);
|
||||
rc = read(fd, &dumpstr, DUMP_STRING_SIZE);
|
||||
if (rc != DUMP_STRING_SIZE) {
|
||||
close(fd);
|
||||
@@ -1937,7 +1958,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
||||
}
|
||||
|
||||
if (k > 0) {
|
||||
bzero(dumpstr, DUMP_STRING_SIZE);
|
||||
memset(dumpstr, 0, DUMP_STRING_SIZE);
|
||||
rc = read(fd, &dumpstr, k);
|
||||
if (rc != (int)k) {
|
||||
close(fd);
|
||||
@@ -1976,8 +1997,8 @@ static void dasdview_print_format_raw(unsigned int size, char *dumpstr)
|
||||
while (residual) {
|
||||
/* we handle at most 16 bytes per line */
|
||||
count = MIN(residual, 16u);
|
||||
bzero(asc, 17);
|
||||
bzero(ebc, 17);
|
||||
memset(asc, 0, 17);
|
||||
memset(ebc, 0, 17);
|
||||
printf("|");
|
||||
memcpy(asc, data, count);
|
||||
memcpy(ebc, data, count);
|
||||
@@ -2066,7 +2087,7 @@ static void dasdview_print_raw_track(char *trackdata,
|
||||
{
|
||||
struct eckd_count *ecount;
|
||||
char *data;
|
||||
u_int32_t record;
|
||||
uint32_t record;
|
||||
|
||||
record = 0;
|
||||
data = trackdata;
|
||||
@@ -2091,8 +2112,8 @@ static void dasdview_print_raw_track(char *trackdata,
|
||||
|
||||
static void dasdview_view_raw(dasdview_info_t *info)
|
||||
{
|
||||
u_int64_t residual, trckstart, trckend, track, trckbuffsize;
|
||||
u_int64_t tracks_to_read, trckcount, i;
|
||||
uint64_t residual, trckstart, trckend, track, trckbuffsize;
|
||||
uint64_t tracks_to_read, trckcount, i;
|
||||
char *trackdata;
|
||||
char *data;
|
||||
int rc;
|
||||
@@ -2187,7 +2208,7 @@ int main(int argc, char *argv[])
|
||||
util_prg_init(&prg);
|
||||
util_opt_init(opt_vec, NULL);
|
||||
|
||||
bzero(&info, sizeof(info));
|
||||
memset(&info, 0, sizeof(info));
|
||||
while (1) {
|
||||
oc = util_opt_getopt_long(argc, argv);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define DASDVIEW_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/********************************************************************************
|
||||
* SECTION: Definitions needed for DASD-API (see dasd.h)
|
||||
@@ -68,7 +69,7 @@ typedef struct dasdview_info
|
||||
int dasd_info_version;
|
||||
unsigned int blksize;
|
||||
struct hd_geometry geo;
|
||||
u_int32_t hw_cylinders;
|
||||
uint32_t hw_cylinders;
|
||||
|
||||
unsigned long long begin;
|
||||
unsigned long long size;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
. ds pfont \\n[.f]
|
||||
. nh
|
||||
. na
|
||||
. ft CW
|
||||
. ft CR
|
||||
\\$*
|
||||
. ft \\*[pfont]
|
||||
. ad
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "dref.h"
|
||||
#include "dump.h"
|
||||
#include "global.h"
|
||||
#include "idcache.h"
|
||||
#include "misc.h"
|
||||
#include "tar.h"
|
||||
|
||||
|
||||
@@ -18,3 +18,17 @@ CPI_SYSTEM_NAME=""
|
||||
# CPI sysplex name
|
||||
#
|
||||
CPI_SYSPLEX_NAME=""
|
||||
|
||||
#
|
||||
# CPI permit on protected virtualization guests
|
||||
#
|
||||
# Important: Set CPI_PERMIT_ON_PVGUEST=1 only if you trust the host system.
|
||||
# Enabling these options allows the host to receive potentially sensitive
|
||||
# Control-Program Identification (CPI) data from the protected virtualization
|
||||
# guest, including:
|
||||
# - system_type
|
||||
# - system_level
|
||||
# - sysplex_name
|
||||
# - system_name
|
||||
#
|
||||
CPI_PERMIT_ON_PVGUEST=
|
||||
|
||||
2
etc/udev/rules.d/59-virtio-blk.rules
Normal file
2
etc/udev/rules.d/59-virtio-blk.rules
Normal file
@@ -0,0 +1,2 @@
|
||||
SUBSYSTEM=="block", ACTION=="add", KERNEL=="vd*[!0-9]", TEST=="queue/rotational", ATTR{queue/rotational}="0"
|
||||
SUBSYSTEM=="block", ACTION=="add", KERNEL=="vd*[!0-9]", TEST=="queue/scheduler", ATTR{queue/scheduler}="none"
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
@@ -211,9 +212,9 @@ static void setpos(fdasd_anchor_t *anc, int dsn, int pos)
|
||||
anc->partno[dsn] = pos;
|
||||
}
|
||||
|
||||
static u_int32_t get_usable_cylinders(fdasd_anchor_t *anc)
|
||||
static uint32_t get_usable_cylinders(fdasd_anchor_t *anc)
|
||||
{
|
||||
u_int32_t cyl;
|
||||
uint32_t cyl;
|
||||
|
||||
/* large volume */
|
||||
if (anc->f4->DS4DEVCT.DS4DSCYL == LV_COMPAT_CYL &&
|
||||
@@ -221,7 +222,7 @@ static u_int32_t get_usable_cylinders(fdasd_anchor_t *anc)
|
||||
return anc->f4->DS4DCYL;
|
||||
/* normal volume */
|
||||
if (anc->f4->DS4DEVCT.DS4DEVFG & ALTERNATE_CYLINDERS_USED)
|
||||
cyl = anc->f4->DS4DEVCT.DS4DSCYL - (u_int16_t)anc->f4->DS4DEVAC;
|
||||
cyl = anc->f4->DS4DEVCT.DS4DSCYL - (uint16_t)anc->f4->DS4DEVAC;
|
||||
else
|
||||
cyl = anc->f4->DS4DEVCT.DS4DSCYL;
|
||||
|
||||
@@ -230,7 +231,7 @@ static u_int32_t get_usable_cylinders(fdasd_anchor_t *anc)
|
||||
|
||||
static void get_addr_of_highest_f1_f8_label(fdasd_anchor_t *anc, cchhb_t *addr)
|
||||
{
|
||||
u_int8_t record;
|
||||
uint8_t record;
|
||||
/* We have to count the following labels:
|
||||
* one format 4
|
||||
* one format 5
|
||||
@@ -406,7 +407,7 @@ static void fdasd_error(fdasd_anchor_t *anc, enum fdasd_failure why, char *str)
|
||||
*/
|
||||
static int read_line(void)
|
||||
{
|
||||
bzero(line_buffer, LINE_LENGTH);
|
||||
memset(line_buffer, 0, LINE_LENGTH);
|
||||
line_ptr = line_buffer;
|
||||
if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
|
||||
clearerr(stdin);
|
||||
@@ -493,7 +494,7 @@ static void fdasd_initialize_anchor(fdasd_anchor_t *anc)
|
||||
volume_label_t *vlabel;
|
||||
int i;
|
||||
|
||||
bzero(anc, sizeof(fdasd_anchor_t));
|
||||
memset(anc, 0, sizeof(fdasd_anchor_t));
|
||||
|
||||
for (i = 0; i < USABLE_PARTITIONS; i++)
|
||||
setpos(anc, i, -1);
|
||||
@@ -519,17 +520,17 @@ static void fdasd_initialize_anchor(fdasd_anchor_t *anc)
|
||||
fdasd_error(anc, malloc_failed,
|
||||
"FMT9 DSCB memory allocation failed.");
|
||||
|
||||
bzero(anc->f4, sizeof(format4_label_t));
|
||||
bzero(anc->f5, sizeof(format5_label_t));
|
||||
bzero(anc->f7, sizeof(format7_label_t));
|
||||
bzero(anc->f9, sizeof(format9_label_t));
|
||||
memset(anc->f4, 0, sizeof(format4_label_t));
|
||||
memset(anc->f5, 0, sizeof(format5_label_t));
|
||||
memset(anc->f7, 0, sizeof(format7_label_t));
|
||||
memset(anc->f9, 0, sizeof(format9_label_t));
|
||||
vtoc_init_format9_label(anc->f9);
|
||||
|
||||
vlabel = malloc(sizeof(volume_label_t));
|
||||
if (vlabel == NULL)
|
||||
fdasd_error(anc, malloc_failed,
|
||||
"Volume label memory allocation failed.");
|
||||
bzero(vlabel, sizeof(volume_label_t));
|
||||
memset(vlabel, 0, sizeof(volume_label_t));
|
||||
anc->vlabel = vlabel;
|
||||
|
||||
for (i = 1; i <= USABLE_PARTITIONS; i++) {
|
||||
@@ -551,7 +552,7 @@ static void fdasd_initialize_anchor(fdasd_anchor_t *anc)
|
||||
if (part_info->f1 == NULL)
|
||||
fdasd_error(anc, malloc_failed,
|
||||
"FMT1 DSCB memory allocation failed.");
|
||||
bzero(part_info->f1, sizeof(format1_label_t));
|
||||
memset(part_info->f1, 0, sizeof(format1_label_t));
|
||||
|
||||
if (prev_part_info) {
|
||||
prev_part_info->next = part_info;
|
||||
@@ -975,7 +976,7 @@ static void fdasd_verify_device(fdasd_anchor_t *anc, char *name)
|
||||
* Note:
|
||||
* - 'version' and 'help' are priority options.
|
||||
* All other parameters are ignored in that case.
|
||||
* - 'silent' and 'verbose' are allways allowed in any
|
||||
* - 'silent' and 'verbose' are always allowed in any
|
||||
* combination.
|
||||
*
|
||||
*/
|
||||
@@ -1052,10 +1053,10 @@ static void fdasd_show_mapping(fdasd_anchor_t *anc)
|
||||
int i = 0, j = 0, dev_len;
|
||||
|
||||
printf("\ndevice .........: %s\n", options.device);
|
||||
bzero(str, sizeof(str));
|
||||
memset(str, 0, sizeof(str));
|
||||
vtoc_volume_label_get_label(anc->vlabel, str);
|
||||
printf("volume label ...: %.4s\n", str);
|
||||
bzero(str, sizeof(str));
|
||||
memset(str, 0, sizeof(str));
|
||||
vtoc_volume_label_get_volser(anc->vlabel, str);
|
||||
printf("volume serial ..: %s\n\n", str);
|
||||
|
||||
@@ -1080,7 +1081,7 @@ static void fdasd_show_mapping(fdasd_anchor_t *anc)
|
||||
if (part_info->used != 0x01)
|
||||
continue;
|
||||
|
||||
bzero(dsname, sizeof(dsname));
|
||||
memset(dsname, 0, sizeof(dsname));
|
||||
strncpy(dsname, part_info->f1->DS1DSNAM, 44);
|
||||
vtoc_ebcdic_dec(dsname, dsname, 44);
|
||||
|
||||
@@ -1103,7 +1104,7 @@ static void fdasd_print_volser(fdasd_anchor_t *anc)
|
||||
{
|
||||
char volser[VOLSER_LENGTH + 1];
|
||||
|
||||
bzero(volser, VOLSER_LENGTH);
|
||||
memset(volser, 0, VOLSER_LENGTH);
|
||||
vtoc_ebcdic_dec(anc->vlabel->volid, volser, VOLSER_LENGTH);
|
||||
printf("%6.6s\n", volser);
|
||||
}
|
||||
@@ -1372,7 +1373,7 @@ static void fdasd_write_vtoc_labels(fdasd_anchor_t *anc)
|
||||
}
|
||||
|
||||
/* write empty labels to the rest of the blocks */
|
||||
bzero(&emptyf1, sizeof(emptyf1));
|
||||
memset(&emptyf1, 0, sizeof(emptyf1));
|
||||
while (blk < maxblk) {
|
||||
vtoc_write_label(options.device, blk, &emptyf1, NULL,
|
||||
NULL, NULL, NULL);
|
||||
@@ -1425,7 +1426,7 @@ static void fdasd_recreate_vtoc_unconditional(fdasd_anchor_t *anc)
|
||||
anc->formatted_cylinders, geo.heads);
|
||||
|
||||
while (part_info != NULL) {
|
||||
bzero(part_info->f1, sizeof(format1_label_t));
|
||||
memset(part_info->f1, 0, sizeof(format1_label_t));
|
||||
|
||||
if (part_info->used == 0x01) {
|
||||
part_info->used = 0x00;
|
||||
@@ -1826,7 +1827,7 @@ static void fdasd_process_valid_vtoc(fdasd_anchor_t *anc, unsigned long blk)
|
||||
|
||||
/* go through remaining labels, f4 label already done */
|
||||
for (i = 1; i < geo.sectors; i++) {
|
||||
bzero(&f1_label, f1_size);
|
||||
memset(&f1_label, 0, f1_size);
|
||||
vtoc_read_label(options.device, blk, &f1_label, NULL, NULL,
|
||||
NULL);
|
||||
|
||||
@@ -2470,9 +2471,9 @@ static int fdasd_get_partition_data(fdasd_anchor_t *anc, extent_t *part_extent,
|
||||
unsigned long start, stop, limit;
|
||||
partition_info_t *part_tmp;
|
||||
cchh_t llimit, ulimit;
|
||||
u_int16_t hh, head;
|
||||
u_int32_t cc, cyl;
|
||||
u_int8_t b1, b2;
|
||||
uint16_t hh, head;
|
||||
uint32_t cc, cyl;
|
||||
uint8_t b1, b2;
|
||||
char mesg[48];
|
||||
|
||||
start = FIRST_USABLE_TRK;
|
||||
@@ -2675,7 +2676,7 @@ static void fdasd_dequeue_old_partition(fdasd_anchor_t *anc,
|
||||
part_info->start_trk = 0x0;
|
||||
part_info->end_trk = 0x0;
|
||||
part_info->fspace_trk = 0x0;
|
||||
bzero(part_info->f1, sizeof(format1_label_t));
|
||||
memset(part_info->f1, 0, sizeof(format1_label_t));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2758,7 +2759,7 @@ static void fdasd_remove_partition(fdasd_anchor_t *anc)
|
||||
if (anc->used_partitions != 0)
|
||||
get_addr_of_highest_f1_f8_label(anc, &hf1);
|
||||
else
|
||||
bzero(&hf1, sizeof(struct cchhb));
|
||||
memset(&hf1, 0, sizeof(struct cchhb));
|
||||
|
||||
vtoc_update_format4_label(anc->f4, &hf1, anc->f4->DS4DSREC + 1);
|
||||
vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '+', anc->verbose,
|
||||
@@ -2777,8 +2778,8 @@ static void fdasd_auto_partition(fdasd_anchor_t *anc)
|
||||
{
|
||||
partition_info_t *part_info = anc->first;
|
||||
cchh_t llimit, ulimit;
|
||||
u_int16_t head;
|
||||
u_int32_t cyl;
|
||||
uint16_t head;
|
||||
uint32_t cyl;
|
||||
extent_t ext;
|
||||
cchhb_t hf1;
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#ifndef FDASD_H
|
||||
#define FDASD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* SECTION: Definitions needed for DASD-API (see dasd.h) *
|
||||
*****************************************************************************/
|
||||
@@ -67,7 +69,7 @@ static struct fdasd_options options = {
|
||||
};
|
||||
|
||||
typedef struct partition_info {
|
||||
u_int8_t used;
|
||||
uint8_t used;
|
||||
unsigned long start_trk;
|
||||
unsigned long end_trk;
|
||||
unsigned long len_trk;
|
||||
@@ -100,7 +102,7 @@ typedef struct fdasd_anchor {
|
||||
int option_reuse;
|
||||
int option_recreate;
|
||||
int partno[USABLE_PARTITIONS];
|
||||
u_int16_t dev_type;
|
||||
uint16_t dev_type;
|
||||
unsigned int used_partitions;
|
||||
unsigned long label_pos;
|
||||
unsigned int blksize;
|
||||
@@ -113,8 +115,8 @@ typedef struct fdasd_anchor {
|
||||
partition_info_t *last;
|
||||
volume_label_t *vlabel;
|
||||
config_data_t confdata[USABLE_PARTITIONS];
|
||||
u_int32_t hw_cylinders;
|
||||
u_int32_t formatted_cylinders;
|
||||
uint32_t hw_cylinders;
|
||||
uint32_t formatted_cylinders;
|
||||
} fdasd_anchor_t;
|
||||
|
||||
enum offset {lower, upper};
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
#define DBFS_WAIT_TIME_US 10000
|
||||
|
||||
extern int dg_debugfs_init(int exit_on_err);
|
||||
extern int dg_debugfs_vm_init(void);
|
||||
extern int dg_debugfs_lpar_init(void);
|
||||
extern int dg_debugfs_open(const char *file);
|
||||
int dg_debugfs_init(int exit_on_err);
|
||||
int dg_debugfs_vm_init(void);
|
||||
int dg_debugfs_lpar_init(void);
|
||||
int dg_debugfs_open(const char *file);
|
||||
|
||||
/*
|
||||
* z/VM diag 0C prototypes
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#define CPU_TYPE_LEN 16
|
||||
#define DEBUGFS_FILE "diag_204"
|
||||
|
||||
static struct sd_sys *l_cur_lpar;
|
||||
static u64 l_update_time_us;
|
||||
static long l_204_buf_size;
|
||||
|
||||
@@ -36,7 +37,8 @@ static long l_204_buf_size;
|
||||
struct l_x_info_blk_hdr {
|
||||
u8 npar;
|
||||
u8 flags;
|
||||
u8 reserved1[6];
|
||||
u8 reserved1[4];
|
||||
u16 this_part;
|
||||
u64 curtod1;
|
||||
u64 curtod2;
|
||||
u8 reserved[40];
|
||||
@@ -158,6 +160,21 @@ static void *l_sd_sys_fill(struct sd_sys *lpar, struct l_x_sys_hdr *sys_hdr)
|
||||
return cpu_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the time delta between samples using current partition's
|
||||
* online time.
|
||||
*/
|
||||
static u64 l_sd_cur_lpar_delta_time_get(void)
|
||||
{
|
||||
struct sd_cpu *cpu;
|
||||
|
||||
cpu = sd_cpu_get(l_cur_lpar, "0");
|
||||
if (!cpu->d_prev || !cpu->d_cur)
|
||||
return 0;
|
||||
return l_sub_64(cpu->d_cur->online_time_us,
|
||||
cpu->d_prev->online_time_us);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill one physical CPU with data
|
||||
*/
|
||||
@@ -241,9 +258,9 @@ static void l_read_debugfs(struct l_debugfs_d204_hdr **hdr,
|
||||
*/
|
||||
static void l_sd_sys_root_fill(struct sd_sys *sys)
|
||||
{
|
||||
struct l_x_sys_hdr *sys_hdr, *this_part;
|
||||
struct l_x_info_blk_hdr *time_hdr;
|
||||
struct l_debugfs_d204_hdr *hdr;
|
||||
struct l_x_sys_hdr *sys_hdr;
|
||||
struct sd_sys *lpar;
|
||||
char lpar_id[10];
|
||||
int i;
|
||||
@@ -262,18 +279,23 @@ static void l_sd_sys_root_fill(struct sd_sys *sys)
|
||||
usleep(DBFS_WAIT_TIME_US);
|
||||
} while (1);
|
||||
sys_hdr = ((void *) time_hdr) + sizeof(struct l_x_info_blk_hdr);
|
||||
this_part = ((void *)time_hdr) + time_hdr->this_part;
|
||||
for (i = 0; i < time_hdr->npar; i++) {
|
||||
l_sys_hdr__sys_name(sys_hdr, lpar_id);
|
||||
lpar = sd_sys_get(sys, lpar_id);
|
||||
if (!lpar)
|
||||
lpar = sd_sys_new(sys, lpar_id);
|
||||
if (sys_hdr == this_part)
|
||||
l_cur_lpar = lpar;
|
||||
lpar->threads_per_core = l_thread_cnt(sys_hdr);
|
||||
sys_hdr = l_sd_sys_fill(lpar, sys_hdr);
|
||||
sd_sys_commit(lpar);
|
||||
}
|
||||
|
||||
if (time_hdr->flags & LPAR_PHYS_FLG)
|
||||
if (time_hdr->flags & LPAR_PHYS_FLG) {
|
||||
l_sd_sys_root_cpu_phys_fill(sys, (void *) sys_hdr);
|
||||
sd_phys_delta_time_us_set(sys, l_sd_cur_lpar_delta_time_get());
|
||||
}
|
||||
ht_free(hdr);
|
||||
sd_sys_commit(sys);
|
||||
}
|
||||
@@ -290,6 +312,16 @@ static void l_sd_update(void)
|
||||
sd_sys_update_end(root, l_update_time_us);
|
||||
}
|
||||
|
||||
/*
|
||||
* Supported physical information items
|
||||
*/
|
||||
static struct sd_sys_item *l_phys_item_vec[] = {
|
||||
&sd_sys_item_core_cnt,
|
||||
&sd_sys_item_phys_mgm_diff,
|
||||
&sd_sys_item_mgm,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* Supported system items
|
||||
*/
|
||||
@@ -364,6 +396,7 @@ static struct sd_cpu_type *l_cpu_type_vec[] = {
|
||||
static struct sd_dg l_sd_dg = {
|
||||
.update_sys = l_sd_update,
|
||||
.cpu_type_vec = l_cpu_type_vec,
|
||||
.phys_item_vec = l_phys_item_vec,
|
||||
.sys_item_vec = l_sys_item_vec,
|
||||
.sys_item_enable_vec = l_sys_item_enable_vec,
|
||||
.cpu_item_vec = l_cpu_item_vec,
|
||||
@@ -383,6 +416,6 @@ int dg_debugfs_lpar_init(void)
|
||||
return fh;
|
||||
else
|
||||
close(fh);
|
||||
sd_dg_register(&l_sd_dg, 1);
|
||||
sd_dg_register(&l_sd_dg, 1, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -358,6 +358,6 @@ int dg_debugfs_vm_init(void)
|
||||
close(fh);
|
||||
l_2fc_buf_size = sizeof(struct l_debugfs_d2fc_hdr);
|
||||
l_guest_name_init();
|
||||
sd_dg_register(&dg_debugfs_vm_dg, 0);
|
||||
sd_dg_register(&dg_debugfs_vm_dg, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <iconv.h>
|
||||
#include <limits.h>
|
||||
#include <mntent.h>
|
||||
#include <mntent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -25,6 +24,10 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef _PATH_MOUNTED
|
||||
#define _PATH_MOUNTED "/etc/mtab"
|
||||
#endif
|
||||
|
||||
#include "lib/util_fmt.h"
|
||||
#include "lib/util_libc.h"
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "lib/util_base.h"
|
||||
#include "lib/util_libc.h"
|
||||
#include "lib/util_time.h"
|
||||
#include "lib/zt_common.h"
|
||||
|
||||
#define G0(x) MAX(0, (s64) (x))
|
||||
@@ -25,23 +26,23 @@
|
||||
/*
|
||||
* Helper Prototypes
|
||||
*/
|
||||
extern void hyptop_helper_init(void);
|
||||
extern char *ht_strstrip(char *str);
|
||||
extern char *ht_strdup(const char *str);
|
||||
extern void ht_print_head(const char *sys);
|
||||
extern void ht_print_help_icon(void);
|
||||
extern void ht_ebcdic_to_ascii(char *in, char *out, size_t len);
|
||||
extern char *ht_mount_point_get(const char *fs_type);
|
||||
extern u64 ht_ext_tod_2_us(void *tod_ext);
|
||||
extern void ht_print_time(void);
|
||||
extern s64 ht_calculate_smt_util(u64 core_us, u64 thr_us, u64 mgm_us, int thread_per_core);
|
||||
void hyptop_helper_init(void);
|
||||
char *ht_strstrip(char *str);
|
||||
char *ht_strdup(const char *str);
|
||||
void ht_print_head(const char *sys);
|
||||
void ht_print_help_icon(void);
|
||||
void ht_ebcdic_to_ascii(char *in, char *out, size_t len);
|
||||
char *ht_mount_point_get(const char *fs_type);
|
||||
u64 ht_ext_tod_2_us(void *tod_ext);
|
||||
void ht_print_time(void);
|
||||
s64 ht_calculate_smt_util(u64 core_us, u64 thr_us, u64 mgm_us, int thread_per_core);
|
||||
|
||||
/*
|
||||
* Memory alloc functions
|
||||
*/
|
||||
extern void *ht_zalloc(size_t size);
|
||||
extern void *ht_alloc(size_t size);
|
||||
extern void *ht_realloc(void *ptr, size_t size);
|
||||
void *ht_zalloc(size_t size);
|
||||
void *ht_alloc(size_t size);
|
||||
void *ht_realloc(void *ptr, size_t size);
|
||||
static inline void ht_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
|
||||
@@ -62,11 +62,11 @@ shown.
|
||||
Select sort field for current window. To reverse the sort order, specify the
|
||||
option twice. See FIELDS below for definitions.
|
||||
.TP
|
||||
.BR "\-t <TYPE>,..." " or " "\-\-cpu_types=<TYPE>,..."
|
||||
.BR "\-t <TYPE>,..." " or " "\-\-cpu-types=<TYPE>,..."
|
||||
Select CPU types that are used for CPU time calculations. See CPU TYPES
|
||||
below for definitions.
|
||||
.TP
|
||||
.BR "\-b" " or " "\-\-batch_mode"
|
||||
.BR "\-b" " or " "\-\-batch-mode"
|
||||
Use batch mode (no curses). This can be useful for sending output from hyptop
|
||||
to another program, a file, or a line mode terminal.
|
||||
In this mode no user input is accepted.
|
||||
@@ -113,13 +113,20 @@ All values are enclosed in double quotation marks and separated by commas. The
|
||||
first line of output contains a list of headings. Subsequent lines each
|
||||
represent data for one system in one iteration.
|
||||
.PP
|
||||
This option implies the "\-\-batch_mode" option.
|
||||
This option implies the "\-\-batch-mode" option.
|
||||
.RE
|
||||
.BR "\-\-all"
|
||||
.RS
|
||||
Use this option with the "--format" option to include fields without valid
|
||||
values in the output. Fields without valid values are omitted from the output
|
||||
by default. When you use the "--all" option, the invalid values are included
|
||||
and shown as "null".
|
||||
.RE
|
||||
.TP
|
||||
.BR "\-d <SECONDS>" " or " "\-\-delay=<SECONDS>"
|
||||
Specifies the delay between screen updates.
|
||||
.TP
|
||||
.BR "\-m <FACTOR>" " or " "\-\-smt_factor=<FACTOR>"
|
||||
.BR "\-m <FACTOR>" " or " "\-\-smt-factor=<FACTOR>"
|
||||
Specifies a workload dependent SMT speedup factor.
|
||||
For IBM z15 servers, the default value is 1.3. If the workload benefits
|
||||
from SMT, you can specify a higher value. If the workload does not benefit
|
||||
@@ -239,7 +246,7 @@ The following units are supported:
|
||||
|
||||
.SH CPU TYPES
|
||||
Depending on the hypervisor different CPU types are supported. These CPU
|
||||
types can be selected either interactively or with the "--cpu_types"
|
||||
types can be selected either interactively or with the "--cpu-types"
|
||||
command line option. The calculation of the CPU data only uses CPUs of
|
||||
the specified types.
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ static enum hyptop_win_action l_sleep(time_t time_s, long time_us)
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = time_s;
|
||||
ts.tv_nsec = time_us * 1000;
|
||||
ts.tv_nsec = util_usecs_to_nsecs(time_us);
|
||||
|
||||
nanosleep(&ts, NULL);
|
||||
return WIN_KEEP;
|
||||
@@ -231,6 +231,8 @@ static void l_fmt_init(void)
|
||||
return;
|
||||
if (g.o.format == FMT_CSV)
|
||||
flags |= FMT_QUOTEALL;
|
||||
if (g.o.format == FMT_CSV || g.o.format_all)
|
||||
flags |= FMT_KEEPINVAL;
|
||||
if (g.o.format == FMT_JSON || g.o.format == FMT_JSONSEQ)
|
||||
flags |= FMT_HANDLEINT;
|
||||
util_fmt_init(stdout, g.o.format, flags, 1);
|
||||
|
||||
@@ -55,6 +55,7 @@ struct hyptop_opts {
|
||||
unsigned int win_specified;
|
||||
unsigned int batch_mode_specified;
|
||||
unsigned int format_specified;
|
||||
unsigned int format_all;
|
||||
enum util_fmt_t format;
|
||||
unsigned int iterations_specified;
|
||||
unsigned int iterations;
|
||||
@@ -183,10 +184,10 @@ enum hyptop_win_action {
|
||||
WIN_KEEP,
|
||||
};
|
||||
|
||||
extern enum hyptop_win_action hyptop_process_input_timeout(void);
|
||||
extern enum hyptop_win_action hyptop_process_input(void);
|
||||
extern enum hyptop_win_action win_switch(struct hyptop_win *w);
|
||||
extern enum hyptop_win_action win_back(void);
|
||||
enum hyptop_win_action hyptop_process_input_timeout(void);
|
||||
enum hyptop_win_action hyptop_process_input(void);
|
||||
enum hyptop_win_action win_switch(struct hyptop_win *w);
|
||||
enum hyptop_win_action win_back(void);
|
||||
|
||||
struct hyptop_win;
|
||||
struct hyptop_win {
|
||||
@@ -205,25 +206,25 @@ struct hyptop_win {
|
||||
* Window sys_list
|
||||
*/
|
||||
extern struct hyptop_win win_sys_list;
|
||||
extern void win_sys_list_init(void);
|
||||
void win_sys_list_init(void);
|
||||
|
||||
/*
|
||||
* Window sys
|
||||
*/
|
||||
extern struct hyptop_win win_sys;
|
||||
extern void win_sys_set(const char *sys_id);
|
||||
extern void win_sys_init(void);
|
||||
void win_sys_set(const char *sys_id);
|
||||
void win_sys_init(void);
|
||||
|
||||
/*
|
||||
* Window cpu_types
|
||||
*/
|
||||
extern void win_cpu_types_init(void);
|
||||
void win_cpu_types_init(void);
|
||||
|
||||
/*
|
||||
* Misc functions
|
||||
*/
|
||||
extern void hyptop_update_term(void);
|
||||
extern void __noreturn hyptop_exit(int rc);
|
||||
extern void hyptop_text_mode(void);
|
||||
void hyptop_update_term(void);
|
||||
void __noreturn hyptop_exit(int rc);
|
||||
void hyptop_text_mode(void);
|
||||
|
||||
#endif /* HYPTOP_H */
|
||||
|
||||
@@ -39,17 +39,28 @@ static char HELP_TEXT[] =
|
||||
"-s, --sys SYSTEM[,..] Systems for current window\n"
|
||||
"-f, --fields LETTER[:UNIT][,..] Fields and units for current window\n"
|
||||
"-S, --sort LETTER Sort field for current window\n"
|
||||
"-t, --cpu_types TYPE[,..] CPU types used for time calculations\n"
|
||||
"-b, --batch_mode Use batch mode (no curses)\n"
|
||||
"-t, --cpu-types TYPE[,..] CPU types used for time calculations\n"
|
||||
"-b, --batch-mode Use batch mode (no curses)\n"
|
||||
" --format FORMAT Output format (" FMT_TYPE_NAMES "), implies -b\n"
|
||||
" --all Include omitted fields (with values of null)\n"
|
||||
" in the output of --format.\n"
|
||||
"-d, --delay SECONDS Delay time between screen updates\n"
|
||||
"-m, --smt_factor FACTOR Machine generation dependent SMT speedup factor.\n"
|
||||
"-m, --smt-factor FACTOR Machine generation dependent SMT speedup factor.\n"
|
||||
"-n, --iterations NUMBER Number of iterations before ending\n";
|
||||
|
||||
/*
|
||||
* Options with long-name only
|
||||
*/
|
||||
#define OPT_FORMAT 256 /* --format */
|
||||
#define OPT_FORMAT_ALL 261 /* --all*/
|
||||
|
||||
/*
|
||||
* Options with underscore to keep compatibility
|
||||
*/
|
||||
#define OPT_BATCH_MODE 257 /* --batch_mode */
|
||||
#define OPT_SORT_FIELD 258 /* --sort | --sort_field */
|
||||
#define OPT_CPU_TYPES 259 /* --cpu_types */
|
||||
#define OPT_SMT_FACTOR 260 /* --smt_factor */
|
||||
|
||||
/*
|
||||
* Initialize default settings
|
||||
@@ -313,6 +324,15 @@ static void l_format_set(const char *str)
|
||||
g.o.format = fmt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the "--all" option to display omitted null values
|
||||
* while using "--format"
|
||||
*/
|
||||
static void l_format_all_set(void)
|
||||
{
|
||||
g.o.format_all = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make option consisteny checks at end of command line parsing
|
||||
*/
|
||||
@@ -320,6 +340,8 @@ static void l_parse_finish(void)
|
||||
{
|
||||
if (g.o.iterations_specified && g.o.iterations == 0)
|
||||
hyptop_exit(0);
|
||||
if (!g.o.format_specified && g.o.format_all)
|
||||
ERR_EXIT("The --all option requires the -–format option\n");
|
||||
if (g.o.cur_win != &win_sys)
|
||||
return;
|
||||
if (!win_sys.opts.sys.specified)
|
||||
@@ -339,15 +361,20 @@ void opts_parse(int argc, char *argv[])
|
||||
static struct option long_options[] = {
|
||||
{ "version", no_argument, NULL, 'v'},
|
||||
{ "help", no_argument, NULL, 'h'},
|
||||
{ "batch_mode", no_argument, NULL, 'b'},
|
||||
{ "batch-mode", no_argument, NULL, 'b'},
|
||||
{ "batch_mode", no_argument, NULL, OPT_BATCH_MODE},
|
||||
{ "all", no_argument, NULL, OPT_FORMAT_ALL },
|
||||
{ "delay", required_argument, NULL, 'd'},
|
||||
{ "smt_factor", required_argument, NULL, 'm'},
|
||||
{ "smt-factor", required_argument, NULL, 'm'},
|
||||
{ "smt_factor", required_argument, NULL, OPT_SMT_FACTOR},
|
||||
{ "window", required_argument, NULL, 'w'},
|
||||
{ "sys", required_argument, NULL, 's'},
|
||||
{ "iterations", required_argument, NULL, 'n'},
|
||||
{ "fields", required_argument, NULL, 'f'},
|
||||
{ "sort_field", required_argument, NULL, 'S'},
|
||||
{ "cpu_types", required_argument, NULL, 't'},
|
||||
{ "sort-field", required_argument, NULL, 'S'},
|
||||
{ "sort_field", required_argument, NULL, OPT_SORT_FIELD},
|
||||
{ "cpu-types", required_argument, NULL, 't'},
|
||||
{ "cpu_types", required_argument, NULL, OPT_CPU_TYPES},
|
||||
{ "format", required_argument, NULL, OPT_FORMAT },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
@@ -366,12 +393,14 @@ void opts_parse(int argc, char *argv[])
|
||||
case 'h':
|
||||
l_usage();
|
||||
hyptop_exit(0);
|
||||
case OPT_BATCH_MODE:
|
||||
case 'b':
|
||||
l_batch_mode_set();
|
||||
break;
|
||||
case 'd':
|
||||
l_delay_set(optarg);
|
||||
break;
|
||||
case OPT_SMT_FACTOR:
|
||||
case 'm':
|
||||
l_factor_set(optarg);
|
||||
break;
|
||||
@@ -384,18 +413,23 @@ void opts_parse(int argc, char *argv[])
|
||||
case 'n':
|
||||
l_iterations_set(optarg);
|
||||
break;
|
||||
case OPT_CPU_TYPES:
|
||||
case 't':
|
||||
l_cpu_types_set(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
l_fields_set(optarg);
|
||||
break;
|
||||
case OPT_SORT_FIELD:
|
||||
case 'S':
|
||||
l_sort_field_set(optarg);
|
||||
break;
|
||||
case OPT_FORMAT:
|
||||
l_format_set(optarg);
|
||||
break;
|
||||
case OPT_FORMAT_ALL:
|
||||
l_format_all_set();
|
||||
break;
|
||||
default:
|
||||
l_std_usage_exit();
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
#include "hyptop.h"
|
||||
|
||||
extern void opts_parse(int argc, char *argv[]);
|
||||
extern void opts_iterations_next(void);
|
||||
extern int opts_sys_specified(struct hyptop_win *win, const char* sys_name);
|
||||
extern void opt_verify_systems(void);
|
||||
void opts_parse(int argc, char *argv[]);
|
||||
void opts_iterations_next(void);
|
||||
int opts_sys_specified(struct hyptop_win *win, const char *sys_name);
|
||||
void opt_verify_systems(void);
|
||||
|
||||
#endif /* OPTS_H */
|
||||
|
||||
26
hyptop/sd.h
26
hyptop/sd.h
@@ -19,6 +19,7 @@
|
||||
|
||||
#define SD_DG_INIT_INTERVAL_SEC 1
|
||||
#define SD_SYS_ID_SIZE 9
|
||||
#define SD_SYS_DEFAULT_ID "PHYSICAL"
|
||||
|
||||
/*
|
||||
* CPU info
|
||||
@@ -77,6 +78,7 @@ struct sd_sys {
|
||||
struct util_list_node list;
|
||||
struct sd_info i;
|
||||
u64 update_time_us;
|
||||
u64 phys_delta_us;
|
||||
u32 child_cnt;
|
||||
u32 child_cnt_active;
|
||||
struct util_list child_list;
|
||||
@@ -134,6 +136,11 @@ static inline void sd_sys_update_time_us_set(struct sd_sys *sys, u64 value)
|
||||
sys->update_time_us = value;
|
||||
}
|
||||
|
||||
static inline void sd_phys_delta_time_us_set(struct sd_sys *sys, u64 value)
|
||||
{
|
||||
sys->phys_delta_us = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* CPU type
|
||||
*/
|
||||
@@ -301,8 +308,8 @@ struct sd_cpu_item {
|
||||
#define sd_cpu_item_type(x) ((x)->type)
|
||||
#define sd_cpu_item_table_col(item) (&(item)->table_col)
|
||||
|
||||
extern int sd_cpu_item_available(struct sd_cpu_item *item);
|
||||
extern int sd_cpu_item_cnt(void);
|
||||
int sd_cpu_item_available(struct sd_cpu_item *item);
|
||||
int sd_cpu_item_cnt(void);
|
||||
|
||||
/*
|
||||
* Item access functions
|
||||
@@ -370,8 +377,8 @@ struct sd_sys_item {
|
||||
#define sd_sys_item_table_col(item) (&item->table_col)
|
||||
#define sd_sys_item_type(item) (item->type)
|
||||
|
||||
extern int sd_sys_item_available(struct sd_sys_item *item);
|
||||
extern int sd_sys_item_cnt(void);
|
||||
int sd_sys_item_available(struct sd_sys_item *item);
|
||||
int sd_sys_item_cnt(void);
|
||||
|
||||
/*
|
||||
* Item access functions
|
||||
@@ -437,19 +444,23 @@ extern struct sd_sys_item sd_sys_item_os_name;
|
||||
extern struct sd_sys_item sd_sys_item_samples_total;
|
||||
extern struct sd_sys_item sd_sys_item_samples_cpu_using;
|
||||
|
||||
extern struct sd_sys_item sd_sys_item_phys_mgm_diff;
|
||||
|
||||
/*
|
||||
* Data gatherer backend
|
||||
*/
|
||||
struct sd_dg {
|
||||
void (*update_sys)(void);
|
||||
struct sd_cpu_type **cpu_type_vec;
|
||||
struct sd_sys_item **phys_item_vec;
|
||||
struct sd_sys_item **sys_item_vec;
|
||||
struct sd_sys_item **sys_item_enable_vec;
|
||||
struct sd_cpu_item **cpu_item_vec;
|
||||
struct sd_cpu_item **cpu_item_enable_vec;
|
||||
};
|
||||
|
||||
void sd_dg_register(struct sd_dg *, int);
|
||||
void sd_dg_register(struct sd_dg *, int, int);
|
||||
int sd_dg_has_phys_data(void);
|
||||
int sd_dg_has_core_data(void);
|
||||
|
||||
/*
|
||||
@@ -461,6 +472,9 @@ int sd_dg_has_core_data(void);
|
||||
#define sd_cpu_iterate(parent, cpu) \
|
||||
util_list_iterate(&parent->cpu_list, cpu)
|
||||
|
||||
#define sd_phys_item_iterate(ptr, i) \
|
||||
for (i = 0; (ptr = sd.dg->phys_item_vec[i]); i++)
|
||||
|
||||
#define sd_sys_item_iterate(ptr, i) \
|
||||
for (i = 0; (ptr = sd.dg->sys_item_vec[i]); i++)
|
||||
|
||||
@@ -506,7 +520,7 @@ static inline s64 l_cpu_info_s64(struct sd_cpu_info *info,
|
||||
* Misc
|
||||
*/
|
||||
void sd_update(void);
|
||||
extern void sd_init(void);
|
||||
void sd_init(void);
|
||||
|
||||
static inline u64 l_sub_64(u64 x, u64 y)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@ static int l_cpu_type_cnt;
|
||||
static int l_sys_item_cnt;
|
||||
static int l_cpu_item_cnt;
|
||||
static int l_has_core_data;
|
||||
static int l_has_phys_data;
|
||||
static struct sd_sys *l_root_sys;
|
||||
|
||||
/*
|
||||
@@ -148,7 +149,7 @@ void sd_update(void)
|
||||
/*
|
||||
* Register a data gatherer
|
||||
*/
|
||||
void sd_dg_register(struct sd_dg *dg, int has_core_data)
|
||||
void sd_dg_register(struct sd_dg *dg, int has_core_data, int has_phys_data)
|
||||
{
|
||||
struct timespec ts = {SD_DG_INIT_INTERVAL_SEC, 0};
|
||||
struct sd_sys_item *sys_item;
|
||||
@@ -156,6 +157,7 @@ void sd_dg_register(struct sd_dg *dg, int has_core_data)
|
||||
unsigned int i;
|
||||
|
||||
l_has_core_data = has_core_data;
|
||||
l_has_phys_data = has_phys_data;
|
||||
sd.dg = dg;
|
||||
for (i = 0; dg->cpu_type_vec[i]; i++)
|
||||
dg->cpu_type_vec[i]->idx = (1UL << i);
|
||||
@@ -172,6 +174,14 @@ void sd_dg_register(struct sd_dg *dg, int has_core_data)
|
||||
l_cpu_types_init();
|
||||
}
|
||||
|
||||
/*
|
||||
* Does backend has physical CPUs data?
|
||||
*/
|
||||
int sd_dg_has_phys_data(void)
|
||||
{
|
||||
return l_has_phys_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does backend has core data?
|
||||
*/
|
||||
@@ -419,7 +429,7 @@ int sd_cpu_item_cnt(void)
|
||||
*/
|
||||
void sd_init(void)
|
||||
{
|
||||
l_root_sys = sd_sys_new(NULL, "root");
|
||||
l_root_sys = sd_sys_new(NULL, SD_SYS_DEFAULT_ID);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -48,7 +48,7 @@ static double l_cpu_diff(struct sd_cpu_item *item, struct sd_cpu *cpu, int sign)
|
||||
if (online_time_diff_us == 0)
|
||||
return 0;
|
||||
|
||||
factor = ((double) online_time_diff_us) / 1000000 * cpu->cnt;
|
||||
factor = util_usecs_to_secs(online_time_diff_us) * cpu->cnt;
|
||||
if (sign)
|
||||
diff_us = l_cpu_info_s64(cpu->d_cur, item->offset) -
|
||||
l_cpu_info_s64(cpu->d_prev, item->offset);
|
||||
|
||||
@@ -171,7 +171,7 @@ static double l_cpu_info_diff_u64(struct sd_sys_item *item, struct sd_cpu *cpu,
|
||||
diff_us = l_sub_64(l_cpu_info_u64(cpu->d_cur, item->offset),
|
||||
l_cpu_info_u64(cpu->d_prev, item->offset));
|
||||
}
|
||||
factor = ((double) online_time_diff_us) / 1000000;
|
||||
factor = util_usecs_to_secs(online_time_diff_us);
|
||||
diff_us /= factor;
|
||||
return diff_us;
|
||||
}
|
||||
@@ -220,9 +220,56 @@ static u64 l_sys_smt_util(struct sd_sys_item *item, struct sd_sys *sys)
|
||||
return ht_calculate_smt_util(core_us, thr_us, mgm_us, sys->threads_per_core);
|
||||
}
|
||||
|
||||
/*
|
||||
* value = (value_current - value_prev) / online_time_diff
|
||||
*/
|
||||
static double l_phys_cpu_info_diff_u64(struct sd_sys_item *item,
|
||||
struct sd_cpu *cpu,
|
||||
u64 time_diff_us)
|
||||
{
|
||||
double factor, diff_us;
|
||||
|
||||
if (!sd_cpu_type_selected(cpu->type))
|
||||
return 0;
|
||||
if (sd_cpu_state(cpu) == SD_CPU_STATE_STOPPED)
|
||||
return 0;
|
||||
if (time_diff_us == 0)
|
||||
return 0;
|
||||
diff_us = l_sub_64(l_cpu_info_u64(cpu->d_cur, item->offset),
|
||||
l_cpu_info_u64(cpu->d_prev, item->offset));
|
||||
factor = util_usecs_to_secs(time_diff_us);
|
||||
diff_us /= factor;
|
||||
return diff_us;
|
||||
}
|
||||
|
||||
/*
|
||||
* SUM over all CPUs: value = (value_current - value_prev) / online_time_diff
|
||||
*/
|
||||
static u64 l_sys_phys_cpu_info_diff_u64(struct sd_sys_item *item, struct sd_sys *sys)
|
||||
{
|
||||
struct sd_cpu *cpu;
|
||||
u64 rc = 0;
|
||||
|
||||
sd_cpu_iterate(sys, cpu) {
|
||||
if (!cpu->d_prev || !cpu->d_cur)
|
||||
return 0;
|
||||
rc += l_phys_cpu_info_diff_u64(item, cpu, sys->phys_delta_us);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* System item definitions
|
||||
*/
|
||||
struct sd_sys_item sd_sys_item_phys_mgm_diff = {
|
||||
.table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"),
|
||||
.offset = SD_CPU_INFO_OFFSET(mgm_time_us),
|
||||
.type = SD_TYPE_U64,
|
||||
.desc = "Management time per second",
|
||||
.fn_set = l_sys_cpu_info_set,
|
||||
.fn_u64 = l_sys_phys_cpu_info_diff_u64,
|
||||
};
|
||||
|
||||
struct sd_sys_item sd_sys_item_core_cnt = {
|
||||
.table_col = TABLE_COL_CNT_SUM('#', "#core"),
|
||||
.type = SD_TYPE_U32,
|
||||
|
||||
@@ -260,6 +260,10 @@ void table_row_del_all(struct table *t)
|
||||
util_list_remove(&t->row_list, row);
|
||||
table_row_free(row);
|
||||
}
|
||||
if (t->row_physical) {
|
||||
table_row_free(t->row_physical);
|
||||
t->row_physical = NULL;
|
||||
}
|
||||
l_row_last_init(t);
|
||||
t->row_cnt_marked = 0;
|
||||
t->ready = 0;
|
||||
@@ -418,6 +422,8 @@ static void l_row_last_calc(struct table *t)
|
||||
*/
|
||||
void table_finish(struct table *t)
|
||||
{
|
||||
if (t->row_physical)
|
||||
l_row_format(t, t->row_physical);
|
||||
l_row_last_calc(t);
|
||||
t->ready = 1;
|
||||
}
|
||||
@@ -463,6 +469,8 @@ void table_rebuild(struct table *t)
|
||||
l_col_max_width_init(t, col);
|
||||
util_list_iterate(&t->row_list, row)
|
||||
l_row_format(t, row);
|
||||
if (t->row_physical)
|
||||
l_row_format(t, t->row_physical);
|
||||
l_row_format(t, t->row_last);
|
||||
}
|
||||
|
||||
@@ -921,6 +929,10 @@ static void l_table_print_curses(struct table *t)
|
||||
}
|
||||
ht_reverse_on();
|
||||
l_row_print(t, t->row_last);
|
||||
if (t->row_physical) {
|
||||
hyptop_print_nl();
|
||||
l_row_print(t, t->row_physical);
|
||||
}
|
||||
hyptop_print_seek_back(0);
|
||||
ht_reverse_off();
|
||||
#ifdef WITH_SCROLL_BAR
|
||||
@@ -952,6 +964,10 @@ static void l_table_print_all(struct table *t)
|
||||
}
|
||||
l_row_print(t, t->row_last);
|
||||
hyptop_print_nl();
|
||||
if (t->row_physical) {
|
||||
l_row_print(t, t->row_physical);
|
||||
hyptop_print_nl();
|
||||
}
|
||||
hyptop_printf("------------------------------------------------------"
|
||||
"-------------------------\n");
|
||||
}
|
||||
@@ -972,10 +988,15 @@ static void l_row_print_formatted(struct table *t, struct table_row *row)
|
||||
unsigned int flags = 0;
|
||||
struct table_entry *e = &row->entries[col_nr];
|
||||
|
||||
if (row == t->row_last && col_nr == 0)
|
||||
if (row == t->row_last && col_nr == 0) {
|
||||
if (g.o.format == FMT_CSV)
|
||||
util_fmt_pair(FMT_QUOTE, col->head, "SUM", e->str);
|
||||
continue;
|
||||
}
|
||||
if (table_col_needs_quotes(col))
|
||||
flags = FMT_QUOTE;
|
||||
if (strcmp(e->str, "-") == 0 || strcmp(e->str, "") == 0)
|
||||
flags |= FMT_INVAL;
|
||||
util_fmt_pair(flags, col->head, "%s", e->str);
|
||||
}
|
||||
}
|
||||
@@ -991,6 +1012,11 @@ static void l_table_print_all_formatted(struct table *t)
|
||||
util_fmt_pair(FMT_PERSIST, "iteration", "%u", g.o.iterations_act);
|
||||
ht_fmt_time();
|
||||
ht_fmt_cpu_types();
|
||||
if (t->row_physical) {
|
||||
util_fmt_obj_start(FMT_ROW, "physical_information");
|
||||
l_row_print_formatted(t, t->row_physical);
|
||||
util_fmt_obj_end(); /* physical_information{} */
|
||||
}
|
||||
if (strcmp(g.o.cur_win->id, "sys_list") == 0)
|
||||
util_fmt_obj_start(FMT_LIST, "systems");
|
||||
else
|
||||
|
||||
@@ -324,6 +324,7 @@ struct table {
|
||||
struct table_col **col_vec;
|
||||
struct table_col *col_selected;
|
||||
struct table_row *row_last;
|
||||
struct table_row *row_physical;
|
||||
int row_cnt;
|
||||
int row_cnt_marked;
|
||||
int row_cnt_extra;
|
||||
@@ -361,37 +362,37 @@ enum table_scroll_unit {
|
||||
*/
|
||||
extern struct table *table_new(int extra_rows, int sorted, int first_bold,
|
||||
int with_units);
|
||||
extern void table_reset(struct table *t);
|
||||
extern void table_rebuild(struct table *t);
|
||||
extern void table_finish(struct table *t);
|
||||
extern void table_print(struct table *t);
|
||||
extern void table_process_input(struct table *t, int c);
|
||||
void table_reset(struct table *t);
|
||||
void table_rebuild(struct table *t);
|
||||
void table_finish(struct table *t);
|
||||
void table_print(struct table *t);
|
||||
void table_process_input(struct table *t, int c);
|
||||
|
||||
extern void table_col_unit_next(struct table *t, char hotkey);
|
||||
extern void table_col_unit_prev(struct table *t, char hotkey);
|
||||
extern int table_col_unit_set(struct table *t, char hotkey, const char *unit);
|
||||
extern void table_col_add(struct table *t, struct table_col *col);
|
||||
extern int table_col_select(struct table *t, char hotkey);
|
||||
extern void table_col_select_next(struct table *t);
|
||||
extern void table_col_select_prev(struct table *t);
|
||||
extern void table_col_enable_toggle(struct table *t, char hotkey);
|
||||
void table_col_unit_next(struct table *t, char hotkey);
|
||||
void table_col_unit_prev(struct table *t, char hotkey);
|
||||
int table_col_unit_set(struct table *t, char hotkey, const char *unit);
|
||||
void table_col_add(struct table *t, struct table_col *col);
|
||||
int table_col_select(struct table *t, char hotkey);
|
||||
void table_col_select_next(struct table *t);
|
||||
void table_col_select_prev(struct table *t);
|
||||
void table_col_enable_toggle(struct table *t, char hotkey);
|
||||
|
||||
extern void table_row_del_all(struct table *t);
|
||||
extern void table_row_add(struct table *t, struct table_row *row);
|
||||
extern void table_row_mark(struct table *t, struct table_row *row);
|
||||
extern void table_row_mark_del_all(struct table *t);
|
||||
extern void table_row_mark_toggle(struct table *t, struct table_row *row);
|
||||
extern void table_row_mark_toggle_by_key(struct table *t, const char *mark_key);
|
||||
extern void table_row_select_down(struct table *t, enum table_scroll_unit unit);
|
||||
extern void table_row_select_up(struct table *t, enum table_scroll_unit unit);
|
||||
extern void table_row_select_key_get(struct table *t, char str[TABLE_STR_MAX]);
|
||||
extern struct table_row *table_row_alloc(struct table *t);
|
||||
void table_row_del_all(struct table *t);
|
||||
void table_row_add(struct table *t, struct table_row *row);
|
||||
void table_row_mark(struct table *t, struct table_row *row);
|
||||
void table_row_mark_del_all(struct table *t);
|
||||
void table_row_mark_toggle(struct table *t, struct table_row *row);
|
||||
void table_row_mark_toggle_by_key(struct table *t, const char *mark_key);
|
||||
void table_row_select_down(struct table *t, enum table_scroll_unit unit);
|
||||
void table_row_select_up(struct table *t, enum table_scroll_unit unit);
|
||||
void table_row_select_key_get(struct table *t, char str[TABLE_STR_MAX]);
|
||||
struct table_row *table_row_alloc(struct table *t);
|
||||
|
||||
extern void table_scroll_down(struct table *t, enum table_scroll_unit unit);
|
||||
extern void table_scroll_up(struct table *t, enum table_scroll_unit unit);
|
||||
void table_scroll_down(struct table *t, enum table_scroll_unit unit);
|
||||
void table_scroll_up(struct table *t, enum table_scroll_unit unit);
|
||||
|
||||
extern void table_fmt_start(void);
|
||||
extern void table_fmt_end(void);
|
||||
void table_fmt_start(void);
|
||||
void table_fmt_end(void);
|
||||
|
||||
/*
|
||||
* Entry add functions
|
||||
|
||||
@@ -153,7 +153,7 @@ struct table_col_unit table_col_unit_us = {
|
||||
*/
|
||||
static int l_unit_ms(struct table_col *col, struct table_entry *e)
|
||||
{
|
||||
return l_unit_raw_div(col, e, 1000, L_COL_FMT_STR_2);
|
||||
return l_unit_raw_div(col, e, USEC_PER_MSEC, L_COL_FMT_STR_2);
|
||||
}
|
||||
|
||||
struct table_col_unit table_col_unit_ms = {
|
||||
@@ -167,7 +167,7 @@ struct table_col_unit table_col_unit_ms = {
|
||||
*/
|
||||
static int l_unit_perc(struct table_col *col, struct table_entry *e)
|
||||
{
|
||||
return l_unit_raw_div(col, e, 10000, L_COL_FMT_STR_2);
|
||||
return l_unit_raw_div(col, e, (USEC_PER_SEC / 100), L_COL_FMT_STR_2);
|
||||
}
|
||||
|
||||
struct table_col_unit table_col_unit_perc = {
|
||||
@@ -182,7 +182,7 @@ struct table_col_unit table_col_unit_perc = {
|
||||
*/
|
||||
static int l_unit_s(struct table_col *col, struct table_entry *e)
|
||||
{
|
||||
return l_unit_raw_div(col, e, 1000000, L_COL_FMT_STR_2);
|
||||
return l_unit_raw_div(col, e, USEC_PER_SEC, L_COL_FMT_STR_2);
|
||||
}
|
||||
|
||||
struct table_col_unit table_col_unit_s = {
|
||||
@@ -197,7 +197,7 @@ struct table_col_unit table_col_unit_s = {
|
||||
*/
|
||||
static int l_unit_m(struct table_col *col, struct table_entry *e)
|
||||
{
|
||||
return l_unit_raw_div(col, e, 1000000 * 60, L_COL_FMT_STR_0);
|
||||
return l_unit_raw_div(col, e, USEC_PER_SEC * 60, L_COL_FMT_STR_0);
|
||||
}
|
||||
|
||||
static struct table_col_unit table_col_unit_m = {
|
||||
@@ -214,7 +214,7 @@ static int l_unit_hm_u64(char *str, u64 v1, int negative)
|
||||
{
|
||||
u64 time_tmp, time_h, time_m;
|
||||
|
||||
time_tmp = v1 / (1000000 * 60);
|
||||
time_tmp = v1 / (USEC_PER_SEC * 60);
|
||||
time_h = time_tmp / 60;
|
||||
time_m = time_tmp - time_h * 60;
|
||||
|
||||
@@ -259,7 +259,7 @@ static int l_unit_dhm_u64(char *str, u64 v1, int negative)
|
||||
{
|
||||
u64 time_tmp, time_d, time_h, time_m;
|
||||
|
||||
time_tmp = v1 / (1000000 * 60);
|
||||
time_tmp = v1 / (USEC_PER_SEC * 60);
|
||||
time_d = time_tmp / (60 * 24);
|
||||
time_h = time_tmp / 60 - time_d * 24;
|
||||
time_m = time_tmp - time_h * 60 - time_d * 60 * 24;
|
||||
@@ -312,10 +312,8 @@ static int l_unit_vis(struct table_col *col, struct table_entry *e)
|
||||
assert(col->type == TABLE_COL_TYPE_U64);
|
||||
|
||||
sprintf(e->str, "|");
|
||||
val1_perc = e->d.u64.v1;
|
||||
val1_perc /= 1000000;
|
||||
val2_perc = e->d.u64.v2;
|
||||
val2_perc /= 1000000;
|
||||
val1_perc = util_usecs_to_secs(e->d.u64.v1);
|
||||
val2_perc = util_usecs_to_secs(e->d.u64.v2);
|
||||
val1_nr = (val1_perc * L_VISUAL_ROW_CNT) + 0.5;
|
||||
val2_nr = (val2_perc * L_VISUAL_ROW_CNT) + 0.5;
|
||||
|
||||
|
||||
@@ -23,6 +23,6 @@ struct win_cpu_types {
|
||||
struct hyptop_win *win_help;
|
||||
};
|
||||
|
||||
extern struct hyptop_win *win_cpu_types_new(void);
|
||||
struct hyptop_win *win_cpu_types_new(void);
|
||||
|
||||
#endif /* WIN_CPU_TYPES_H */
|
||||
|
||||
@@ -162,6 +162,22 @@ static void l_sys_item_add(struct table_row *table_row, struct sd_sys *sys,
|
||||
}
|
||||
}
|
||||
|
||||
static void l_row_add_physical(struct table *t, struct sd_sys *sys)
|
||||
{
|
||||
struct sd_sys_item *item;
|
||||
struct table_row *row;
|
||||
unsigned int i;
|
||||
|
||||
row = table_row_alloc(t);
|
||||
table_row_entry_str_add(row, &l_col_sys, sd_sys_id(sys));
|
||||
sd_phys_item_iterate(item, i) {
|
||||
if (!sd_sys_item_set(sys, item))
|
||||
continue;
|
||||
l_sys_item_add(row, sys, item);
|
||||
}
|
||||
t->row_physical = row;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add system to table
|
||||
*/
|
||||
@@ -196,6 +212,8 @@ static void l_table_create(void)
|
||||
continue;
|
||||
l_sys_add(guest);
|
||||
}
|
||||
if (sd_dg_has_phys_data())
|
||||
l_row_add_physical(l_t, parent);
|
||||
table_finish(l_t);
|
||||
}
|
||||
|
||||
@@ -324,6 +342,11 @@ static void l_run(struct hyptop_win *win)
|
||||
}
|
||||
}
|
||||
|
||||
static void win_sys_list_set_phys_table_cols(void)
|
||||
{
|
||||
sd_sys_item_phys_mgm_diff.table_col = sd_sys_item_mgm_diff.table_col;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize window
|
||||
*/
|
||||
@@ -337,7 +360,7 @@ void win_sys_list_init(void)
|
||||
int item_cnt;
|
||||
|
||||
/* Alloc table and add columns */
|
||||
l_t = table_new(1, 1, 1, 1);
|
||||
l_t = table_new(2, 1, 1, 1);
|
||||
table_col_add(l_t, &l_col_sys);
|
||||
|
||||
item_cnt = sd_sys_item_cnt() + 1;
|
||||
@@ -351,6 +374,8 @@ void win_sys_list_init(void)
|
||||
col_vec[i] = col;
|
||||
col_desc_vec[i] = item->desc;
|
||||
}
|
||||
if (sd_dg_has_phys_data())
|
||||
win_sys_list_set_phys_table_cols();
|
||||
/* Enable fields */
|
||||
if (win_sys_list.opts.fields.specified)
|
||||
l_fields_enable_cmdline();
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#define UNPACK_FACILITY _AC(161, U)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <asm/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
@@ -380,18 +381,6 @@ static __always_inline int is_zvm(void)
|
||||
return cpuid.version == 0xff;
|
||||
}
|
||||
|
||||
/* To avoid conflicts add a macro guard since __vector128 is also
|
||||
* defined in 'linux/asm/types.h'.
|
||||
*/
|
||||
#ifndef _S390_TYPES_H
|
||||
/*
|
||||
* Vector register definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t u[4];
|
||||
} __vector128;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Save vector registers
|
||||
*/
|
||||
|
||||
@@ -379,6 +379,25 @@ int ekmf_generate_ss_cert(const struct ekmf_config *config,
|
||||
const char *cert_pem_filename,
|
||||
const struct ekmf_ext_lib *ext_lib, bool verbose);
|
||||
|
||||
/**
|
||||
* Validates that a certificate has the same public key as the secure identity
|
||||
* key (field identity_secure_key in config structure) .
|
||||
*
|
||||
* @param config the configuration structure. Only field
|
||||
* identity_secure_key must be specified, all others
|
||||
* are optional.
|
||||
* @param x509_cert the X509 certificate object to validate
|
||||
* @param ext_lib External secure key crypto library to use
|
||||
* @param verbose if true, verbose messages are printed
|
||||
*
|
||||
* @returns a negative errno in case of an error, 0 if success.
|
||||
* -EINVAL: invalid parameter, or certificate is not valid
|
||||
* -ENOMEM: Failed to allocate memory
|
||||
* any other errno from file I/O routines
|
||||
*/
|
||||
int ekmf_validate_cert(const struct ekmf_config *config, const X509 *x509_cert,
|
||||
const struct ekmf_ext_lib *ext_lib, bool verbose);
|
||||
|
||||
/**
|
||||
* Retrieves settings from the EKMFWeb server, such as the template names for
|
||||
* generating keys in EKMFWeb.
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <sched.h>
|
||||
#include <stdbool.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#define S390_CPUMF_CF "devices/cpum_cf/"
|
||||
#define S390_CPUMF_CFDIAG "devices/cpum_cf_diag/"
|
||||
@@ -115,7 +117,7 @@ bool libcpumf_have_cpumcf(void);
|
||||
*
|
||||
* @param[out] min Minimum supported sampling interval
|
||||
* @param[out] max Maximum supported sampling interval
|
||||
* @param[out] speed Current CPU speed, number of CPU cylces per
|
||||
* @param[out] speed Current CPU speed, number of CPU cycles per
|
||||
* microsecond
|
||||
* @param[out] basic_sz Basic sample size in bytes
|
||||
* @param[out] diag_sz Diagnostic sample size in bytes
|
||||
@@ -182,4 +184,37 @@ bool libcpumf_have_pai_ext(void);
|
||||
* @retval false PAI_NNPA counter Facility is not available
|
||||
*/
|
||||
bool libcpumf_have_pai_nnpa(void);
|
||||
|
||||
/**
|
||||
* Wrapper for the perf_event_open syscall used to configure performance events.
|
||||
* This function simplifies usage of perf_event_open and provides a consistent
|
||||
* interface for libcpumf internals.
|
||||
*
|
||||
* @param hw_event Pointer to perf_event_attr structure describing the event
|
||||
* @param pid Target process ID (0 for current process)
|
||||
* @param cpu Target CPU (-1 for all CPUs)
|
||||
* @param group_fd File descriptor of event group leader, or -1 if none
|
||||
* @param flags Additional flags (usually 0)
|
||||
*
|
||||
* @return File descriptor for the opened event on success
|
||||
* @return -1 on failure, errno is set appropriately
|
||||
*/
|
||||
|
||||
long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd,
|
||||
unsigned long flags);
|
||||
|
||||
/**
|
||||
* Check if a counter name is present in a comma-separated list of counters.
|
||||
*
|
||||
* This function checks whether the given counter name appears in the
|
||||
* provided list. If the list is NULL, the function assumes all counters
|
||||
* are allowed and returns true.
|
||||
*
|
||||
* @param name Name of the counter to search for
|
||||
* @param ctrlist Comma-separated list of counter names, or NULL
|
||||
*
|
||||
* @return true if the counter is in the list or list is NULL
|
||||
* @return false otherwise
|
||||
*/
|
||||
bool ctr_in_list(char *name, char *ctrlist);
|
||||
#endif
|
||||
|
||||
22
include/lib/util_autocomp.h
Normal file
22
include/lib/util_autocomp.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* autocomp - command line autocompletion
|
||||
*
|
||||
* Generating autocompletion scripts for bash and zsh
|
||||
* based on util_opt struct
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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_AUTOCOMP_H
|
||||
#define LIB_UTIL_AUTOCOMP_H
|
||||
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
void generate_autocomp(struct util_opt *opt_vec, char *tool_name);
|
||||
|
||||
#endif
|
||||
@@ -45,7 +45,7 @@ void *__util_zalloc(const char *func, const char *file, int line, size_t size);
|
||||
/**
|
||||
* Re-allocate memory or exit in case of failure
|
||||
*
|
||||
* @param[in] ptr Pointer ot old memory buffer
|
||||
* @param[in] ptr Pointer to old memory buffer
|
||||
* @param[in] size Number of bytes to be allocated
|
||||
*
|
||||
* @returns Pointer to memory buffer created with realloc()
|
||||
|
||||
17
include/lib/util_str.h
Normal file
17
include/lib/util_str.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @defgroup util_str_h util_str: String functions
|
||||
* @{
|
||||
* @brief Manipulate and work with strings
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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_STR_H
|
||||
#define LIB_UTIL_STR_H
|
||||
|
||||
void util_str_rm_whitespace(const char *src, char *dest);
|
||||
|
||||
#endif /** LIB_UTIL_STR_H @} */
|
||||
@@ -13,6 +13,7 @@
|
||||
#define LIB_UTIL_SYS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int util_sys_get_dev_addr(const char *dev, char *addr);
|
||||
bool util_sys_dev_is_partition(dev_t dev);
|
||||
|
||||
202
include/lib/util_time.h
Normal file
202
include/lib/util_time.h
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* util_time - Time related helper functions and definitions
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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_TIME_H
|
||||
#define LIB_UTIL_TIME_H
|
||||
|
||||
#define NSEC_PER_USEC 1000L
|
||||
#define NSEC_PER_MSEC 1000000L
|
||||
#define NSEC_PER_SEC 1000000000L
|
||||
|
||||
#define USEC_PER_MSEC 1000L
|
||||
#define USEC_PER_SEC 1000000L
|
||||
|
||||
#define MSEC_PER_SEC 1000L
|
||||
|
||||
/**
|
||||
* Convert nanoseconds to microseconds
|
||||
*
|
||||
* Convert value from nanoseconds to microseconds by dividing the
|
||||
* value to NSEC_PER_USEC constant.
|
||||
*
|
||||
* @param[in] val Time value in nanoseconds
|
||||
*
|
||||
* @returns Time value in microseconds
|
||||
*/
|
||||
static inline double util_nsecs_to_usecs(double val)
|
||||
{
|
||||
return val / NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert nanoseconds to milliseconds
|
||||
*
|
||||
* Convert value from nanoseconds to milliseconds by dividing the
|
||||
* value to NSEC_PER_MSEC constant.
|
||||
*
|
||||
* @param[in] val Time value in nanoseconds
|
||||
*
|
||||
* @returns Time value in milliseconds
|
||||
*/
|
||||
static inline double util_nsecs_to_msecs(double val)
|
||||
{
|
||||
return val / NSEC_PER_MSEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert nanoseconds to seconds
|
||||
*
|
||||
* Convert value from nanoseconds to seconds by dividing the
|
||||
* value to NSEC_PER_SEC constant.
|
||||
*
|
||||
* @param[in] val Time value in nanoseconds
|
||||
*
|
||||
* @returns Time value in seconds
|
||||
*/
|
||||
static inline double util_nsecs_to_secs(double val)
|
||||
{
|
||||
return val / NSEC_PER_SEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert microseconds to nanoseconds
|
||||
*
|
||||
* Convert value from microseconds to nanoseconds by multiplying the
|
||||
* value with NSEC_PER_USEC constant.
|
||||
*
|
||||
* @param[in] val Time value in microseconds
|
||||
*
|
||||
* @returns Time value in nanoseconds
|
||||
*/
|
||||
static inline double util_usecs_to_nsecs(double val)
|
||||
{
|
||||
return val * NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert microseconds to milliseconds
|
||||
*
|
||||
* Convert value from microseconds to milliseconds by dividing the
|
||||
* value to USEC_PER_MSEC constant.
|
||||
*
|
||||
* @param[in] val Time value in microseconds
|
||||
*
|
||||
* @returns Time value in milliseconds
|
||||
*/
|
||||
static inline double util_usecs_to_msecs(double val)
|
||||
{
|
||||
return val / USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert microseconds to seconds
|
||||
*
|
||||
* Convert value from microseconds to seconds by dividing the
|
||||
* value to USEC_PER_SEC constant.
|
||||
*
|
||||
* @param[in] val Time value in nanoseconds
|
||||
*
|
||||
* @returns Time value in seconds
|
||||
*/
|
||||
static inline double util_usecs_to_secs(double val)
|
||||
{
|
||||
return val / USEC_PER_SEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert milliseconds to nanoseconds
|
||||
*
|
||||
* Convert value from milliseconds to nanoseconds by multiplying the
|
||||
* value with NSEC_PER_MSEC constant.
|
||||
*
|
||||
* @param[in] val Time value in milliseconds
|
||||
*
|
||||
* @returns Time value in nanoseconds
|
||||
*/
|
||||
static inline double util_msecs_to_nsecs(double val)
|
||||
{
|
||||
return val * NSEC_PER_MSEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert milliseconds to microseconds
|
||||
*
|
||||
* Convert value from milliseconds to microseconds by multiplying the
|
||||
* value with USEC_PER_MSEC constant.
|
||||
*
|
||||
* @param[in] val Time value in milliseconds
|
||||
*
|
||||
* @returns Time value in microseconds
|
||||
*/
|
||||
static inline double util_msecs_to_usecs(double val)
|
||||
{
|
||||
return val * USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert milliseconds to seconds
|
||||
*
|
||||
* Convert value from milliseconds to seconds by dividing the
|
||||
* value to MSEC_PER_SEC constant.
|
||||
*
|
||||
* @param[in] val Time value in milliseconds
|
||||
*
|
||||
* @returns Time value in seconds
|
||||
*/
|
||||
static inline double util_msecs_to_secs(double val)
|
||||
{
|
||||
return val / MSEC_PER_SEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert seconds to nanoseconds
|
||||
*
|
||||
* Convert value from seconds to nanoseconds by multiplying the
|
||||
* value with NSEC_PER_SEC constant.
|
||||
*
|
||||
* @param[in] val Time value in seconds
|
||||
*
|
||||
* @returns Time value in nanoseconds
|
||||
*/
|
||||
static inline double util_secs_to_nsecs(double val)
|
||||
{
|
||||
return val * NSEC_PER_SEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert seconds to microseconds
|
||||
*
|
||||
* Convert value from seconds to microseconds by multiplying the
|
||||
* value with USEC_PER_SEC constant.
|
||||
*
|
||||
* @param[in] val Time value in seconds
|
||||
*
|
||||
* @returns Time value in microseconds
|
||||
*/
|
||||
static inline double util_secs_to_usecs(double val)
|
||||
{
|
||||
return val * USEC_PER_SEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert seconds to milliseconds
|
||||
*
|
||||
* Convert value from seconds to milliseconds by multiplying the
|
||||
* value with MSEC_PER_SEC constant.
|
||||
*
|
||||
* @param[in] val Time value in seconds
|
||||
*
|
||||
* @returns Time value in milliseconds
|
||||
*/
|
||||
static inline double util_secs_to_msecs(double val)
|
||||
{
|
||||
return val * MSEC_PER_SEC;
|
||||
}
|
||||
|
||||
#endif /* LIB_UTIL_TIME_H */
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -44,27 +45,27 @@
|
||||
|
||||
typedef struct ttr
|
||||
{
|
||||
u_int16_t tt;
|
||||
u_int8_t r;
|
||||
uint16_t tt;
|
||||
uint8_t r;
|
||||
} __attribute__ ((packed)) ttr_t;
|
||||
|
||||
typedef struct cchhb
|
||||
{
|
||||
u_int16_t cc;
|
||||
u_int16_t hh;
|
||||
u_int8_t b;
|
||||
uint16_t cc;
|
||||
uint16_t hh;
|
||||
uint8_t b;
|
||||
} __attribute__ ((packed)) cchhb_t;
|
||||
|
||||
typedef struct cchh
|
||||
{
|
||||
u_int16_t cc;
|
||||
u_int16_t hh;
|
||||
uint16_t cc;
|
||||
uint16_t hh;
|
||||
} __attribute__ ((packed)) cchh_t;
|
||||
|
||||
typedef struct labeldate
|
||||
{
|
||||
u_int8_t year;
|
||||
u_int16_t day;
|
||||
uint8_t year;
|
||||
uint16_t day;
|
||||
} __attribute__ ((packed)) labeldate_t;
|
||||
|
||||
/*
|
||||
@@ -84,7 +85,7 @@ typedef struct volume_label
|
||||
char volkey[4]; /* volume key = volume label */
|
||||
char vollbl[4]; /* volume label */
|
||||
char volid[6]; /* volume identifier */
|
||||
u_int8_t security; /* security byte */
|
||||
uint8_t security; /* security byte */
|
||||
cchhb_t vtoc; /* VTOC address */
|
||||
char res1[5]; /* reserved */
|
||||
char cisize[4]; /* CI-size for FBA,... */
|
||||
@@ -118,8 +119,8 @@ static inline int is_vol1(char *this)
|
||||
|
||||
typedef struct extent
|
||||
{
|
||||
u_int8_t typeind; /* extent type indicator */
|
||||
u_int8_t seqno; /* extent sequence number */
|
||||
uint8_t typeind; /* extent type indicator */
|
||||
uint8_t seqno; /* extent sequence number */
|
||||
cchh_t llimit; /* starting point of this extent */
|
||||
cchh_t ulimit; /* ending point of this extent */
|
||||
} __attribute__ ((packed)) extent_t;
|
||||
@@ -127,16 +128,16 @@ typedef struct extent
|
||||
|
||||
typedef struct dev_const
|
||||
{
|
||||
u_int16_t DS4DSCYL; /* number of logical cyls */
|
||||
u_int16_t DS4DSTRK; /* number of tracks in a logical cylinder */
|
||||
u_int16_t DS4DEVTK; /* device track length */
|
||||
u_int8_t DS4DEVI; /* non-last keyed record overhead */
|
||||
u_int8_t DS4DEVL; /* last keyed record overhead */
|
||||
u_int8_t DS4DEVK; /* non-keyed record overhead differential */
|
||||
u_int8_t DS4DEVFG; /* flag byte */
|
||||
u_int16_t DS4DEVTL; /* device tolerance */
|
||||
u_int8_t DS4DEVDT; /* number of DSCB's per track */
|
||||
u_int8_t DS4DEVDB; /* number of directory blocks per track */
|
||||
uint16_t DS4DSCYL; /* number of logical cyls */
|
||||
uint16_t DS4DSTRK; /* number of tracks in a logical cylinder */
|
||||
uint16_t DS4DEVTK; /* device track length */
|
||||
uint8_t DS4DEVI; /* non-last keyed record overhead */
|
||||
uint8_t DS4DEVL; /* last keyed record overhead */
|
||||
uint8_t DS4DEVK; /* non-keyed record overhead differential */
|
||||
uint8_t DS4DEVFG; /* flag byte */
|
||||
uint16_t DS4DEVTL; /* device tolerance */
|
||||
uint8_t DS4DEVDT; /* number of DSCB's per track */
|
||||
uint8_t DS4DEVDB; /* number of directory blocks per track */
|
||||
} __attribute__ ((packed)) dev_const_t;
|
||||
|
||||
/*
|
||||
@@ -146,33 +147,33 @@ typedef struct dev_const
|
||||
typedef struct format1_label
|
||||
{
|
||||
char DS1DSNAM[44]; /* data set name */
|
||||
u_int8_t DS1FMTID; /* format identifier */
|
||||
uint8_t DS1FMTID; /* format identifier */
|
||||
unsigned char DS1DSSN[6];/* data set serial number */
|
||||
u_int16_t DS1VOLSQ; /* volume sequence number */
|
||||
uint16_t DS1VOLSQ; /* volume sequence number */
|
||||
labeldate_t DS1CREDT; /* creation date: ydd */
|
||||
labeldate_t DS1EXPDT; /* expiration date */
|
||||
u_int8_t DS1NOEPV; /* number of extents on volume */
|
||||
u_int8_t DS1NOBDB; /* no. of bytes used in last direction blk */
|
||||
u_int8_t DS1FLAG1; /* flag 1 */
|
||||
uint8_t DS1NOEPV; /* number of extents on volume */
|
||||
uint8_t DS1NOBDB; /* no. of bytes used in last direction blk */
|
||||
uint8_t DS1FLAG1; /* flag 1 */
|
||||
unsigned char DS1SYSCD[13]; /* system code */
|
||||
labeldate_t DS1REFD; /* date last referenced */
|
||||
u_int8_t DS1SMSFG; /* system managed storage indicators */
|
||||
u_int8_t DS1SCXTF; /* sec. space extension flag byte */
|
||||
u_int16_t DS1SCXTV; /* secondary space extension value */
|
||||
u_int8_t DS1DSRG1; /* data set organisation byte 1 */
|
||||
u_int8_t DS1DSRG2; /* data set organisation byte 2 */
|
||||
u_int8_t DS1RECFM; /* record format */
|
||||
u_int8_t DS1OPTCD; /* option code */
|
||||
u_int16_t DS1BLKL; /* block length */
|
||||
u_int16_t DS1LRECL; /* record length */
|
||||
u_int8_t DS1KEYL; /* key length */
|
||||
u_int16_t DS1RKP; /* relative key position */
|
||||
u_int8_t DS1DSIND; /* data set indicators */
|
||||
u_int8_t DS1SCAL1; /* secondary allocation flag byte */
|
||||
uint8_t DS1SMSFG; /* system managed storage indicators */
|
||||
uint8_t DS1SCXTF; /* sec. space extension flag byte */
|
||||
uint16_t DS1SCXTV; /* secondary space extension value */
|
||||
uint8_t DS1DSRG1; /* data set organisation byte 1 */
|
||||
uint8_t DS1DSRG2; /* data set organisation byte 2 */
|
||||
uint8_t DS1RECFM; /* record format */
|
||||
uint8_t DS1OPTCD; /* option code */
|
||||
uint16_t DS1BLKL; /* block length */
|
||||
uint16_t DS1LRECL; /* record length */
|
||||
uint8_t DS1KEYL; /* key length */
|
||||
uint16_t DS1RKP; /* relative key position */
|
||||
uint8_t DS1DSIND; /* data set indicators */
|
||||
uint8_t DS1SCAL1; /* secondary allocation flag byte */
|
||||
char DS1SCAL3[3]; /* secondary allocation quantity */
|
||||
ttr_t DS1LSTAR; /* last used track and block on track */
|
||||
u_int16_t DS1TRBAL; /* space remaining on last used track */
|
||||
u_int16_t res1; /* reserved */
|
||||
uint16_t DS1TRBAL; /* space remaining on last used track */
|
||||
uint16_t res1; /* reserved */
|
||||
extent_t DS1EXT1; /* first extent description */
|
||||
extent_t DS1EXT2; /* second extent description */
|
||||
extent_t DS1EXT3; /* third extent description */
|
||||
@@ -184,7 +185,7 @@ typedef struct format3_label
|
||||
{
|
||||
char DS3KEYID[4]; /* key identifier */
|
||||
extent_t DS3EXTNT[4]; /* first 4 extent descriptions */
|
||||
u_int8_t DS3FMTID; /* format identifier */
|
||||
uint8_t DS3FMTID; /* format identifier */
|
||||
extent_t DS3ADEXT[9]; /* last 9 extent description */
|
||||
cchhb_t DS3PTRDS; /* pointer to next format3 DSCB */
|
||||
} __attribute__ ((packed)) format3_label_t;
|
||||
@@ -193,15 +194,15 @@ typedef struct format3_label
|
||||
typedef struct format4_label
|
||||
{
|
||||
char DS4KEYCD[44]; /* key code for VTOC labels: 44 times 0x04 */
|
||||
u_int8_t DS4IDFMT; /* format identifier */
|
||||
uint8_t DS4IDFMT; /* format identifier */
|
||||
cchhb_t DS4HPCHR; /* highest address of a format 1 DSCB */
|
||||
u_int16_t DS4DSREC; /* number of available DSCB's */
|
||||
uint16_t DS4DSREC; /* number of available DSCB's */
|
||||
cchh_t DS4HCCHH; /* CCHH of next available alternate track */
|
||||
u_int16_t DS4NOATK; /* number of remaining alternate tracks */
|
||||
u_int8_t DS4VTOCI; /* VTOC indicators */
|
||||
u_int8_t DS4NOEXT; /* number of extents in VTOC */
|
||||
u_int8_t DS4SMSFG; /* system managed storage indicators */
|
||||
u_int8_t DS4DEVAC; /* number of alternate cylinders.
|
||||
uint16_t DS4NOATK; /* number of remaining alternate tracks */
|
||||
uint8_t DS4VTOCI; /* VTOC indicators */
|
||||
uint8_t DS4NOEXT; /* number of extents in VTOC */
|
||||
uint8_t DS4SMSFG; /* system managed storage indicators */
|
||||
uint8_t DS4DEVAC; /* number of alternate cylinders.
|
||||
Subtract from first two bytes of
|
||||
DS4DEVSZ to get number of usable
|
||||
cylinders. can be zero. valid
|
||||
@@ -214,21 +215,21 @@ typedef struct format4_label
|
||||
char DS4F6PTR[5]; /* pointer to first format 6 DSCB */
|
||||
extent_t DS4VTOCE; /* VTOC extent description */
|
||||
char res2[10]; /* reserved */
|
||||
u_int8_t DS4EFLVL; /* extended free-space management level */
|
||||
uint8_t DS4EFLVL; /* extended free-space management level */
|
||||
cchhb_t DS4EFPTR; /* pointer to extended free-space info */
|
||||
char res3; /* reserved */
|
||||
u_int32_t DS4DCYL; /* number of logical cyls */
|
||||
uint32_t DS4DCYL; /* number of logical cyls */
|
||||
char res4[2]; /* reserved */
|
||||
u_int8_t DS4DEVF2; /* device flags */
|
||||
uint8_t DS4DEVF2; /* device flags */
|
||||
char res5; /* reserved */
|
||||
} __attribute__ ((packed)) format4_label_t;
|
||||
|
||||
|
||||
typedef struct ds5ext
|
||||
{
|
||||
u_int16_t t; /* RTA of the first track of free extent */
|
||||
u_int16_t fc; /* number of whole cylinders in free ext. */
|
||||
u_int8_t ft; /* number of remaining free tracks */
|
||||
uint16_t t; /* RTA of the first track of free extent */
|
||||
uint16_t fc; /* number of whole cylinders in free ext. */
|
||||
uint8_t ft; /* number of remaining free tracks */
|
||||
} __attribute__ ((packed)) ds5ext_t;
|
||||
|
||||
|
||||
@@ -237,7 +238,7 @@ typedef struct format5_label
|
||||
char DS5KEYID[4]; /* key identifier */
|
||||
ds5ext_t DS5AVEXT; /* first available (free-space) extent. */
|
||||
ds5ext_t DS5EXTAV[7]; /* seven available extents */
|
||||
u_int8_t DS5FMTID; /* format identifier */
|
||||
uint8_t DS5FMTID; /* format identifier */
|
||||
ds5ext_t DS5MAVET[18]; /* eighteen available extents */
|
||||
cchhb_t DS5PTRDS; /* pointer to next format5 DSCB */
|
||||
} __attribute__ ((packed)) format5_label_t;
|
||||
@@ -245,8 +246,8 @@ typedef struct format5_label
|
||||
|
||||
typedef struct ds7ext
|
||||
{
|
||||
u_int32_t a; /* starting RTA value */
|
||||
u_int32_t b; /* ending RTA value + 1 */
|
||||
uint32_t a; /* starting RTA value */
|
||||
uint32_t b; /* ending RTA value + 1 */
|
||||
} __attribute__ ((packed)) ds7ext_t;
|
||||
|
||||
|
||||
@@ -254,7 +255,7 @@ typedef struct format7_label
|
||||
{
|
||||
char DS7KEYID[4]; /* key identifier */
|
||||
ds7ext_t DS7EXTNT[5]; /* space for 5 extent descriptions */
|
||||
u_int8_t DS7FMTID; /* format identifier */
|
||||
uint8_t DS7FMTID; /* format identifier */
|
||||
ds7ext_t DS7ADEXT[11]; /* space for 11 extent descriptions */
|
||||
char res1[2]; /* reserved */
|
||||
cchhb_t DS7PTRDS; /* pointer to next FMT7 DSCB */
|
||||
@@ -263,12 +264,12 @@ typedef struct format7_label
|
||||
|
||||
typedef struct format9_label
|
||||
{
|
||||
u_int8_t DS9KEYID; /* key code for format 9 labels (0x09) */
|
||||
u_int8_t DS9SUBTY; /* subtype (0x01) */
|
||||
u_int8_t DS9NUMF9; /* number of F9 datasets */
|
||||
u_int8_t res1[41]; /* reserved */
|
||||
u_int8_t DS9FMTID; /* format identifier */
|
||||
u_int8_t res2[90]; /* reserved */
|
||||
uint8_t DS9KEYID; /* key code for format 9 labels (0x09) */
|
||||
uint8_t DS9SUBTY; /* subtype (0x01) */
|
||||
uint8_t DS9NUMF9; /* number of F9 datasets */
|
||||
uint8_t res1[41]; /* reserved */
|
||||
uint8_t DS9FMTID; /* format identifier */
|
||||
uint8_t res2[90]; /* reserved */
|
||||
cchhb_t DS9PTRDS; /* pointer to next DSCB */
|
||||
} __attribute__ ((packed)) format9_label_t;
|
||||
|
||||
@@ -276,31 +277,31 @@ char * vtoc_ebcdic_enc (char *source, char *target, int l);
|
||||
char * vtoc_ebcdic_dec (char *source, char *target, int l);
|
||||
void vtoc_set_extent (
|
||||
extent_t * ext,
|
||||
u_int8_t typeind,
|
||||
u_int8_t seqno,
|
||||
uint8_t typeind,
|
||||
uint8_t seqno,
|
||||
cchh_t * lower,
|
||||
cchh_t * upper);
|
||||
void vtoc_set_cchh (
|
||||
cchh_t * addr,
|
||||
u_int32_t cc,
|
||||
u_int16_t hh);
|
||||
u_int32_t vtoc_get_cyl_from_cchh(cchh_t *addr);
|
||||
u_int16_t vtoc_get_head_from_cchh(cchh_t *addr);
|
||||
uint32_t cc,
|
||||
uint16_t hh);
|
||||
uint32_t vtoc_get_cyl_from_cchh(cchh_t *addr);
|
||||
uint16_t vtoc_get_head_from_cchh(cchh_t *addr);
|
||||
void vtoc_set_cchhb (
|
||||
cchhb_t * addr,
|
||||
u_int32_t cc,
|
||||
u_int16_t hh,
|
||||
u_int8_t b);
|
||||
u_int32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr);
|
||||
u_int16_t vtoc_get_head_from_cchhb(cchhb_t *addr);
|
||||
u_int64_t cchhb2blk(cchhb_t *p, struct hd_geometry *geo);
|
||||
u_int64_t cchh2blk (cchh_t *p, struct hd_geometry *geo);
|
||||
u_int32_t cchh2trk (cchh_t *p, struct hd_geometry *geo);
|
||||
uint32_t cc,
|
||||
uint16_t hh,
|
||||
uint8_t b);
|
||||
uint32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr);
|
||||
uint16_t vtoc_get_head_from_cchhb(cchhb_t *addr);
|
||||
uint64_t cchhb2blk(cchhb_t *p, struct hd_geometry *geo);
|
||||
uint64_t cchh2blk (cchh_t *p, struct hd_geometry *geo);
|
||||
uint32_t cchh2trk (cchh_t *p, struct hd_geometry *geo);
|
||||
|
||||
void vtoc_set_date (
|
||||
labeldate_t * d,
|
||||
u_int8_t year,
|
||||
u_int16_t day);
|
||||
uint8_t year,
|
||||
uint16_t day);
|
||||
|
||||
void vtoc_volume_label_init (
|
||||
volume_label_t *vlabel);
|
||||
@@ -365,12 +366,12 @@ void vtoc_init_format4_label (
|
||||
unsigned int tracks,
|
||||
unsigned int blocks,
|
||||
unsigned int blksize,
|
||||
u_int16_t dev_type);
|
||||
uint16_t dev_type);
|
||||
|
||||
void vtoc_update_format4_label (
|
||||
format4_label_t *f4,
|
||||
cchhb_t *highest_f1,
|
||||
u_int16_t unused_update);
|
||||
uint16_t unused_update);
|
||||
|
||||
void vtoc_init_format5_label (
|
||||
format5_label_t *f5);
|
||||
@@ -379,17 +380,17 @@ void vtoc_update_format5_label_add (
|
||||
format5_label_t *f5,
|
||||
int verbose,
|
||||
int trk,
|
||||
u_int16_t a,
|
||||
u_int16_t b,
|
||||
u_int8_t c);
|
||||
uint16_t a,
|
||||
uint16_t b,
|
||||
uint8_t c);
|
||||
|
||||
void vtoc_update_format5_label_del (
|
||||
format5_label_t *f5,
|
||||
int verbose,
|
||||
int trk,
|
||||
u_int16_t a,
|
||||
u_int16_t b,
|
||||
u_int8_t c);
|
||||
uint16_t a,
|
||||
uint16_t b,
|
||||
uint8_t c);
|
||||
|
||||
void vtoc_init_format7_label (
|
||||
format7_label_t *f7);
|
||||
@@ -397,14 +398,14 @@ void vtoc_init_format7_label (
|
||||
void vtoc_update_format7_label_add (
|
||||
format7_label_t *f7,
|
||||
int verbose,
|
||||
u_int32_t a,
|
||||
u_int32_t b);
|
||||
uint32_t a,
|
||||
uint32_t b);
|
||||
|
||||
void vtoc_update_format7_label_del (
|
||||
format7_label_t *f7,
|
||||
int verbose,
|
||||
u_int32_t a,
|
||||
u_int32_t b);
|
||||
uint32_t a,
|
||||
uint32_t b);
|
||||
|
||||
void vtoc_init_format8_label (
|
||||
unsigned int blksize,
|
||||
@@ -424,9 +425,9 @@ void vtoc_set_freespace(
|
||||
format7_label_t *f7,
|
||||
char ch,
|
||||
int verbose,
|
||||
u_int32_t start,
|
||||
u_int32_t stop,
|
||||
u_int32_t cyl,
|
||||
u_int32_t trk);
|
||||
uint32_t start,
|
||||
uint32_t stop,
|
||||
uint32_t cyl,
|
||||
uint32_t trk);
|
||||
|
||||
#endif /* LIB_VTOC_H */
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#define TOOLS_BINDIR STRINGIFY (S390_TOOLS_BINDIR)
|
||||
#define TOOLS_DATADIR STRINGIFY (S390_TOOLS_DATADIR)
|
||||
|
||||
#define __used __attribute__((used))
|
||||
#define __noreturn __attribute__((noreturn))
|
||||
#define __packed __attribute__((packed))
|
||||
#define __aligned(x) __attribute__((aligned(x)))
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -99,7 +100,7 @@ static int next_entry(DIR *dir, char *in_path, char *out_path,
|
||||
static int nvme_getdev_by_fid(char *fidstr, char *devpath)
|
||||
{
|
||||
char temp_path[PATH_MAX + 19], real_path[PATH_MAX];
|
||||
u_int64_t target_fid, curfid;
|
||||
uint64_t target_fid, curfid;
|
||||
char *sys_path;
|
||||
DIR *dir;
|
||||
char *end;
|
||||
@@ -140,7 +141,7 @@ static int nvme_getdev_by_nsid(char *nsid_str, char *path, char *dev_path)
|
||||
{
|
||||
char full_path[NVME_PATH_MAX+1], nsid_path[sizeof(full_path)+5];
|
||||
char *end;
|
||||
u_int64_t nsid, curnsid;
|
||||
uint64_t nsid, curnsid;
|
||||
DIR *dir;
|
||||
|
||||
nsid = strtoul(nsid_str, &end, 10);
|
||||
|
||||
@@ -15,6 +15,7 @@ install-man: $(MANS)
|
||||
msection=`echo $$man |sed 's/.*\.\([1-9]\)$$/man\1/'` ; \
|
||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 -D $$man $(DESTDIR)$(MANDIR)/$$msection/$$man ; \
|
||||
done
|
||||
ln -f -s chiucvallow.8 $(DESTDIR)$(MANDIR)/man8/lsiucvallow.8
|
||||
|
||||
clean:
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ terminal application
|
||||
To connect to the first z/VM IUCV HVC terminal device on the z/VM guest virtual
|
||||
machine "LNX1234", run:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
iucvconn LNX1234 lnxhvc0
|
||||
@@ -215,7 +215,7 @@ For each HVC terminal device, a \fBgetty\fP program must be started.
|
||||
To configure and start \fBgetty\fP on a HVC terminal, open
|
||||
.BR /etc/inittab (5),
|
||||
and add a new entry similar to this one:
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
|
||||
@@ -261,7 +261,7 @@ IUCV HVC terminal:
|
||||
.IP "1." 4
|
||||
To display the current terminal name, issue the command:
|
||||
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
user@host:~$ echo $TERM
|
||||
@@ -275,7 +275,7 @@ To connect to a z/VM IUCV HVC terminal, run
|
||||
.BR iucvconn (1)
|
||||
and log in as usual:
|
||||
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
user@host:~$ iucvconn MYLNX01 lnxhvc0
|
||||
@@ -289,7 +289,7 @@ user@MYLNX01:~$
|
||||
To assign the terminal name from step 1. to the terminal environment variable,
|
||||
issue the following command:
|
||||
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
user@MYLNX01:~$ export TERM=xterm
|
||||
@@ -304,7 +304,7 @@ environment variable.
|
||||
.PP
|
||||
For getty programs, a sample terminal environment configuration might look like:
|
||||
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
h0:2345:respawn:/sbin/agetty -L 9600 hvc0 linux
|
||||
|
||||
@@ -123,7 +123,7 @@ the characters to the connected terminal.
|
||||
To access the "lnxterm" terminal on the Linux instance in
|
||||
z/VM guest virtual machine LNXSYS01:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
iucvconn LNXSYS01 lnxterm
|
||||
@@ -134,7 +134,7 @@ iucvconn LNXSYS01 lnxterm
|
||||
To access the first z/VM IUCV HVC terminal on the Linux instance in
|
||||
z/VM guest virtual machine LNXSYS02:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
iucvconn LNXSYS02 lnxhvc0
|
||||
@@ -145,7 +145,7 @@ iucvconn LNXSYS02 lnxhvc0
|
||||
To create a transcript of the terminal session to the Linux instance in
|
||||
z/VM guest virtual machine LNXSYS99:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
iucvconn -s ~/transcripts/lnxsys99 LNXSYS99 lnxhvc0
|
||||
|
||||
@@ -94,7 +94,7 @@ additional options.
|
||||
.SH EXAMPLES
|
||||
To allow remote logins using the terminal identifier "lnxterm":
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
iucvtty lnxterm
|
||||
@@ -104,7 +104,7 @@ iucvtty lnxterm
|
||||
|
||||
To only allow users from LNXSYS01 to connect to terminal "lnxterm":
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
iucvtty -a LNXSYS01 lnxterm
|
||||
@@ -115,7 +115,7 @@ iucvtty -a LNXSYS01 lnxterm
|
||||
To only allow users from LNXSYS10 through LNXSYS19 to connect to terminal
|
||||
"lnxterm":
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
iucvtty -a "LNXSYS1[0-9]" lnxterm
|
||||
@@ -125,7 +125,7 @@ iucvtty -a "LNXSYS1[0-9]" lnxterm
|
||||
|
||||
To use \fB/sbin/sulogin\fP instead of \fB/bin/login\fP for terminal "suterm":
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
iucvtty suterm -- /sbin/sulogin
|
||||
@@ -136,7 +136,7 @@ iucvtty suterm -- /sbin/sulogin
|
||||
An entry in \fB/etc/inittab\fP to facilitate user logins on terminal "lnxterm"
|
||||
with \fB/bin/login\fP could be:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
t1:2345:respawn:/usr/bin/iucvtty lnxterm
|
||||
@@ -147,7 +147,7 @@ t1:2345:respawn:/usr/bin/iucvtty lnxterm
|
||||
An entry in \fB/etc/inittab\fP to facilitate user logins on terminal "suterm"
|
||||
with \fB/sbin/sulogin\fP in single user mode could be:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
s1:S:respawn:/usr/bin/iucvtty suterm -- /sbin/sulogin
|
||||
|
||||
@@ -79,7 +79,7 @@ users".
|
||||
|
||||
The output for "list" authorization is a list of z/VM guest virtual machines,
|
||||
for example:
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25i
|
||||
.nf
|
||||
|
||||
@@ -94,7 +94,7 @@ guest5
|
||||
.ft
|
||||
The output for "regex" authorization is a list of one or more
|
||||
regular expressions, for example:
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25i
|
||||
.nf
|
||||
|
||||
@@ -109,7 +109,7 @@ Regular expressions for your authorization:
|
||||
If \fBts-shell\fP is configured to connect to particular z/VM guest virtual
|
||||
machines only, the output for "regex" authorization is followed by a list of
|
||||
the user IDs that match at least one of the regular expressions:
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25i
|
||||
.nf
|
||||
|
||||
@@ -139,7 +139,7 @@ To change the default terminal identifier, use the \fBterminal\fP command.
|
||||
|
||||
In the following example, a user opens a terminal connection to the Linux
|
||||
instance in z/VM guest virtual machine LNXSYS01:
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25i
|
||||
.nf
|
||||
|
||||
@@ -164,7 +164,7 @@ If \fBterminal\fP is called with the \fIidentifier\fP being specified,
|
||||
If \fIidentifier\fP is not specified, the current default terminal identifier
|
||||
is displayed:
|
||||
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25i
|
||||
.nf
|
||||
user@ts-shell> terminal
|
||||
@@ -212,7 +212,7 @@ guest virtual machines.
|
||||
A typical \fBIUCV\fP authorization statement in the z/VM directory entry of the
|
||||
terminal server z/VM guest virtual machine might be:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
IUCV ANY
|
||||
@@ -301,7 +301,7 @@ instance.
|
||||
|
||||
For example, to create a list of all z/VM guest virtual machines with names that
|
||||
start with "LINUX" and are followed by digits, use:
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
|
||||
@@ -373,7 +373,7 @@ group name and prefixed with "@".
|
||||
|
||||
Here is an example of a Linux user and group authorization:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
alice = list:guest01,guest02
|
||||
@@ -395,7 +395,7 @@ name on a separate line.
|
||||
.PP
|
||||
The following example shows the usage of the \fIfile:\fP prefix:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
@testgrp = file:/etc/iucvterm/auth/test-systems.list
|
||||
@@ -427,7 +427,7 @@ To authorize user bob for all z/VM guest virtual machines with names that
|
||||
start with "lnx" and are followed with at least three but not more than five
|
||||
alphanumeric characters, use:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
bob = regex:lnx\\w{3,5}
|
||||
@@ -441,7 +441,7 @@ test or production environment: authorize all users in the "testgrp" group for
|
||||
all systems in the test environment; and respectively, authorize all users in
|
||||
the "prodgrp" group for all systems in the production environment:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
@testgrp = regex:test\\w+
|
||||
@@ -461,7 +461,7 @@ of the other type are ignored.
|
||||
|
||||
Example:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
@users = list:guest01,guest03,guest05
|
||||
@@ -484,7 +484,7 @@ To use the \fBts-shell\fP as the login shell for Linux users, follow these steps
|
||||
Add the path of the \fBts-shell\fP program to the \fI/etc/shells\fP file that
|
||||
contains the list of valid login shells:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
echo $(which ts-shell) >> /etc/shells
|
||||
@@ -498,7 +498,7 @@ Change the login shell of a particular Linux user using the
|
||||
.BR chsh (1)
|
||||
program:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
chsh -s $(which ts-shell) alice
|
||||
|
||||
@@ -116,7 +116,7 @@ specifies an exit status in this range.
|
||||
.SS inittab
|
||||
To start \fB/sbin/agetty\fP on terminal device "hvc1", specify:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
h1:2345:respawn:/sbin/\*s hvc1 /sbin/agetty -L 9600 %t linux
|
||||
@@ -128,7 +128,7 @@ h1:2345:respawn:/sbin/\*s hvc1 /sbin/agetty -L 9600 %t linux
|
||||
To start \fB/sbin/agetty\fP on terminal device "hvc1", add the following
|
||||
settings to the job file:
|
||||
.PP
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25in
|
||||
.nf
|
||||
respawn
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "lib/ccw.h"
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "lib/libcpumf.h"
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_libc.h"
|
||||
|
||||
#define SERVICELEVEL "/proc/service_levels"
|
||||
|
||||
@@ -169,3 +170,31 @@ bool libcpumf_have_pai_nnpa(void)
|
||||
{
|
||||
return libcpumf_have_pai_sysfs(S390_SYSFS_PAI_NNPA);
|
||||
}
|
||||
|
||||
long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd,
|
||||
unsigned long flags)
|
||||
{
|
||||
return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
|
||||
}
|
||||
|
||||
bool ctr_in_list(char *name, char *ctrlist)
|
||||
{
|
||||
char *token;
|
||||
char *list;
|
||||
|
||||
if (!ctrlist) /* No --counters means all counters */
|
||||
return true;
|
||||
|
||||
list = util_strdup(ctrlist);
|
||||
token = strtok(list, ",");
|
||||
while (token) {
|
||||
if (strcmp(token, name) == 0) {
|
||||
free(list);
|
||||
return true;
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
free(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
include ../common.mak
|
||||
|
||||
VERSION = 1.0
|
||||
VERSION = 1.1
|
||||
VERM = $(shell echo $(VERSION) | cut -d '.' -f 1)
|
||||
|
||||
ifneq (${HAVE_OPENSSL},0)
|
||||
@@ -91,13 +91,13 @@ libekmfweb.so.$(VERSION): ALL_LDFLAGS += -shared -Wl,--version-script=libekmfweb
|
||||
-Wl,-z,defs,-Bsymbolic -Wl,-soname,libekmfweb.so.$(VERM)
|
||||
libekmfweb.so.$(VERSION): ekmfweb.o utilities.o cca.o $(libs)
|
||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
||||
ln -srf libekmfweb.so.$(VERSION) libekmfweb.so.$(VERM)
|
||||
ln -srf libekmfweb.so.$(VERSION) libekmfweb.so
|
||||
ln -sf libekmfweb.so.$(VERSION) libekmfweb.so.$(VERM)
|
||||
ln -sf libekmfweb.so.$(VERSION) libekmfweb.so
|
||||
|
||||
install-libekmfweb.so.$(VERSION): libekmfweb.so.$(VERSION)
|
||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 -T libekmfweb.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libekmfweb.so.$(VERSION)
|
||||
ln -srf $(DESTDIR)$(SOINSTALLDIR)/libekmfweb.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libekmfweb.so.$(VERM)
|
||||
ln -srf $(DESTDIR)$(SOINSTALLDIR)/libekmfweb.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libekmfweb.so
|
||||
ln -sf libekmfweb.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libekmfweb.so.$(VERM)
|
||||
ln -sf libekmfweb.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libekmfweb.so
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(USRINCLUDEDIR)/ekmfweb
|
||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 $(rootdir)include/ekmfweb/ekmfweb.h $(DESTDIR)$(USRINCLUDEDIR)/ekmfweb
|
||||
|
||||
|
||||
@@ -5099,14 +5099,15 @@ int ekmf_generate_csr(const struct ekmf_config *config,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
|
||||
if (rsa_pss_params != NULL)
|
||||
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
|
||||
|
||||
rc = SK_OPENSSL_generate_csr(key_blob, key_blob_size,
|
||||
subject_rdns, num_subject_rdns,
|
||||
subject_utf8, cert,
|
||||
extensions, num_extensions,
|
||||
digest_nid, &pss_params, &req,
|
||||
digest_nid, rsa_pss_params != NULL ?
|
||||
&pss_params : NULL, &req,
|
||||
&ext_lib_info.ext_lib, verbose);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "SK_OPENSSL_generate_csr failed "
|
||||
@@ -5245,14 +5246,16 @@ int ekmf_generate_ss_cert(const struct ekmf_config *config,
|
||||
}
|
||||
}
|
||||
|
||||
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
|
||||
if (rsa_pss_params != NULL)
|
||||
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
|
||||
|
||||
rc = SK_OPENSSL_generate_ss_cert(key_blob, key_blob_size,
|
||||
subject_rdns, num_subject_rdns,
|
||||
subject_utf8, rcert,
|
||||
extensions, num_extensions,
|
||||
validity_days, digest_nid,
|
||||
&pss_params, &cert,
|
||||
rsa_pss_params != NULL ?
|
||||
&pss_params : NULL, &cert,
|
||||
&ext_lib_info.ext_lib, verbose);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "SK_OPENSSL_generate_ss_cert failed "
|
||||
@@ -5280,6 +5283,85 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a certificate has the same public key as the secure identity
|
||||
* key (field identity_secure_key in config structure) .
|
||||
*
|
||||
* @param config the configuration structure. Only field
|
||||
* identity_secure_key must be specified, all others
|
||||
* are optional.
|
||||
* @param x509_cert the X509 certificate object to validate
|
||||
* @param ext_lib External secure key crypto library to use
|
||||
* @param verbose if true, verbose messages are printed
|
||||
*
|
||||
* @returns a negative errno in case of an error, 0 if success.
|
||||
* -EINVAL: invalid parameter, or certificate is not valid
|
||||
* -ENOMEM: Failed to allocate memory
|
||||
* any other errno from file I/O routines
|
||||
*/
|
||||
int ekmf_validate_cert(const struct ekmf_config *config, const X509 *x509_cert,
|
||||
const struct ekmf_ext_lib *ext_lib, bool verbose)
|
||||
{
|
||||
unsigned char key_blob[MAX_KEY_BLOB_SIZE];
|
||||
size_t key_blob_size = sizeof(key_blob);
|
||||
struct ext_lib_info ext_lib_info;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
int rc;
|
||||
|
||||
if (config == NULL || ext_lib == NULL || x509_cert == NULL)
|
||||
return -EINVAL;
|
||||
if (config->identity_secure_key == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
_ekmf_copy_ext_lib(ext_lib, &ext_lib_info);
|
||||
|
||||
rc = SK_OPENSSL_init(verbose);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "Failed to initialize secure key support: "
|
||||
"%s", strerror(-rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = read_key_blob(config->identity_secure_key, key_blob,
|
||||
&key_blob_size);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "Failed to read identity key from file "
|
||||
"'%s': %s", config->identity_secure_key,
|
||||
strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = SK_OPENSSL_get_secure_key_as_pkey(key_blob, key_blob_size,
|
||||
false, &pkey,
|
||||
&ext_lib_info.ext_lib, verbose);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "Failed to get the PKEY from the identity "
|
||||
"key: %s", strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if !OPENSSL_VERSION_PREREQ(3, 0)
|
||||
if (EVP_PKEY_cmp(pkey, X509_get0_pubkey(x509_cert)) != 1) {
|
||||
#else
|
||||
if (EVP_PKEY_eq(pkey, X509_get0_pubkey(x509_cert)) != 1) {
|
||||
#endif
|
||||
pr_verbose(verbose, "The certificate does not match with the "
|
||||
"identity key");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_verbose(verbose, "Certificate successfully validated");
|
||||
|
||||
out:
|
||||
if (pkey != NULL)
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
SK_OPENSSL_term();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the connection to the EKMFWeb server by destroying the CURL handle.
|
||||
*
|
||||
|
||||
@@ -8,6 +8,7 @@ LIBEKMFWEB_1.0 {
|
||||
ekmf_reencipher_identity_key;
|
||||
ekmf_generate_csr;
|
||||
ekmf_generate_ss_cert;
|
||||
ekmf_validate_cert;
|
||||
ekmf_get_public_key;
|
||||
ekmf_get_settings;
|
||||
ekmf_check_feature;
|
||||
@@ -28,3 +29,9 @@ LIBEKMFWEB_1.0 {
|
||||
ekmf_curl_destroy;
|
||||
local: *;
|
||||
};
|
||||
|
||||
LIBEKMFWEB_1.1 {
|
||||
global:
|
||||
ekmf_validate_cert;
|
||||
local: *;
|
||||
};
|
||||
|
||||
@@ -113,13 +113,13 @@ libkmipclient.so.$(VERSION): ALL_LDFLAGS += -shared -Wl,--version-script=libkmip
|
||||
libkmipclient.so.$(VERSION): kmip.o request.o response.o attribute.o key.o ttlv.o json.o \
|
||||
xml.o https.o tls.o names.o utils.o
|
||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
||||
ln -srf libkmipclient.so.$(VERSION) libkmipclient.so.$(VERM)
|
||||
ln -srf libkmipclient.so.$(VERSION) libkmipclient.so
|
||||
ln -sf libkmipclient.so.$(VERSION) libkmipclient.so.$(VERM)
|
||||
ln -sf libkmipclient.so.$(VERSION) libkmipclient.so
|
||||
|
||||
install-libkmipclient.so.$(VERSION): libkmipclient.so.$(VERSION)
|
||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 -T libkmipclient.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so.$(VERSION)
|
||||
ln -srf $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so.$(VERM)
|
||||
ln -srf $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so
|
||||
ln -sf libkmipclient.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so.$(VERM)
|
||||
ln -sf libkmipclient.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(USRINCLUDEDIR)/kmipclient
|
||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 $(rootdir)include/kmipclient/kmipclient.h $(DESTDIR)$(USRINCLUDEDIR)/kmipclient
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ out:
|
||||
if (server_cert != NULL)
|
||||
X509_free(server_cert);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
include ../common.mak
|
||||
include ../common_autocomp.mak
|
||||
|
||||
lib := libutil.a
|
||||
|
||||
sources := $(filter-out %_example.c,$(wildcard *.c))
|
||||
sources := $(filter-out %_example.c %_host.c, $(wildcard *.c))
|
||||
objects := $(patsubst %.c,%.o,$(sources))
|
||||
|
||||
autocomp-object := util_autocomp_host.o
|
||||
|
||||
examples := $(patsubst %.c,%,$(wildcard *_example.c))
|
||||
|
||||
all: $(lib)
|
||||
all: $(lib) $(autocomp-object)
|
||||
examples: $(examples)
|
||||
|
||||
$(examples): %: %.o $(lib)
|
||||
|
||||
299
libutil/util_autocomp_host.c
Normal file
299
libutil/util_autocomp_host.c
Normal file
@@ -0,0 +1,299 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* autocomp - command line autocompletion
|
||||
*
|
||||
* Generating autocompletion scripts for bash and zsh
|
||||
* based on util_opt struct
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static const char *bash_script_part1 = "() {\n\n\
|
||||
\tlocal current_word previous_word options_array\n\n\
|
||||
\tCOMPREPLY=()\n\n\
|
||||
\tcurrent_word=\"${COMP_WORDS[COMP_CWORD]}\"\n\n\
|
||||
\tprevious_word=\"${COMP_WORDS[COMP_CWORD-1]}\"\n\n\
|
||||
\toptions_array=\"";
|
||||
|
||||
static const char *bash_script_part2 = "\tif [[ ${current_word} == -* || ${COMP_CWORD} -eq 1 ]] ; then\n\n\
|
||||
\t\tCOMPREPLY=( $(compgen -W \"${options_array}\" -- ${current_word} ) )\n\n\
|
||||
\t\treturn 0\n\n\
|
||||
\tfi\n\n\
|
||||
}\n\n\
|
||||
complete -F ";
|
||||
|
||||
static char *format_name(const char *fmt, char *tool_name)
|
||||
{
|
||||
char *func_name;
|
||||
|
||||
if (asprintf(&func_name, fmt, tool_name) == -1)
|
||||
return NULL;
|
||||
return func_name;
|
||||
}
|
||||
|
||||
/*
|
||||
* The convention for a completion function name is to be the same
|
||||
* as the command's name, but prefixed by '_'.
|
||||
*/
|
||||
static char *generate_func_name(char *tool_name)
|
||||
{
|
||||
return format_name("_%s", tool_name);
|
||||
}
|
||||
|
||||
static char *generate_bash_filename(char *tool_name)
|
||||
{
|
||||
return format_name("%s.bash", tool_name);
|
||||
}
|
||||
|
||||
static int init_scriptfile(char *file_path)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(file_path, O_CREAT | O_WRONLY, 0644);
|
||||
if (fd < 0)
|
||||
return -EIO;
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int start_bash_scriptfile(int fd, char *func_name)
|
||||
{
|
||||
int len, ret = 0;
|
||||
char *str;
|
||||
|
||||
len = asprintf(&str, "%s%s", func_name, bash_script_part1);
|
||||
if (len == -1)
|
||||
return -EIO;
|
||||
|
||||
if (write(fd, str, len) != len)
|
||||
ret = -EIO;
|
||||
free(str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int start_zsh_scriptfile(int fd, char *func_name, char *tool_name)
|
||||
{
|
||||
const char *part3 = " {\n\n\t_arguments -C \\\n";
|
||||
const char *part2 = "\n\nfunction ";
|
||||
const char *part1 = "#compdef ";
|
||||
int len, ret = 0;
|
||||
char *str;
|
||||
|
||||
len = asprintf(&str, "%s%s%s%s%s", part1, tool_name, part2, func_name, part3);
|
||||
if (len == -1)
|
||||
return -EIO;
|
||||
|
||||
if (write(fd, str, len) != len)
|
||||
ret = -EIO;
|
||||
free(str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int write_bash_command_options(struct util_opt *opt_vec, int fd)
|
||||
{
|
||||
const char *prefix = " --";
|
||||
char *str;
|
||||
int len;
|
||||
|
||||
for (int i = 0; opt_vec[i].desc; i++) {
|
||||
if (opt_vec[i].option.name) {
|
||||
len = asprintf(&str, "%s%s", prefix, opt_vec[i].option.name);
|
||||
if (len == -1)
|
||||
return -EIO;
|
||||
if (write(fd, str, len) != len) {
|
||||
free(str);
|
||||
return -EIO;
|
||||
}
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
if (write(fd, "\"\n\n", 3) != 3)
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_zsh_command_options(struct util_opt *opt_vec, int fd)
|
||||
{
|
||||
const char *name, *desc;
|
||||
char *str;
|
||||
int len;
|
||||
|
||||
for (int i = 0; opt_vec[i].desc; i++) {
|
||||
if (opt_vec[i].option.name) {
|
||||
name = opt_vec[i].option.name;
|
||||
desc = opt_vec[i].desc;
|
||||
len = asprintf(&str, "\t\t\"--%s[%s]\" \\\n", name, desc);
|
||||
if (len == -1)
|
||||
return -EIO;
|
||||
if (write(fd, str, len) != len) {
|
||||
free(str);
|
||||
return -EIO;
|
||||
}
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
if (write(fd, "\n}\n", 3) != 3)
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int finish_bash_scriptfile(char *tool_name, int fd, char *func_name)
|
||||
{
|
||||
int len, ret = 0;
|
||||
char *str;
|
||||
|
||||
len = asprintf(&str, "%s%s %s\n", bash_script_part2, func_name, tool_name);
|
||||
if (len == -1)
|
||||
return -EIO;
|
||||
|
||||
if (write(fd, str, len) != len)
|
||||
ret = -EIO;
|
||||
free(str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds tab completion in bash for a command.
|
||||
* Works by generating an autocompletion
|
||||
* script file at '/usr/share/bash-completion/completions'.
|
||||
*
|
||||
* The full script will be as follows, supposing the tool name is
|
||||
* 'example' and it only has the options '--help' and
|
||||
* '--version':
|
||||
*
|
||||
* _example() {
|
||||
*
|
||||
* local current_word previous_word options_array
|
||||
*
|
||||
* COMPREPLY=()
|
||||
*
|
||||
* current_word="${COMP_WORDS[COMP_CWORD]}"
|
||||
*
|
||||
* previous_word="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
*
|
||||
* options_array="--version --help"
|
||||
*
|
||||
* if [[ ${current_word} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
||||
*
|
||||
* COMPREPLY=( $(compgen -W "${options_array}" -- ${current_word} ) )
|
||||
*
|
||||
* return 0
|
||||
*
|
||||
* fi
|
||||
*
|
||||
* }
|
||||
*
|
||||
* complete -F _example example
|
||||
*
|
||||
*/
|
||||
static void generate_bash_autocomp(struct util_opt *opt_vec, char *tool_name)
|
||||
{
|
||||
char *func_name, *filename;
|
||||
int fd, ret = 0;
|
||||
|
||||
func_name = generate_func_name(tool_name);
|
||||
if (!func_name) {
|
||||
ret = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
filename = generate_bash_filename(tool_name);
|
||||
if (!filename) {
|
||||
ret = -ENOMEM;
|
||||
goto free_func;
|
||||
}
|
||||
fd = init_scriptfile(filename);
|
||||
if (fd < 0) {
|
||||
ret = fd;
|
||||
goto free_file;
|
||||
}
|
||||
ret = start_bash_scriptfile(fd, func_name);
|
||||
if (ret < 0)
|
||||
goto close;
|
||||
ret = write_bash_command_options(opt_vec, fd);
|
||||
if (ret < 0)
|
||||
goto close;
|
||||
ret = finish_bash_scriptfile(tool_name, fd, func_name);
|
||||
close:
|
||||
close(fd);
|
||||
if (ret)
|
||||
remove(filename);
|
||||
free_file:
|
||||
free(filename);
|
||||
free_func:
|
||||
free(func_name);
|
||||
end:
|
||||
printf(" AUTOCOMP\t%s/%s.bash\n", tool_name, tool_name);
|
||||
if (ret)
|
||||
printf("%s.bash: error - %s\n", tool_name, strerror(abs(ret)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds tab completion in zsh for a command.
|
||||
* Works by generating an autocompletion
|
||||
* script file at '/usr/share/zsh/site-functions'.
|
||||
*
|
||||
* The full script will be as follows, supposing the tool name is
|
||||
* 'example' and it only has the options '--help', -h and
|
||||
* '--version' (the descriptions, as well as the flags are
|
||||
* taken from a util_opt struct):
|
||||
*
|
||||
* #compdef example_completion
|
||||
*
|
||||
* function _example_completion {
|
||||
*
|
||||
* _arguments -C \
|
||||
* "-h[Show help information]" \
|
||||
* "--help[Show help but long format]" \
|
||||
* "--version[Show version]"
|
||||
* }
|
||||
*
|
||||
*/
|
||||
static void generate_zsh_autocomp(struct util_opt *opt_vec, char *tool_name)
|
||||
{
|
||||
char *func_name;
|
||||
int fd, ret = 0;
|
||||
|
||||
func_name = generate_func_name(tool_name);
|
||||
if (!func_name) {
|
||||
ret = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
fd = init_scriptfile(func_name);
|
||||
if (fd < 0) {
|
||||
ret = fd;
|
||||
goto free_func;
|
||||
}
|
||||
ret = start_zsh_scriptfile(fd, func_name, tool_name);
|
||||
if (ret < 0)
|
||||
goto close;
|
||||
ret = write_zsh_command_options(opt_vec, fd);
|
||||
close:
|
||||
close(fd);
|
||||
if (ret)
|
||||
remove(func_name);
|
||||
free_func:
|
||||
free(func_name);
|
||||
end:
|
||||
printf(" AUTOCOMP\t%s/_%s\n", tool_name, tool_name);
|
||||
if (ret)
|
||||
printf("_%s: error - %s\n", tool_name, strerror(abs(ret)));
|
||||
}
|
||||
|
||||
void generate_autocomp(struct util_opt *opt_vec, char *tool_name)
|
||||
{
|
||||
generate_bash_autocomp(opt_vec, tool_name);
|
||||
generate_zsh_autocomp(opt_vec, tool_name);
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <argz.h>
|
||||
#include <libgen.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __GLIBC__
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
#include "lib/util_base.h"
|
||||
#include "lib/util_panic.h"
|
||||
@@ -24,6 +26,7 @@
|
||||
*
|
||||
* To get symbols, link the code with "-rdynamic".
|
||||
*/
|
||||
#ifdef __GLIBC__
|
||||
static void print_backtrace(void)
|
||||
{
|
||||
void *array[256];
|
||||
@@ -42,6 +45,9 @@ static void print_backtrace(void)
|
||||
|
||||
free(strings);
|
||||
}
|
||||
#else
|
||||
static void print_backtrace(void) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for core ulimit
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lib/util_base.h"
|
||||
#include "lib/util_libc.h"
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_prg.h"
|
||||
|
||||
/*
|
||||
* Verify that directory exists
|
||||
|
||||
33
libutil/util_str.c
Normal file
33
libutil/util_str.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* util - Utility function library
|
||||
*
|
||||
* Manipulate and work with strings
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* 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 <ctype.h>
|
||||
|
||||
#include "lib/util_str.h"
|
||||
|
||||
/**
|
||||
* Copy characters from \a src to \a dest, omitting all blank characters
|
||||
* (spaces and tabs). The resulting string in \a dest will be NUL terminated.
|
||||
*
|
||||
* @param[in] src Source string
|
||||
* @param[out] dest Destination buffer
|
||||
*/
|
||||
void util_str_rm_whitespace(const char *src, char *dest)
|
||||
{
|
||||
while (*src != '\0') {
|
||||
if (!isblank(*src)) {
|
||||
*dest = *src;
|
||||
dest++;
|
||||
}
|
||||
src++;
|
||||
}
|
||||
*dest = '\0';
|
||||
}
|
||||
134
libvtoc/vtoc.c
134
libvtoc/vtoc.c
@@ -6,6 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "lib/vtoc.h"
|
||||
|
||||
static unsigned char EBCtoASC[256] =
|
||||
@@ -198,7 +200,7 @@ char * vtoc_ebcdic_dec (char *source, char *target, int l)
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void vtoc_set_extent (extent_t *ext, u_int8_t typeind, u_int8_t seqno,
|
||||
void vtoc_set_extent (extent_t *ext, uint8_t typeind, uint8_t seqno,
|
||||
cchh_t *lower, cchh_t *upper)
|
||||
{
|
||||
ext->typeind = typeind;
|
||||
@@ -211,17 +213,17 @@ void vtoc_set_extent (extent_t *ext, u_int8_t typeind, u_int8_t seqno,
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void vtoc_set_cchh (cchh_t *addr, u_int32_t cc, u_int16_t hh)
|
||||
void vtoc_set_cchh (cchh_t *addr, uint32_t cc, uint16_t hh)
|
||||
{
|
||||
addr->cc = (u_int16_t) cc;
|
||||
addr->cc = (uint16_t) cc;
|
||||
addr->hh = cc >> 16;
|
||||
addr->hh <<= 4;
|
||||
addr->hh |= hh;
|
||||
}
|
||||
|
||||
u_int32_t vtoc_get_cyl_from_cchh(cchh_t *addr)
|
||||
uint32_t vtoc_get_cyl_from_cchh(cchh_t *addr)
|
||||
{
|
||||
u_int32_t cyl;
|
||||
uint32_t cyl;
|
||||
|
||||
/*decode cylinder for large volumes */
|
||||
cyl = addr->hh & 0xFFF0;
|
||||
@@ -230,7 +232,7 @@ u_int32_t vtoc_get_cyl_from_cchh(cchh_t *addr)
|
||||
return cyl;
|
||||
}
|
||||
|
||||
u_int16_t vtoc_get_head_from_cchh(cchh_t *addr)
|
||||
uint16_t vtoc_get_head_from_cchh(cchh_t *addr)
|
||||
{
|
||||
/* decode heads for large volumes */
|
||||
return addr->hh & 0x000F;
|
||||
@@ -239,7 +241,7 @@ u_int16_t vtoc_get_head_from_cchh(cchh_t *addr)
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void vtoc_set_ttr (ttr_t *addr, u_int16_t tt, u_int8_t r)
|
||||
static void vtoc_set_ttr (ttr_t *addr, uint16_t tt, uint8_t r)
|
||||
{
|
||||
addr->tt = tt;
|
||||
addr->r = r;
|
||||
@@ -249,18 +251,18 @@ static void vtoc_set_ttr (ttr_t *addr, u_int16_t tt, u_int8_t r)
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void vtoc_set_cchhb (cchhb_t *addr, u_int32_t cc, u_int16_t hh, u_int8_t b)
|
||||
void vtoc_set_cchhb (cchhb_t *addr, uint32_t cc, uint16_t hh, uint8_t b)
|
||||
{
|
||||
addr->cc = (u_int16_t) cc;
|
||||
addr->cc = (uint16_t) cc;
|
||||
addr->hh = cc >> 16;
|
||||
addr->hh <<= 4;
|
||||
addr->hh |= hh;
|
||||
addr->b = b;
|
||||
}
|
||||
|
||||
u_int32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr)
|
||||
uint32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr)
|
||||
{
|
||||
u_int32_t cyl;
|
||||
uint32_t cyl;
|
||||
|
||||
/* decode cylinder for large volumes */
|
||||
cyl = addr->hh & 0xFFF0;
|
||||
@@ -269,7 +271,7 @@ u_int32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr)
|
||||
return cyl;
|
||||
}
|
||||
|
||||
u_int16_t vtoc_get_head_from_cchhb(cchhb_t *addr)
|
||||
uint16_t vtoc_get_head_from_cchhb(cchhb_t *addr)
|
||||
{
|
||||
/* decode heads for large volumes */
|
||||
return addr->hh & 0x000F;
|
||||
@@ -281,22 +283,22 @@ u_int16_t vtoc_get_head_from_cchhb(cchhb_t *addr)
|
||||
* Note: Record zero is special, so first block on a track is
|
||||
* in record 1!
|
||||
*/
|
||||
u_int64_t cchhb2blk(cchhb_t *p, struct hd_geometry *geo)
|
||||
uint64_t cchhb2blk(cchhb_t *p, struct hd_geometry *geo)
|
||||
{
|
||||
return (u_int64_t) vtoc_get_cyl_from_cchhb(p) *
|
||||
return (uint64_t) vtoc_get_cyl_from_cchhb(p) *
|
||||
geo->heads * geo->sectors +
|
||||
vtoc_get_head_from_cchhb(p) * geo->sectors +
|
||||
p->b;
|
||||
}
|
||||
|
||||
u_int64_t cchh2blk (cchh_t *p, struct hd_geometry *geo) {
|
||||
uint64_t cchh2blk (cchh_t *p, struct hd_geometry *geo) {
|
||||
|
||||
return (u_int64_t) vtoc_get_cyl_from_cchh(p) *
|
||||
return (uint64_t) vtoc_get_cyl_from_cchh(p) *
|
||||
geo->heads * geo->sectors +
|
||||
vtoc_get_head_from_cchh(p) * geo->sectors;
|
||||
}
|
||||
|
||||
u_int32_t cchh2trk (cchh_t *p, struct hd_geometry *geo) {
|
||||
uint32_t cchh2trk (cchh_t *p, struct hd_geometry *geo) {
|
||||
|
||||
return vtoc_get_cyl_from_cchh(p) * geo->heads +
|
||||
vtoc_get_head_from_cchh(p);
|
||||
@@ -305,7 +307,7 @@ u_int32_t cchh2trk (cchh_t *p, struct hd_geometry *geo) {
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void vtoc_set_date (labeldate_t * d, u_int8_t year, u_int16_t day)
|
||||
void vtoc_set_date (labeldate_t * d, uint8_t year, uint16_t day)
|
||||
{
|
||||
d->year = year;
|
||||
d->day = day;
|
||||
@@ -625,7 +627,7 @@ vtoc_init_format4_label (
|
||||
unsigned int tracks,
|
||||
unsigned int blocks,
|
||||
unsigned int blksize,
|
||||
u_int16_t dev_type)
|
||||
uint16_t dev_type)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -674,24 +676,24 @@ vtoc_init_format4_label (
|
||||
f4->DS4DEVCT.DS4DEVDB = 0x00;
|
||||
/* -- end f4->DS4DEVCT -- */
|
||||
|
||||
bzero(f4->DS4AMTIM, sizeof(f4->DS4AMTIM));
|
||||
bzero(f4->DS4AMCAT, sizeof(f4->DS4AMCAT));
|
||||
bzero(f4->DS4R2TIM, sizeof(f4->DS4R2TIM));
|
||||
bzero(f4->res1, sizeof(f4->res1));
|
||||
bzero(f4->DS4F6PTR, sizeof(f4->DS4F6PTR));
|
||||
memset(f4->DS4AMTIM, 0, sizeof(f4->DS4AMTIM));
|
||||
memset(f4->DS4AMCAT, 0, sizeof(f4->DS4AMCAT));
|
||||
memset(f4->DS4R2TIM, 0, sizeof(f4->DS4R2TIM));
|
||||
memset(f4->res1, 0, sizeof(f4->res1));
|
||||
memset(f4->DS4F6PTR, 0, sizeof(f4->DS4F6PTR));
|
||||
|
||||
/* -- begin f4lbl->DS4VTOCE -- */
|
||||
vtoc_set_extent(&f4->DS4VTOCE, 0x01, 0x00, &lower, &upper);
|
||||
/* -- end f4lbl->DS4VTOCE -- */
|
||||
|
||||
bzero(f4->res2, sizeof(f4->res2));
|
||||
memset(f4->res2, 0, sizeof(f4->res2));
|
||||
f4->DS4EFLVL = 0x00;
|
||||
bzero(&f4->DS4EFPTR, sizeof(f4->DS4EFPTR));
|
||||
bzero(&f4->res3, sizeof(f4->res3));
|
||||
memset(&f4->DS4EFPTR, 0, sizeof(f4->DS4EFPTR));
|
||||
memset(&f4->res3, 0, sizeof(f4->res3));
|
||||
f4->DS4DCYL = real_cylinders;
|
||||
bzero(f4->res4, sizeof(f4->res4));
|
||||
memset(f4->res4, 0, sizeof(f4->res4));
|
||||
f4->DS4DEVF2 = 0x40; /* allow format 8 and 9 labels */
|
||||
bzero(&f4->res5, sizeof(f4->res5));
|
||||
memset(&f4->res5, 0, sizeof(f4->res5));
|
||||
}
|
||||
|
||||
|
||||
@@ -703,7 +705,7 @@ vtoc_init_format5_label (format5_label_t *f5)
|
||||
{
|
||||
int i;
|
||||
|
||||
bzero(f5, sizeof(format5_label_t));
|
||||
memset(f5, 0, sizeof(format5_label_t));
|
||||
for (i=0; i<4; i++) f5->DS5KEYID[i] = 0x05;
|
||||
f5->DS5FMTID = 0xf5;
|
||||
}
|
||||
@@ -717,7 +719,7 @@ vtoc_init_format7_label (format7_label_t *f7)
|
||||
{
|
||||
int i;
|
||||
|
||||
bzero(f7, sizeof(format7_label_t));
|
||||
memset(f7, 0, sizeof(format7_label_t));
|
||||
for (i=0; i<4; i++) f7->DS7KEYID[i] = 0x07;
|
||||
f7->DS7FMTID = 0xf7;
|
||||
}
|
||||
@@ -740,7 +742,7 @@ static void vtoc_init_format_1_8_label (
|
||||
t = time(NULL);
|
||||
creatime = gmtime(&t);
|
||||
|
||||
bzero(f1->DS1DSNAM, sizeof(f1->DS1DSNAM));
|
||||
memset(f1->DS1DSNAM, 0, sizeof(f1->DS1DSNAM));
|
||||
sprintf(str, "PART .NEW ");
|
||||
vtoc_ebcdic_enc(str, str, 44);
|
||||
memcpy(f1->DS1DSNAM, str, 44);
|
||||
@@ -748,8 +750,8 @@ static void vtoc_init_format_1_8_label (
|
||||
f1->DS1VOLSQ = 0x0001;
|
||||
|
||||
vtoc_set_date(&f1->DS1CREDT,
|
||||
(u_int8_t) creatime->tm_year,
|
||||
(u_int16_t) creatime->tm_yday);
|
||||
(uint8_t) creatime->tm_year,
|
||||
(uint16_t) creatime->tm_yday);
|
||||
/* expires never - 99 365 */
|
||||
vtoc_set_date(&f1->DS1EXPDT,
|
||||
0x63,
|
||||
@@ -760,8 +762,8 @@ static void vtoc_init_format_1_8_label (
|
||||
vtoc_ebcdic_enc("IBM LINUX ", str, 13);
|
||||
memcpy((char *)f1->DS1SYSCD, str, 13);
|
||||
vtoc_set_date(&f1->DS1REFD,
|
||||
(u_int8_t) creatime->tm_year,
|
||||
(u_int16_t) creatime->tm_yday);
|
||||
(uint8_t) creatime->tm_year,
|
||||
(uint16_t) creatime->tm_yday);
|
||||
f1->DS1SMSFG = 0x00;
|
||||
f1->DS1SCXTF = 0x00;
|
||||
f1->DS1SCXTV = 0x0000;
|
||||
@@ -775,17 +777,17 @@ static void vtoc_init_format_1_8_label (
|
||||
f1->DS1RKP = 0x0000;
|
||||
f1->DS1DSIND = 0x80; /* last volume for this dataset */
|
||||
f1->DS1SCAL1 = 0x80;
|
||||
bzero(&f1->DS1SCAL3, sizeof(f1->DS1SCAL3));
|
||||
memset(&f1->DS1SCAL3, 0, sizeof(f1->DS1SCAL3));
|
||||
vtoc_set_ttr(&f1->DS1LSTAR,
|
||||
0x0000,
|
||||
0x00);
|
||||
f1->DS1TRBAL = 0x00;
|
||||
bzero(&f1->res1, sizeof(f1->res1));
|
||||
memset(&f1->res1, 0, sizeof(f1->res1));
|
||||
memcpy(&f1->DS1EXT1,
|
||||
part_extent,
|
||||
sizeof(extent_t));
|
||||
bzero(&f1->DS1EXT2, sizeof(extent_t));
|
||||
bzero(&f1->DS1EXT3, sizeof(extent_t));
|
||||
memset(&f1->DS1EXT2, 0, sizeof(extent_t));
|
||||
memset(&f1->DS1EXT3, 0, sizeof(extent_t));
|
||||
vtoc_set_cchhb(&f1->DS1PTRDS,
|
||||
0x0000, 0x0000, 0x00);
|
||||
}
|
||||
@@ -831,7 +833,7 @@ void
|
||||
vtoc_update_format4_label (
|
||||
format4_label_t *f4,
|
||||
cchhb_t *highest_f1,
|
||||
u_int16_t unused_update)
|
||||
uint16_t unused_update)
|
||||
{
|
||||
/* update highest address of a format 1 label */
|
||||
memcpy(&f4->DS4HPCHR, highest_f1, sizeof(cchhb_t));
|
||||
@@ -893,9 +895,9 @@ void
|
||||
vtoc_update_format5_label_add (format5_label_t *f5,
|
||||
int verbose,
|
||||
int trk,
|
||||
u_int16_t a,
|
||||
u_int16_t b,
|
||||
u_int8_t c)
|
||||
uint16_t a,
|
||||
uint16_t b,
|
||||
uint8_t c)
|
||||
{
|
||||
ds5ext_t *ext = NULL, *tmp = NULL;
|
||||
int i;
|
||||
@@ -954,7 +956,7 @@ vtoc_update_format5_label_add (format5_label_t *f5,
|
||||
/* this extent precedes the new one */
|
||||
ext->fc += (tmp->fc + (tmp->ft + ext->ft)/trk);
|
||||
ext->ft = (tmp->ft + ext->ft) % trk;
|
||||
bzero(tmp, sizeof(ds5ext_t));
|
||||
memset(tmp, 0, sizeof(ds5ext_t));
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
printf("FMT5 add extent: " \
|
||||
@@ -969,7 +971,7 @@ vtoc_update_format5_label_add (format5_label_t *f5,
|
||||
ext->t = tmp->t;
|
||||
ext->fc += (tmp->fc + (tmp->ft + ext->ft)/trk);
|
||||
ext->ft = (tmp->ft + ext->ft) % trk;
|
||||
bzero(tmp, sizeof(ds5ext_t));
|
||||
memset(tmp, 0, sizeof(ds5ext_t));
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
printf("FMT5 add extent: " \
|
||||
@@ -988,9 +990,9 @@ void
|
||||
vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
int verbose,
|
||||
int trk,
|
||||
u_int16_t a,
|
||||
u_int16_t b,
|
||||
u_int8_t c)
|
||||
uint16_t a,
|
||||
uint16_t b,
|
||||
uint8_t c)
|
||||
{
|
||||
ds5ext_t *ext;
|
||||
int i, counter=0;
|
||||
@@ -1007,7 +1009,7 @@ vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
if ((a == ext->t) && (b == ext->fc) && (c == ext->ft))
|
||||
{
|
||||
/* fills up whole free space gap */
|
||||
bzero(ext, sizeof(ds5ext_t));
|
||||
memset(ext, 0, sizeof(ds5ext_t));
|
||||
if (verbose)
|
||||
printf("FMT5 del extent: fills whole gap\n");
|
||||
counter++;
|
||||
@@ -1057,10 +1059,10 @@ vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
if ((a > ext->t) &&
|
||||
((ext->t + ext->fc*trk + ext->ft) > (a + b*trk + c)))
|
||||
{
|
||||
/* partition devides free space into 2 pieces */
|
||||
u_int16_t x = a + b*trk + c;
|
||||
u_int16_t w,y;
|
||||
u_int8_t z;
|
||||
/* partition divides free space into 2 pieces */
|
||||
uint16_t x = a + b*trk + c;
|
||||
uint16_t w,y;
|
||||
uint8_t z;
|
||||
|
||||
w = (ext->t + ext->fc*trk + ext->ft) - (a + b*trk + c);
|
||||
y = w / trk;
|
||||
@@ -1149,7 +1151,7 @@ vtoc_reorganize_FMT7_extents (format7_label_t *f7)
|
||||
* add a free space extent description to the VTOC FMT7 DSCB
|
||||
*/
|
||||
void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
u_int32_t a, u_int32_t b)
|
||||
uint32_t a, uint32_t b)
|
||||
{
|
||||
ds7ext_t *ext = NULL, *tmp = NULL;
|
||||
int i;
|
||||
@@ -1194,7 +1196,7 @@ void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
if ((ext->b) == tmp->a) {
|
||||
/* this extent precedes the new one */
|
||||
ext->b = tmp->b;
|
||||
bzero(tmp, sizeof(ds7ext_t));
|
||||
memset(tmp, 0, sizeof(ds7ext_t));
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
printf("FMT7 add extent: " \
|
||||
@@ -1207,7 +1209,7 @@ void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
{
|
||||
/* this extent succeeds the new one */
|
||||
ext->a = tmp->a;
|
||||
bzero(tmp, sizeof(ds7ext_t));
|
||||
memset(tmp, 0, sizeof(ds7ext_t));
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
printf("FMT7 add extent: " \
|
||||
@@ -1223,7 +1225,7 @@ void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
* remove a free space extent description from the VTOC FMT7 DSCB
|
||||
*/
|
||||
void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
|
||||
u_int32_t a, u_int32_t b)
|
||||
uint32_t a, uint32_t b)
|
||||
{
|
||||
ds7ext_t *ext;
|
||||
int i, counter=0;
|
||||
@@ -1236,7 +1238,7 @@ void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
|
||||
|
||||
if ((a == ext->a) && (b == ext->b)) {
|
||||
/* fills up whole free space gap */
|
||||
bzero(ext, sizeof(ds7ext_t));
|
||||
memset(ext, 0, sizeof(ds7ext_t));
|
||||
if (verbose)
|
||||
printf("FMT7 del extent: fills whole gap\n");
|
||||
counter++;
|
||||
@@ -1262,7 +1264,7 @@ void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
|
||||
}
|
||||
|
||||
if ((a > ext->a) && (b < ext->b)) {
|
||||
/* partition devides free space into 2 pieces */
|
||||
/* partition divides free space into 2 pieces */
|
||||
vtoc_update_format7_label_add(f7, verbose,
|
||||
b, ext->b);
|
||||
ext->b = a;
|
||||
@@ -1294,7 +1296,7 @@ void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
|
||||
*/
|
||||
void vtoc_set_freespace(format4_label_t *f4, format5_label_t *f5,
|
||||
format7_label_t *f7, char ch, int verbose,
|
||||
u_int32_t start, u_int32_t stop, u_int32_t cyl, u_int32_t trk)
|
||||
uint32_t start, uint32_t stop, uint32_t cyl, uint32_t trk)
|
||||
{
|
||||
if ((cyl * trk) > BIG_DISK_SIZE) {
|
||||
if (ch == '+') {
|
||||
@@ -1317,12 +1319,12 @@ void vtoc_set_freespace(format4_label_t *f4, format5_label_t *f5,
|
||||
f4->DS4EFLVL = 0x07;
|
||||
vtoc_set_cchhb(&f4->DS4EFPTR, 0x0000, 0x0001, 0x03);
|
||||
} else {
|
||||
u_int16_t x,y;
|
||||
u_int8_t z;
|
||||
uint16_t x,y;
|
||||
uint8_t z;
|
||||
|
||||
x = (u_int16_t) start;
|
||||
y = (u_int16_t) ((stop - start + 1) / trk);
|
||||
z = (u_int8_t) ((stop - start + 1) % trk);
|
||||
x = (uint16_t) start;
|
||||
y = (uint16_t) ((stop - start + 1) / trk);
|
||||
z = (uint8_t) ((stop - start + 1) % trk);
|
||||
|
||||
if (ch == '+') {
|
||||
vtoc_update_format5_label_add(f5, verbose, trk,
|
||||
|
||||
@@ -89,7 +89,7 @@ Socket communication with applications utilizing CMS AF_IUCV support
|
||||
An AF_IUCV socket is represented by the following format:
|
||||
.PP
|
||||
.RS 8
|
||||
.ft CW
|
||||
.ft CR
|
||||
.nf
|
||||
#define AF_IUCV 32
|
||||
|
||||
@@ -290,7 +290,7 @@ It must not match any z/VM user ID in your environment.
|
||||
To set an identifier, issue a command like this:
|
||||
.PP
|
||||
.RS 8
|
||||
.ft CW
|
||||
.ft CR
|
||||
echo \fIidentifier\fP > /sys/devices/qeth/\fI<bus-ID>\fP/hsuid
|
||||
.ft
|
||||
.RE
|
||||
@@ -303,7 +303,7 @@ For example, to use "MYHOST01" to bind AF_IUCV sockets to the
|
||||
HiperSockets device with bus-ID 0.0.8000, run:
|
||||
.PP
|
||||
.RS 8
|
||||
.ft CW
|
||||
.ft CR
|
||||
.nf
|
||||
echo "MYHOST01" > /sys/devices/qeth/0.0.8000/hsuid
|
||||
.fi
|
||||
@@ -366,7 +366,7 @@ z/VM guest virtual machine with a maximum of 10\^000 outstanding messages for ea
|
||||
incoming connection. Your z/VM guest virtual machine is permitted to connect to
|
||||
all other z/VM guest virtual machines. The total number of connections for your
|
||||
z/VM guest virtual machine cannot exceed 100.
|
||||
.ft CW
|
||||
.ft CR
|
||||
.in +0.25i
|
||||
.nf
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
# Offsets
|
||||
OFFS_INITRD_START_BYTES=66568
|
||||
OFFS_INITRD_SIZE_BYTES=66576
|
||||
OFFS_COMMANDLINE_MAX_SIZE_BYTES=66608
|
||||
OFFS_COMMANDLINE_BYTES=66688
|
||||
MAX_PARMFILE_SIZE=896
|
||||
LEGACY_MAX_PARMFILE_SIZE=896
|
||||
|
||||
# Variables
|
||||
cmd=$(basename $0)
|
||||
cmd=$(basename -- "$0")
|
||||
kernel=
|
||||
ramdisk=
|
||||
parmfile=
|
||||
@@ -34,15 +35,14 @@ binval=
|
||||
success=no
|
||||
|
||||
# Cleanup on exit
|
||||
# shellcheck disable=SC2317
|
||||
cleanup()
|
||||
{
|
||||
if [ -n "$binval" ]
|
||||
then
|
||||
rm -f $binval
|
||||
if [ -n "$binval" ]; then
|
||||
rm -f -- "$binval"
|
||||
fi
|
||||
if [ -n "$image" -a $success = no ]
|
||||
then
|
||||
rm $image
|
||||
if [ -n "$image" ] && [ "$success" = no ]; then
|
||||
rm -f -- "$image"
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
@@ -50,25 +50,25 @@ trap cleanup EXIT
|
||||
# Usage
|
||||
usage()
|
||||
{
|
||||
cat <<-EOF
|
||||
Usage: $cmd KERNEL BOOT_IMAGE [-r RAMDISK] [-p PARMFILE]
|
||||
cat <<- EOF
|
||||
Usage: $cmd KERNEL BOOT_IMAGE [-r RAMDISK] [-p PARMFILE]
|
||||
|
||||
Build an s390 image BOOT_IMAGE suitable for CD/tape/network boot or as a
|
||||
KVM firmware image using a stripped Linux kernel file KERNEL.
|
||||
Build an s390 image BOOT_IMAGE suitable for CD/tape/network boot or as a
|
||||
KVM firmware image using a stripped Linux kernel file KERNEL.
|
||||
|
||||
OPTIONS
|
||||
-p Use PARMFILE with kernel parameters in the image
|
||||
-r Include RAMDISK in the image
|
||||
-h Print this help, then exit
|
||||
-v Print version information, then exit
|
||||
EOF
|
||||
OPTIONS
|
||||
-p Use PARMFILE with kernel parameters in the image
|
||||
-r Include RAMDISK in the image
|
||||
-h Print this help, then exit
|
||||
-v Print version information, then exit
|
||||
EOF
|
||||
}
|
||||
|
||||
printversion()
|
||||
{
|
||||
cat <<-EOD
|
||||
$cmd: version %S390_TOOLS_VERSION%
|
||||
Copyright IBM Corp. 2017
|
||||
cat <<- EOD
|
||||
$cmd: version %S390_TOOLS_VERSION%
|
||||
Copyright IBM Corp. 2017
|
||||
EOD
|
||||
}
|
||||
|
||||
@@ -78,12 +78,30 @@ dec2be64()
|
||||
local num=$1
|
||||
local b
|
||||
local i
|
||||
for i in $(seq 1 8)
|
||||
do
|
||||
b="\\x$(printf '%x' $(expr $num % 256))$b"
|
||||
num=$(expr $num / 256) || true
|
||||
for i in $(seq 1 8); do
|
||||
b="\\x$(printf '%x' "$((num % 256))")$b"
|
||||
num=$((num / 256)) || true
|
||||
done
|
||||
printf $b
|
||||
printf '%b' "$b"
|
||||
}
|
||||
|
||||
max_kernel_cmdline_size()
|
||||
{
|
||||
local __kernel=$1 size v
|
||||
|
||||
size_be="$(od -A n -j "${OFFS_COMMANDLINE_MAX_SIZE_BYTES}" -N 8 -t uL -- "$__kernel")"
|
||||
# If little endian then swap bytes
|
||||
if (("$(printf '\1' | od -dAn)" == 1)); then
|
||||
v="$(printf '%016x0' "$size_be")"
|
||||
size="0x${v:14:2}${v:12:2}${v:10:2}${v:8:2}${v:6:2}${v:4:2}${v:2:2}${v:0:2}"
|
||||
else
|
||||
size="$size_be"
|
||||
fi
|
||||
if ((size == 0)); then
|
||||
size="${LEGACY_MAX_PARMFILE_SIZE}"
|
||||
fi
|
||||
# Use arithmetic expression to remove leading and trailing whitespace.
|
||||
printf '%s' "$((size))"
|
||||
}
|
||||
|
||||
# Do the image build
|
||||
@@ -95,16 +113,17 @@ dobuild()
|
||||
local ramdisk_offset
|
||||
local parmfile_size
|
||||
# check whether all specified files exist
|
||||
for i in $kernel $ramdisk $parmfile
|
||||
do
|
||||
if [ ! -f $i ]
|
||||
then
|
||||
echo "$cmd: File $i not found" >&2
|
||||
return 1
|
||||
fi
|
||||
for i in $kernel $ramdisk $parmfile; do
|
||||
if [ ! -f "$i" ]; then
|
||||
echo "$cmd: File $i not found" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ ! -r "$i" ]; then
|
||||
echo "$cmd: File $i cannot be read, no read permission" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
if ! file -b $(readlink -f $kernel) | grep "Linux S390" > /dev/null
|
||||
then
|
||||
if ! file -b -- "$(readlink -f -- "$kernel")" | grep "Linux S390" > /dev/null; then
|
||||
echo "$cmd: Unrecognized file format for $kernel" >&2
|
||||
return 1
|
||||
fi
|
||||
@@ -114,37 +133,36 @@ dobuild()
|
||||
set -e
|
||||
|
||||
# copy over kernel padded with zeroes to page boundary
|
||||
dd if=$kernel of=$image bs=4096 conv=sync status=none
|
||||
dd if="$kernel" of="$image" bs=4096 conv=sync status=none
|
||||
|
||||
# append ramdisk if specified
|
||||
if [ "$ramdisk" != "" ]
|
||||
then
|
||||
ramdisk_size=$(du -b -L $ramdisk | cut -f1)
|
||||
kernel_size=$(du -b -L $kernel | cut -f1)
|
||||
ramdisk_offset=$(du -b -L $image | cut -f1)
|
||||
cat $ramdisk >> $image
|
||||
if [ "$ramdisk" != "" ]; then
|
||||
ramdisk_size=$(du -b -L -- "$ramdisk" | cut -f1)
|
||||
# shellcheck disable=SC2034
|
||||
kernel_size=$(du -b -L -- "$kernel" | cut -f1)
|
||||
ramdisk_offset=$(du -b -L -- "$image" | cut -f1)
|
||||
cat -- "$ramdisk" >> "$image"
|
||||
binval=$(mktemp)
|
||||
dec2be64 $ramdisk_offset > $binval
|
||||
dd seek=$OFFS_INITRD_START_BYTES if=$binval of=$image bs=1 \
|
||||
dec2be64 "$ramdisk_offset" > "$binval"
|
||||
dd seek=$OFFS_INITRD_START_BYTES if="$binval" of="$image" bs=1 \
|
||||
count=8 conv=notrunc status=none
|
||||
dec2be64 $ramdisk_size > $binval
|
||||
dd seek=$OFFS_INITRD_SIZE_BYTES if=$binval of=$image bs=1 \
|
||||
dec2be64 "$ramdisk_size" > "$binval"
|
||||
dd seek=$OFFS_INITRD_SIZE_BYTES if="$binval" of="$image" bs=1 \
|
||||
count=8 conv=notrunc status=none
|
||||
fi
|
||||
|
||||
# set cmdline
|
||||
if [ "$parmfile" != "" ]
|
||||
then
|
||||
parmfile_size=$(du -b -L $parmfile | cut -f1)
|
||||
if [ $parmfile_size -le $MAX_PARMFILE_SIZE ]
|
||||
then
|
||||
if [ "$parmfile" != "" ]; then
|
||||
max_parmfile_size=$(max_kernel_cmdline_size "$kernel")
|
||||
parmfile_size=$(du -b -L -- "$parmfile" | cut -f1)
|
||||
if ((parmfile_size <= max_parmfile_size)); then
|
||||
# Clear any previous parameters
|
||||
dd seek=$OFFS_COMMANDLINE_BYTES bs=1 count=$MAX_PARMFILE_SIZE \
|
||||
if=/dev/zero of=$image conv=notrunc status=none
|
||||
dd seek=$OFFS_COMMANDLINE_BYTES bs=1 if=$parmfile \
|
||||
of=$image conv=notrunc status=none
|
||||
dd seek=$OFFS_COMMANDLINE_BYTES bs=1 count="$max_parmfile_size" \
|
||||
if=/dev/zero of="$image" conv=notrunc status=none
|
||||
dd seek=$OFFS_COMMANDLINE_BYTES bs=1 count="$parmfile_size" \
|
||||
if="$parmfile" of="$image" conv=notrunc status=none
|
||||
else
|
||||
echo "$cmd: Size $parmfile_size of $parmfile exceeds command line limit of $MAX_PARMFILE_SIZE" >&2
|
||||
echo "$cmd: Size $parmfile_size of $parmfile exceeds command line limit of $max_parmfile_size bytes" >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
@@ -154,25 +172,41 @@ dobuild()
|
||||
}
|
||||
|
||||
# check args and build
|
||||
args=$(getopt "r:p:hv" $*)
|
||||
if [ $? = 0 ]
|
||||
then
|
||||
# shellcheck disable=SC2086,SC2048
|
||||
if args=$(getopt "r:p:hv" $*); then
|
||||
# shellcheck disable=SC2086
|
||||
set -- $args
|
||||
while [ $1 != "" ]
|
||||
do
|
||||
while [ "$1" != "" ]; do
|
||||
case $1 in
|
||||
-r) ramdisk=$2; shift 2;;
|
||||
-p) parmfile=$2; shift 2;;
|
||||
-h) usage; exit 0;;
|
||||
-v) printversion; exit 0;;
|
||||
--) shift; break;;
|
||||
*) echo "$cmd: Unexpected argument $1, exiting..." >&2; exit 1;;
|
||||
-r)
|
||||
ramdisk=$2
|
||||
shift 2
|
||||
;;
|
||||
-p)
|
||||
parmfile=$2
|
||||
shift 2
|
||||
;;
|
||||
-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-v)
|
||||
printversion
|
||||
exit 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "$cmd: Unexpected argument $1, exiting..." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if [ $# = 2 ]
|
||||
then
|
||||
if [ $# = 2 ]; then
|
||||
kernel=$1
|
||||
image=$2
|
||||
dobuild
|
||||
|
||||
@@ -42,17 +42,17 @@ install:
|
||||
else
|
||||
|
||||
ifneq ($(shell sh -c 'command -v pkg-config'),)
|
||||
LIB_CFLAGS += $(shell pkg-config --silence-errors --cflags libnl-3.0)
|
||||
LIB_CFLAGS += $(shell pkg-config --silence-errors --cflags libnl-genl-3.0)
|
||||
LIB_CFLAGS += $(shell pkg-config --silence-errors --cflags libnl-route-3.0)
|
||||
LIB_CFLAGS += $(shell $(PKG_CONFIG) --silence-errors --cflags libnl-3.0)
|
||||
LIB_CFLAGS += $(shell $(PKG_CONFIG) --silence-errors --cflags libnl-genl-3.0)
|
||||
LIB_CFLAGS += $(shell $(PKG_CONFIG) --silence-errors --cflags libnl-route-3.0)
|
||||
|
||||
LIB_CFLAGS += $(shell pkg-config --silence-errors --cflags libcrypto)
|
||||
LIB_CFLAGS += $(shell $(PKG_CONFIG) --silence-errors --cflags libcrypto)
|
||||
|
||||
LIB_LFLAGS += $(shell pkg-config --silence-errors --libs libnl-3.0)
|
||||
LIB_LFLAGS += $(shell pkg-config --silence-errors --libs libnl-genl-3.0)
|
||||
LIB_LFLAGS += $(shell pkg-config --silence-errors --libs libnl-route-3.0)
|
||||
LIB_LFLAGS += $(shell $(PKG_CONFIG) --silence-errors --libs libnl-3.0)
|
||||
LIB_LFLAGS += $(shell $(PKG_CONFIG) --silence-errors --libs libnl-genl-3.0)
|
||||
LIB_LFLAGS += $(shell $(PKG_CONFIG) --silence-errors --libs libnl-route-3.0)
|
||||
|
||||
LIB_LFLAGS += $(shell pkg-config --silence-errors --libs libcrypto)
|
||||
LIB_LFLAGS += $(shell $(PKG_CONFIG) --silence-errors --libs libcrypto)
|
||||
else
|
||||
LIB_CFLAGS += -I /usr/include/libnl3/
|
||||
LIB_LFLAGS += -lnl-route-3 -lnl-genl-3 -lnl-3
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user