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_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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user