zipl/src: Enable heterogeneous mirrors support

Drop limitations on identical target parameters of base disks per
logical device;

Fix verbose zipl output to include geometry of each mirror and
component load addresses that would be used when booting from each
mirror.


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>
This commit is contained in:
Eduard Shishkin
2025-07-30 14:11:12 +02:00
committed by Steffen Eiden
parent 2945593991
commit 731f00202c
4 changed files with 55 additions and 95 deletions

View File

@@ -144,7 +144,7 @@ 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 device_print_info(struct device_info *info, int source);
void device_print_info(struct device_info *info, struct job_target_data *td);
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,
struct disk_info *info);

View File

@@ -1507,7 +1507,7 @@ static int prepare_build_program_table_device(struct job_data *job,
if (verbose) {
printf("Target device information\n");
device_print_info(bis->info, job->target.source);
device_print_info(bis->info, &job->target);
}
/* Mirrored dump devices are not supported */
info = &bis->info->base[FIRST_MIRROR_ID];
@@ -1639,7 +1639,7 @@ static int prepare_build_program_table_file(struct job_data *job,
}
if (verbose) {
printf("Target device information\n");
device_print_info(bis->info, job->target.source);
device_print_info(bis->info, &job->target);
}
for (i = 0; i < job_get_nr_targets(job); i++) {
if (misc_temp_dev(bis->info->base[i].disk,

View File

@@ -287,27 +287,6 @@ 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_type_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));
}
}
/**
* Set disk info using ready target parameters provided either by
* user, or by script
@@ -326,22 +305,6 @@ static int device_set_info_by_hint(struct job_target_data *td,
data->base[i].type = get_targettype(td, i);
data->base[i].phy_block_size = get_targetblocksize(td, i);
if (data->base[0].type !=
data->base[i].type ||
data->base[0].phy_block_size !=
data->base[i].phy_block_size) {
/*
* Currently multiple base disks with different
* parameters are not supported
*/
print_base_disk_params(td, 0);
print_base_disk_params(td, i);
error_reason("Inconsistent base disk geometry in target device");
return -1;
}
}
/* set disk, targetbase_def, partnum, is_nvme */
for (i = 0; i < td->nr_targets; i++) {
if (sscanf(get_targetbase(td, i),
"%d:%d", &majnum, &minnum) == 2) {
data->base[i].disk = makedev(majnum, minnum);
@@ -577,20 +540,6 @@ static int device_set_geometry_by_hint(struct job_target_data *td,
data->base[i].geo.sectors = get_targetsectors(td, i);
data->base[i].geo.cylinders = get_targetcylinders(td, i);
data->base[i].geo.start = get_targetoffset(td, i);
if (data->base[i].geo.heads != data->base[0].geo.heads ||
data->base[i].geo.sectors != data->base[0].geo.sectors ||
data->base[i].geo.cylinders != data->base[0].geo.cylinders ||
data->base[i].geo.start != data->base[0].geo.start) {
/*
* Currently multiple base disks with different
* parameters are not supported
*/
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;
}
@@ -1209,71 +1158,82 @@ disk_is_large_volume(struct disk_info *info)
info->geo.cylinders == 0xfffe;
}
/* Print textual representation of INFO contents. */
void device_print_info(struct device_info *this, int source)
static void disk_print_info(struct disk_info *info, int source)
{
struct disk_info *info = &this->base[FIRST_MIRROR_ID];
const char *prefix = " ";
char footnote[4] = "";
prepare_footnote_ptr(source, footnote);
printf(" Device..........................: ");
disk_print_devt(this->device);
printf("%sDisk............................: ", prefix);
disk_print_devt(info->disk);
if (info->targetbase_def == defined_as_device)
printf("%s", footnote);
printf("\n");
if (info->partnum != 0) {
printf(" Partition.......................: ");
printf("%sPartition.......................: ", prefix);
disk_print_devt(info->partition);
printf("\n");
}
if (this->name) {
printf(" Device name.....................: %s",
this->name);
if (info->targetbase_def == defined_as_name)
printf("%s", footnote);
printf("\n");
}
if (this->drv_name) {
printf(" Device driver name..............: %s\n",
this->drv_name);
}
if (((info->type == disk_type_fba) ||
(info->type == disk_type_diag) ||
(info->type == disk_type_eckd_ldl) ||
(info->type == disk_type_eckd_cdl)) &&
(source == source_auto)) {
printf(" DASD device number..............: %04x\n",
info->devno);
printf("%sDASD device number..............: %04x\n",
prefix, info->devno);
}
printf(" Type............................: disk %s\n",
(info->partnum != 0) ? "partition" : "device");
printf(" Disk layout.....................: %s%s\n",
disk_get_type_name(info->type), footnote);
printf("%sType............................: disk %s\n",
prefix, (info->partnum != 0) ? "partition" : "device");
printf("%sDisk layout.....................: %s%s\n",
prefix, disk_get_type_name(info->type), footnote);
if (disk_type_is_eckd(info->type)) {
printf(" Geometry - heads................: %d%s\n",
info->geo.heads, footnote);
printf(" Geometry - sectors..............: %d%s\n",
info->geo.sectors, footnote);
printf("%sGeometry - heads................: %d%s\n",
prefix, info->geo.heads, footnote);
printf("%sGeometry - sectors..............: %d%s\n",
prefix, info->geo.sectors, footnote);
if (disk_is_large_volume(info)) {
/* ECKD large volume. There is not enough information
* available in INFO to calculate disk cylinder size. */
printf(" Geometry - cylinders............: > 65534\n");
printf("%sGeometry - cylinders............: > 65534\n",
prefix);
} else {
printf(" Geometry - cylinders............: %d%s\n",
info->geo.cylinders, footnote);
printf("%sGeometry - cylinders............: %d%s\n",
prefix, info->geo.cylinders, footnote);
}
}
printf(" Geometry - start................: %ld%s\n",
info->geo.start, footnote);
printf("%sGeometry - start................: %ld%s\n",
prefix, info->geo.start, footnote);
printf("%sPhysical block size.............: %d%s\n",
prefix, info->phy_block_size, footnote);
printf("%sDisk size in physical blocks....: %ld\n",
prefix, (long)info->phy_blocks);
print_footnote_ref(source, prefix);
}
void device_print_info(struct device_info *this, struct job_target_data *td)
{
int i;
printf(" Device............................: ");
disk_print_devt(this->device);
printf("\n");
if (this->name) {
printf(" Device name.......................: %s",
this->name);
printf("\n");
}
if (this->drv_name) {
printf(" Device driver name................: %s\n",
this->drv_name);
}
if (this->fs_block_size >= 0)
printf(" File system block size..........: %d\n",
printf(" File system block size............: %d\n",
this->fs_block_size);
printf(" Physical block size.............: %d%s\n",
info->phy_block_size, footnote);
printf(" Device size in physical blocks..: %ld\n",
(long) info->phy_blocks);
print_footnote_ref(source, " ");
for (i = 0; i < td->nr_targets; i++) {
printf(" Base %d:\n", i + 1);
disk_print_info(&this->base[i], td->source);
}
}
/* Check whether a block is a zero block which identifies a hole in a file.

View File

@@ -1179,7 +1179,7 @@ install_dump(const char *device, struct job_target_data *target, uint64_t mem,
}
if (verbose) {
printf("Target device information\n");
device_print_info(dev_info, target->source);
device_print_info(dev_info, target);
}
rc = misc_temp_dev(dev_info->device, 1, &tempdev);
if (rc) {
@@ -1344,7 +1344,7 @@ install_mvdump(char* const device[], struct job_target_data* target, int count,
if (verbose) {
for (i = 0; i < count; i++) {
printf("Multi-volume dump target %d:\n", i + 1);
device_print_info(dev_info[i], target->source);
device_print_info(dev_info[i], target);
printf("-------------------------------------------\n");
}
}