From 9882aabe4434594cd055b95ad8427338207a8763 Mon Sep 17 00:00:00 2001 From: Eduard Shishkin Date: Mon, 8 Jun 2026 17:12:05 +0200 Subject: [PATCH] zipl/src: Update format of zipl helpers output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the format of zipl helpers output to support hybrid mirrors (i.e. composed of disks of different types and geometry). The new format imposes an additional requirement that any key-value pair "targetbase=X:Y" titles a new section with a set of target parmeters for the base disk identified by that pair. Without this change, zipl reports "Inconsistent script output". To reproduce the problem, build a mixed mirrored setup with first SCSI disk and second DASD disk, and prepare it for IPL. Fixes: 731f00202c53 ("zipl/src: Enable heterogeneous mirrors support") Reviewed-by: Stefan Haberland Signed-off-by: Eduard Shishkin Signed-off-by: Jan Höppner --- zipl/include/job.h | 2 +- zipl/src/disk.c | 81 ++++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/zipl/include/job.h b/zipl/include/job.h index 0acea592..3e93a323 100644 --- a/zipl/include/job.h +++ b/zipl/include/job.h @@ -167,7 +167,7 @@ struct job_data { static inline struct target *target_at(struct job_target_data *data, int index) { - return index >= MAX_TARGETS ? NULL : &data->targets[index]; + return index < 0 || index >= MAX_TARGETS ? NULL : &data->targets[index]; } static inline char *get_targetbase(struct job_target_data *data, int index) diff --git a/zipl/src/disk.c b/zipl/src/disk.c index 86ec6bc7..673224fb 100644 --- a/zipl/src/disk.c +++ b/zipl/src/disk.c @@ -176,6 +176,15 @@ out_err: return rc; } +#define GET_TARGET_OR_GOTO_ERR() \ + do { \ + if (target_id < 0) \ + goto err_inc; \ + t = target_at(td, target_id); \ + if (!t) \ + goto err_exc; \ + } while (0) + /** * Process a script output represented by FH and consisting * of pairs 'key=value' (each such pair is on a separate line). @@ -189,57 +198,46 @@ out_err: */ static int set_target_parameters(FILE *fh, struct job_target_data *td) { - int idx[LAST_TARGET_PARAM] = {0}; + int target_id = -1; struct target *t; char buffer[80]; char value[40]; - char *error; int i; /* reset array of target parameters */ memset(td->targets, 0, sizeof(td->targets)); - /** - * Process a stream of 'key=value' pairs and distribute - * them into groups. - * The i-th occurrence of some "key" in the stream means - * that the respective pair belongs to the group #i + /* + * Process a stream of key-value pairs and complete the array of + * target parameters. + * Each key-value pair "targetbase=foo" title a group of parameters + * for a new target. */ - error = "Exceeded the maximum number of base disks"; while (fgets(buffer, 80, fh)) { if (sscanf(buffer, "targetbase=%s", value) == 1) { - t = target_at(td, idx[TARGET_BASE]++); - if (!t) - goto error; + target_id++; /* new title */ + GET_TARGET_OR_GOTO_ERR(); t->targetbase = misc_strdup(value); goto found; } if (sscanf(buffer, "targettype=%s", value) == 1) { - t = target_at(td, idx[TARGET_TYPE]++); - if (!t) - goto error; + GET_TARGET_OR_GOTO_ERR(); type_from_target(value, &t->targettype); goto found; } if (sscanf(buffer, "targetgeometry=%s", value) == 1) { - t = target_at(td, idx[TARGET_GEOMETRY]++); - if (!t) - goto error; + GET_TARGET_OR_GOTO_ERR(); t->targetcylinders = atoi(strtok(value, ",")); t->targetheads = atoi(strtok(NULL, ",")); t->targetsectors = atoi(strtok(NULL, ",")); goto found; } if (sscanf(buffer, "targetblocksize=%s", value) == 1) { - t = target_at(td, idx[TARGET_BLOCKSIZE]++); - if (!t) - goto error; + GET_TARGET_OR_GOTO_ERR(); t->targetblocksize = atoi(value); goto found; } if (sscanf(buffer, "targetoffset=%s", value) == 1) { - t = target_at(td, idx[TARGET_OFFSET]++); - if (!t) - goto error; + GET_TARGET_OR_GOTO_ERR(); t->targetoffset = atol(value); goto found; } @@ -247,43 +245,26 @@ static int set_target_parameters(FILE *fh, struct job_target_data *td) found: t->check_params++; } + td->nr_targets = target_id + 1; /* Check for consistency */ - error = "Inconsistent script output"; - /* - * First, calculate total number of groups - */ - td->nr_targets = 0; - for (i = 0; i < MAX_TARGETS; i++) { - t = target_at(td, i); - if (t->check_params == 0) - break; - td->nr_targets++; - } if (!td->nr_targets) - /* No keywords found in the stream */ - goto error; + /* Missed a title pair "targetbase=foo" in the stream */ + goto err_inc; /* - * Each group has to include targetbase, targettype, - * targetblocksize and targetoffset. - */ - if (td->nr_targets != idx[TARGET_BASE] || - td->nr_targets != idx[TARGET_TYPE] || - td->nr_targets != idx[TARGET_BLOCKSIZE] || - td->nr_targets != idx[TARGET_OFFSET]) - goto error; - /* - * In addition, any group of "ECKD" type has to include - * targetgeometry + * Any group of "ECKD" type has to include targetgeometry */ for (i = 0; i < td->nr_targets; i++) { t = target_at(td, i); assert(t->check_params >= 4); if (disk_type_is_eckd(t->targettype) && t->check_params != 5) - goto error; + goto err_inc; } return 0; -error: - error_reason("%s", error); +err_inc: + error_reason("%s", "Inconsistent script output"); + return -1; +err_exc: + error_reason("%s", "Exceeded the maximum number of base disks"); return -1; }