zipl/src: make disk type detecton fail

When detecting disk type, the function disk_get_info() is called.
It can fail for various reasons (e.g. when the logial target is not
eligible for boot record installation).

Once disk_get_info() fails, don't proceed with type detection.
Return error instead. When applicable, mark the dump job with
"is_ngdump" flag to avoid extra type detection calls.

Acked-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Eduard Shishkin
2024-09-05 14:48:51 +02:00
committed by Jan Höppner
parent f43789e16a
commit 41da0f0809
7 changed files with 82 additions and 63 deletions

View File

@@ -53,6 +53,11 @@ typedef enum {
disk_type_eckd_cdl, disk_type_eckd_cdl,
} disk_type_t; } disk_type_t;
struct disk_ext_type {
disk_type_t type;
bool is_nvme;
};
/* targetbase definition */ /* targetbase definition */
typedef enum { typedef enum {
defined_as_device, defined_as_device,
@@ -87,12 +92,15 @@ struct file_range {
struct job_target_data; struct job_target_data;
int disk_get_info(const char* device, struct job_target_data* target, int disk_get_info(const char *device, struct job_target_data *target,
struct disk_info** info); struct disk_info **info);
int disk_is_tape(const char* device); int disk_get_ext_type(const char *device, struct disk_ext_type *ext_type);
int disk_is_scsi(const char* device, struct job_target_data* target); int disk_is_tape(const char *device);
int disk_is_eckd_ldl(const char* device, struct job_target_data* target); int disk_type_is_scsi(struct disk_ext_type *ext_type);
int disk_is_nvme(const char* device, struct job_target_data* target); int disk_type_is_eckd_ldl(struct disk_ext_type *ext_type);
int disk_type_is_nvme(struct disk_ext_type *ext_type);
int disk_type_is_eckd(disk_type_t type);
int disk_get_info_from_file(const char* filename, int disk_get_info_from_file(const char* filename,
struct job_target_data* target, struct job_target_data* target,
struct disk_info** info); struct disk_info** info);

View File

@@ -99,6 +99,7 @@ struct job_dump_data {
struct job_common_ipl_data common; struct job_common_ipl_data common;
char* device; char* device;
uint64_t mem; uint64_t mem;
bool is_ngdump;
bool no_compress; bool no_compress;
}; };
@@ -256,6 +257,8 @@ void free_target_data(struct job_target_data *td);
int type_from_target(char *target, disk_type_t *type); int type_from_target(char *target, disk_type_t *type);
int check_job_dump_images(struct job_dump_data* dump, char* name); int check_job_dump_images(struct job_dump_data* dump, char* name);
int check_job_images_ngdump(struct job_dump_data* dump, char* name); int check_job_images_ngdump(struct job_dump_data* dump, char* name);
bool is_ngdump_enabled(struct job_data *job); void job_dump_check_set_ngdump(struct job_data *job,
struct disk_ext_type *ext_type);
bool job_dump_is_ngdump(struct job_data *job);
#endif /* not JOB_H */ #endif /* not JOB_H */

View File

@@ -1436,7 +1436,7 @@ check_dump_device(struct job_data *job, const struct disk_info *info,
if (!disk_is_appropriate(job, info)) if (!disk_is_appropriate(job, info))
return -1; return -1;
if (is_ngdump_enabled(job)) if (job_dump_is_ngdump(job))
return 0; return 0;
rc = util_part_search(device, info->geo.start, rc = util_part_search(device, info->geo.start,
@@ -1827,7 +1827,7 @@ int prepare_bootloader(struct job_data *job, struct install_set *bis)
if (init_bis(job, bis)) if (init_bis(job, bis))
return -1; return -1;
if (job->id == job_dump_partition) { if (job->id == job_dump_partition) {
if (is_ngdump_enabled(job)) if (job_dump_is_ngdump(job))
return prepare_bootloader_ngdump(job, bis); return prepare_bootloader_ngdump(job, bis);
else else
return prepare_bootloader_device(job, bis); return prepare_bootloader_device(job, bis);
@@ -1843,7 +1843,7 @@ int prepare_bootloader(struct job_data *job, struct install_set *bis)
int post_install_bootloader(struct job_data *job, struct install_set *bis) int post_install_bootloader(struct job_data *job, struct install_set *bis)
{ {
if (job->id == job_dump_partition) { if (job->id == job_dump_partition) {
if (is_ngdump_enabled(job)) if (job_dump_is_ngdump(job))
return dry_run ? 0 : finalize_create_file(job, bis); return dry_run ? 0 : finalize_create_file(job, bis);
else else
return 0; return 0;

View File

@@ -92,14 +92,6 @@ disk_determine_dasd_type(struct disk_info *data,
return 0; return 0;
} }
/* Return non-zero for ECKD type. */
static int
disk_is_eckd(disk_type_t type)
{
return (type == disk_type_eckd_ldl ||
type == disk_type_eckd_cdl);
}
static int static int
read_block_by_offset(int fd, int blksize, uint64_t offset, char *buffer) read_block_by_offset(int fd, int blksize, uint64_t offset, char *buffer)
{ {
@@ -287,7 +279,7 @@ found:
for (i = 0; i < td->nr_targets; i++) { for (i = 0; i < td->nr_targets; i++) {
t = target_at(td, i); t = target_at(td, i);
assert(t->check_params >= 4); assert(t->check_params >= 4);
if (disk_is_eckd(t->targettype) && t->check_params != 5) if (disk_type_is_eckd(t->targettype) && t->check_params != 5)
goto error; goto error;
} }
return 0; return 0;
@@ -306,7 +298,7 @@ static void print_base_disk_params(struct job_target_data *td, int index)
fprintf(stderr, "Base disk '%s':\n", get_targetbase(td, index)); fprintf(stderr, "Base disk '%s':\n", get_targetbase(td, index));
fprintf(stderr, " layout........: %s\n", disk_get_type_name(type)); fprintf(stderr, " layout........: %s\n", disk_get_type_name(type));
} }
if (disk_is_eckd(type)) { if (disk_type_is_eckd(type)) {
fprintf(stderr, " heads.........: %u\n", get_targetheads(td, index)); fprintf(stderr, " heads.........: %u\n", get_targetheads(td, index));
fprintf(stderr, " sectors.......: %u\n", get_targetsectors(td, index)); fprintf(stderr, " sectors.......: %u\n", get_targetsectors(td, index));
fprintf(stderr, " cylinders.....: %u\n", get_targetcylinders(td, index)); fprintf(stderr, " cylinders.....: %u\n", get_targetcylinders(td, index));
@@ -617,7 +609,7 @@ static int disk_set_info_complete(struct job_target_data *td,
return -1; return -1;
} }
/* Check for valid CHS geometry data. */ /* Check for valid CHS geometry data. */
if (disk_is_eckd(data->type) && (data->geo.cylinders == 0 || if (disk_type_is_eckd(data->type) && (data->geo.cylinders == 0 ||
data->geo.heads == 0 || data->geo.sectors == 0)) { data->geo.heads == 0 || data->geo.sectors == 0)) {
error_reason("Invalid disk geometry (CHS=%d/%d/%d)", error_reason("Invalid disk geometry (CHS=%d/%d/%d)",
data->geo.cylinders, data->geo.heads, data->geo.cylinders, data->geo.heads,
@@ -769,45 +761,48 @@ disk_is_tape(const char* device)
return rc; return rc;
} }
int /**
disk_is_scsi(const char* device, struct job_target_data* target) * Get "extended type" of base disk by logical DEVICE
{ *
struct disk_info* info; * This function may fail for various reasons. E.g. in case when
int rc = 0; * DEVICE is not eligible for boot record installation (not a
* partition, etc). In case of success the resulted disk type is
if (disk_get_info(device, target, &info) == -1) * stored in EXT_TYPE.
return 0; */
if (info->type == disk_type_scsi) int disk_get_ext_type(const char *device, struct disk_ext_type *ext_type)
rc = 1;
disk_free_info(info);
return rc;
}
int disk_is_eckd_ldl(const char *device, struct job_target_data *target)
{ {
struct job_target_data tmp = {.source = source_unknown};
struct disk_info *info; struct disk_info *info;
int rc = 0;
if (disk_get_info(device, target, &info) == -1) if (disk_get_info(device, &tmp, &info))
return 0; return -1;
if (info->type == disk_type_eckd_ldl) ext_type->type = info->type;
rc = 1; ext_type->is_nvme = info->is_nvme;
disk_free_info(info); disk_free_info(info);
return rc; free_target_data(&tmp);
return 0;
} }
int int disk_type_is_scsi(struct disk_ext_type *ext_type)
disk_is_nvme(const char* device, struct job_target_data* target)
{ {
struct disk_info* info; return ext_type->type == disk_type_scsi;
int rc = 0; }
if (disk_get_info(device, target, &info) == -1) int disk_type_is_eckd_ldl(struct disk_ext_type *ext_type)
return 0; {
if (info->type == disk_type_scsi && info->is_nvme) return ext_type->type == disk_type_eckd_ldl;
rc = 1; }
disk_free_info(info);
return rc; int disk_type_is_nvme(struct disk_ext_type *ext_type)
{
return ext_type->is_nvme;
}
int disk_type_is_eckd(disk_type_t type)
{
return (type == disk_type_eckd_ldl ||
type == disk_type_eckd_cdl);
} }
int int
@@ -1205,7 +1200,7 @@ void disk_print_info(struct disk_info *info, int source)
(info->partnum != 0) ? "partition" : "device"); (info->partnum != 0) ? "partition" : "device");
printf(" Disk layout.....................: %s%s\n", printf(" Disk layout.....................: %s%s\n",
disk_get_type_name(info->type), footnote); disk_get_type_name(info->type), footnote);
if (disk_is_eckd(info->type)) { if (disk_type_is_eckd(info->type)) {
printf(" Geometry - heads................: %d%s\n", printf(" Geometry - heads................: %d%s\n",
info->geo.heads, footnote); info->geo.heads, footnote);
printf(" Geometry - sectors..............: %d%s\n", printf(" Geometry - sectors..............: %d%s\n",

View File

@@ -493,7 +493,7 @@ int install_bootloader(struct job_data *job, struct install_set *bis)
if (job->id == job_dump_partition) { if (job->id == job_dump_partition) {
rc = install_bootloader_dump(bis->tables, info, rc = install_bootloader_dump(bis->tables, info,
scsi_dump_sb_blockptr, scsi_dump_sb_blockptr,
is_ngdump_enabled(job), job_dump_is_ngdump(job),
fd); fd);
} else { } else {
rc = install_bootloader_ipl(bis->tables, info, rc = install_bootloader_ipl(bis->tables, info,

View File

@@ -2057,10 +2057,18 @@ job_get(int argc, char* argv[], struct job_data** data)
return rc; return rc;
} }
bool void job_dump_check_set_ngdump(struct job_data *job,
is_ngdump_enabled(struct job_data *job) struct disk_ext_type *ext_type)
{ {
if (job->is_ldipl_dump) assert(job->id == job_dump_partition);
return true;
return disk_is_nvme(job->data.dump.device, &job->target); if (job->is_ldipl_dump || disk_type_is_nvme(ext_type))
job->data.dump.is_ngdump = true;
}
bool job_dump_is_ngdump(struct job_data *job)
{
assert(job->id == job_dump_partition);
return job->data.dump.is_ngdump;
} }

View File

@@ -128,6 +128,7 @@ check_for_root(void)
int int
main(int argc, char* argv[]) main(int argc, char* argv[])
{ {
struct disk_ext_type ext_type = {0};
struct install_set bis; struct install_set bis;
struct job_data* job; struct job_data* job;
int rc; int rc;
@@ -173,9 +174,13 @@ main(int argc, char* argv[])
/* Do it */ /* Do it */
switch (job->id) { switch (job->id) {
case job_dump_partition: case job_dump_partition:
if (!is_ngdump_enabled(job) && rc = disk_get_ext_type(job->data.dump.device, &ext_type);
if (rc)
break;
job_dump_check_set_ngdump(job, &ext_type);
if (!job_dump_is_ngdump(job) &&
(disk_is_tape(job->data.dump.device) || (disk_is_tape(job->data.dump.device) ||
!disk_is_scsi(job->data.dump.device, &job->target))) { !disk_type_is_scsi(&ext_type))) {
rc = install_dump(job->data.dump.device, &job->target, rc = install_dump(job->data.dump.device, &job->target,
job->data.dump.mem, job->data.dump.no_compress); job->data.dump.mem, job->data.dump.no_compress);
break; break;
@@ -187,8 +192,8 @@ main(int argc, char* argv[])
rc = -1; rc = -1;
break; break;
} }
if (is_ngdump_enabled(job)) { if (job_dump_is_ngdump(job)) {
if (disk_is_eckd_ldl(job->data.dump.device, &job->target)) { if (disk_type_is_eckd_ldl(&ext_type)) {
error_reason("List-directed dump on ECKD with LDL not supported"); error_reason("List-directed dump on ECKD with LDL not supported");
rc = -1; rc = -1;
break; break;