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_t;
struct disk_ext_type {
disk_type_t type;
bool is_nvme;
};
/* targetbase definition */
typedef enum {
defined_as_device,
@@ -87,12 +92,15 @@ struct file_range {
struct job_target_data;
int disk_get_info(const char* device, struct job_target_data* target,
struct disk_info** info);
int disk_is_tape(const char* device);
int disk_is_scsi(const char* device, struct job_target_data* target);
int disk_is_eckd_ldl(const char* device, struct job_target_data* target);
int disk_is_nvme(const char* device, struct job_target_data* target);
int disk_get_info(const char *device, struct job_target_data *target,
struct disk_info **info);
int disk_get_ext_type(const char *device, struct disk_ext_type *ext_type);
int disk_is_tape(const char *device);
int disk_type_is_scsi(struct disk_ext_type *ext_type);
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,
struct job_target_data* target,
struct disk_info** info);

View File

@@ -99,6 +99,7 @@ struct job_dump_data {
struct job_common_ipl_data common;
char* device;
uint64_t mem;
bool is_ngdump;
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 check_job_dump_images(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 */

View File

@@ -1436,7 +1436,7 @@ check_dump_device(struct job_data *job, const struct disk_info *info,
if (!disk_is_appropriate(job, info))
return -1;
if (is_ngdump_enabled(job))
if (job_dump_is_ngdump(job))
return 0;
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))
return -1;
if (job->id == job_dump_partition) {
if (is_ngdump_enabled(job))
if (job_dump_is_ngdump(job))
return prepare_bootloader_ngdump(job, bis);
else
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)
{
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);
else
return 0;

View File

@@ -92,14 +92,6 @@ disk_determine_dasd_type(struct disk_info *data,
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
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++) {
t = target_at(td, i);
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;
}
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, " 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, " sectors.......: %u\n", get_targetsectors(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;
}
/* 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)) {
error_reason("Invalid disk geometry (CHS=%d/%d/%d)",
data->geo.cylinders, data->geo.heads,
@@ -769,45 +761,48 @@ disk_is_tape(const char* device)
return rc;
}
int
disk_is_scsi(const char* device, struct job_target_data* target)
{
struct disk_info* info;
int rc = 0;
if (disk_get_info(device, target, &info) == -1)
return 0;
if (info->type == disk_type_scsi)
rc = 1;
disk_free_info(info);
return rc;
}
int disk_is_eckd_ldl(const char *device, struct job_target_data *target)
/**
* Get "extended type" of base disk by logical DEVICE
*
* This function may fail for various reasons. E.g. in case when
* DEVICE is not eligible for boot record installation (not a
* partition, etc). In case of success the resulted disk type is
* stored in EXT_TYPE.
*/
int disk_get_ext_type(const char *device, struct disk_ext_type *ext_type)
{
struct job_target_data tmp = {.source = source_unknown};
struct disk_info *info;
int rc = 0;
if (disk_get_info(device, target, &info) == -1)
return 0;
if (info->type == disk_type_eckd_ldl)
rc = 1;
if (disk_get_info(device, &tmp, &info))
return -1;
ext_type->type = info->type;
ext_type->is_nvme = info->is_nvme;
disk_free_info(info);
return rc;
free_target_data(&tmp);
return 0;
}
int
disk_is_nvme(const char* device, struct job_target_data* target)
int disk_type_is_scsi(struct disk_ext_type *ext_type)
{
struct disk_info* info;
int rc = 0;
return ext_type->type == disk_type_scsi;
}
if (disk_get_info(device, target, &info) == -1)
return 0;
if (info->type == disk_type_scsi && info->is_nvme)
rc = 1;
disk_free_info(info);
return rc;
int disk_type_is_eckd_ldl(struct disk_ext_type *ext_type)
{
return ext_type->type == disk_type_eckd_ldl;
}
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
@@ -1205,7 +1200,7 @@ void disk_print_info(struct disk_info *info, int source)
(info->partnum != 0) ? "partition" : "device");
printf(" Disk layout.....................: %s%s\n",
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",
info->geo.heads, footnote);
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) {
rc = install_bootloader_dump(bis->tables, info,
scsi_dump_sb_blockptr,
is_ngdump_enabled(job),
job_dump_is_ngdump(job),
fd);
} else {
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;
}
bool
is_ngdump_enabled(struct job_data *job)
void job_dump_check_set_ngdump(struct job_data *job,
struct disk_ext_type *ext_type)
{
if (job->is_ldipl_dump)
return true;
return disk_is_nvme(job->data.dump.device, &job->target);
assert(job->id == job_dump_partition);
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
main(int argc, char* argv[])
{
struct disk_ext_type ext_type = {0};
struct install_set bis;
struct job_data* job;
int rc;
@@ -173,9 +174,13 @@ main(int argc, char* argv[])
/* Do it */
switch (job->id) {
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_scsi(job->data.dump.device, &job->target))) {
!disk_type_is_scsi(&ext_type))) {
rc = install_dump(job->data.dump.device, &job->target,
job->data.dump.mem, job->data.dump.no_compress);
break;
@@ -187,8 +192,8 @@ main(int argc, char* argv[])
rc = -1;
break;
}
if (is_ngdump_enabled(job)) {
if (disk_is_eckd_ldl(job->data.dump.device, &job->target)) {
if (job_dump_is_ngdump(job)) {
if (disk_type_is_eckd_ldl(&ext_type)) {
error_reason("List-directed dump on ECKD with LDL not supported");
rc = -1;
break;