Merge ~fheimes/ubuntu/+source/s390-tools:s390-tools-sru-lp1903984-focal into ubuntu/+source/s390-tools:ubuntu/focal-devel
- Git
- lp:~fheimes/ubuntu/+source/s390-tools
- s390-tools-sru-lp1903984-focal
- Merge into ubuntu/focal-devel
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merge reported by: | Frank Heimes | ||||||||||||
Merged at revision: | 2e2fee8f9b265c8eeb192b9085dd28eb0a43956f | ||||||||||||
Proposed branch: | ~fheimes/ubuntu/+source/s390-tools:s390-tools-sru-lp1903984-focal | ||||||||||||
Merge into: | ubuntu/+source/s390-tools:ubuntu/focal-devel | ||||||||||||
Diff against target: |
1194 lines (+1160/-0) 5 files modified
debian/changelog (+17/-0) debian/patches/s390-tools-sru-lp1902179-focal.patch (+689/-0) debian/patches/s390-tools-sru-lp1903984-focal.patch (+49/-0) debian/patches/s390-tools-sru-lp1908371-focal.patch (+402/-0) debian/patches/series (+3/-0) |
||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lukas Märdian (community) | Approve | ||
Review via email: mp+396775@code.launchpad.net |
Commit message
Description of the change
debian/
zcryptstats: Fix handling of partial results with many domains
- zconf/zcrypt/
to the subsequent CHSC call of a partial response
debian/
zipl command isn't working correctly in combination with the -M
(respectively --mvdump) option.
debian/
zcryptstats: Fix handling of partial results with many domains
Test build is available here:
https:/
Frank Heimes (fheimes) wrote : | # |
The issue with the i Makefile (pl_tools/Makefile) especially the duplicate line "libs = $(rootdir)
It's not in H/devel, nor in G, but was introduced with 795d2c9 (which is Head -19).
Frank Heimes (fheimes) wrote : | # |
Regarding the "enum target_type target_type;" line,
this line was indeed in the past commented like this:
enum target_type target_type; /* CCW, FCP, NSS or NODE */
and with the expansion of the target types by target_type NVMe, the comment was changed to:
enum target_type target_type; /* CCW,FCP,NVME,NSS or NODE */
and this is also upstream the case - and indeed unusual, because other comments follow the form:
/* CCW, FCP, NVME, NSS */
(means <comma><space>)
I assume that the NVME support was added by a different IBM developer, hence the different style.
Since I simply picked the upstream commit and applied it (w/o any adjustments), this little difference in style was transferred, too.
Lukas Märdian (slyon) wrote : | # |
Okay, so as discussed on a side-channel, we're refreshing the path "debian/
See this MP for reference: https:/
Build of the package with refreshed patch confirmed: https:/
Preview Diff
1 | diff --git a/debian/changelog b/debian/changelog |
2 | index 33febaf..402dbc6 100644 |
3 | --- a/debian/changelog |
4 | +++ b/debian/changelog |
5 | @@ -1,3 +1,20 @@ |
6 | +s390-tools (2.12.0-0ubuntu3.2) focal; urgency=medium |
7 | + |
8 | + * debian/patches/s390-tools-sru-lp1903984-focal.patch |
9 | + zcryptstats: Fix handling of partial results with many domains |
10 | + Thanks to Ingo Franzki (LP: #1903984) |
11 | + * debian/patches/s390-tools-sru-lp1908371-focal.patch: |
12 | + zipl command isn't working correctly in combination with the -M |
13 | + (respectively --mvdump) option. |
14 | + cherry-picking 4 commits from s390-tools v2.15.1 to v2.14 |
15 | + Thanks to Stefan Haberland and Sven Schnelle (LP: #1908371) |
16 | + * debian/patches/s390-tools-sru-lp1902179-focal.patch: |
17 | + Enabling IPL (boot) from NVMe devices by adding 2 upstream commits |
18 | + from s390-tools v2.13/2.14 as backports to this v2.12 base. |
19 | + Thanks to Jason J. Herne (LP: #1902179) |
20 | + |
21 | + -- Frank Heimes <frank.heimes@canonical.com> Fri, 22 Jan 2021 15:52:19 +0100 |
22 | + |
23 | s390-tools (2.12.0-0ubuntu3.1) focal; urgency=medium |
24 | |
25 | * debian/patches/0082-*.patch .. 0111-*.patch (LP: #1892350) |
26 | diff --git a/debian/patches/s390-tools-sru-lp1902179-focal.patch b/debian/patches/s390-tools-sru-lp1902179-focal.patch |
27 | new file mode 100644 |
28 | index 0000000..91c2dcf |
29 | --- /dev/null |
30 | +++ b/debian/patches/s390-tools-sru-lp1902179-focal.patch |
31 | @@ -0,0 +1,689 @@ |
32 | +Description: Enabling IPL (boot) from NVMe devices in focal |
33 | + These three patches are needed to enable IPL (boot on s390x) from NVMe devices |
34 | + They are already upstream and in the groovy and hirsute versions of the s390-tools. |
35 | + A cherry pick wasn't cleanly possible, hence these backports that are based on: |
36 | + 1b65b23b4398 "zipl: Support nvme devices" (went in v2.13.0) |
37 | + 0472b5ea5c97 "ipl-tools: Add nvme device support to lsreipl/chreipl" (went in v2.14.0) |
38 | +Author: Jason J. Herne <jjherne@linux.ibm.com> |
39 | +Origin: backports of: |
40 | + https://github.com/ibm-s390-tools/s390-tools/commit/1b65b23b43985cb8a1da2ef399ec6def31bbcc69 |
41 | + https://github.com/ibm-s390-tools/s390-tools/commit/0472b5ea5c97f2c59a938deebe53b7f27e8a9a32 |
42 | +Bug: IBM Bugzilla 188732 |
43 | +Bug-IBM: https://bugs.launchpad.net/bugs/1902179 |
44 | +Forwarded: not-needed |
45 | +Applied-Upstream: >= 2.14.0 |
46 | +Reviewed-by: Frank Heimes <frank.heimes@canonical.com> |
47 | +Last-Update: 2021-01-22 |
48 | +--- |
49 | +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ |
50 | +--- a/ipl_tools/cmd_chreipl.c |
51 | ++++ b/ipl_tools/cmd_chreipl.c |
52 | +@@ -28,12 +28,14 @@ |
53 | + TT_FCP, |
54 | + TT_NSS, |
55 | + TT_NODE, |
56 | ++ TT_NVME, |
57 | + }; |
58 | + |
59 | + enum reipl_type { |
60 | + REIPL_FCP, |
61 | + REIPL_CCW, |
62 | +- REIPL_NSS |
63 | ++ REIPL_NSS, |
64 | ++ REIPL_NVME, |
65 | + }; |
66 | + |
67 | + static const char *const usage_chreipl = |
68 | +@@ -41,6 +43,7 @@ |
69 | + "\n" |
70 | + " chreipl [ccw] [-d] <DEVICE> [OPTIONS]\n" |
71 | + " chreipl [fcp] [-d] <DEVICE> [-w] <WWPN> [-l] <LUN> [OPTIONS]\n" |
72 | ++" chreipl nvme [-i] <FID> [-s] <NSID> [OPTIONS]\n" |
73 | + " chreipl [node] <NODE|DIR> [OPTIONS]\n" |
74 | + " chreipl nss [-n] <NAME> [OPTIONS]\n" |
75 | + " chreipl [-h] [-v]\n" |
76 | +@@ -48,6 +51,7 @@ |
77 | + "The following re-IPL targets are supported:\n" |
78 | + " ccw IPL from CCW device\n" |
79 | + " fcp IPL from FCP device\n" |
80 | ++" nvme IPL from NVME device\n" |
81 | + " nss IPL from NSS\n" |
82 | + " node IPL from device specified by device node or directory\n" |
83 | + "\n" |
84 | +@@ -68,6 +72,12 @@ |
85 | + " -b, --bootprog <BPROG> Bootprog specification\n" |
86 | + " -L, --loadparm <PARM> Loadparm specification\n" |
87 | + "\n" |
88 | ++"Options for nvme target:\n" |
89 | ++" -i, --fid <FUNCTION_ID> PCI Function ID of NVME IPL device (hex)\n" |
90 | ++" -s --nsid <NAMESPACE_ID> Namespace ID of NVME IPL device (decimal, default 1)\n" |
91 | ++" -b, --bootprog <BPROG> Bootprog specification\n" |
92 | ++" -L, --loadparm <PARM> Loadparm specification\n" |
93 | ++"\n" |
94 | + "Options for nss target:\n" |
95 | + " -n, --name <NAME> Identifier of the NSS\n" |
96 | + "\n" |
97 | +@@ -84,6 +94,10 @@ |
98 | + char lun[20]; /* 18 character +0x" */ |
99 | + int lun_set; |
100 | + char busid[10]; /* Bus ID e.g. 0.0.4711 */ |
101 | ++ int fid_set; |
102 | ++ char fid[FID_MAX_LEN]; |
103 | ++ int nsid_set; |
104 | ++ char nsid[11]; /* 10 decimal chars + null */ |
105 | + int busid_set; |
106 | + char dev[15]; /* Device (e.g. dasda) */ |
107 | + int dev_set; |
108 | +@@ -92,10 +106,10 @@ |
109 | + char bootparms[4096]; |
110 | + int bootparms_set; |
111 | + int force_set; |
112 | +- enum target_type target_type; /* CCW, FCP, NSS or NODE */ |
113 | ++ enum target_type target_type; /* CCW, FCP, NVME, NSS or NODE */ |
114 | + int target_type_set; |
115 | + int target_type_auto_mode; |
116 | +- enum reipl_type reipl_type; /* CCW, FCP, NSS */ |
117 | ++ enum reipl_type reipl_type; /* CCW, FCP, NVME, NSS */ |
118 | + } l; |
119 | + |
120 | + static void __noreturn print_usage_chreipl_exit(void) |
121 | +@@ -226,6 +240,34 @@ |
122 | + l.wwpn_set = 1; |
123 | + } |
124 | + |
125 | ++static void set_nvme_nsid(const char *nsid) |
126 | ++{ |
127 | ++ unsigned long long nsid_tmp; |
128 | ++ char *endptr; |
129 | ++ |
130 | ++ nsid_tmp = strtoull(nsid, &endptr, 10); |
131 | ++ if (*endptr) |
132 | ++ ERR_EXIT("NSID \"%s\" is not a decimal number", nsid); |
133 | ++ snprintf(l.nsid, sizeof(l.nsid), "%08llu", nsid_tmp); |
134 | ++ l.nsid_set = 1; |
135 | ++} |
136 | ++ |
137 | ++static void set_nvme_fid(const char *fid) |
138 | ++{ |
139 | ++ unsigned long long fid_tmp; |
140 | ++ char *endptr; |
141 | ++ |
142 | ++ fid_tmp = strtoull(fid, &endptr, 16); |
143 | ++ if (*endptr) |
144 | ++ ERR_EXIT("FID \"%s\" is not a hexadecimal number", fid); |
145 | ++ snprintf(l.fid, sizeof(l.fid), "0x%08llx", fid_tmp); |
146 | ++ l.fid_set = 1; |
147 | ++ |
148 | ++ /* nsid defaults to 1, if not already set */ |
149 | ++ if (!l.nsid_set) |
150 | ++ set_nvme_nsid("1"); |
151 | ++} |
152 | ++ |
153 | + static void parse_fcp_args(char *nargv[], int nargc) |
154 | + { |
155 | + /* |
156 | +@@ -245,6 +287,28 @@ |
157 | + set_lun(nargv[2]); |
158 | + } |
159 | + |
160 | ++static void parse_nvme_args(char *nargv[], int nargc) |
161 | ++{ |
162 | ++ /* |
163 | ++ * we might be called like this: |
164 | ++ * chreipl nvme 0x13 1 |
165 | ++ */ |
166 | ++ if (l.busid_set || l.fid_set || l.nsid_set || l.dev_set) |
167 | ++ ERR_EXIT("Use either options or positional parameters"); |
168 | ++ if (nargc > 2) |
169 | ++ ERR_EXIT("Too many arguments specified for \"nvme\" re-IPL " |
170 | ++ "type"); |
171 | ++ else if (nargc < 1) |
172 | ++ ERR_EXIT("The \"nvme\" re-IPL type requires function id, and " |
173 | ++ "optional namespace id"); |
174 | ++ set_nvme_fid(nargv[0]); |
175 | ++ |
176 | ++ if (nargc == 2) |
177 | ++ set_nvme_nsid(nargv[1]); |
178 | ++ else |
179 | ++ set_nvme_nsid("1"); |
180 | ++} |
181 | ++ |
182 | + static void parse_ccw_args(char *nargv[], int nargc) |
183 | + { |
184 | + /* |
185 | +@@ -285,6 +349,13 @@ |
186 | + dev_name[i] = 0; |
187 | + } |
188 | + |
189 | ++static void dev_from_part_nvme(char *dev_name) |
190 | ++{ |
191 | ++ char *delim = strrchr(dev_name, 'p'); |
192 | ++ if (delim) |
193 | ++ *delim = 0; |
194 | ++} |
195 | ++ |
196 | + static int set_reipl_type(const char *dev_name) |
197 | + { |
198 | + if (strncmp(dev_name, "dasd", strlen("dasd")) == 0 || |
199 | +@@ -292,11 +363,18 @@ |
200 | + l.reipl_type = REIPL_CCW; |
201 | + else if (strncmp(dev_name, "sd", strlen("sd")) == 0) |
202 | + l.reipl_type = REIPL_FCP; |
203 | ++ else if (strncmp(dev_name, "nvme", strlen("nvme")) == 0) |
204 | ++ l.reipl_type = REIPL_NVME; |
205 | + else |
206 | + return -1; |
207 | + |
208 | + util_strlcpy(l.dev, dev_name, sizeof(l.dev)); |
209 | +- dev_from_part(l.dev); |
210 | ++ |
211 | ++ if (l.reipl_type == REIPL_NVME) |
212 | ++ dev_from_part_nvme(l.dev); |
213 | ++ else |
214 | ++ dev_from_part(l.dev); |
215 | ++ |
216 | + l.dev_set = 1; |
217 | + return 0; |
218 | + } |
219 | +@@ -399,6 +477,9 @@ |
220 | + case TT_FCP: |
221 | + parse_fcp_args(nargv, nargc); |
222 | + break; |
223 | ++ case TT_NVME: |
224 | ++ parse_nvme_args(nargv, nargc); |
225 | ++ break; |
226 | + case TT_CCW: |
227 | + parse_ccw_args(nargv, nargc); |
228 | + break; |
229 | +@@ -420,6 +501,14 @@ |
230 | + "and LUN"); |
231 | + } |
232 | + |
233 | ++static void check_nvme_opts(void) |
234 | ++{ |
235 | ++ if (l.nss_name_set || l.wwpn_set || l.lun_set || l.busid_set) |
236 | ++ ERR_EXIT("Invalid option for \"nvme\" target specified"); |
237 | ++ if (!(l.fid_set && l.nsid_set)) |
238 | ++ ERR_EXIT("The \"nvme\" target requires FID, and optional NSID"); |
239 | ++} |
240 | ++ |
241 | + static void check_ccw_opts(void) |
242 | + { |
243 | + if (l.bootprog_set || l.lun_set || l.wwpn_set || l.nss_name_set) |
244 | +@@ -469,6 +558,8 @@ |
245 | + { "device", required_argument, NULL, 'd' }, |
246 | + { "lun", required_argument, NULL, 'l' }, |
247 | + { "wwpn", required_argument, NULL, 'w' }, |
248 | ++ { "fid", required_argument, NULL, 'i' }, |
249 | ++ { "nsid", required_argument, NULL, 's' }, |
250 | + { "loadparm", required_argument, NULL, 'L' }, |
251 | + { "name", required_argument, NULL, 'n' }, |
252 | + { "bootparms", required_argument, NULL, 'p' }, |
253 | +@@ -476,7 +567,7 @@ |
254 | + { "version", no_argument, NULL, 'v' }, |
255 | + { NULL, 0, NULL, 0 } |
256 | + }; |
257 | +- static const char optstr[] = "hcd:vw:l:fL:b:n:p:"; |
258 | ++ static const char optstr[] = "hcd:vw:l:fL:b:n:p:i:s:"; |
259 | + |
260 | + /* dont run without any argument */ |
261 | + if (argc == 1) |
262 | +@@ -488,6 +579,8 @@ |
263 | + set_target_type(TT_CCW, 0); |
264 | + else if (strcmp(argv[1], "nss") == 0) |
265 | + set_target_type(TT_NSS, 0); |
266 | ++ else if (strcmp(argv[1], "nvme") == 0) |
267 | ++ set_target_type(TT_NVME, 0); |
268 | + else if (strcmp(argv[1], "node") == 0) |
269 | + set_target_type(TT_NODE, 0); |
270 | + else |
271 | +@@ -500,9 +593,15 @@ |
272 | + case 'd': |
273 | + set_device(optarg); |
274 | + break; |
275 | ++ case 'i': |
276 | ++ set_nvme_fid(optarg); |
277 | ++ break; |
278 | + case 'l': |
279 | + set_lun(optarg); |
280 | + break; |
281 | ++ case 's': |
282 | ++ set_nvme_nsid(optarg); |
283 | ++ break; |
284 | + case 'w': |
285 | + set_wwpn(optarg); |
286 | + break; |
287 | +@@ -650,6 +749,40 @@ |
288 | + print_fcp(0, 0); |
289 | + } |
290 | + |
291 | ++static void chreipl_nvme(void) |
292 | ++{ |
293 | ++ check_nvme_opts(); |
294 | ++ |
295 | ++ if (!nvme_is_device(l.fid, l.nsid) && !l.force_set) { |
296 | ++ ERR_EXIT("Could not find NVME device with fid %s and nsid %s", |
297 | ++ l.fid, l.nsid); |
298 | ++ } |
299 | ++ check_exists("reipl/nvme/fid", "\"nvme\" re-IPL target"); |
300 | ++ |
301 | ++ if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_FCP_MAX) { |
302 | ++ ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)", |
303 | ++ strlen(l.bootparms), BOOTPARMS_FCP_MAX); |
304 | ++ } |
305 | ++ |
306 | ++ write_str_optional(l.loadparm, "reipl/nvme/loadparm", l.loadparm_set, |
307 | ++ "loadparm"); |
308 | ++ write_str_optional(l.bootparms, "reipl/nvme/scp_data", l.bootparms_set, |
309 | ++ "boot parameters"); |
310 | ++ write_str(l.fid, "reipl/nvme/fid"); |
311 | ++ write_str(l.nsid, "reipl/nvme/nsid"); |
312 | ++ /* |
313 | ++ * set the boot record logical block address. Master boot |
314 | ++ * record. It is always 0 for Linux |
315 | ++ */ |
316 | ++ write_str("0", "reipl/nvme/br_lba"); |
317 | ++ if (!l.bootprog_set) |
318 | ++ sprintf(l.bootprog, "0"); |
319 | ++ write_str(l.bootprog, "reipl/nvme/bootprog"); |
320 | ++ write_str("nvme", "reipl/reipl_type"); |
321 | ++ |
322 | ++ print_nvme(0, 0); |
323 | ++} |
324 | ++ |
325 | + static void chreipl_nss(void) |
326 | + { |
327 | + check_nss_opts(); |
328 | +@@ -690,6 +823,13 @@ |
329 | + l.busid_set = 1; |
330 | + chreipl_fcp(); |
331 | + break; |
332 | ++ case REIPL_NVME: |
333 | ++ nvme_fid_get(l.dev, l.fid); |
334 | ++ l.fid_set = 1; |
335 | ++ nvme_nsid_get(l.dev, l.nsid); |
336 | ++ l.nsid_set = 1; |
337 | ++ chreipl_nvme(); |
338 | ++ break; |
339 | + default: |
340 | + ERR_EXIT("Internal error: chreipl_node"); |
341 | + } |
342 | +@@ -705,6 +845,9 @@ |
343 | + case TT_FCP: |
344 | + chreipl_fcp(); |
345 | + break; |
346 | ++ case TT_NVME: |
347 | ++ chreipl_nvme(); |
348 | ++ break; |
349 | + case TT_NSS: |
350 | + chreipl_nss(); |
351 | + break; |
352 | +--- a/ipl_tools/cmd_lsreipl.c |
353 | ++++ b/ipl_tools/cmd_lsreipl.c |
354 | +@@ -81,6 +81,35 @@ |
355 | + print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data"); |
356 | + } |
357 | + |
358 | ++void print_nvme(int show_ipl, int dump) |
359 | ++{ |
360 | ++ char *dir = show_ipl ? "ipl" : "reipl/nvme"; |
361 | ++ char *path_bootparms = show_ipl ? "/sys/firmware/ipl/scp_data" : |
362 | ++ "/sys/firmware/reipl/nvme/scp_data"; |
363 | ++ char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" : |
364 | ++ "/sys/firmware/reipl/nvme/loadparm"; |
365 | ++ char loadparm[9], loadparm_path[PATH_MAX]; |
366 | ++ |
367 | ++ if (dump) |
368 | ++ printf("%-12s nvme_dump\n", get_ipl_banner(show_ipl)); |
369 | ++ else |
370 | ++ printf("%-12s nvme\n", get_ipl_banner(show_ipl)); |
371 | ++ |
372 | ++ print_fw_str("FID: %s\n", dir, "fid"); |
373 | ++ print_fw_str("NSID: %s\n", dir, "nsid"); |
374 | ++ print_fw_str("bootprog: %s\n", dir, "bootprog"); |
375 | ++ print_fw_str("br_lba: %s\n", dir, "br_lba"); |
376 | ++ if (access(path_loadparm, R_OK) == 0) { |
377 | ++ sprintf(loadparm_path, "%s/%s", dir, "loadparm"); |
378 | ++ read_fw_str(loadparm, loadparm_path, sizeof(loadparm)); |
379 | ++ if (strcmp(loadparm, " ") == 0) |
380 | ++ loadparm[0] = 0; |
381 | ++ printf("Loadparm: \"%s\"\n", loadparm); |
382 | ++ } |
383 | ++ if (access(path_bootparms, R_OK) == 0) |
384 | ++ print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data"); |
385 | ++} |
386 | ++ |
387 | + void print_ccw(int show_ipl) |
388 | + { |
389 | + char loadparm[9], loadparm_path[PATH_MAX]; |
390 | +@@ -149,6 +178,10 @@ |
391 | + print_fcp(l.ipl_set, 0); |
392 | + else if (strcmp(reipl_type_str, "fcp_dump") == 0) |
393 | + print_fcp(l.ipl_set, 1); |
394 | ++ else if (strcmp(reipl_type_str, "nvme") == 0) |
395 | ++ print_nvme(l.ipl_set, 0); |
396 | ++ else if (strcmp(reipl_type_str, "nvme_dump") == 0) |
397 | ++ print_nvme(l.ipl_set, 1); |
398 | + else if (strcmp(reipl_type_str, "ccw") == 0) |
399 | + print_ccw(l.ipl_set); |
400 | + else if (strcmp(reipl_type_str, "nss") == 0) |
401 | +--- a/ipl_tools/ipl_tools.h |
402 | ++++ b/ipl_tools/ipl_tools.h |
403 | +@@ -43,6 +43,7 @@ |
404 | + |
405 | + extern void print_ccw(int show_ipl); |
406 | + extern void print_fcp(int show_ipl, int dump); |
407 | ++extern void print_nvme(int show_ipl, int dump); |
408 | + extern void print_nss(int show_ipl); |
409 | + |
410 | + /* |
411 | +@@ -71,6 +72,16 @@ |
412 | + extern void fcp_busid_get(const char *device, char *devno); |
413 | + |
414 | + /* |
415 | ++ * NVME |
416 | ++ */ |
417 | ++#define FID_MAX_LEN 11 /* 8 characters + 0x + null */ |
418 | ++#define NVME_PATH_MAX (PATH_MAX + NAME_MAX + 1) |
419 | ++ |
420 | ++extern void nvme_fid_get(const char *device, char *fid); |
421 | ++extern void nvme_nsid_get(const char *device, char *nsid); |
422 | ++int nvme_is_device(char *fid_str, char *nsid_str); |
423 | ++ |
424 | ++/* |
425 | + * CCW |
426 | + */ |
427 | + extern int ccw_is_device(const char *devno); |
428 | +--- a/ipl_tools/Makefile |
429 | ++++ b/ipl_tools/Makefile |
430 | +@@ -6,7 +6,7 @@ |
431 | + |
432 | + libs = $(rootdir)/libutil/libutil.a |
433 | + |
434 | +-objects = main.o ccw.o fcp.o system.o shutdown.o \ |
435 | ++objects = main.o ccw.o fcp.o nvme.o system.o shutdown.o \ |
436 | + cmd_lsshut.o cmd_chshut.o cmd_lsreipl.o cmd_chreipl.o proc.o |
437 | + |
438 | + chreipl: $(objects) $(libs) |
439 | +@@ -40,4 +40,3 @@ |
440 | + $(DESTDIR)$(MANDIR)/man8 |
441 | + |
442 | + .PHONY: all install clean |
443 | +- |
444 | +--- a/ipl_tools/man/chreipl.8 |
445 | ++++ b/ipl_tools/man/chreipl.8 |
446 | +@@ -39,6 +39,9 @@ |
447 | + .RB "- " fcp : |
448 | + Specify a FCP device for reboot |
449 | + .TP |
450 | ++.RB "- " nvme : |
451 | ++Specify an NVMe device for reboot |
452 | ++.TP |
453 | + .RB "- " nss : |
454 | + Specify a named saved system (NSS) for reboot |
455 | + .TP |
456 | +@@ -118,6 +121,11 @@ |
457 | + append kernel parameter "mem=" to restrict memory to 512 MB: |
458 | + |
459 | + \fB# chreipl 0.0.1700 0x500507630300c562 0x401040b300000000 -p "mem=512M"\fP |
460 | ++ |
461 | ++4. Next time reboot from the NVMe device with function id 0x13, namespace 1: |
462 | ++ |
463 | ++\fB# chreipl nvme 0x13 1 |
464 | ++ |
465 | + .SH ccw |
466 | + Use the ccw re-IPL target for DASD devices that are accessed by the hardware |
467 | + using channel command word (CCW) channels. |
468 | +@@ -192,6 +200,44 @@ |
469 | + .br |
470 | + |
471 | + \fB# chreipl fcp -d 0.0.1700 -w 0x5005076... -l 0x401040b3... -b 2\fP |
472 | ++.SH nvme |
473 | ++Use the nvme re-IPL target for specifying an NVMe disk for reboot. |
474 | ++.TP |
475 | ++.BR "\-i" " or " "\-\-fid" |
476 | ++PCI Function ID of NVME IPL device (hex). |
477 | ++ |
478 | ++.TP |
479 | ++.BR "\-s" " or " "\-\-nsid" |
480 | ++Namespace ID of the NVME IPL device (decimal, default 1). |
481 | ++ |
482 | ++.TP |
483 | ++.BR "\-b" " or " "\-\-bootprog" |
484 | ++Specifies an entry in the boot configuration by defining the IPL boot |
485 | ++program selector. If omitted, '0' will be used. |
486 | ++ |
487 | ++.TP |
488 | ++.BR "\-L" " or " "\-\-loadparm" |
489 | ++The loadparm for the nvme re-IPL target is not used to control the boot |
490 | ++configuration that is defined by the |
491 | ++.BR zipl (8) |
492 | ++boot menu. Instead it can be used to control higher level boot loaders |
493 | ++like GRUB. For more details refer to distribution specific documentation. |
494 | ++ |
495 | ++.PP |
496 | ++\fBExamples:\fP |
497 | ++.br |
498 | ++ |
499 | ++1. Next time reboot from the NVMe disk with function-id 0x13 and namespace 1: |
500 | ++.br |
501 | ++ |
502 | ++\fB# chreipl nvme 0x13 1\fP |
503 | ++.br |
504 | ++ |
505 | ++2. Use same configuration as (1) but choose boot program selector 2 and |
506 | ++use options instead of positional parameters: |
507 | ++.br |
508 | ++ |
509 | ++\fB# chreipl nvme -i 0x13 -s 1 -b 2\fP |
510 | + .SH nss |
511 | + Use the nss re-IPL target to specify z/VM named saved systems (NSS) for |
512 | + reboot. |
513 | +@@ -206,7 +252,7 @@ |
514 | + |
515 | + \fB# chreipl nss LINUX1\fP |
516 | + .SH node |
517 | +-You can identify DASD or SCSI re-IPL devices indirectly through a device |
518 | ++You can identify DASD or SCSI, or NVMe re-IPL devices indirectly through a device |
519 | + node or directory. The chreipl tool then determines the information |
520 | + that you would otherwise have to specify with the ccw or fcp target. |
521 | + .PP |
522 | +@@ -229,6 +275,11 @@ |
523 | + |
524 | + \fB# chreipl node /mnt/boot\fP |
525 | + |
526 | ++4. Next time reboot from the NVMe device represented by /dev/nvme0n1 |
527 | ++.br |
528 | ++ |
529 | ++\fB# chreipl node /dev/nvme0n1\fP |
530 | ++ |
531 | + .SH SEE ALSO |
532 | + .BR lsreipl (8), |
533 | + .BR zipl (8), |
534 | +--- /dev/null |
535 | ++++ b/ipl_tools/nvme.c |
536 | +@@ -0,0 +1,169 @@ |
537 | ++/* |
538 | ++ * ipl_tools - Linux for System z reipl and shutdown tools |
539 | ++ * |
540 | ++ * NVMe device functions |
541 | ++ * |
542 | ++ * Copyright IBM Corp. 2020 |
543 | ++ * |
544 | ++ * s390-tools is free software; you can redistribute it and/or modify |
545 | ++ * it under the terms of the MIT license. See LICENSE for details. |
546 | ++ */ |
547 | ++#include <sys/types.h> |
548 | ++#include <dirent.h> |
549 | ++#include <limits.h> |
550 | ++#include <stdlib.h> |
551 | ++#include <unistd.h> |
552 | ++ |
553 | ++#include "lib/util_libc.h" |
554 | ++#include "lib/util_file.h" |
555 | ++#include "ipl_tools.h" |
556 | ++ |
557 | ++/* |
558 | ++ * Return the fid of a device |
559 | ++ */ |
560 | ++void nvme_fid_get(const char *device, char *fid) |
561 | ++{ |
562 | ++ char path[PATH_MAX], buf[FID_MAX_LEN]; |
563 | ++ |
564 | ++ snprintf(path, PATH_MAX, "/sys/block/%s/device/device/function_id", |
565 | ++ device); |
566 | ++ if (util_file_read_line(buf, FID_MAX_LEN, path)) |
567 | ++ ERR_EXIT_ERRNO("Could not read from \"%s\"", path); |
568 | ++ |
569 | ++ util_strlcpy(fid, buf, FID_MAX_LEN); |
570 | ++} |
571 | ++/* |
572 | ++ * Return the nsid of a device |
573 | ++ */ |
574 | ++void nvme_nsid_get(const char *device, char *nsid) |
575 | ++{ |
576 | ++ char path[PATH_MAX], buf[FID_MAX_LEN]; |
577 | ++ |
578 | ++ snprintf(path, PATH_MAX, "/sys/block/%s/nsid", device); |
579 | ++ if (util_file_read_line(buf, FID_MAX_LEN, path)) |
580 | ++ ERR_EXIT_ERRNO("Could not read from \"%s\"", path); |
581 | ++ |
582 | ++ util_strlcpy(nsid, buf, FID_MAX_LEN); |
583 | ++} |
584 | ++ |
585 | ++static int next_entry(DIR *dir, char *in_path, char *out_path, |
586 | ++ unsigned char entry_type) |
587 | ++{ |
588 | ++ struct dirent *dirent; |
589 | ++ char temp_path[NVME_PATH_MAX]; |
590 | ++ |
591 | ++ while ((dirent = readdir(dir)) != NULL) { |
592 | ++ if (strcmp(dirent->d_name, ".") == 0 || |
593 | ++ strcmp(dirent->d_name, "..") == 0 || |
594 | ++ dirent->d_type != entry_type) |
595 | ++ continue; |
596 | ++ |
597 | ++ /* Resolve the symlink, if needed */ |
598 | ++ if (dirent->d_type == DT_LNK) { |
599 | ++ snprintf(temp_path, sizeof(temp_path), "%s/%s", in_path, |
600 | ++ dirent->d_name); |
601 | ++ if (!realpath(temp_path, out_path)) |
602 | ++ ERR_EXIT_ERRNO("Could not resolve link %s", |
603 | ++ temp_path); |
604 | ++ return 1; |
605 | ++ } |
606 | ++ |
607 | ++ snprintf(out_path, NVME_PATH_MAX, "%s/%s", in_path, |
608 | ++ dirent->d_name); |
609 | ++ return 1; |
610 | ++ } |
611 | ++ return 0; |
612 | ++} |
613 | ++ |
614 | ++static int nvme_getdev_by_fid(char *fidstr, char *devpath) |
615 | ++{ |
616 | ++ char temp_path[PATH_MAX+19], real_path[PATH_MAX]; |
617 | ++ char *sys_path = "/sys/class/nvme"; |
618 | ++ u_int64_t target_fid, curfid; |
619 | ++ DIR *dir; |
620 | ++ char *end; |
621 | ++ int rc = -1; |
622 | ++ |
623 | ++ target_fid = strtoul(fidstr, &end, 16); |
624 | ++ if (*end) |
625 | ++ ERR_EXIT("Invalid function_id given %s", fidstr); |
626 | ++ |
627 | ++ dir = opendir(sys_path); |
628 | ++ if (!dir) |
629 | ++ ERR_EXIT("Could not open %s", sys_path); |
630 | ++ |
631 | ++ errno = 0; |
632 | ++ while (next_entry(dir, sys_path, real_path, DT_LNK)) { |
633 | ++ snprintf(temp_path, sizeof(temp_path), "%s/%s", real_path, |
634 | ++ "device/function_id"); |
635 | ++ if (access(temp_path, F_OK)) |
636 | ++ continue; |
637 | ++ |
638 | ++ if (util_file_read_ul(&curfid, 16, temp_path)) |
639 | ++ ERR_EXIT("Invalid function_id found in %s", temp_path); |
640 | ++ |
641 | ++ if (curfid == target_fid) { |
642 | ++ strncpy(devpath, real_path, PATH_MAX); |
643 | ++ rc = 0; |
644 | ++ break; |
645 | ++ } |
646 | ++ } |
647 | ++ |
648 | ++ closedir(dir); |
649 | ++ return rc; |
650 | ++} |
651 | ++ |
652 | ++static int nvme_getdev_by_nsid(char *nsid_str, char *path, char *dev_path) |
653 | ++{ |
654 | ++ char full_path[NVME_PATH_MAX+1], nsid_path[sizeof(full_path)+5]; |
655 | ++ char *end; |
656 | ++ u_int64_t nsid, curnsid; |
657 | ++ DIR *dir; |
658 | ++ |
659 | ++ nsid = strtoul(nsid_str, &end, 10); |
660 | ++ if (*end) |
661 | ++ ERR_EXIT_ERRNO("Invalid namespace id given %s", nsid_str); |
662 | ++ |
663 | ++ dir = opendir(path); |
664 | ++ if (!dir) |
665 | ++ ERR_EXIT_ERRNO("Could not open %s", path); |
666 | ++ |
667 | ++ errno = 0; |
668 | ++ while (next_entry(dir, path, full_path, DT_DIR)) { |
669 | ++ snprintf(nsid_path, sizeof(nsid_path), "%s/%s", full_path, |
670 | ++ "nsid"); |
671 | ++ if (access(nsid_path, F_OK)) |
672 | ++ continue; |
673 | ++ |
674 | ++ if (util_file_read_ul(&curnsid, 10, nsid_path)) |
675 | ++ ERR_EXIT("Invalid namespace id found in %s", nsid_path); |
676 | ++ |
677 | ++ if (curnsid == nsid) { |
678 | ++ strncpy(dev_path, full_path, NVME_PATH_MAX+1); |
679 | ++ closedir(dir); |
680 | ++ return 0; |
681 | ++ } |
682 | ++ } |
683 | ++ closedir(dir); |
684 | ++ return -1; |
685 | ++} |
686 | ++ |
687 | ++static int nvme_getdev(char *fid_str, char *nsid_str, char *dev_path) |
688 | ++{ |
689 | ++ char path_tmp[NVME_PATH_MAX]; |
690 | ++ |
691 | ++ if (nvme_getdev_by_fid(fid_str, path_tmp)) |
692 | ++ return -1; |
693 | ++ |
694 | ++ return nvme_getdev_by_nsid(nsid_str, path_tmp, dev_path); |
695 | ++} |
696 | ++ |
697 | ++/* |
698 | ++ * Check if the specified fid and nsid leads to a valid nvme device |
699 | ++ */ |
700 | ++int nvme_is_device(char *fid_str, char *nsid_str) |
701 | ++{ |
702 | ++ char path_tmp[NVME_PATH_MAX+1]; |
703 | ++ |
704 | ++ return !(nvme_getdev(fid_str, nsid_str, path_tmp)); |
705 | ++} |
706 | +--- a/zipl/src/disk.c |
707 | ++++ b/zipl/src/disk.c |
708 | +@@ -421,6 +421,12 @@ |
709 | + data->device = stats.st_rdev; |
710 | + data->partnum = 0; |
711 | + } |
712 | ++ /* NVMe path, driver name is 'blkext' */ |
713 | ++ } else if (strcmp(data->drv_name, "blkext") == 0) { |
714 | ++ data->devno = -1; |
715 | ++ data->type = disk_type_scsi; |
716 | ++ data->partnum = stats.st_rdev & SCSI_PARTN_MASK; |
717 | ++ data->device = stats.st_rdev & ~SCSI_PARTN_MASK; |
718 | + } else { |
719 | + /* Driver name is unknown */ |
720 | + error_reason("Unsupported device driver '%s'", data->drv_name); |
721 | diff --git a/debian/patches/s390-tools-sru-lp1903984-focal.patch b/debian/patches/s390-tools-sru-lp1903984-focal.patch |
722 | new file mode 100644 |
723 | index 0000000..fc4952f |
724 | --- /dev/null |
725 | +++ b/debian/patches/s390-tools-sru-lp1903984-focal.patch |
726 | @@ -0,0 +1,49 @@ |
727 | +Description: zcryptstats fails |
728 | + The zcryptstats tool reports data for only the last two domain IDs. |
729 | + Further, it hangs if one collect data for a complete crypto card, |
730 | + and then one has to kill the ssh session to get back. |
731 | + Patch/commit is: |
732 | + cf2311f cf2311f1f1de17435b49ba8c8697be91705ba031 |
733 | + "zcryptstats: Fix handling of partial results with many domains" |
734 | + - zconf/zcrypt/zcryptstats.c: code fix to pass the correct next-domain |
735 | + to the subsequent CHSC call of a partial response |
736 | +Author: Ingo Franzki <ifranzki@linux.ibm.com> |
737 | +Origin: https://github.com/ibm-s390-tools/s390-tools/commit/cf2311f1f1de17435b49ba8c8697be91705ba031 |
738 | +Bug-IBM: IBM Bugzilla 189183 |
739 | +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1903984 |
740 | +Forwarded: not-needed |
741 | +Applied-Upstream: upstream accepted with > v2.15.1 |
742 | +Reviewed-by: Frank Heimes <frank.heimes@canonical.com> |
743 | +Last-Update: 2021-01-19 |
744 | +--- |
745 | +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ |
746 | +--- a/zconf/zcrypt/zcryptstats.c |
747 | ++++ b/zconf/zcrypt/zcryptstats.c |
748 | +@@ -1178,8 +1178,14 @@ |
749 | + scdmd_area.request.header.code = 0x102d; |
750 | + scdmd_area.request.header.length = |
751 | + sizeof(struct chsc_scdmd_request); |
752 | +- scdmd_area.request.first_drid.ap_index = card; |
753 | +- scdmd_area.request.first_drid.domain_index = g.min_domain; |
754 | ++ if (scdmd_area.response.p) { |
755 | ++ scdmd_area.request.first_drid = |
756 | ++ scdmd_area.response.crid; |
757 | ++ } else { |
758 | ++ scdmd_area.request.first_drid.ap_index = card; |
759 | ++ scdmd_area.request.first_drid.domain_index = |
760 | ++ g.min_domain; |
761 | ++ } |
762 | + scdmd_area.request.last_drid.ap_index = card; |
763 | + scdmd_area.request.last_drid.domain_index = g.max_domain; |
764 | + scdmd_area.request.s = 1; |
765 | +@@ -1217,10 +1223,6 @@ |
766 | + rc = process_apqn_measurement_data(&scdmd_area); |
767 | + if (rc != 0) |
768 | + break; |
769 | +- |
770 | +- if (scdmd_area.response.p) |
771 | +- scdmd_area.request.first_drid = |
772 | +- scdmd_area.response.crid; |
773 | + } while (scdmd_area.response.p); |
774 | + |
775 | + return rc; |
776 | diff --git a/debian/patches/s390-tools-sru-lp1908371-focal.patch b/debian/patches/s390-tools-sru-lp1908371-focal.patch |
777 | new file mode 100644 |
778 | index 0000000..7ba3725 |
779 | --- /dev/null |
780 | +++ b/debian/patches/s390-tools-sru-lp1908371-focal.patch |
781 | @@ -0,0 +1,402 @@ |
782 | +Description: The zipl command doesn't work correctly in combination with the -M |
783 | + (respectively --mvdump) option. There is an error with the preparation of |
784 | + multi-volume dumps, since the bus-ID for the first disk partition that is |
785 | + listed in file dump_conf (DEVLIST) isn't found. |
786 | + - include/lib/util_sys.h: declaration of new util_sys_* functions |
787 | + - include/lib/util_file.h: declaration of two new util_file_read_* functions |
788 | + - libutil/util_sys.c: implementation of new util_sys_* functions; |
789 | + getting minor and major device number now based on base device |
790 | + and prechecking if base device available util_file_read_* functions |
791 | + - libutil/util_file.c: implementation of two new |
792 | + - zipl/src/disk.c: removing blkext_* function set and changing code to |
793 | + use the new util_sys_* functions |
794 | +Author: Stefan Haberland <sth@linux.ibm.com>, Sven Schnelle <svens@linux.ibm.com> |
795 | +Origin: https://github.com/ibm-s390-tools/s390-tools/commit/fa7a4dafa3d89b2e8787de102e4362e895d44b05 |
796 | + https://github.com/ibm-s390-tools/s390-tools/commit/aa8c2945cc7b047c626e75817c6a3e3924413023 |
797 | + https://github.com/ibm-s390-tools/s390-tools/commit/6802b86414b48c4f118da09c7bf7ee142a459fa0 |
798 | + https://github.com/ibm-s390-tools/s390-tools/commit/37348ef662a7052dae798e500ca8c9b769fff3e6 |
799 | +Bug-IBM: IBM Bugzilla 187221 |
800 | +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1908371 |
801 | +Forwarded: not-needed |
802 | +Applied-Upstream: >= v2.15.1 |
803 | +Reviewed-by: Frank Heimes <frank.heimes@canonical.com> |
804 | +Last-Update: 2020-12-22 |
805 | +--- |
806 | +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ |
807 | +--- a/include/lib/util_file.h |
808 | ++++ b/include/lib/util_file.h |
809 | +@@ -12,8 +12,10 @@ |
810 | + #define LIB_UTIL_FILE_H |
811 | + |
812 | + int util_file_read_line(char *str, size_t size, const char *fmt, ...); |
813 | ++int util_file_read_i(int *val, int base, const char *fmt, ...); |
814 | + int util_file_read_l(long *val, int base, const char *fmt, ...); |
815 | + int util_file_read_ll(long long *val, int base, const char *fmt, ...); |
816 | ++int util_file_read_ui(unsigned int *val, int base, const char *fmt, ...); |
817 | + int util_file_read_ul(unsigned long *val, int base, const char *fmt, ...); |
818 | + int util_file_read_ull(unsigned long long *val, int base, const char *fmt, ...); |
819 | + |
820 | +--- a/include/lib/util_sys.h |
821 | ++++ b/include/lib/util_sys.h |
822 | +@@ -12,6 +12,11 @@ |
823 | + #ifndef LIB_UTIL_SYS_H |
824 | + #define LIB_UTIL_SYS_H |
825 | + |
826 | ++#include <stdbool.h> |
827 | ++ |
828 | + int util_sys_get_dev_addr(const char *dev, char *addr); |
829 | ++bool util_sys_dev_is_partition(dev_t dev); |
830 | ++int util_sys_get_partnum(dev_t dev); |
831 | ++int util_sys_get_base_dev(dev_t dev, dev_t *base_dev); |
832 | + |
833 | + #endif /** LIB_UTIL_SYS_H @} */ |
834 | +--- a/libutil/util_file.c |
835 | ++++ b/libutil/util_file.c |
836 | +@@ -282,6 +282,44 @@ |
837 | + } |
838 | + |
839 | + /** |
840 | ++ * Read a file and convert it to signed int according to given base |
841 | ++ * |
842 | ++ * @param[out] val Buffer for value |
843 | ++ * @param[in] base Base for conversion, either 8, 10, or 16 |
844 | ++ * @param[in] fmt Format string for generation of the path name |
845 | ++ * @param[in] ... Parameters for format string |
846 | ++ * |
847 | ++ * @retval 0 Integer has been read correctly |
848 | ++ * @retval -1 Error while reading file |
849 | ++ */ |
850 | ++int util_file_read_i(int *val, int base, const char *fmt, ...) |
851 | ++{ |
852 | ++ char path[PATH_MAX], buf[512]; |
853 | ++ va_list ap; |
854 | ++ int count; |
855 | ++ |
856 | ++ /* Construct the file name */ |
857 | ++ UTIL_VSPRINTF(path, fmt, ap); |
858 | ++ |
859 | ++ if (file_gets(buf, sizeof(buf), path)) |
860 | ++ return -1; |
861 | ++ switch (base) { |
862 | ++ case 8: |
863 | ++ count = sscanf(buf, "%do", val); |
864 | ++ break; |
865 | ++ case 10: |
866 | ++ count = sscanf(buf, "%dd", val); |
867 | ++ break; |
868 | ++ case 16: |
869 | ++ count = sscanf(buf, "%dx", val); |
870 | ++ break; |
871 | ++ default: |
872 | ++ util_panic("Invalid base: %d\n", base); |
873 | ++ } |
874 | ++ return (count == 1) ? 0 : -1; |
875 | ++} |
876 | ++ |
877 | ++/** |
878 | + * Read a file and convert it to signed long according to given base |
879 | + * |
880 | + * @param[out] val Buffer for value |
881 | +@@ -353,6 +391,44 @@ |
882 | + break; |
883 | + default: |
884 | + util_panic("Invalid base: %d\n", base); |
885 | ++ } |
886 | ++ return (count == 1) ? 0 : -1; |
887 | ++} |
888 | ++ |
889 | ++/** |
890 | ++ * Read a file and convert it to unsigned int according to given base |
891 | ++ * |
892 | ++ * @param[out] val Buffer for value |
893 | ++ * @param[in] base Base for conversion, either 8, 10, or 16 |
894 | ++ * @param[in] fmt Format string for generation of the path name |
895 | ++ * @param[in] ... Parameters for format string |
896 | ++ * |
897 | ++ * @retval 0 Integer has been read correctly |
898 | ++ * @retval -1 Error while reading file |
899 | ++ */ |
900 | ++int util_file_read_ui(unsigned int *val, int base, const char *fmt, ...) |
901 | ++{ |
902 | ++ char path[PATH_MAX], buf[512]; |
903 | ++ va_list ap; |
904 | ++ int count; |
905 | ++ |
906 | ++ /* Construct the file name */ |
907 | ++ UTIL_VSPRINTF(path, fmt, ap); |
908 | ++ |
909 | ++ if (file_gets(buf, sizeof(buf), path)) |
910 | ++ return -1; |
911 | ++ switch (base) { |
912 | ++ case 8: |
913 | ++ count = sscanf(buf, "%uo", val); |
914 | ++ break; |
915 | ++ case 10: |
916 | ++ count = sscanf(buf, "%uu", val); |
917 | ++ break; |
918 | ++ case 16: |
919 | ++ count = sscanf(buf, "%ux", val); |
920 | ++ break; |
921 | ++ default: |
922 | ++ util_panic("Invalid base: %d\n", base); |
923 | + } |
924 | + return (count == 1) ? 0 : -1; |
925 | + } |
926 | +--- a/libutil/util_sys.c |
927 | ++++ b/libutil/util_sys.c |
928 | +@@ -11,17 +11,114 @@ |
929 | + |
930 | + #include <err.h> |
931 | + #include <errno.h> |
932 | ++#include <linux/fs.h> |
933 | + #include <stdlib.h> |
934 | ++#include <stdio.h> |
935 | + #include <string.h> |
936 | + #include <sys/stat.h> |
937 | + #include <sys/sysmacros.h> |
938 | + #include <unistd.h> |
939 | + |
940 | ++#include "lib/util_file.h" |
941 | ++#include "lib/util_libc.h" |
942 | + #include "lib/util_path.h" |
943 | + #include "lib/util_sys.h" |
944 | + |
945 | + /* lstat() doesn't work for sysfs files, a fixed size is therefore inevitable */ |
946 | + #define READLINK_SIZE 256 |
947 | ++#define PAGE_SIZE 4096 |
948 | ++ |
949 | ++/** |
950 | ++ * Return the partition number of a given partition. |
951 | ++ * |
952 | ++ * @param[in] dev Device node of interest |
953 | ++ * |
954 | ++ * @retval int Partition number of the device |
955 | ++ * @retval -1 Error when trying to read the partition number. |
956 | ++ */ |
957 | ++int util_sys_get_partnum(dev_t dev) |
958 | ++{ |
959 | ++ int partnum = -1; |
960 | ++ char *path; |
961 | ++ |
962 | ++ path = util_path_sysfs("dev/block/%u:%u/partition", |
963 | ++ major(dev), minor(dev)); |
964 | ++ if (util_file_read_i(&partnum, 10, path)) { |
965 | ++ warnx("Could not read from path '%s'", path); |
966 | ++ goto out; |
967 | ++ } |
968 | ++ if (partnum <= 0) { |
969 | ++ warnx("Bad partition number in '%s'", path); |
970 | ++ partnum = -1; |
971 | ++ goto out; |
972 | ++ } |
973 | ++ |
974 | ++out: |
975 | ++ free(path); |
976 | ++ return partnum; |
977 | ++} |
978 | ++ |
979 | ++/** |
980 | ++ * Determine if the given device is a partition. |
981 | ++ * |
982 | ++ * @param[in] dev Device node of interest |
983 | ++ * |
984 | ++ * @retval true Device is partition |
985 | ++ * @retval false Device is not a partition |
986 | ++ */ |
987 | ++bool util_sys_dev_is_partition(dev_t dev) |
988 | ++{ |
989 | ++ bool is_part; |
990 | ++ char *path; |
991 | ++ |
992 | ++ path = util_path_sysfs("dev/block/%u:%u/partition", |
993 | ++ major(dev), minor(dev)); |
994 | ++ is_part = util_path_exists(path); |
995 | ++ free(path); |
996 | ++ |
997 | ++ return is_part; |
998 | ++} |
999 | ++ |
1000 | ++/** |
1001 | ++ * Determine base device |
1002 | ++ * |
1003 | ++ * This function determines the base device \p base_dev of a given |
1004 | ++ * device \p dev. If \p dev is a base device, \p base_dev becomes \p dev. |
1005 | ++ * |
1006 | ++ * @param[in] dev Device node of interest |
1007 | ++ * @param[out] base_dev Identified base device |
1008 | ++ * |
1009 | ++ * @retval 0 Success |
1010 | ++ * @retval -1 Error while reading device information or |
1011 | ++ * constructed path |
1012 | ++ */ |
1013 | ++int util_sys_get_base_dev(dev_t dev, dev_t *base_dev) |
1014 | ++{ |
1015 | ++ int base_major, base_minor; |
1016 | ++ char buf[PAGE_SIZE]; |
1017 | ++ char *path; |
1018 | ++ |
1019 | ++ /* check if the device already is a base device */ |
1020 | ++ if (!util_sys_dev_is_partition(dev)) { |
1021 | ++ *base_dev = makedev(major(dev), minor(dev)); |
1022 | ++ return 0; |
1023 | ++ } |
1024 | ++ path = util_path_sysfs("dev/block/%d:%d/../dev", |
1025 | ++ major(dev), minor(dev)); |
1026 | ++ if (util_file_read_line(buf, sizeof(buf), path)) { |
1027 | ++ warnx("Could not read from path '%s'", path); |
1028 | ++ free(path); |
1029 | ++ return -1; |
1030 | ++ } |
1031 | ++ free(path); |
1032 | ++ if (sscanf(buf, "%i:%i", &base_major, &base_minor) != 2) { |
1033 | ++ warn("Could not parse major:minor from string '%s'", buf); |
1034 | ++ return -1; |
1035 | ++ } |
1036 | ++ *base_dev = makedev(base_major, base_minor); |
1037 | ++ |
1038 | ++ return 0; |
1039 | ++} |
1040 | + |
1041 | + /** |
1042 | + * Identify device address |
1043 | +@@ -44,13 +141,17 @@ |
1044 | + unsigned int maj, min; |
1045 | + struct stat s; |
1046 | + ssize_t len; |
1047 | ++ dev_t base; |
1048 | + char *path; |
1049 | + |
1050 | + if (stat(dev, &s) != 0) |
1051 | + return -1; |
1052 | + |
1053 | +- maj = major(s.st_rdev); |
1054 | +- min = minor(s.st_rdev); |
1055 | ++ if (util_sys_get_base_dev(s.st_rdev, &base)) |
1056 | ++ return -1; |
1057 | ++ |
1058 | ++ maj = major(base); |
1059 | ++ min = minor(base); |
1060 | + |
1061 | + if (S_ISBLK(s.st_mode)) |
1062 | + path = util_path_sysfs("dev/block/%u:%u/device", maj, min); |
1063 | +--- a/zipl/src/disk.c |
1064 | ++++ b/zipl/src/disk.c |
1065 | +@@ -25,6 +25,7 @@ |
1066 | + #include <linux/fiemap.h> |
1067 | + |
1068 | + #include "lib/util_proc.h" |
1069 | ++#include "lib/util_sys.h" |
1070 | + |
1071 | + #include "disk.h" |
1072 | + #include "error.h" |
1073 | +@@ -89,88 +90,6 @@ |
1074 | + return 0; |
1075 | + } |
1076 | + |
1077 | +-static int blkext_get_partnum(dev_t dev) |
1078 | +-{ |
1079 | +- char path[PATH_MAX], *buf; |
1080 | +- int dev_major, dev_minor, partnum = -1; |
1081 | +- |
1082 | +- dev_major = major(dev); |
1083 | +- dev_minor = minor(dev); |
1084 | +- snprintf(path, PATH_MAX, "/sys/dev/block/%d:%d/partition", |
1085 | +- dev_major, dev_minor); |
1086 | +- |
1087 | +- if (misc_read_special_file(path, &buf, NULL, 1)) { |
1088 | +- error_text("Could not read from path '%s'", path); |
1089 | +- return -1; |
1090 | +- } |
1091 | +- |
1092 | +- partnum = atoi(buf); |
1093 | +- free(buf); |
1094 | +- if (partnum < 0) { |
1095 | +- error_text("Bad partition number in '%s'", path); |
1096 | +- return -1; |
1097 | +- } |
1098 | +- |
1099 | +- return partnum; |
1100 | +-} |
1101 | +- |
1102 | +-static int blkext_is_base_device(dev_t dev) |
1103 | +-{ |
1104 | +- int dev_major, dev_minor; |
1105 | +- char path[PATH_MAX]; |
1106 | +- struct stat stats; |
1107 | +- |
1108 | +- dev_major = major(dev); |
1109 | +- dev_minor = minor(dev); |
1110 | +- |
1111 | +- snprintf(path, PATH_MAX, "/sys/dev/block/%d:%d/partition", |
1112 | +- dev_major, dev_minor); |
1113 | +- return (stat(path, &stats)); |
1114 | +-} |
1115 | +- |
1116 | +-static int blkext_get_base_dev(dev_t dev, dev_t *base_dev) |
1117 | +-{ |
1118 | +- int base_major, base_minor; |
1119 | +- char dev_path[PATH_MAX], base_path[PATH_MAX]; |
1120 | +- char *temp_path, *buf; |
1121 | +- |
1122 | +- misc_asprintf(&temp_path, "/sys/dev/block/%d:%d", major(dev), minor(dev)); |
1123 | +- if (!realpath(temp_path, dev_path)) { |
1124 | +- error_reason(strerror(errno)); |
1125 | +- error_text("Could not resolve link %s", temp_path); |
1126 | +- free(temp_path); |
1127 | +- return -1; |
1128 | +- } |
1129 | +- free(temp_path); |
1130 | +- |
1131 | +- misc_asprintf(&temp_path, "%s/..", dev_path); |
1132 | +- if (!realpath(temp_path, base_path)) { |
1133 | +- error_reason(strerror(errno)); |
1134 | +- error_text("Could not resolve path %s", temp_path); |
1135 | +- free(temp_path); |
1136 | +- return -1; |
1137 | +- } |
1138 | +- free(temp_path); |
1139 | +- |
1140 | +- misc_asprintf(&temp_path, "%s/dev", base_path); |
1141 | +- if (misc_read_special_file(temp_path, &buf, NULL, 1)) { |
1142 | +- error_text("Could not read from path '%s'", temp_path); |
1143 | +- free(temp_path); |
1144 | +- return -1; |
1145 | +- } |
1146 | +- free(temp_path); |
1147 | +- |
1148 | +- if (sscanf(buf, "%i:%i", &base_major, &base_minor) != 2) { |
1149 | +- error_text("Could not parse major:minor from string '%s'", buf); |
1150 | +- free(buf); |
1151 | +- return -1; |
1152 | +- } |
1153 | +- |
1154 | +- free(buf); |
1155 | +- *base_dev = makedev(base_major, base_minor); |
1156 | +- return 0; |
1157 | +-} |
1158 | +- |
1159 | + /* Return non-zero for ECKD type. */ |
1160 | + int |
1161 | + disk_is_eckd(disk_type_t type) |
1162 | +@@ -492,15 +411,15 @@ |
1163 | + data->devno = -1; |
1164 | + data->type = disk_type_scsi; |
1165 | + |
1166 | +- if (blkext_is_base_device(stats.st_rdev)) { |
1167 | +- data->device = stats.st_rdev; |
1168 | +- data->partnum = 0; |
1169 | +- } else { |
1170 | +- if (blkext_get_base_dev(stats.st_rdev, &data->device)) |
1171 | ++ if (util_sys_dev_is_partition(stats.st_rdev)) { |
1172 | ++ if (util_sys_get_base_dev(stats.st_rdev, &data->device)) |
1173 | + goto out_close; |
1174 | +- data->partnum = blkext_get_partnum(stats.st_rdev); |
1175 | ++ data->partnum = util_sys_get_partnum(stats.st_rdev); |
1176 | + if (data->partnum == -1) |
1177 | + goto out_close; |
1178 | ++ } else { |
1179 | ++ data->device = stats.st_rdev; |
1180 | ++ data->partnum = 0; |
1181 | + } |
1182 | + } else { |
1183 | + /* Driver name is unknown */ |
1184 | diff --git a/debian/patches/series b/debian/patches/series |
1185 | index e779db8..894d113 100644 |
1186 | --- a/debian/patches/series |
1187 | +++ b/debian/patches/series |
1188 | @@ -110,3 +110,6 @@ f742ed73e1db99dc04b821a1f9aa4a852584e4d8.patch |
1189 | 0110-zipl-stage3-correctly-handle-diag308-response-code.patch |
1190 | 0111-zipl-fix-incorrect-setup-of-stage3-flags.patch |
1191 | 0112-cpumf-lscpumf.pl-displays-raw-event-number-incorrect.patch |
1192 | +s390-tools-sru-lp1903984-focal.patch |
1193 | +s390-tools-sru-lp1908371-focal.patch |
1194 | +s390-tools-sru-lp1902179-focal.patch |
Hi Frank, thank you very much for preparing this SRU! I like your extensive DEP-3 headers. I double-checked that the package builds with all new patches applied in Focal. Also, I checked it against the referenced upstream patches. I found some slight divergence there, mentioned inline.
Could you please comment on why we need to modify the upstream commit at those places, or alternatively adopt to the same changeset upstream applied? I'd like to stay as close to upstream as possible, so we won't have problems applying additional patches in the future.
Cheers,
Lukas