Accepting request 555780 from home:markkp:branches:hardware
- Added qclib-sles15-fix-mismatch-case-with-STHYI.patch (bsc#1071687). OBS-URL: https://build.opensuse.org/request/show/555780 OBS-URL: https://build.opensuse.org/package/show/hardware/qclib?expand=0&rev=13
This commit is contained in:
parent
01805ebb47
commit
9987af121b
147
qclib-sles15-fix-mismatch-case-with-STHYI.patch
Normal file
147
qclib-sles15-fix-mismatch-case-with-STHYI.patch
Normal file
@ -0,0 +1,147 @@
|
||||
commit 13d7aafb0cb8946880abbb73725b0340bec1cd3a
|
||||
Author: Stefan Raspl <stefan.raspl@de.ibm.com>
|
||||
Date: Fri Dec 8 22:11:29 2017 +0100
|
||||
|
||||
STHYI: Fix mismatch case with STHYI and /proc/sysinfo data
|
||||
|
||||
Reported via Bz162324. Symptom was that qclib wouldn't work on a z/VM 5.4.
|
||||
Analysis revealed that although the STHYI instruction wasn't available, the
|
||||
newly added STHYI syscall would work, but (as intended) reported only layers
|
||||
up to LPAR. In contrast, /proc/sysinfo would report all layers, including the
|
||||
z/VM layer. Some detection logic kicked in and reported an error.
|
||||
The problem was rooted in a bizarr combination of multiple glitches:
|
||||
* An (unnecessary) extra handling for z/VM that was previously added would
|
||||
raise an error on mismatching layer counts in STHYI and /proc/sysinfo. This
|
||||
was to detect cases with more than 3 levels of nested virtualization. But the
|
||||
check just was for mismatching counts and didn't check for the 3 layers
|
||||
reported by STHYI at all.
|
||||
* Furthermore, the check mentioned above was unnecessary to begin with: When
|
||||
STHYI reports data for 3 VM layers, and /proc/sysinfo for more, then the
|
||||
extra layers will simply not get any data from STHYI - no harm done.
|
||||
* STHYI in KVM worked like a charm ever since, though it is supposed to fail
|
||||
with the same error as z/VM since STHYI in KVM (and likewise the syscall in
|
||||
LPARs) cannot report data beyond the LPAR layer - it should result in the
|
||||
same mismatch that z/VM experienced. However, the respective routines would
|
||||
only ever consider VM layers in z/VM and ignore the ones in KVM! Hence all
|
||||
layers beyond LPAR wouldn't be accounted for on KVM!
|
||||
To fix, we're ripping out the extra check, and rewrite the remaining code to
|
||||
handle z/VM and KVM alike.
|
||||
Furthermore, we rename "STHYI@VM" to "STHYI instruction", and "STHYI@LPAR" to
|
||||
"STHYI syscall" for improved clarity.
|
||||
|
||||
diff --git a/query_capacity_sthyi.c b/query_capacity_sthyi.c
|
||||
index b3bd9e8..688062f 100644
|
||||
--- a/query_capacity_sthyi.c
|
||||
+++ b/query_capacity_sthyi.c
|
||||
@@ -91,16 +91,16 @@ static int qc_sthyi_lpar(struct qc_handle *hdl, struct sthyi_priv *priv) {
|
||||
#ifdef __NR_s390_sthyi
|
||||
sthyi = __NR_s390_sthyi
|
||||
#endif
|
||||
- qc_debug(hdl, "Try STHYI@LPAR\n");
|
||||
+ qc_debug(hdl, "Try STHYI syscall\n");
|
||||
if (syscall(sthyi, 0, priv->data, &cc, 0) || cc) {
|
||||
if (errno == ENOSYS) {
|
||||
- qc_debug(hdl, "STHYI@LPAR is not available\n");
|
||||
+ qc_debug(hdl, "STHYI syscall is not available\n");
|
||||
return 0;
|
||||
}
|
||||
- qc_debug(hdl, "Error: STHYI@LPAR execution failed: errno='%s', cc=%" PRIu64 "\n", strerror(errno), cc);
|
||||
+ qc_debug(hdl, "Error: STHYI syscall execution failed: errno='%s', cc=%" PRIu64 "\n", strerror(errno), cc);
|
||||
return -1;
|
||||
}
|
||||
- qc_debug(hdl, "STHYI@LPAR succeeded\n");
|
||||
+ qc_debug(hdl, "STHYI syscall succeeded\n");
|
||||
priv->avail = STHYI_AVAILABLE;
|
||||
#endif
|
||||
|
||||
@@ -281,25 +281,15 @@ static int qc_parse_sthyi_guest(struct qc_handle *gst, struct inf0gst *guest) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int qc_get_num_vm_layers(struct qc_handle *hdl, int *rc) {
|
||||
- int i;
|
||||
-
|
||||
- for (hdl = hdl->root, i = 0; hdl != NULL; hdl = hdl->next) {
|
||||
- if (*(int *)(hdl->layer) == QC_LAYER_TYPE_ZVM_HYPERVISOR)
|
||||
- i++;
|
||||
- }
|
||||
-
|
||||
- return i;
|
||||
-}
|
||||
-
|
||||
/* Returns pointer to the n-th hypervisor handle. num starts at 0, and handles
|
||||
are returned in sequence from handle linked list */
|
||||
static struct qc_handle *qc_get_HV_layer(struct qc_handle *hdl, int num) {
|
||||
struct qc_handle *h = hdl;
|
||||
- int i;
|
||||
+ int i, type;
|
||||
|
||||
for (hdl = hdl->root, i = 0, num++; hdl != NULL; hdl = hdl->next) {
|
||||
- if (*(int *)(hdl->layer) == QC_LAYER_TYPE_ZVM_HYPERVISOR && ++i == num)
|
||||
+ type = *(int *)(hdl->layer);
|
||||
+ if ((type == QC_LAYER_TYPE_ZVM_HYPERVISOR || type == QC_LAYER_TYPE_KVM_HYPERVISOR) && ++i == num)
|
||||
return hdl;
|
||||
}
|
||||
qc_debug(h, "Error: Couldn't find HV layer %d, only %d layer(s) found\n", num, i);
|
||||
@@ -309,7 +299,7 @@ static struct qc_handle *qc_get_HV_layer(struct qc_handle *hdl, int num) {
|
||||
|
||||
static int qc_sthyi_process(struct qc_handle *hdl, char *buf) {
|
||||
struct sthyi_priv *priv = (struct sthyi_priv *)buf;
|
||||
- int no_hyp_gst, num_vm_layers, i, rc = 0;
|
||||
+ int no_hyp_gst, i, rc = 0;
|
||||
struct inf0gst *guest[INF0YGMX];
|
||||
struct inf0hyp *hv[INF0YGMX];
|
||||
struct inf0par *partition;
|
||||
@@ -371,30 +361,14 @@ static int qc_sthyi_process(struct qc_handle *hdl, char *buf) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
- num_vm_layers = qc_get_num_vm_layers(hdl, &rc);
|
||||
- if (rc != 0) {
|
||||
- rc = -2;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- if (num_vm_layers != no_hyp_gst) {
|
||||
- /* STHYI doesn't support more than 3rd level z/VM */
|
||||
- qc_debug(hdl, "Error: /proc/sysinfo reported %d layers, but STHYI only "
|
||||
- "covers %d\n", num_vm_layers, no_hyp_gst);
|
||||
- rc = -6;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
for (i = 0; i < no_hyp_gst; i++) {
|
||||
if ((hdl = qc_get_HV_layer(hdl, i)) == NULL) {
|
||||
rc = -7;
|
||||
goto out;
|
||||
}
|
||||
- if (*(int *)(hdl->layer) == QC_LAYER_TYPE_ZVM_HYPERVISOR) {
|
||||
- if (qc_parse_sthyi_hypervisor(hdl, hv[i]) || qc_parse_sthyi_guest(hdl->next, guest[i])) {
|
||||
- rc = -9;
|
||||
- goto out;
|
||||
- }
|
||||
+ if (qc_parse_sthyi_hypervisor(hdl, hv[i]) || qc_parse_sthyi_guest(hdl->next, guest[i])) {
|
||||
+ rc = -9;
|
||||
+ goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
@@ -508,15 +482,15 @@ static int qc_sthyi_open(struct qc_handle *hdl, char **buf) {
|
||||
/* There is no way for us to check programmatically whether
|
||||
we're in an LPAR or in a VM, so we simply try out both */
|
||||
if (qc_is_sthyi_available_vm(hdl)) {
|
||||
- qc_debug(hdl, "Executing STHYI@VM\n");
|
||||
+ qc_debug(hdl, "Executing STHYI instruction\n");
|
||||
/* we assume we are not relocated at this spot, between STFLE and STHYI */
|
||||
if (qc_sthyi_vm(priv)) {
|
||||
- qc_debug(hdl, "Error: STHYI@VM execution failed\n");
|
||||
+ qc_debug(hdl, "Error: STHYI instruction execution failed\n");
|
||||
rc = -3;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
- qc_debug(hdl, "STHYI@VM is not available\n");
|
||||
+ qc_debug(hdl, "STHYI instruction is not available\n");
|
||||
rc = qc_sthyi_lpar(hdl, priv);
|
||||
}
|
||||
}
|
@ -1,3 +1,8 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Dec 8 22:07:04 UTC 2017 - mpost@suse.com
|
||||
|
||||
- Added qclib-sles15-fix-mismatch-case-with-STHYI.patch (bsc#1071687).
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Nov 2 20:03:27 UTC 2017 - mpost@suse.com
|
||||
|
||||
|
@ -26,6 +26,7 @@ Url: http://www.ibm.com/developerworks/linux/linux390/qclib.html
|
||||
Source: %{name}-%{version}.tgz
|
||||
Source1: %{name}-rpmlintrc
|
||||
Patch1: qclib.makefile.libdir.patch
|
||||
Patch2: qclib-sles15-fix-mismatch-case-with-STHYI.patch
|
||||
BuildRequires: doxygen
|
||||
BuildRequires: gcc-c++
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
@ -96,6 +97,7 @@ Systems.
|
||||
%prep
|
||||
%setup -q
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
|
||||
%build
|
||||
MYCFLAGS=$(grep ^CFLAGS Makefile | cut -f2 -d=)
|
||||
|
Loading…
Reference in New Issue
Block a user