mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
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:
committed by
Jan Höppner
parent
f43789e16a
commit
41da0f0809
@@ -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);
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user