Accepting request 1201422 from Base:System

* Applied patches (bsc#1230345)
  - zipl/src: add basic support for multiple target base disks
  - s390-tools-01-zipl-src-add-basic-support-for-multiple-target-base-disks.patch
  - s390-tools-02-zipl-src-add-basic-support-for-multiple-target-base-disks.patch

OBS-URL: https://build.opensuse.org/request/show/1201422
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/s390-tools?expand=0&rev=81
This commit is contained in:
Ana Guerrero 2024-09-16 15:46:06 +00:00 committed by Git OBS Bridge
commit f85aac9036
4 changed files with 994 additions and 0 deletions

View File

@ -0,0 +1,969 @@
From d6b702d5791b47f735960ad1f6986e0a32768df6 Mon Sep 17 00:00:00 2001
From: Eduard Shishkin <edward6@linux.ibm.com>
Date: Thu, 11 Jul 2024 10:43:37 +0200
Subject: [PATCH] zipl/src: add basic support for multiple target base disks
. Modify disk_get_info() to process multiple sets of target parameters
provided by the helper script and store it in the array of "targets"
of the structure job_target_data;
. Besides the logical device, maintain an array of physical base disks
in the disk_info structure;
. Use the logical target device only to create bootmap (it is
automatically mirrored by the respective linux driver (dm, or md)
managing the mirrored target). In contrast, install bootstrap blocks
to each physical base disk individually, bypassing that driver;
. Report in verbose mode on which base disks the bootstrap
installation was performed;
. Use the following logic of setting @info->device (which is printed
as "Device...:" in verbose mode):
. source_auto - the target base disk is set;
. source_script - the target (logical) device is set;
. source_user - the device specified by user (via --targetbase
option), or config file is set.
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
zipl/include/disk.h | 14 +-
zipl/include/install.h | 2
zipl/include/job.h | 122 ++++++++++++++++++--
zipl/include/zipl.h | 1
zipl/src/bootmap.c | 23 ++-
zipl/src/disk.c | 295 +++++++++++++++++++++++++++++++++++++------------
zipl/src/install.c | 89 +++++++++-----
zipl/src/job.c | 82 +++++++------
8 files changed, 469 insertions(+), 159 deletions(-)
--- a/zipl/include/disk.h
+++ b/zipl/include/disk.h
@@ -56,13 +56,14 @@
/* targetbase definition */
typedef enum {
defined_as_device,
- defined_as_name
+ defined_as_name,
+ undefined
} definition_t;
/* Disk information type */
struct disk_info {
disk_type_t type;
- dev_t device;
+ dev_t device; /* logical device for bootmap creation */
dev_t partition;
int devno;
int partnum;
@@ -72,8 +73,11 @@
struct hd_geometry geo;
char* name;
char* drv_name;
- definition_t targetbase;
+ definition_t targetbase_def;
int is_nvme;
+ dev_t basedisks[MAX_TARGETS]; /* array of physical disks for
+ * bootstrap blocks recording
+ */
};
struct file_range {
@@ -113,6 +117,9 @@
struct disk_info *info, int align,
off_t *offset);
void disk_print_devt(dev_t d);
+void disk_print_devname(dev_t d);
+void prepare_footnote_ptr(int source, char *ptr);
+void print_footnote_ref(int source, const char *prefix);
void disk_print_info(struct disk_info *info, int source);
int disk_is_zero_block(disk_blockptr_t* block, struct disk_info* info);
blocknum_t disk_compact_blocklist(disk_blockptr_t* list, blocknum_t count,
@@ -122,7 +129,6 @@
disk_blockptr_t** blocklist,
struct disk_info* pinfo);
int disk_check_subchannel_set(int devno, dev_t device, char* dev_name);
-void disk_print_geo(struct disk_info *data);
int fs_map(int fd, uint64_t offset, blocknum_t *mapped, int fs_block_size);
#endif /* not DISK_H */
--- a/zipl/include/install.h
+++ b/zipl/include/install.h
@@ -71,7 +71,7 @@
struct program_component *components[NR_PROGRAM_COMPONENTS];
int nr_menu_entries;
int fd;
- char *device;
+ char *basetmp[MAX_TARGETS];
char *filename;
unsigned int tmp_filename_created:1;
unsigned int skip_prepare:1;
--- a/zipl/include/job.h
+++ b/zipl/include/job.h
@@ -18,7 +18,6 @@
#include "disk.h"
#include "zipl.h"
-
enum job_id {
job_print_usage = 1,
job_print_version = 2,
@@ -30,6 +29,21 @@
job_mvdump = 8,
};
+/*
+ * Set of parameters per physical disk, which are provided
+ * either by user, or by helper script
+ */
+struct target {
+ char *targetbase;
+ disk_type_t targettype;
+ int targetcylinders;
+ int targetheads;
+ int targetsectors;
+ int targetblocksize;
+ blocknum_t targetoffset;
+ int check_params;
+};
+
/* target information source */
typedef enum {
source_unknown = 0,
@@ -39,17 +53,21 @@
} source_t;
struct job_target_data {
- char* bootmap_dir;
- char* targetbase;
- disk_type_t targettype;
- int targetcylinders;
- int targetheads;
- int targetsectors;
- int targetblocksize;
- blocknum_t targetoffset;
+ char *bootmap_dir;
+ int nr_targets;
+ struct target targets[MAX_TARGETS];
source_t source;
};
+enum target_params {
+ TARGET_BASE,
+ TARGET_TYPE,
+ TARGET_GEOMETRY,
+ TARGET_BLOCKSIZE,
+ TARGET_OFFSET,
+ LAST_TARGET_PARAM
+};
+
struct job_common_ipl_data {
char* image;
char* parmline;
@@ -142,12 +160,94 @@
int is_ldipl_dump;
};
+static inline struct target *target_at(struct job_target_data *data,
+ int index)
+{
+ return index >= MAX_TARGETS ? NULL : &data->targets[index];
+}
+
+static inline char *get_targetbase(struct job_target_data *data, int index)
+{
+ return target_at(data, index)->targetbase;
+}
+
+static inline void set_targetbase(struct job_target_data *data, int index,
+ char *value)
+{
+ target_at(data, index)->targetbase = value;
+}
+
+static inline disk_type_t get_targettype(struct job_target_data *data,
+ int index)
+{
+ return target_at(data, index)->targettype;
+}
+
+int set_targettype(struct job_target_data *data, int index, char *value);
+
+static inline char *job_get_targetbase(struct job_data *job)
+{
+ return get_targetbase(&job->target, 0);
+}
+
+static inline void job_set_targetbase(struct job_data *job, char *value)
+{
+ set_targetbase(&job->target, 0, value);
+}
+
+static inline int job_get_nr_targets(struct job_data *job)
+{
+ return job->target.nr_targets;
+}
+
+static inline void job_set_nr_targets(struct job_data *job, int value)
+{
+ job->target.nr_targets = value;
+}
+
+static inline disk_type_t job_get_targettype(struct job_data *job)
+{
+ return get_targettype(&job->target, 0);
+}
+
+int job_set_targettype(struct job_data *job, char *value);
+
+#define define_target_param_ops(_TYPE_, _PARAM_) \
+static inline _TYPE_ get_target##_PARAM_(struct job_target_data *data, \
+ int index) \
+{ \
+ return target_at(data, index)->target##_PARAM_; \
+} \
+ \
+static inline void set_target##_PARAM_(struct job_target_data *data, \
+ int index, _TYPE_ value) \
+{ \
+ target_at(data, index)->target##_PARAM_ = value; \
+} \
+ \
+static inline _TYPE_ job_get_target##_PARAM_(struct job_data *job) \
+{ \
+ return get_target##_PARAM_(&job->target, 0); \
+} \
+ \
+static inline void job_set_target##_PARAM_(struct job_data *job, \
+ _TYPE_ value) \
+{ \
+ set_target##_PARAM_(&job->target, 0, value); \
+}
+
+define_target_param_ops(int, cylinders)
+define_target_param_ops(int, heads)
+define_target_param_ops(int, sectors)
+define_target_param_ops(int, blocksize)
+define_target_param_ops(blocknum_t, offset)
+
/**
- * Return true, if target parameters for the base disk are set
+ * Return true, if target parameters are set at least for one target base disk
*/
static inline int target_parameters_are_set(struct job_target_data *td)
{
- return td->targetbase != NULL;
+ return get_targetbase(td, 0) != NULL;
}
int job_get(int argc, char* argv[], struct job_data** data);
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -41,6 +41,7 @@
#define MENU_DEFAULT_TIMEOUT 0
#define MAX_DUMP_VOLUMES 32
+#define MAX_TARGETS 32
#define SECURE_BOOT_UNDEFINED -1
#define SECURE_BOOT_DISABLED 0
--- a/zipl/src/bootmap.c
+++ b/zipl/src/bootmap.c
@@ -1477,9 +1477,9 @@
printf("Target device information\n");
disk_print_info(bis->info, job->target.source);
}
- if (misc_temp_dev(bis->info->device, 1, &bis->device))
+ if (misc_temp_dev(bis->info->device, 1, &bis->basetmp[0]))
return -1;
- if (check_dump_device(job, bis->info, bis->device))
+ if (check_dump_device(job, bis->info, bis->basetmp[0]))
return -1;
printf("Building bootmap directly on partition '%s'%s\n",
bis->filename,
@@ -1543,6 +1543,8 @@
static int prepare_build_program_table_file(struct job_data *job,
struct install_set *bis)
{
+ int i;
+
if (bis->skip_prepare)
/* skip the preparation work */
return 0;
@@ -1576,8 +1578,12 @@
printf("Target device information\n");
disk_print_info(bis->info, job->target.source);
}
- if (misc_temp_dev(bis->info->device, 1, &bis->device))
- return -1;
+ for (i = 0; i < job_get_nr_targets(job); i++) {
+ if (misc_temp_dev(bis->info->basedisks[i],
+ 1,
+ &bis->basetmp[i]))
+ return -1;
+ }
/* Check configuration number limits */
if (job->id == job_menu) {
if (check_menu_positions(&job->data.menu, job->name,
@@ -1692,9 +1698,9 @@
/* Retrieve target device information */
if (disk_get_info(job->data.dump.device, &job->target, &info))
return -1;
- if (misc_temp_dev(info->device, 1, &bis->device))
+ if (misc_temp_dev(info->device, 1, &bis->basetmp[0]))
return -1;
- if (check_dump_device(job, info, bis->device))
+ if (check_dump_device(job, info, bis->basetmp[0]))
return -1;
assert(!job->target.bootmap_dir);
@@ -1844,6 +1850,9 @@
if (bis->tmp_filename_created)
misc_free_temp_file(bis->filename);
free(bis->filename);
- misc_free_temp_dev(bis->device);
+ for (i = 0; i < MAX_TARGETS; i++) {
+ if (bis->basetmp[i])
+ misc_free_temp_dev(bis->basetmp[i]);
+ }
disk_free_info(bis->info);
}
--- a/zipl/src/disk.c
+++ b/zipl/src/disk.c
@@ -187,43 +187,134 @@
return rc;
}
+/**
+ * Process a script output represented by FH and consisting
+ * of pairs 'key=value' (each such pair is on a separate line).
+ * Check its consistency and set the extracted target parameters
+ * to the array of "targets" at TD.
+ *
+ * NOTE: this function defines specifications on valid output of
+ * zipl helper scripts. See zipl-support-for-mirrored-devices.txt
+ * for details. Before modifying this function, make sure that it
+ * won't lead to format change.
+ */
static int set_target_parameters(FILE *fh, struct job_target_data *td)
{
- int checkparm = 0;
+ int idx[LAST_TARGET_PARAM] = {0};
+ struct target *t;
char buffer[80];
char value[40];
+ char *error;
+ int i;
+ /**
+ * 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
+ */
+ error = "Exceeded the maximum number of base disks";
while (fgets(buffer, 80, fh)) {
if (sscanf(buffer, "targetbase=%s", value) == 1) {
- td->targetbase = misc_strdup(value);
- checkparm++;
+ t = target_at(td, idx[TARGET_BASE]++);
+ if (!t)
+ goto error;
+ t->targetbase = misc_strdup(value);
+ goto found;
}
if (sscanf(buffer, "targettype=%s", value) == 1) {
- type_from_target(value, &td->targettype);
- checkparm++;
+ t = target_at(td, idx[TARGET_TYPE]++);
+ if (!t)
+ goto error;
+ type_from_target(value, &t->targettype);
+ goto found;
}
if (sscanf(buffer, "targetgeometry=%s", value) == 1) {
- td->targetcylinders =
- atoi(strtok(value, ","));
- td->targetheads = atoi(strtok(NULL, ","));
- td->targetsectors = atoi(strtok(NULL, ","));
- checkparm++;
+ t = target_at(td, idx[TARGET_GEOMETRY]++);
+ if (!t)
+ goto error;
+ t->targetcylinders = atoi(strtok(value, ","));
+ t->targetheads = atoi(strtok(NULL, ","));
+ t->targetsectors = atoi(strtok(NULL, ","));
+ goto found;
}
if (sscanf(buffer, "targetblocksize=%s", value) == 1) {
- td->targetblocksize = atoi(value);
- checkparm++;
+ t = target_at(td, idx[TARGET_BLOCKSIZE]++);
+ if (!t)
+ goto error;
+ t->targetblocksize = atoi(value);
+ goto found;
}
if (sscanf(buffer, "targetoffset=%s", value) == 1) {
- td->targetoffset = atol(value);
- checkparm++;
+ t = target_at(td, idx[TARGET_OFFSET]++);
+ if (!t)
+ goto error;
+ t->targetoffset = atol(value);
+ goto found;
}
+ continue;
+found:
+ t->check_params++;
}
- if ((!disk_is_eckd(td->targettype) && checkparm < 4) ||
- (disk_is_eckd(td->targettype) && checkparm != 5)) {
- error_reason("Target parameters missing from script");
- return -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;
+ /*
+ * 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
+ */
+ for (i = 0; i < td->nr_targets; i++) {
+ t = target_at(td, i);
+ assert(t->check_params >= 4);
+ if (disk_is_eckd(t->targettype) && t->check_params != 5)
+ goto error;
}
return 0;
+error:
+ error_reason("%s", error);
+ return -1;
+}
+
+static void print_base_disk_params(struct job_target_data *td, int index)
+{
+ disk_type_t type = get_targettype(td, index);
+
+ if (!verbose)
+ return;
+ {
+ fprintf(stderr, "Base disk '%s':\n", get_targetbase(td, index));
+ fprintf(stderr, " layout........: %s\n", disk_get_type_name(type));
+ }
+ if (disk_is_eckd(type)) {
+ fprintf(stderr, " heads.........: %u\n", get_targetheads(td, index));
+ fprintf(stderr, " sectors.......: %u\n", get_targetsectors(td, index));
+ fprintf(stderr, " cylinders.....: %u\n", get_targetcylinders(td, index));
+ }
+ {
+ fprintf(stderr, " start.........: %lu\n", get_targetoffset(td, index));
+ fprintf(stderr, " blksize.......: %u\n", get_targetblocksize(td, index));
+ }
}
/**
@@ -235,31 +326,57 @@
{
int majnum, minnum;
struct stat stats;
-
+ int i;
+ /*
+ * Currently multiple base disks with different parameters
+ * are not supported
+ */
data->devno = -1;
- data->phy_block_size = td->targetblocksize;
- data->type = td->targettype;
- data->partnum = 0;
+ data->phy_block_size = get_targetblocksize(td, 0);
+ data->type = get_targettype(td, 0);
- if (sscanf(td->targetbase, "%d:%d", &majnum, &minnum) == 2) {
- data->device = makedev(majnum, minnum);
- data->targetbase = defined_as_device;
- data->partnum = minor(stats.st_rdev) - minnum;
- } else {
- if (stat(td->targetbase, &stats)) {
- error_reason(strerror(errno));
- error_text("Could not get information for "
- "file '%s'", td->targetbase);
+ assert(td->nr_targets != 0);
+ for (i = 1; i < td->nr_targets; i++) {
+ if (data->type != get_targettype(td, i) ||
+ data->phy_block_size != get_targetblocksize(td, i)) {
+ print_base_disk_params(td, 0);
+ print_base_disk_params(td, i);
+ error_reason("Inconsistent base disk geometry in target device");
return -1;
}
- if (!S_ISBLK(stats.st_mode)) {
- error_reason("Target base device '%s' is not "
- "a block device",
- td->targetbase);
+ }
+ data->partnum = 0;
+ data->targetbase_def = undefined;
+
+ for (i = 0; i < td->nr_targets; i++) {
+ definition_t defined_as;
+
+ if (sscanf(get_targetbase(td, i),
+ "%d:%d", &majnum, &minnum) == 2) {
+ data->basedisks[i] = makedev(majnum, minnum);
+ defined_as = defined_as_device;
+ } else {
+ if (stat(get_targetbase(td, i), &stats)) {
+ error_reason(strerror(errno));
+ error_text("Could not get information for "
+ "file '%s'", get_targetbase(td, i));
+ return -1;
+ }
+ if (!S_ISBLK(stats.st_mode)) {
+ error_reason("Target base device '%s' is not "
+ "a block device",
+ get_targetbase(td, i));
+ return -1;
+ }
+ data->basedisks[i] = stats.st_rdev;
+ defined_as = defined_as_name;
+ }
+ if (data->targetbase_def != undefined &&
+ data->targetbase_def != defined_as) {
+ error_reason("Target base disks are defined by different ways");
return -1;
}
- data->device = stats.st_rdev;
- data->targetbase = defined_as_name;
+ data->targetbase_def = defined_as;
}
if (data->type == disk_type_scsi && ioctl(fd, NVME_IOCTL_ID) >= 0)
data->is_nvme = 1;
@@ -446,11 +563,28 @@
static int disk_set_geometry_by_hint(struct job_target_data *td,
struct disk_info *data)
{
- data->geo.heads = td->targetheads;
- data->geo.sectors = td->targetsectors;
- data->geo.cylinders = td->targetcylinders;
- data->geo.start = td->targetoffset;
-
+ int i;
+ /*
+ * Currently multiple base disks with different parameters
+ * are not supported
+ */
+ data->geo.heads = get_targetheads(td, 0);
+ data->geo.sectors = get_targetsectors(td, 0);
+ data->geo.cylinders = get_targetcylinders(td, 0);
+ data->geo.start = get_targetoffset(td, 0);
+
+ assert(td->nr_targets != 0);
+ for (i = 1; i < td->nr_targets; i++) {
+ if (data->geo.heads != get_targetheads(td, i) ||
+ data->geo.sectors != get_targetsectors(td, i) ||
+ data->geo.cylinders != get_targetcylinders(td, i) ||
+ data->geo.start != get_targetoffset(td, i)) {
+ print_base_disk_params(td, 0);
+ print_base_disk_params(td, i);
+ error_reason("Inconsistent base disk geometry in target device");
+ return -1;
+ }
+ }
return 0;
}
@@ -515,14 +649,16 @@
}
/**
- * Prepare INFO required to perform IPL installation on the physical
- * disk where the logical DEVICE is located.
+ * Prepare INFO required to perform IPL installation on physical disks
+ * participating in the logical DEVICE.
* Preparation is performed in 2 steps:
*
- * 1. Find out a physical "base" disk where the logical DEVICE is
- * located. Calculate "target" parameters (type, geometry, physical
- * block size, data offset, etc);
- * 2. Complete INFO by the found base disk and target parameters.
+ * 1. Find out a set of physical "base" disks participating in the
+ * logical DEVICE. For each found disk calculate "target" parameters
+ * (type, geometry, physical block size, data offset, etc) and store
+ * it in the array of "targets" of TD;
+ * 2. Complete INFO using the found base disks and calculated target
+ * parameters.
*
* TD: optionally contains target parameters specified by user via
* config file, or special "target options" of zipl tool.
@@ -566,6 +702,7 @@
goto error;
if (disk_set_info_by_hint(td, data, fd))
goto error;
+ data->device = stats.st_rdev;
break;
case source_user:
/*
@@ -578,6 +715,12 @@
goto error;
if (disk_set_info_by_hint(td, data, fd))
goto error;
+ /*
+ * multiple base disks are not supported
+ * with this source type
+ */
+ assert(td->nr_targets == 1);
+ data->device = data->basedisks[0];
break;
case source_auto:
/* no ready target parameters are available */
@@ -585,6 +728,12 @@
goto error;
if (disk_set_info_auto(data, &stats, fd))
goto error;
+ /*
+ * multiple base disks are not supported
+ * with this source type
+ */
+ data->basedisks[0] = data->device;
+ td->nr_targets = 1;
break;
default:
assert(0);
@@ -940,6 +1089,33 @@
printf("%02x:%02x", major(d), minor(d));
}
+void disk_print_devname(dev_t dev)
+{
+ struct util_proc_part_entry part_entry;
+
+ if (!util_proc_part_get_entry(dev, &part_entry)) {
+ printf("%s", part_entry.name);
+ util_proc_part_free_entry(&part_entry);
+ } else {
+ disk_print_devt(dev);
+ }
+}
+
+void prepare_footnote_ptr(int source, char *ptr)
+{
+ if (source == source_user || source == source_script)
+ strcpy(ptr, " *)");
+ else
+ strcpy(ptr, "");
+}
+
+void print_footnote_ref(int source, const char *prefix)
+{
+ if (source == source_user)
+ printf("%s*) Data provided by user.\n", prefix);
+ else if (source == source_script)
+ printf("%s*) Data provided by script.\n", prefix);
+}
/* Return a name for a given disk TYPE. */
char *
@@ -991,12 +1167,11 @@
void disk_print_info(struct disk_info *info, int source)
{
char footnote[4] = "";
- if (source == source_user || source == source_script)
- strcpy(footnote, " *)");
+ prepare_footnote_ptr(source, footnote);
printf(" Device..........................: ");
disk_print_devt(info->device);
- if (info->targetbase == defined_as_device)
+ if (info->targetbase_def == defined_as_device)
printf("%s", footnote);
printf("\n");
if (info->partnum != 0) {
@@ -1007,7 +1182,7 @@
if (info->name) {
printf(" Device name.....................: %s",
info->name);
- if (info->targetbase == defined_as_name)
+ if (info->targetbase_def == defined_as_name)
printf("%s", footnote);
printf("\n");
}
@@ -1050,21 +1225,7 @@
info->phy_block_size, footnote);
printf(" Device size in physical blocks..: %ld\n",
(long) info->phy_blocks);
- if (source == source_user)
- printf(" *) Data provided by user.\n");
- if (source == source_script)
- printf(" *) Data provided by script.\n");
-}
-
-/* Print textual representation of geo structure. */
-void
-disk_print_geo(struct disk_info *data)
-{
- printf(" geo.heads.........:%u\n", data->geo.heads);
- printf(" geo.sectors.......:%u\n", data->geo.sectors);
- printf(" geo.cylinders.....:%u\n", data->geo.cylinders);
- printf(" geo.start.........:%lu\n", data->geo.start);
- printf(" blksize...........:%u\n", data->phy_block_size);
+ print_footnote_ref(source, " ");
}
/* Check whether a block is a zero block which identifies a hole in a file.
--- a/zipl/src/install.c
+++ b/zipl/src/install.c
@@ -434,11 +434,14 @@
{
disk_blockptr_t *scsi_dump_sb_blockptr = &bis->scsi_dump_sb_blockptr;
struct disk_info *info = bis->info;
- char *device = bis->device;
- int fd, rc;
+ char footnote[4];
+ int rc;
+ int i;
if (!info)
return 0;
+
+ prepare_footnote_ptr(job->target.source, footnote);
/* Inform user about what we're up to */
printf("Preparing boot device for %s%s: ",
disk_get_ipl_type(info->type,
@@ -455,40 +458,58 @@
disk_print_devt(info->device);
printf(".\n");
}
- /* Open device file */
- fd = open(device, O_RDWR);
- if (fd == -1) {
- error_reason(strerror(errno));
- error_text("Could not open temporary device file '%s'",
- device);
- return -1;
- }
- /* Ensure that potential cache inconsistencies between disk and
- * partition are resolved by flushing the corresponding buffers. */
- if (!dry_run) {
- if (ioctl(fd, BLKFLSBUF)) {
- fprintf(stderr, "Warning: Could not flush disk "
- "caches.\n");
+ /* Install independently on each physical target base */
+
+ for (i = 0; i < job_get_nr_targets(job); i++) {
+ int fd;
+
+ if (verbose) {
+ printf("Installing on base disk: ");
+ disk_print_devname(info->basedisks[i]);
+ printf("%s.\n", footnote);
}
+ /* Open device file */
+ fd = open(bis->basetmp[i], O_RDWR);
+ if (fd == -1) {
+ error_reason(strerror(errno));
+ error_text("Could not open temporary device file '%s'",
+ bis->basetmp[i]);
+ return -1;
+ }
+ /* Ensure that potential cache inconsistencies between disk and
+ * partition are resolved by flushing the corresponding buffers.
+ */
+ if (!dry_run) {
+ if (ioctl(fd, BLKFLSBUF)) {
+ fprintf(stderr, "Warning: Could not flush disk "
+ "caches.\n");
+ }
+ }
+ /*
+ * Depending on disk type, install one or two program tables
+ * for CCW-type IPL and (or) for List-Directed IPL (see the
+ * picture in comments above)
+ */
+ if (job->id == job_dump_partition) {
+ rc = install_bootloader_dump(bis->tables, info,
+ scsi_dump_sb_blockptr,
+ is_ngdump_enabled(job),
+ fd);
+ } else {
+ rc = install_bootloader_ipl(bis->tables, info,
+ fd);
+ }
+ if (fsync(fd))
+ error_text("Could not sync device file '%s'",
+ bis->basetmp[i]);
+ if (close(fd))
+ error_text("Could not close device file '%s'",
+ bis->basetmp[i]);
+ if (rc)
+ break;
}
- /*
- * Depending on disk type, install one or two program tables
- * for CCW-type IPL and (or) for List-Directed IPL (see the
- * picture in comments above)
- */
- if (job->id == job_dump_partition) {
- rc = install_bootloader_dump(bis->tables, info,
- scsi_dump_sb_blockptr,
- is_ngdump_enabled(job),
- fd);
- } else {
- rc = install_bootloader_ipl(bis->tables, info, fd);
- }
-
- if (fsync(fd))
- error_text("Could not sync device file '%s'", device);
- if (close(fd))
- error_text("Could not close device file '%s'", device);
+ if (verbose)
+ print_footnote_ref(job->target.source, "");
if (!dry_run && rc == 0) {
if (info->devno >= 0)
--- a/zipl/src/job.c
+++ b/zipl/src/job.c
@@ -1346,6 +1346,27 @@
}
}
+int set_targettype(struct job_target_data *data, int index, char *value)
+{
+ return type_from_target(value,
+ &target_at(data, index)->targettype);
+}
+
+int job_set_targettype(struct job_data *job, char *value)
+{
+ return set_targettype(&job->target, 0, value);
+}
+
+static int job_set_target(struct job_data *job, char *value)
+{
+ job_set_targetbase(job, value);
+ if (!job_get_targetbase(job))
+ return -1;
+ job_set_nr_targets(job, 1);
+ job->target.source = source_user;
+ return 0;
+}
+
static int
get_job_from_section_data(char* data[], struct job_data* job, char* section)
{
@@ -1362,32 +1383,28 @@
return -1;
/* Fill in target */
if (data[(int) scan_keyword_targetbase] != NULL) {
- job->target.targetbase =
- misc_strdup(data[(int)
- scan_keyword_targetbase]);
- if (job->target.targetbase == NULL)
+ if (job_set_target(job, misc_strdup(data[(int)
+ scan_keyword_targetbase])))
return -1;
- job->target.source = source_user;
}
if (data[(int) scan_keyword_targettype] != NULL) {
- if (type_from_target(
- data[(int) scan_keyword_targettype],
- &job->target.targettype))
+ if (job_set_targettype(job,
+ data[(int) scan_keyword_targettype]))
return -1;
}
if (data[(int) scan_keyword_targetgeometry] != NULL) {
- job->target.targetcylinders =
+ job_set_targetcylinders(job,
atoi(strtok(data[(int)
- scan_keyword_targetgeometry], ","));
- job->target.targetheads = atoi(strtok(NULL, ","));
- job->target.targetsectors = atoi(strtok(NULL, ","));
+ scan_keyword_targetgeometry], ",")));
+ job_set_targetheads(job, atoi(strtok(NULL, ",")));
+ job_set_targetsectors(job, atoi(strtok(NULL, ",")));
}
if (data[(int) scan_keyword_targetblocksize] != NULL)
- job->target.targetblocksize =
- atoi(data[(int) scan_keyword_targetblocksize]);
+ job_set_targetblocksize(job,
+ atoi(data[(int) scan_keyword_targetblocksize]));
if (data[(int) scan_keyword_targetoffset] != NULL)
- job->target.targetoffset =
- atol(data[(int) scan_keyword_targetoffset]);
+ job_set_targetoffset(job,
+ atol(data[(int) scan_keyword_targetoffset]));
/* Fill in name and address of image file */
job->data.ipl.common.image = misc_strdup(
@@ -1615,37 +1632,32 @@
return -1;
break;
case scan_keyword_targetbase:
- job->target.targetbase = misc_strdup(
- scan[i].content.keyword.value);
- if (job->target.targetbase == NULL)
+ if (job_set_target(job, misc_strdup(
+ scan[i].content.keyword.value)))
return -1;
- job->target.source = source_user;
break;
case scan_keyword_targettype:
- if (type_from_target(
- scan[i].content.keyword.value,
- &job->target.targettype))
+ if (job_set_targettype(job,
+ scan[i].content.keyword.value))
return -1;
break;
case scan_keyword_targetgeometry:
- job->target.targetcylinders =
+ job_set_targetcylinders(job,
atoi(strtok(
scan[i].content.keyword.value,
- ","));
- job->target.targetheads =
- atoi(strtok(NULL, ","));
- job->target.targetsectors =
- atoi(strtok(NULL, ","));
+ ",")));
+ job_set_targetheads(job,
+ atoi(strtok(NULL, ",")));
+ job_set_targetsectors(job,
+ atoi(strtok(NULL, ",")));
break;
case scan_keyword_targetblocksize:
- job->target.targetblocksize =
- atoi(
- scan[i].content.keyword.value);
+ job_set_targetblocksize(job, atoi(
+ scan[i].content.keyword.value));
break;
case scan_keyword_targetoffset:
- job->target.targetoffset =
- atol(
- scan[i].content.keyword.value);
+ job_set_targetoffset(job, atol(
+ scan[i].content.keyword.value));
break;
default:
/* Should not happen */

View File

@ -0,0 +1,15 @@
--- a/zipl/src/job.c 2024-09-16 14:20:09.321762661 +0200
+++ b/zipl/src/job.c 2024-09-16 14:29:28.601846724 +0200
@@ -373,8 +373,11 @@
static void
free_target_data(struct job_target_data* data)
{
+ int i;
+
free(data->bootmap_dir);
- free(data->targetbase);
+ for (i = 0; i < data->nr_targets; i++)
+ free(get_targetbase(data, i));
}
static void

View File

@ -1,3 +1,11 @@
-------------------------------------------------------------------
Mon Sep 16 12:49:55 UTC 2024 - Nikolay Gueorguiev <nikolay.gueorguiev@suse.com>
* Applied patches (bsc#1230345)
- zipl/src: add basic support for multiple target base disks
- s390-tools-01-zipl-src-add-basic-support-for-multiple-target-base-disks.patch
- s390-tools-02-zipl-src-add-basic-support-for-multiple-target-base-disks.patch
------------------------------------------------------------------- -------------------------------------------------------------------
Mon Aug 26 09:17:17 UTC 2024 - Nikolay Gueorguiev <nikolay.gueorguiev@suse.com> Mon Aug 26 09:17:17 UTC 2024 - Nikolay Gueorguiev <nikolay.gueorguiev@suse.com>

View File

@ -155,6 +155,8 @@ Patch912: s390-tools-ALP-zdev-live.patch
Patch913: s390-tools-sles15sp6-kdump-initrd-59-zfcp-compat-rules.patch Patch913: s390-tools-sles15sp6-kdump-initrd-59-zfcp-compat-rules.patch
Patch914: s390-tools-slfo-01-parse-ipl-device-for-activation.patch Patch914: s390-tools-slfo-01-parse-ipl-device-for-activation.patch
Patch915: s390-tools-2.34-Fix-Rust-compilation-errors.patch Patch915: s390-tools-2.34-Fix-Rust-compilation-errors.patch
Patch916: s390-tools-01-zipl-src-add-basic-support-for-multiple-target-base-disks.patch
Patch917: s390-tools-02-zipl-src-add-basic-support-for-multiple-target-base-disks.patch
### ###
BuildRequires: curl-devel BuildRequires: curl-devel