From f375327085e7dd923159e3761be552f79c97a86b Mon Sep 17 00:00:00 2001 From: Eduard Shishkin Date: Thu, 17 Jul 2025 16:43:45 +0200 Subject: [PATCH] zipl/src: Support multiple disk_info structures per logical device Replace struct disk_info with new 2 types. Old type: struct disk_info { A; /* logical device info */ B; /* basedisk info */ }; New types: struct disk_info { B; /* basedisk info */ }; and struct device_info { A; /* logical device info */ struct disk_info C [MAX_TARGETS]; /* array of base disks */ }; Here A (logical device info) is the following: dev_t device; /* logical device for bootmap creation */ char *name; /* name of logical device as reetrieved from "/proc/partitions" */ char *drv_name; /* name of the driver managing the logical device as retrieved from "/proc/devices", or evaluated */ int fs_block_size; Refactor the code respectively, to use only the first element of the array C, so that this patch represents an equivalent transform. Signed-off-by: Eduard Shishkin Reviewed-by: Stefan Haberland Signed-off-by: Steffen Eiden --- zipl/include/disk.h | 65 ++++++---- zipl/include/install.h | 8 +- zipl/src/bootmap.c | 205 ++++++++++++++++++------------ zipl/src/disk.c | 280 ++++++++++++++++++++++------------------- zipl/src/install.c | 131 +++++++++++-------- zipl/src/zipl.c | 3 +- 6 files changed, 402 insertions(+), 290 deletions(-) diff --git a/zipl/include/disk.h b/zipl/include/disk.h index fa562428..22c18912 100644 --- a/zipl/include/disk.h +++ b/zipl/include/disk.h @@ -68,24 +68,33 @@ typedef enum { undefined } definition_t; -/* Disk information type */ +/* Physical disk information type */ struct disk_info { + dev_t disk; disk_type_t type; - dev_t device; /* logical device for bootmap creation */ dev_t partition; int devno; int partnum; int phy_block_size; - int fs_block_size; uint64_t phy_blocks; struct hd_geometry geo; - char* name; - char* drv_name; definition_t targetbase_def; int is_nvme; - dev_t basedisks[MAX_TARGETS]; /* array of physical disks for - * bootstrap blocks recording - */ +}; + +/* Logical device information type */ +struct device_info { + dev_t device; /* logical device for bootmap creation */ + char *name; /* name of the logical device as retrieved + * from "/proc/partitions" + */ + char *drv_name; /* name of the driver managing the logical device + * as retrieved from "/proc/devices", or evaluated + */ + int fs_block_size; + struct disk_info base[MAX_TARGETS]; /* array of physical disks for + * bootstrap blocks recording + */ }; struct file_range { @@ -95,51 +104,55 @@ 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_get_ext_type(const char *device, struct disk_ext_type *ext_type); +int device_get_info(const char *device, struct job_target_data *target, + struct device_info **info); +int disk_get_ext_type(const char *device, struct disk_ext_type *ext_type, + int disk_id); 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_info_set_fs_block(const char *filename, struct disk_info *info); -int disk_get_info_from_file(const char* filename, - struct job_target_data* target, - struct disk_info** info); -void disk_free_info(struct disk_info* info); -char* disk_get_type_name(disk_type_t type); +int device_info_set_fs_block(const char *filename, struct device_info *info); +int device_get_info_from_file(const char *filename, + struct job_target_data *target, + struct device_info **info); +void device_free_info(struct device_info *info); +char *disk_get_type_name(disk_type_t type); char *disk_get_ipl_type(disk_type_t type, int is_dump); int disk_is_large_volume(struct disk_info* info); int disk_cyl_from_blocknum(blocknum_t blocknum, struct disk_info* info); int disk_head_from_blocknum(blocknum_t blocknum, struct disk_info* info); int disk_sec_from_blocknum(blocknum_t blocknum, struct disk_info* info); void disk_blockptr_from_blocknum(disk_blockptr_t* ptr, blocknum_t blocknum, - struct disk_info* info); -int disk_write_block_aligned(struct misc_fd *mfd, const void *data, size_t bytecount, - disk_blockptr_t *block, struct disk_info *info); + struct disk_info *info); +int disk_write_block_aligned(struct misc_fd *mfd, const void *data, + size_t bytecount, disk_blockptr_t *block, + int fs_block_size, struct disk_info *info); blocknum_t disk_write_block_buffer(struct misc_fd *fd, int fd_is_basedisk, const void* buffer, size_t bytecount, disk_blockptr_t** blocklist, - struct disk_info *info); + int fs_block_size, struct disk_info *info); blocknum_t disk_write_block_buffer_align(struct misc_fd *mfd, int fd_is_basedisk, const void *buffer, size_t bytecount, disk_blockptr_t **blocklist, + int fs_block_size, struct disk_info *info, int align, off_t *offset); 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 disk_print_info(struct disk_info *info, int source); -int disk_is_zero_block(disk_blockptr_t* block, struct disk_info* info); +void device_print_info(struct device_info *info, int source); +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); + struct disk_info *info); blocknum_t disk_get_blocklist_from_file(const char* filename, struct file_range *reg, - disk_blockptr_t** blocklist, - struct disk_info* pinfo); + disk_blockptr_t **blocklist, + int fs_block_size, + struct disk_info *info); int disk_check_subchannel_set(int devno, dev_t device, char* dev_name); int fs_map(int fd, uint64_t offset, blocknum_t *mapped, int fs_block_size); diff --git a/zipl/include/install.h b/zipl/include/install.h index 04d54c87..300a9492 100644 --- a/zipl/include/install.h +++ b/zipl/include/install.h @@ -77,7 +77,7 @@ struct install_set { unsigned int tmp_filename_created:1; unsigned int skip_prepare:1; unsigned int print_details:1; - struct disk_info *info; + struct device_info *info; disk_blockptr_t scsi_dump_sb_blockptr; }; @@ -127,11 +127,13 @@ int install_mvdump(char* const device[], struct job_target_data* target, int install_fba_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, disk_blockptr_t *stage2_list, - blocknum_t stage2_count, struct disk_info *info); + blocknum_t stage2_count, int fs_block_size, + struct disk_info *info); int install_eckd_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, disk_blockptr_t *stage2_list, - blocknum_t stage2_count, struct disk_info *info); + blocknum_t stage2_count, int fs_block_size, + struct disk_info *info); int rewind_tape(int fd); #endif /* INSTALL_H */ diff --git a/zipl/src/bootmap.c b/zipl/src/bootmap.c index 9b9136c6..b50d875c 100644 --- a/zipl/src/bootmap.c +++ b/zipl/src/bootmap.c @@ -45,7 +45,7 @@ static bool secure_boot_supported; /* Get size of a bootmap block pointer for disk with given INFO. */ static int -get_blockptr_size(struct disk_info* info) +get_blockptr_size(struct disk_info *info) { switch (info->type) { case disk_type_scsi: @@ -69,8 +69,7 @@ get_blockptr_size(struct disk_info* info) * defined by FORMAT_ID (relevant only for ECKD disk types) */ void bootmap_store_blockptr(void *buffer, disk_blockptr_t *ptr, - struct disk_info *info, - int format_id) + struct disk_info *info, int format_id) { struct eckd_blockptr_legacy *eckd_legacy; struct eckd_blockptr *eckd; @@ -121,7 +120,7 @@ void bootmap_store_blockptr(void *buffer, disk_blockptr_t *ptr, /* Calculate the maximum number of entries in the program table. INFO * specifies the type of disk. */ static int -get_program_table_size(struct disk_info* info) +get_program_table_size(struct disk_info *info) { return PROGRAM_TABLE_BLOCK_SIZE / get_blockptr_size(info) - 1; } @@ -130,7 +129,7 @@ get_program_table_size(struct disk_info* info) static int check_menu_positions(struct job_menu_data* menu, char* name, - struct disk_info* info) + struct disk_info *info) { int i; @@ -181,9 +180,10 @@ check_secure_boot_support(void) * of segment table blocks to the file identified by file descriptor FD. Upon * success, return 0 and set SECTION_POINTER to point to the first block in * the resulting segment table. Return non-zero otherwise. */ -static int add_segment_table(struct misc_fd *mfd, disk_blockptr_t *list, blocknum_t count, - disk_blockptr_t *segment_pointer, - struct disk_info *info, int program_table_id) +static int add_segment_table(struct misc_fd *mfd, disk_blockptr_t *list, + blocknum_t count, disk_blockptr_t *segment_pointer, + int fs_block_size, struct disk_info *info, + int program_table_id) { disk_blockptr_t next; void* buffer; @@ -221,7 +221,7 @@ static int add_segment_table(struct misc_fd *mfd, disk_blockptr_t *list, blocknu &next, info, program_table_id); rc = disk_write_block_aligned(mfd, buffer, info->phy_block_size, - &next, info); + &next, fs_block_size, info); if (rc) { free(buffer); return rc; @@ -233,8 +233,9 @@ static int add_segment_table(struct misc_fd *mfd, disk_blockptr_t *list, blocknu } -static int add_program_table(struct misc_fd *mfd, disk_blockptr_t *table, int entries, - disk_blockptr_t *pointer, struct disk_info *info, +static int add_program_table(struct misc_fd *mfd, disk_blockptr_t *table, + int entries, disk_blockptr_t *pointer, + int fs_block_size, struct disk_info *info, int program_table_id) { void* block; @@ -256,7 +257,7 @@ static int add_program_table(struct misc_fd *mfd, disk_blockptr_t *table, int en } /* Write program table */ rc = disk_write_block_aligned(mfd, block, PROGRAM_TABLE_BLOCK_SIZE, - pointer, info); + pointer, fs_block_size, info); free(block); return rc; } @@ -307,16 +308,16 @@ create_component_header(void* buffer, component_header_type type) * Return 0, if auto-detection succeeded, and it is proven that the * file does NOT locate on DISK. Otherwise, return 1. */ -static int file_is_on_disk(const char *filename, struct disk_info *where) +static int file_is_on_device(const char *filename, struct device_info *where) { /* * Retrieve info of the underlying disk without any user hints */ struct job_target_data tmp = {.source = source_unknown}; - struct disk_info *info; + struct device_info *info; int rc; - rc = disk_get_info_from_file(filename, &tmp, &info); + rc = device_get_info_from_file(filename, &tmp, &info); free_target_data(&tmp); if (rc) { /* @@ -332,11 +333,11 @@ static int file_is_on_disk(const char *filename, struct disk_info *where) "Warning: Preparing a logical device for boot might fail\n"); return 1; } - if (info->basedisks[0] != where->basedisks[0]) { - disk_free_info(info); + if (info->base[0].disk != where->base[0].disk) { + device_free_info(info); return 0; } - disk_free_info(info); + device_free_info(info); return 1; } @@ -350,6 +351,7 @@ static int add_component_file_range(struct install_set *bis, int program_table_id) { struct program_component *pc = get_component(bis, comp_id, menu_idx); + struct disk_info *info = &bis->info->base[0]; struct component_loc *location = &pc->loc; disk_blockptr_t **list = &pc->list; blocknum_t *count = &pc->count; @@ -372,39 +374,44 @@ static int add_component_file_range(struct install_set *bis, size -= trailer; /* Write buffer */ *count = disk_write_block_buffer(&bis->mfd, 0, buffer, - size, list, bis->info); + size, list, + bis->info->fs_block_size, + info); free(buffer); if (*count == 0) { error_text("Could not write to bootmap file"); return -1; } } else { - if (!file_is_on_disk(filename, bis->info)) { + if (!file_is_on_device(filename, bis->info)) { error_reason("File is not on target device"); return -1; } /* Get block list from existing file */ *count = disk_get_blocklist_from_file(filename, reg, - list, bis->info); + list, + bis->info->fs_block_size, + info); if (*count == 0) return -1; - *count -= DIV_ROUND_UP(trailer, bis->info->phy_block_size); + *count -= DIV_ROUND_UP(trailer, info->phy_block_size); } /* Fill in component location */ location->addr = load_address; - location->size = *count * bis->info->phy_block_size; + location->size = *count * info->phy_block_size; /* Try to compact list */ - *count = disk_compact_blocklist(*list, *count, bis->info); + *count = disk_compact_blocklist(*list, *count, info); write_segment_table: assert(*list != NULL); assert(*count != 0); - rc = add_segment_table(&bis->mfd, *list, *count, &segment, bis->info, + rc = add_segment_table(&bis->mfd, *list, *count, &segment, + bis->info->fs_block_size, info, program_table_id); if (rc == 0) create_component_entry(component, &segment, component_type_by_id(comp_id), (component_data)load_address, - bis->info, program_table_id); + info, program_table_id); return rc; } @@ -426,6 +433,7 @@ static int add_component_buffer_align(struct install_set *bis, void *buffer, int program_table_id) { struct program_component *pc = get_component(bis, comp_id, menu_idx); + struct disk_info *info = &bis->info->base[0]; struct component_loc *location = &pc->loc; disk_blockptr_t **list = &pc->list; blocknum_t *count = &pc->count; @@ -437,7 +445,8 @@ static int add_component_buffer_align(struct install_set *bis, void *buffer, goto write_segment_table; /* Write buffer */ *count = disk_write_block_buffer_align(&bis->mfd, 0, buffer, size, list, - bis->info, align, offset); + bis->info->fs_block_size, + info, align, offset); if (*count == 0) { error_text("Could not write to bootmap file"); return -1; @@ -445,23 +454,24 @@ static int add_component_buffer_align(struct install_set *bis, void *buffer, if (component_type_by_id(comp_id) == COMPONENT_TYPE_LOAD) { /* Fill in component location */ location->addr = data.load_address; - location->size = *count * bis->info->phy_block_size; + location->size = *count * info->phy_block_size; } else { location->addr = 0; location->size = 0; } /* Try to compact list */ - *count = disk_compact_blocklist(*list, *count, bis->info); + *count = disk_compact_blocklist(*list, *count, info); write_segment_table: assert(*list != NULL); assert(*count != 0); - rc = add_segment_table(&bis->mfd, *list, *count, &segment, bis->info, + rc = add_segment_table(&bis->mfd, *list, *count, &segment, + bis->info->fs_block_size, info, program_table_id); if (rc == 0) create_component_entry(component, &segment, component_type_by_id(comp_id), - data, bis->info, program_table_id); + data, info, program_table_id); return rc; } @@ -470,8 +480,10 @@ static int add_component_buffer(struct install_set *bis, void *buffer, void *component, int comp_id, int menu_idx, int program_table_id) { + struct disk_info *info = &bis->info->base[0]; + return add_component_buffer_align(bis, buffer, size, data, component, - bis->info->phy_block_size, NULL, + info->phy_block_size, NULL, comp_id, menu_idx, program_table_id); } @@ -579,6 +591,7 @@ static int add_ipl_program(struct install_set *bis, char *filename, int verbose, int add_files, component_header_type type, int is_secure, int menu_idx, int program_table_id) { + struct disk_info *info = &bis->info->base[0]; struct signature_header sig_head; size_t ramdisk_size, image_size; size_t stage3_params_size; @@ -593,7 +606,7 @@ static int add_ipl_program(struct install_set *bis, char *filename, int rc; memset(&sig_head, 0, sizeof(sig_head)); - table = util_zalloc(bis->info->phy_block_size); + table = util_zalloc(info->phy_block_size); if (table == NULL) return -1; /* Create component table */ @@ -622,7 +635,7 @@ static int add_ipl_program(struct install_set *bis, char *filename, } } ramdisk_size = stats.st_size; - if (bis->info->type == disk_type_scsi) { + if (info->type == disk_type_scsi) { flags |= STAGE3_FLAG_SCSI; /* * Add dummy components for stage 3 heap and stack to block the @@ -715,7 +728,7 @@ static int add_ipl_program(struct install_set *bis, char *filename, ramdisk_size, ipl->is_kdump ? IMAGE_ENTRY_KDUMP : IMAGE_ENTRY, - (bis->info->type == disk_type_scsi) ? 0 : 1, + (info->type == disk_type_scsi) ? 0 : 1, flags, ipl->common.image_addr, image_size, ipl->envblk_addr, add_envblk ? envblk->size : 0); @@ -760,7 +773,7 @@ static int add_ipl_program(struct install_set *bis, char *filename, } offset += sizeof(struct component_entry); free(signature); - check_remaining_filesize(image_size, signature_size, bis->info, + check_remaining_filesize(image_size, signature_size, info, ipl->common.image); } else if (is_secure == SECURE_BOOT_ENABLED) { /* @@ -830,8 +843,7 @@ static int add_ipl_program(struct install_set *bis, char *filename, offset += sizeof(struct component_entry); free(signature); check_remaining_filesize(ramdisk_size, signature_size, - bis->info, - ipl->common.ramdisk); + info, ipl->common.ramdisk); } rc = add_component_file(bis, ipl->common.ramdisk, ipl->common.ramdisk_addr, @@ -912,11 +924,11 @@ static int add_ipl_program(struct install_set *bis, char *filename, COMPONENT_TYPE_EXECUTE, (component_data) (uint64_t) (STAGE3_ENTRY | PSW_LOAD), - bis->info, program_table_id); + info, program_table_id); /* Write component table */ rc = disk_write_block_aligned(&bis->mfd, table, - bis->info->phy_block_size, - program, bis->info); + info->phy_block_size, program, + bis->info->fs_block_size, info); free(table); return rc; } @@ -927,11 +939,12 @@ static int add_segment_program(struct install_set *bis, int add_files, component_header_type type, int program_table_id) { + struct disk_info *info = &bis->info->base[0]; void *table; int offset; int rc; - table = util_zalloc(bis->info->phy_block_size); + table = util_zalloc(info->phy_block_size); if (table == NULL) return -1; /* Create component table */ @@ -961,11 +974,11 @@ static int add_segment_program(struct install_set *bis, create_component_entry(VOID_ADD(table, offset), NULL, COMPONENT_TYPE_EXECUTE, (component_data)(uint64_t)PSW_DISABLED_WAIT, - bis->info, program_table_id); + info, program_table_id); /* Write component table */ rc = disk_write_block_aligned(&bis->mfd, table, - bis->info->phy_block_size, - program, bis->info); + info->phy_block_size, program, + bis->info->fs_block_size, info); free(table); return rc; } @@ -998,13 +1011,14 @@ static int add_dump_program(struct install_set *bis, static int build_program_table(struct job_data *job, struct install_set *bis, int program_table_id) { + struct disk_info *info = &bis->info->base[0]; int entries, component_header; disk_blockptr_t *table; int is_secure; int i; int rc; - entries = get_program_table_size(bis->info); + entries = get_program_table_size(info); /* Get some memory for the program table */ table = (disk_blockptr_t *) misc_malloc(sizeof(disk_blockptr_t) * entries); @@ -1140,7 +1154,7 @@ static int build_program_table(struct job_data *job, /* Add program table block */ pointer = &bis->tables[program_table_id].table; rc = add_program_table(&bis->mfd, table, entries, - pointer, bis->info, + pointer, bis->info->fs_block_size, info, program_table_id); } free(table); @@ -1151,7 +1165,8 @@ static int build_program_table(struct job_data *job, /* Write block of zeroes to the bootmap file FD and store the resulting * block pointer in BLOCK. Return zero on success, non-zero otherwise. */ static int -write_empty_block(struct misc_fd *mfd, disk_blockptr_t *block, struct disk_info *info) +write_empty_block(struct misc_fd *mfd, disk_blockptr_t *block, + int fs_block_size, struct disk_info *info) { void* buffer; int rc; @@ -1161,7 +1176,7 @@ write_empty_block(struct misc_fd *mfd, disk_blockptr_t *block, struct disk_info return -1; memset(buffer, 0, info->phy_block_size); rc = disk_write_block_aligned(mfd, buffer, info->phy_block_size, block, - info); + fs_block_size, info); free(buffer); return rc; } @@ -1169,6 +1184,7 @@ write_empty_block(struct misc_fd *mfd, disk_blockptr_t *block, struct disk_info static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename, struct job_data *job, + int fs_block_size, struct disk_info *info, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, @@ -1190,14 +1206,17 @@ static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename, return -1; stage2_count = disk_write_block_buffer(mfd, 0, stage2_data, stage2_size, - &stage2_list, info); + &stage2_list, + fs_block_size, + info); free(stage2_data); if (stage2_count == 0) { error_text("Could not write to file '%s'", filename); return -1; } if (install_fba_stage1b(mfd, stage1b_list, stage1b_count, - stage2_list, stage2_count, info)) + stage2_list, stage2_count, + fs_block_size, info)) return -1; free(stage2_list); break; @@ -1217,6 +1236,7 @@ static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename, static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename, struct job_data *job, + int fs_block_size, struct disk_info *info, disk_blockptr_t *program_table, disk_blockptr_t **stage1b_list, @@ -1239,6 +1259,7 @@ static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename, stage2b_count = disk_write_block_buffer(mfd, 0, stage2b_data, stage2b_size, &stage2b_list, + fs_block_size, info); free(stage2b_data); if (stage2b_count == 0) { @@ -1246,7 +1267,8 @@ static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename, return -1; } if (install_eckd_stage1b(mfd, stage1b_list, stage1b_count, - stage2b_list, stage2b_count, info)) + stage2b_list, stage2b_count, + fs_block_size, info)) return -1; free(stage2b_list); break; @@ -1263,6 +1285,7 @@ static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename, stage2b_count = disk_write_block_buffer(mfd, 0, stage2b_data, stage2b_size, stage1b_list, + fs_block_size, info); free(stage2b_data); if (stage2b_count == 0) { @@ -1281,12 +1304,14 @@ static int bootmap_install_stages(struct job_data *job, struct install_set *bis, int program_table_id) { struct program_table *pt = &bis->tables[program_table_id]; + struct disk_info *info = &bis->info->base[0]; int rc = 0; - switch (bis->info->type) { + switch (info->type) { case disk_type_fba: rc = install_stages_dasd_fba(&bis->mfd, bis->filename, job, - bis->info, + bis->info->fs_block_size, + info, &pt->stage1b_list, &pt->stage1b_count, program_table_id); @@ -1294,7 +1319,8 @@ static int bootmap_install_stages(struct job_data *job, struct install_set *bis, case disk_type_eckd_ldl: case disk_type_eckd_cdl: rc = install_stages_eckd_dasd(&bis->mfd, bis->filename, job, - bis->info, + bis->info->fs_block_size, + info, &pt->table, &pt->stage1b_list, &pt->stage1b_count, @@ -1310,7 +1336,8 @@ static int bootmap_install_stages(struct job_data *job, struct install_set *bis, } static int -bootmap_write_scsi_superblock(struct misc_fd *mfd, struct disk_info *info, +bootmap_write_scsi_superblock(struct misc_fd *mfd, int fs_block_size, + struct disk_info *info, disk_blockptr_t *scsi_dump_sb_blockptr, ulong dump_size) { @@ -1327,9 +1354,9 @@ bootmap_write_scsi_superblock(struct misc_fd *mfd, struct disk_info *info, scsi_sb.csum_size = SCSI_DUMP_SB_CSUM_SIZE; /* Set seed because otherwise csum over zero block is 0 */ scsi_sb.csum = SCSI_DUMP_SB_SEED; - return disk_write_block_aligned(mfd, &scsi_sb, - sizeof(scsi_sb), - scsi_dump_sb_blockptr, info); + return disk_write_block_aligned(mfd, &scsi_sb, sizeof(scsi_sb), + scsi_dump_sb_blockptr, fs_block_size, + info); } @@ -1438,6 +1465,7 @@ check_dump_device(struct job_data *job, const struct disk_info *info, static int prepare_build_program_table_device(struct job_data *job, struct install_set *bis) { + struct disk_info *info; ulong unused_size; if (bis->skip_prepare) @@ -1452,16 +1480,17 @@ static int prepare_build_program_table_device(struct job_data *job, return -1; } /* Retrieve target device information */ - if (disk_get_info(bis->filename, &job->target, &bis->info)) + if (device_get_info(bis->filename, &job->target, &bis->info)) return -1; if (verbose) { printf("Target device information\n"); - disk_print_info(bis->info, job->target.source); + device_print_info(bis->info, job->target.source); } - if (misc_temp_dev(bis->info->basedisks[0], 1, &bis->basetmp[0])) + info = &bis->info->base[0]; + if (misc_temp_dev(info->disk, 1, &bis->basetmp[0])) return -1; - if (check_dump_device(job, bis->info, bis->basetmp[0])) + if (check_dump_device(job, info, bis->basetmp[0])) return -1; printf("Building bootmap directly on partition '%s'%s\n", bis->filename, @@ -1469,7 +1498,7 @@ static int prepare_build_program_table_device(struct job_data *job, : ""); /* For partition dump set raw partition offset to expected size before end of disk */ - if (estimate_scsi_dump_size(job, bis->info, &unused_size)) + if (estimate_scsi_dump_size(job, info, &unused_size)) return -1; if (lseek(bis->mfd.fd, unused_size, SEEK_SET) < 0) return -1; @@ -1481,12 +1510,14 @@ static int prepare_build_program_table_device(struct job_data *job, return -1; } /* Write empty block to be read in place of holes in files */ - if (write_empty_block(&bis->mfd, &empty_block, bis->info)) { + if (write_empty_block(&bis->mfd, &empty_block, + bis->info->fs_block_size, info)) { error_text("Could not write to file '%s'", bis->filename); return -1; } - if (bootmap_write_scsi_superblock(&bis->mfd, bis->info, + if (bootmap_write_scsi_superblock(&bis->mfd, + bis->info->fs_block_size, info, &bis->scsi_dump_sb_blockptr, unused_size)) { error_text("Could not write SCSI superblock to file '%s'", @@ -1525,6 +1556,7 @@ static int prepare_bootloader_device(struct job_data *job, static int prepare_build_program_table_file(struct job_data *job, struct install_set *bis) { + struct disk_info *info; int i; if (bis->skip_prepare) @@ -1561,36 +1593,36 @@ static int prepare_build_program_table_file(struct job_data *job, * Retrieve file system block size from the proxy * file system */ - if (disk_get_info(job->data.dump.device, - &job->target, &bis->info)) + if (device_get_info(job->data.dump.device, + &job->target, &bis->info)) return -1; - if (disk_info_set_fs_block(bis->filename, bis->info)) + if (device_info_set_fs_block(bis->filename, bis->info)) return -1; } else { /* * ngdump or ipl job. */ - if (disk_get_info_from_file(bis->filename, - &job->target, - &bis->info)) + if (device_get_info_from_file(bis->filename, + &job->target, + &bis->info)) return -1; } - if (!disk_is_appropriate(job, bis->info)) + info = &bis->info->base[0]; + + if (!disk_is_appropriate(job, info)) return -1; if (verbose) { printf("Target device information\n"); - disk_print_info(bis->info, job->target.source); + device_print_info(bis->info, job->target.source); } for (i = 0; i < job_get_nr_targets(job); i++) { - if (misc_temp_dev(bis->info->basedisks[i], - 1, - &bis->basetmp[i])) + if (misc_temp_dev(bis->info->base[i].disk, 1, &bis->basetmp[i])) return -1; } /* Check configuration number limits */ if (job->id == job_menu) { if (check_menu_positions(&job->data.menu, job->name, - bis->info)) + info)) return -1; } printf("Building bootmap in '%s'%s\n", job->target.bootmap_dir, @@ -1603,7 +1635,8 @@ static int prepare_build_program_table_file(struct job_data *job, return -1; } /* Write empty block to be read in place of holes in files */ - if (write_empty_block(&bis->mfd, &empty_block, bis->info)) { + if (write_empty_block(&bis->mfd, &empty_block, + bis->info->fs_block_size, info)) { error_text("Could not write to file '%s'", bis->filename); return -1; } @@ -1760,12 +1793,14 @@ static char *build_mount_point_pathname(void) static int prepare_bootloader_ngdump(struct job_data *job, struct install_set *bis) { + struct device_info *dev_info; struct disk_info *info; /* Retrieve target device information */ - if (disk_get_info(job->data.dump.device, &job->target, &info)) + if (device_get_info(job->data.dump.device, &job->target, &dev_info)) return -1; - if (misc_temp_dev(info->basedisks[0], 1, &bis->basetmp[0])) + info = &dev_info->base[0]; + if (misc_temp_dev(info->disk, 1, &bis->basetmp[0])) return -1; if (check_dump_device(job, info, bis->basetmp[0])) return -1; @@ -1810,6 +1845,8 @@ static int prepare_bootloader_ngdump(struct job_data *job, */ static int prepare_bootloader_ipl(struct job_data *job, struct install_set *bis) { + struct disk_info *info; + /* * Build a program table for List-Directed IPL from * SCSI or ECKD DASD @@ -1817,7 +1854,9 @@ static int prepare_bootloader_ipl(struct job_data *job, struct install_set *bis) bis->print_details = 1; if (bootmap_create_file(job, bis, BLKPTR_FORMAT_ID)) return -1; - if (bis->info->type == disk_type_scsi) + + info = &bis->info->base[0]; + if (info->type == disk_type_scsi) /* only one table to be installed per device */ return 0; /* @@ -1917,5 +1956,5 @@ void free_bootloader(struct install_set *bis) if (bis->basetmp[i]) misc_free_temp_dev(bis->basetmp[i]); } - disk_free_info(bis->info); + device_free_info(bis->info); } diff --git a/zipl/src/disk.c b/zipl/src/disk.c index 2b320511..15195aa7 100644 --- a/zipl/src/disk.c +++ b/zipl/src/disk.c @@ -104,9 +104,10 @@ read_block_by_offset(int fd, int blksize, uint64_t offset, char *buffer) return 0; } -static int determine_virtblk_type(struct disk_info *data, +static int determine_virtblk_type(struct device_info *dev_info, const struct stat *stats) { + struct disk_info *data = &dev_info->base[0]; char *device; char *buffer; int fd, rc, shift, sb; @@ -131,9 +132,9 @@ static int determine_virtblk_type(struct disk_info *data, if (data->geo.heads == 15) { /* assume DASD */ data->partnum = stats->st_rdev & DASD_PARTN_MASK; - data->device = stats->st_rdev & ~DASD_PARTN_MASK; + dev_info->device = stats->st_rdev & ~DASD_PARTN_MASK; - rc = misc_temp_dev(data->device, 1, &device); + rc = misc_temp_dev(dev_info->device, 1, &device); if (rc) goto out_err; @@ -167,7 +168,7 @@ static int determine_virtblk_type(struct disk_info *data, } else { data->type = disk_type_scsi; data->partnum = stats->st_rdev & SCSI_PARTN_MASK; - data->device = stats->st_rdev & ~SCSI_PARTN_MASK; + dev_info->device = stats->st_rdev & ~SCSI_PARTN_MASK; } out_err: @@ -309,40 +310,40 @@ static void print_base_disk_params(struct job_target_data *td, int index) * Set disk info using ready target parameters provided either by * user, or by script */ -static int disk_set_info_by_hint(struct job_target_data *td, - struct disk_info *data, int fd) +static int device_set_info_by_hint(struct job_target_data *td, + struct device_info *data, int fd) { int majnum, minnum; struct stat stats; int i; - /* - * Currently multiple base disks with different parameters - * are not supported - */ - data->devno = -1; - data->phy_block_size = get_targetblocksize(td, 0); - data->type = get_targettype(td, 0); assert(td->nr_targets != 0); - for (i = 1; i < td->nr_targets; i++) { - if (data->type != get_targettype(td, i) || - data->phy_block_size != get_targetblocksize(td, i)) { + /* set devno, type, phy_block_size */ + for (i = 0; i < td->nr_targets; i++) { + data->base[i].devno = -1; + 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; } } - data->partnum = 0; - data->targetbase_def = undefined; - + /* set disk, targetbase_def, partnum, is_nvme */ for (i = 0; i < td->nr_targets; i++) { - definition_t defined_as; - if (sscanf(get_targetbase(td, i), "%d:%d", &majnum, &minnum) == 2) { - data->basedisks[i] = makedev(majnum, minnum); - defined_as = defined_as_device; + data->base[i].disk = makedev(majnum, minnum); + data->base[i].targetbase_def = defined_as_device; } else { if (stat(get_targetbase(td, i), &stats)) { error_reason(strerror(errno)); @@ -356,47 +357,51 @@ static int disk_set_info_by_hint(struct job_target_data *td, get_targetbase(td, i)); return -1; } - data->basedisks[i] = stats.st_rdev; - defined_as = defined_as_name; + data->base[i].disk = stats.st_rdev; + data->base[i].targetbase_def = defined_as_name; } - if (data->targetbase_def != undefined && - data->targetbase_def != defined_as) { + if (data->base[i].targetbase_def != + data->base[0].targetbase_def) { error_reason("Target base disks are defined by different ways"); return -1; } - data->targetbase_def = defined_as; + data->base[i].partnum = 0; + if (data->base[i].type == disk_type_scsi && + ioctl(fd, NVME_IOCTL_ID) >= 0) + data->base[i].is_nvme = 1; } - if (data->type == disk_type_scsi && ioctl(fd, NVME_IOCTL_ID) >= 0) - data->is_nvme = 1; return 0; } /** * Calculate target parameters in the case when no hints were provided */ -static int disk_set_info_auto(struct disk_info *data, +static int disk_set_info_auto(struct device_info *dev_info, const struct stat *stats, int fd) { + struct disk_info *data = &dev_info->base[0]; struct dasd_information dasd_info; if (ioctl(fd, BLKSSZGET, &data->phy_block_size)) { error_reason("Could not get blocksize"); return -1; } - if (!data->drv_name) { + if (!dev_info->drv_name) { /* Driver name cannot be read */ if (ioctl(fd, BIODASDINFO, &dasd_info)) { data->devno = -1; if (data->geo.start) { /* SCSI partition */ data->type = disk_type_scsi; - data->partnum = stats->st_rdev & SCSI_PARTN_MASK; - data->device = stats->st_rdev & ~SCSI_PARTN_MASK; + data->partnum = + stats->st_rdev & SCSI_PARTN_MASK; + dev_info->device = + stats->st_rdev & ~SCSI_PARTN_MASK; } else { /* SCSI disk */ data->type = disk_type_scsi; data->partnum = 0; - data->device = stats->st_rdev; + dev_info->device = stats->st_rdev; } } else { /* DASD */ @@ -404,9 +409,9 @@ static int disk_set_info_auto(struct disk_info *data, if (disk_determine_dasd_type(data, dasd_info)) return -1; data->partnum = stats->st_rdev & DASD_PARTN_MASK; - data->device = stats->st_rdev & ~DASD_PARTN_MASK; + dev_info->device = stats->st_rdev & ~DASD_PARTN_MASK; } - } else if (strcmp(data->drv_name, UTIL_PROC_DEV_ENTRY_DASD) == 0) { + } else if (strcmp(dev_info->drv_name, UTIL_PROC_DEV_ENTRY_DASD) == 0) { /* Driver name is 'dasd' */ if (ioctl(fd, BIODASDINFO, &dasd_info)) { error_reason("Could not determine DASD type"); @@ -416,27 +421,29 @@ static int disk_set_info_auto(struct disk_info *data, if (disk_determine_dasd_type(data, dasd_info)) return -1; data->partnum = stats->st_rdev & DASD_PARTN_MASK; - data->device = stats->st_rdev & ~DASD_PARTN_MASK; - } else if (strcmp(data->drv_name, UTIL_PROC_DEV_ENTRY_SD) == 0) { + dev_info->device = stats->st_rdev & ~DASD_PARTN_MASK; + } else if (strcmp(dev_info->drv_name, UTIL_PROC_DEV_ENTRY_SD) == 0) { /* Driver name is 'sd' */ data->devno = -1; data->type = disk_type_scsi; data->partnum = stats->st_rdev & SCSI_PARTN_MASK; - data->device = stats->st_rdev & ~SCSI_PARTN_MASK; + dev_info->device = stats->st_rdev & ~SCSI_PARTN_MASK; - } else if (strcmp(data->drv_name, UTIL_PROC_DEV_ENTRY_VIRTBLK) == 0) { + } else if (strcmp(dev_info->drv_name, + UTIL_PROC_DEV_ENTRY_VIRTBLK) == 0) { /* Driver name is 'virtblk' */ if (ioctl(fd, HDIO_GETGEO, &data->geo) != 0) perror("Could not retrieve disk geometry information."); if (ioctl(fd, BLKSSZGET, &data->phy_block_size) != 0) perror("Could not retrieve blocksize information."); - if (determine_virtblk_type(data, stats)) { + if (determine_virtblk_type(dev_info, stats)) { error_reason("Virtblk device type not clearly " "determined."); return -1; } - } else if (strcmp(data->drv_name, UTIL_PROC_DEV_ENTRY_BLKEXT) == 0 && + } else if (strcmp(dev_info->drv_name, + UTIL_PROC_DEV_ENTRY_BLKEXT) == 0 && ioctl(fd, NVME_IOCTL_ID) >= 0) { /* NVMe path, driver name is 'blkext' */ data->devno = -1; @@ -444,18 +451,20 @@ static int disk_set_info_auto(struct disk_info *data, data->is_nvme = 1; if (util_sys_dev_is_partition(stats->st_rdev)) { - if (util_sys_get_base_dev(stats->st_rdev, &data->device)) + if (util_sys_get_base_dev(stats->st_rdev, + &dev_info->device)) return -1; data->partnum = util_sys_get_partnum(stats->st_rdev); if (data->partnum == -1) return -1; } else { - data->device = stats->st_rdev; + dev_info->device = stats->st_rdev; data->partnum = 0; } } else { /* Driver name is unknown */ - error_reason("Unsupported device driver '%s'", data->drv_name); + error_reason("Unsupported device driver '%s'", + dev_info->drv_name); return -1; } return 0; @@ -488,7 +497,7 @@ static void set_source_type(struct job_target_data *td, td->source = source_auto; } -static void set_driver_name(int fd, struct disk_info *info, dev_t device) +static void set_driver_name(int fd, struct device_info *info, dev_t device) { struct util_proc_dev_entry dev_entry; @@ -555,25 +564,26 @@ static int run_targetbase_script(struct job_target_data *td, * Note: geo.start contains a sector number offset measured in * physical blocks, not sectors (512 bytes) */ -static int disk_set_geometry_by_hint(struct job_target_data *td, - struct disk_info *data) +static int device_set_geometry_by_hint(struct job_target_data *td, + struct device_info *data) { int i; - /* - * Currently multiple base disks with different parameters - * are not supported - */ - data->geo.heads = get_targetheads(td, 0); - data->geo.sectors = get_targetsectors(td, 0); - data->geo.cylinders = get_targetcylinders(td, 0); - data->geo.start = get_targetoffset(td, 0); assert(td->nr_targets != 0); - for (i = 1; i < td->nr_targets; i++) { - if (data->geo.heads != get_targetheads(td, i) || - data->geo.sectors != get_targetsectors(td, i) || - data->geo.cylinders != get_targetcylinders(td, i) || - data->geo.start != get_targetoffset(td, i)) { + for (i = 0; i < td->nr_targets; i++) { + data->base[i].geo.heads = get_targetheads(td, i); + 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"); @@ -600,9 +610,10 @@ static int disk_set_geometry_auto(int fd, struct disk_info *info) * Pre-condition: disk type is already known and set at DATA->type */ static int disk_set_info_complete(struct job_target_data *td, - struct disk_info *data, + struct device_info *dev_info, struct stat *stats, int fd) { + struct disk_info *data = &dev_info->base[0]; struct util_proc_part_entry part_entry; long devsize; @@ -632,14 +643,14 @@ static int disk_set_info_complete(struct job_target_data *td, if (data->partnum != 0) data->partition = stats->st_rdev; /* Try to get device name */ - if (util_proc_part_get_entry(data->device, &part_entry) == 0) { - data->name = misc_strdup(part_entry.name); + if (util_proc_part_get_entry(dev_info->device, &part_entry) == 0) { + dev_info->name = misc_strdup(part_entry.name); util_proc_part_free_entry(&part_entry); - if (data->name == NULL) + if (!dev_info->name) return -1; } /* Initialize file system block size with invalid value */ - data->fs_block_size = -1; + dev_info->fs_block_size = -1; return 0; } @@ -666,11 +677,11 @@ static int disk_set_info_complete(struct job_target_data *td, * DEVICE: logical, or physical device, optionally formatted with a * file system. */ -int disk_get_info(const char *device, struct job_target_data *td, - struct disk_info **info) +int device_get_info(const char *device, struct job_target_data *td, + struct device_info **info) { char *script_file = NULL; - struct disk_info *data; + struct device_info *data; struct stat stats; int fd; @@ -683,10 +694,10 @@ int disk_get_info(const char *device, struct job_target_data *td, error_reason(strerror(errno)); return -1; } - data = (struct disk_info *)misc_malloc(sizeof(struct disk_info)); + data = (struct device_info *)misc_malloc(sizeof(struct device_info)); if (!data) goto error; - memset((void *)data, 0, sizeof(struct disk_info)); + memset((void *)data, 0, sizeof(struct device_info)); set_driver_name(fd, data, stats.st_rdev); set_source_type(td, data->drv_name, &script_file); switch (td->source) { @@ -696,9 +707,9 @@ int disk_get_info(const char *device, struct job_target_data *td, /* target parameters were set by the script output */ assert(target_parameters_are_set(td)); - if (disk_set_geometry_by_hint(td, data)) + if (device_set_geometry_by_hint(td, data)) goto error; - if (disk_set_info_by_hint(td, data, fd)) + if (device_set_info_by_hint(td, data, fd)) goto error; data->device = stats.st_rdev; break; @@ -709,20 +720,20 @@ int disk_get_info(const char *device, struct job_target_data *td, */ assert(target_parameters_are_set(td)); - if (disk_set_geometry_by_hint(td, data)) + if (device_set_geometry_by_hint(td, data)) goto error; - if (disk_set_info_by_hint(td, data, fd)) + if (device_set_info_by_hint(td, data, fd)) goto error; /* * multiple base disks are not supported * with this source type */ assert(td->nr_targets == 1); - data->device = data->basedisks[0]; + data->device = data->base[0].disk; break; case source_auto: /* no ready target parameters are available */ - if (disk_set_geometry_auto(fd, data)) + if (disk_set_geometry_auto(fd, &data->base[0])) goto error; if (disk_set_info_auto(data, &stats, fd)) goto error; @@ -730,7 +741,7 @@ int disk_get_info(const char *device, struct job_target_data *td, * multiple base disks are not supported * with this source type */ - data->basedisks[0] = data->device; + data->base[0].disk = data->device; td->nr_targets = 1; break; default: @@ -772,17 +783,20 @@ disk_is_tape(const char* device) * 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) +int disk_get_ext_type(const char *device, struct disk_ext_type *ext_type, + int disk_idx) { struct job_target_data tmp = {.source = source_unknown}; + struct device_info *dev_info; struct disk_info *info; - if (disk_get_info(device, &tmp, &info)) + if (device_get_info(device, &tmp, &dev_info)) return -1; + info = &dev_info->base[disk_idx]; ext_type->type = info->type; ext_type->is_nvme = info->is_nvme; - disk_free_info(info); + device_free_info(dev_info); free_target_data(&tmp); return 0; } @@ -811,7 +825,7 @@ int disk_type_is_eckd(disk_type_t type) /** * Retrieve and set block size of the file system which contains FILENAME */ -int disk_info_set_fs_block(const char *filename, struct disk_info *info) +int device_info_set_fs_block(const char *filename, struct device_info *dinfo) { int blocksize; int fd; @@ -830,7 +844,7 @@ int disk_info_set_fs_block(const char *filename, struct disk_info *info) filename); return -1; } - info->fs_block_size = blocksize; + dinfo->fs_block_size = blocksize; return 0; } @@ -838,9 +852,9 @@ int disk_info_set_fs_block(const char *filename, struct disk_info *info) * Retrieve disk info of the device which contains FILENAME * and set the filesystem block size */ -int disk_get_info_from_file(const char *filename, - struct job_target_data *target, - struct disk_info **info) +int device_get_info_from_file(const char *filename, + struct job_target_data *target, + struct device_info **info) { struct stat stats; char *device; @@ -851,15 +865,15 @@ int disk_get_info_from_file(const char *filename, } if (misc_temp_dev(stats.st_dev, 1, &device)) return -1; - if (disk_get_info(device, target, info)) { + if (device_get_info(device, target, info)) { misc_free_temp_dev(device); return -1; } misc_free_temp_dev(device); - return disk_info_set_fs_block(filename, *info); + return device_info_set_fs_block(filename, *info); } -void disk_free_info(struct disk_info *info) +void device_free_info(struct device_info *info) { if (!info) return; @@ -877,28 +891,29 @@ void disk_free_info(struct disk_info *info) * otherwise. */ static int disk_get_blocknum(int fd, int fd_is_basedisk, blocknum_t logical, - blocknum_t* physical, struct disk_info* info) + blocknum_t *physical, int fs_block_size, + struct disk_info *disk_info) { blocknum_t phy_per_fs; blocknum_t mapped; int subblock; /* No file system: partition or raw disk */ - if (info->fs_block_size == -1) { + if (fs_block_size == -1) { if (fd_is_basedisk) *physical = logical; else - *physical = logical + info->geo.start; + *physical = logical + disk_info->geo.start; return 0; } /* * Get mapping in file system blocks */ - phy_per_fs = info->fs_block_size / info->phy_block_size; + phy_per_fs = fs_block_size / disk_info->phy_block_size; subblock = logical % phy_per_fs; - if (fs_map(fd, logical * info->phy_block_size, - &mapped, info->fs_block_size) != 0) + if (fs_map(fd, logical * disk_info->phy_block_size, + &mapped, fs_block_size) != 0) return -1; if (mapped == 0) { /* This is a hole in the file */ @@ -907,7 +922,7 @@ disk_get_blocknum(int fd, int fd_is_basedisk, blocknum_t logical, /* Convert file system block to physical */ *physical = mapped * phy_per_fs + subblock; /* Add partition start */ - *physical += info->geo.start; + *physical += disk_info->geo.start; } return 0; } @@ -916,7 +931,7 @@ disk_get_blocknum(int fd, int fd_is_basedisk, blocknum_t logical, /* Return the cylinder on which the block number BLOCKNUM is stored on the * CHS device identified by INFO. */ int -disk_cyl_from_blocknum(blocknum_t blocknum, struct disk_info* info) +disk_cyl_from_blocknum(blocknum_t blocknum, struct disk_info *info) { return blocknum / (info->geo.heads * info->geo.sectors); } @@ -925,7 +940,7 @@ disk_cyl_from_blocknum(blocknum_t blocknum, struct disk_info* info) /* Return the head on which the block number BLOCKNUM is stored on the * CHS device identified by INFO. */ int -disk_head_from_blocknum(blocknum_t blocknum, struct disk_info* info) +disk_head_from_blocknum(blocknum_t blocknum, struct disk_info *info) { return (blocknum / info->geo.sectors) % info->geo.heads; } @@ -934,7 +949,7 @@ disk_head_from_blocknum(blocknum_t blocknum, struct disk_info* info) /* Return the sector on which the block number BLOCKNUM is stored on the * CHS device identified by INFO. */ int -disk_sec_from_blocknum(blocknum_t blocknum, struct disk_info* info) +disk_sec_from_blocknum(blocknum_t blocknum, struct disk_info *info) { return blocknum % info->geo.sectors + 1; } @@ -945,7 +960,7 @@ disk_sec_from_blocknum(blocknum_t blocknum, struct disk_info* info) * layout. */ void disk_blockptr_from_blocknum(disk_blockptr_t* ptr, blocknum_t blocknum, - struct disk_info* info) + struct disk_info *info) { switch (info->type) { case disk_type_scsi: @@ -986,8 +1001,9 @@ disk_blockptr_from_blocknum(disk_blockptr_t* ptr, blocknum_t blocknum, * otherwise. On success OFFSET contains offset of the first written byte */ static int -disk_write_block_aligned_base(struct misc_fd *mfd, int is_base_disk, const void *data, - size_t bytecount, disk_blockptr_t *block, +disk_write_block_aligned_base(struct misc_fd *mfd, int is_base_disk, + const void *data, size_t bytecount, + disk_blockptr_t *block, int fs_block_size, struct disk_info *info, int align, off_t *offset) { blocknum_t current_block; @@ -1021,7 +1037,7 @@ disk_write_block_aligned_base(struct misc_fd *mfd, int is_base_disk, const void if (block != NULL) { /* Store block pointer */ if (disk_get_blocknum(mfd->fd, is_base_disk, current_block, - &blocknum, info)) + &blocknum, fs_block_size, info)) return -1; disk_blockptr_from_blocknum(block, blocknum, info); } @@ -1030,11 +1046,13 @@ disk_write_block_aligned_base(struct misc_fd *mfd, int is_base_disk, const void return 0; } -int disk_write_block_aligned(struct misc_fd *mfd, const void *data, size_t bytecount, - disk_blockptr_t *block, struct disk_info *info) +int disk_write_block_aligned(struct misc_fd *mfd, const void *data, + size_t bytecount, disk_blockptr_t *block, + int fs_block_size, struct disk_info *info) { return disk_write_block_aligned_base(mfd, 0, data, bytecount, block, - info, info->phy_block_size, NULL); + fs_block_size, info, + info->phy_block_size, NULL); } /** @@ -1047,8 +1065,9 @@ int disk_write_block_aligned(struct misc_fd *mfd, const void *data, size_t bytec * otherwise. */ blocknum_t -disk_write_block_buffer_align(struct misc_fd *mfd, int fd_is_basedisk, const void *buffer, - size_t bytecount, disk_blockptr_t **blocklist, +disk_write_block_buffer_align(struct misc_fd *mfd, int fd_is_basedisk, + const void *buffer, size_t bytecount, + disk_blockptr_t **blocklist, int fs_block_size, struct disk_info *info, int align, off_t *offset) { blocknum_t count; @@ -1074,6 +1093,7 @@ disk_write_block_buffer_align(struct misc_fd *mfd, int fd_is_basedisk, const voi rc = disk_write_block_aligned_base(mfd, fd_is_basedisk, VOID_ADD(buffer, written), chunk_size, &(*blocklist)[i], + fs_block_size, info, i == 0 ? align : info->phy_block_size, &pos); @@ -1086,12 +1106,14 @@ disk_write_block_buffer_align(struct misc_fd *mfd, int fd_is_basedisk, const voi } blocknum_t -disk_write_block_buffer(struct misc_fd *mfd, int fd_is_basedisk, const void *buffer, - size_t bytecount, disk_blockptr_t **blocklist, +disk_write_block_buffer(struct misc_fd *mfd, int fd_is_basedisk, + const void *buffer, size_t bytecount, + disk_blockptr_t **blocklist, int fs_block_size, struct disk_info *info) { return disk_write_block_buffer_align(mfd, fd_is_basedisk, buffer, - bytecount, blocklist, info, + bytecount, blocklist, + fs_block_size, info, info->phy_block_size, NULL); } @@ -1168,7 +1190,7 @@ char *disk_get_ipl_type(disk_type_t type, int is_dump) /* Return non-zero for ECKD large volumes. */ int -disk_is_large_volume(struct disk_info* info) +disk_is_large_volume(struct disk_info *info) { return (info->type == disk_type_eckd_ldl || info->type == disk_type_eckd_cdl) && @@ -1177,13 +1199,14 @@ disk_is_large_volume(struct disk_info* info) /* Print textual representation of INFO contents. */ -void disk_print_info(struct disk_info *info, int source) +void device_print_info(struct device_info *this, int source) { + struct disk_info *info = &this->base[0]; char footnote[4] = ""; prepare_footnote_ptr(source, footnote); printf(" Device..........................: "); - disk_print_devt(info->device); + disk_print_devt(this->device); if (info->targetbase_def == defined_as_device) printf("%s", footnote); printf("\n"); @@ -1192,16 +1215,16 @@ void disk_print_info(struct disk_info *info, int source) disk_print_devt(info->partition); printf("\n"); } - if (info->name) { + if (this->name) { printf(" Device name.....................: %s", - info->name); + this->name); if (info->targetbase_def == defined_as_name) printf("%s", footnote); printf("\n"); } - if (info->drv_name) { + if (this->drv_name) { printf(" Device driver name..............: %s\n", - info->drv_name); + this->drv_name); } if (((info->type == disk_type_fba) || (info->type == disk_type_diag) || @@ -1231,9 +1254,9 @@ void disk_print_info(struct disk_info *info, int source) } printf(" Geometry - start................: %ld%s\n", info->geo.start, footnote); - if (info->fs_block_size >= 0) + if (this->fs_block_size >= 0) printf(" File system block size..........: %d\n", - info->fs_block_size); + this->fs_block_size); printf(" Physical block size.............: %d%s\n", info->phy_block_size, footnote); printf(" Device size in physical blocks..: %ld\n", @@ -1244,7 +1267,7 @@ void disk_print_info(struct disk_info *info, int source) /* Check whether a block is a zero block which identifies a hole in a file. * Return non-zero if BLOCK is a zero block, 0 otherwise. */ int -disk_is_zero_block(disk_blockptr_t* block, struct disk_info* info) +disk_is_zero_block(disk_blockptr_t *block, struct disk_info *info) { switch (info->type) { case disk_type_scsi: @@ -1270,7 +1293,7 @@ disk_is_zero_block(disk_blockptr_t* block, struct disk_info* info) * blocks can be merged, 0 otherwise. */ static int can_merge_blocks(disk_blockptr_t* first, disk_blockptr_t* second, - struct disk_info* info) + struct disk_info *info) { int max_count; @@ -1316,7 +1339,7 @@ can_merge_blocks(disk_blockptr_t* first, disk_blockptr_t* second, * type. */ static void merge_blocks(disk_blockptr_t* first, disk_blockptr_t* second, - struct disk_info* info) + struct disk_info *info) { switch (info->type) { case disk_type_scsi: @@ -1339,7 +1362,7 @@ merge_blocks(disk_blockptr_t* first, disk_blockptr_t* second, * number of elements in the list. */ blocknum_t disk_compact_blocklist(disk_blockptr_t* list, blocknum_t count, - struct disk_info* info) + struct disk_info *info) { blocknum_t i; blocknum_t last; @@ -1366,8 +1389,8 @@ disk_compact_blocklist(disk_blockptr_t* list, blocknum_t count, */ blocknum_t disk_get_blocklist_from_file(const char *filename, struct file_range *reg, - disk_blockptr_t **blocklist, - struct disk_info* info) + disk_blockptr_t **blocklist, int fs_block_size, + struct disk_info *info) { struct stat stats; int fd; @@ -1420,7 +1443,8 @@ disk_get_blocklist_from_file(const char *filename, struct file_range *reg, } /* Build list */ for (i = 0; i < blk_count; i++) { - if (disk_get_blocknum(fd, 0, blk_off + i, &blocknum, info)) { + if (disk_get_blocknum(fd, 0, blk_off + i, &blocknum, + fs_block_size, info)) { close(fd); return 0; } diff --git a/zipl/src/install.c b/zipl/src/install.c index 0d0e3c89..3c614f3d 100644 --- a/zipl/src/install.c +++ b/zipl/src/install.c @@ -172,7 +172,8 @@ install_fba_ccw(int fd, disk_blockptr_t *program_table, int install_eckd_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, disk_blockptr_t *stage2_list, - blocknum_t stage2_count, struct disk_info *info) + blocknum_t stage2_count, int fs_block_size, + struct disk_info *info) { struct boot_eckd_stage1b *stage1b; int stage1b_size, rc = -1; @@ -187,7 +188,8 @@ install_eckd_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, if (boot_init_eckd_stage1b(stage1b, stage2_list, stage2_count)) goto out_free_stage1b; *stage1b_count = disk_write_block_buffer(mfd, 1, stage1b, stage1b_size, - stage1b_list, info); + stage1b_list, fs_block_size, + info); if (*stage1b_count == 0) goto out_free_stage1b; rc = 0; @@ -430,7 +432,7 @@ static int install_bootloader_dump(struct program_table *tables, int install_bootloader(struct job_data *job, struct install_set *bis) { disk_blockptr_t *scsi_dump_sb_blockptr = &bis->scsi_dump_sb_blockptr; - struct disk_info *info = bis->info; + struct disk_info *info = &bis->info->base[0]; char footnote[4]; int rc; int i; @@ -444,15 +446,15 @@ int install_bootloader(struct job_data *job, struct install_set *bis) disk_get_ipl_type(info->type, job->id == job_dump_partition), job->id == job_dump_partition ? "dump" : "IPL"); - if (info->name) { - printf("%s", info->name); + if (bis->info->name) { + printf("%s", bis->info->name); if (info->devno >= 0) printf(" (%04x)", info->devno); printf(".\n"); } else if (info->devno >= 0) { printf("%04x.\n", info->devno); } else { - disk_print_devt(info->device); + disk_print_devt(bis->info->device); printf(".\n"); } /* Install independently on each physical target base */ @@ -462,7 +464,7 @@ int install_bootloader(struct job_data *job, struct install_set *bis) if (verbose) { printf("Installing on base disk: "); - disk_print_devname(info->basedisks[i]); + disk_print_devname(bis->info->base[i].disk); printf("%s.\n", footnote); } /* Open device file */ @@ -488,12 +490,14 @@ int install_bootloader(struct job_data *job, struct install_set *bis) * picture in comments above) */ if (job->id == job_dump_partition) { - rc = install_bootloader_dump(bis->tables, info, + rc = install_bootloader_dump(bis->tables, + &bis->info->base[i], scsi_dump_sb_blockptr, job_dump_is_ngdump(job), fd); } else { - rc = install_bootloader_ipl(bis->tables, info, + rc = install_bootloader_ipl(bis->tables, + &bis->info->base[i], fd); } if (fsync(fd)) @@ -512,13 +516,16 @@ int install_bootloader(struct job_data *job, struct install_set *bis) if (info->devno >= 0) syslog(LOG_INFO, "Boot loader written to %s (%04x) - " "%02x:%02x", - (info->name ? info->name : "-"), info->devno, - major(info->device), minor(info->device)); + (bis->info->name ? bis->info->name : "-"), + info->devno, + major(bis->info->device), + minor(bis->info->device)); else syslog(LOG_INFO, "Boot loader written to %s - " "%02x:%02x", - (info->name ? info->name : "-"), - major(info->device), minor(info->device)); + (bis->info->name ? bis->info->name : "-"), + major(bis->info->device), + minor(bis->info->device)); } return rc; } @@ -793,7 +800,7 @@ install_tapeloader(const char* device, const char* image, const char* parmline, /* Write 64k null bytes with dump signature at offset 512 to * start of dump partition */ static int -overwrite_partition_start(int fd, struct disk_info* info, int mv_dump_magic) +overwrite_partition_start(int fd, struct disk_info *info, int mv_dump_magic) { int rc; unsigned int bytes = 65536; @@ -826,7 +833,7 @@ overwrite_partition_start(int fd, struct disk_info* info, int mv_dump_magic) * Force block size of 4KiB because otherwise there is not enough space * to write the dump tool. */ -static int check_eckd_dump_partition(struct disk_info* info) +static int check_eckd_dump_partition(struct disk_info *info) { unsigned long long end_blk = info->geo.start + info->phy_blocks - 1; @@ -856,8 +863,10 @@ static void eckd_dump_store_param(struct eckd_dump_param *param, param->bpt = info->geo.sectors; } -static int install_svdump_eckd_ldl(struct misc_fd *mfd, struct disk_info *info, - const struct stage2dump_parm_tail *stage2dump_parms) +static int +install_svdump_eckd_ldl(struct misc_fd *mfd, int fs_block_size, + struct disk_info *info, + const struct stage2dump_parm_tail *stage2dump_parms) { disk_blockptr_t *stage2_list, *stage1b_list; blocknum_t stage2_count, stage1b_count; @@ -880,11 +889,13 @@ static int install_svdump_eckd_ldl(struct misc_fd *mfd, struct disk_info *info, if (misc_seek(mfd->fd, info->geo.start * info->phy_block_size)) goto out_free_stage2; stage2_count = disk_write_block_buffer(mfd, 1, stage2, stage2_size, - &stage2_list, info); + &stage2_list, + fs_block_size, info); if (stage2_count == 0) goto out_free_stage2_list; if (install_eckd_stage1b(mfd, &stage1b_list, &stage1b_count, - stage2_list, stage2_count, info)) + stage2_list, stage2_count, fs_block_size, + info)) goto out_free_stage2_list; /* Install stage 0 - afterwards we are at stage 1 position*/ boot_init_eckd_ldl_stage0(&stage0); @@ -911,8 +922,9 @@ out: return rc; } -static int install_dump_eckd_cdl(struct misc_fd *mfd, struct disk_info *info, - void *stage2, size_t stage2_size, int mvdump, +static int install_dump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, + struct disk_info *info, void *stage2, + size_t stage2_size, int mvdump, int force) { blocknum_t count, stage2_count, stage1b_count; @@ -936,12 +948,14 @@ static int install_dump_eckd_cdl(struct misc_fd *mfd, struct disk_info *info, if (misc_seek(mfd->fd, ECKD_CDL_DUMP_REC * info->phy_block_size)) goto out; stage2_count = disk_write_block_buffer(mfd, 1, stage2, stage2_size, - &stage2_list, info); + &stage2_list, fs_block_size, + info); if (stage2_count == 0) goto out; /* Install stage 1b behind stage 2*/ if (install_eckd_stage1b(mfd, &stage1b_list, &stage1b_count, - stage2_list, stage2_count, info)) + stage2_list, stage2_count, fs_block_size, + info)) goto out_free_stage2_list; /* Install stage 0 */ boot_init_eckd_cdl_stage0(&stage0_cdl); @@ -968,7 +982,8 @@ out: } static int -install_svdump_eckd_cdl(struct misc_fd *mfd, struct disk_info *info, +install_svdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, + struct disk_info *info, const struct stage2dump_parm_tail *stage2dump_parms) { size_t stage2_size; @@ -977,13 +992,15 @@ install_svdump_eckd_cdl(struct misc_fd *mfd, struct disk_info *info, if (boot_get_eckd_dump_stage2(&stage2, &stage2_size, stage2dump_parms)) return -1; - rc = install_dump_eckd_cdl(mfd, info, stage2, stage2_size, 0, 0); + rc = install_dump_eckd_cdl(mfd, fs_block_size, + info, stage2, stage2_size, 0, 0); free(stage2); return rc; } static int -install_mvdump_eckd_cdl(struct misc_fd *mfd, struct disk_info *info, +install_mvdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size, + struct disk_info *info, const struct stage2dump_parm_tail *stage2dump_parms, const struct mvdump_parm_table *mv_parm_table) { @@ -995,7 +1012,8 @@ install_mvdump_eckd_cdl(struct misc_fd *mfd, struct disk_info *info, if (boot_get_eckd_mvdump_stage2(&stage2, &stage2_size, stage2dump_parms, mv_parm_table)) return -1; - rc = install_dump_eckd_cdl(mfd, info, stage2, stage2_size, 1, + rc = install_dump_eckd_cdl(mfd, fs_block_size, info, stage2, + stage2_size, 1, stage2dump_parms->mvdump_force); free(stage2); return rc; @@ -1004,7 +1022,8 @@ install_mvdump_eckd_cdl(struct misc_fd *mfd, struct disk_info *info, int install_fba_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, blocknum_t *stage1b_count, disk_blockptr_t *stage2_list, - blocknum_t stage2_count, struct disk_info *info) + blocknum_t stage2_count, int fs_block_size, + struct disk_info *info) { struct boot_fba_stage1b *stage1b; int stage1b_size, rc = -1; @@ -1019,7 +1038,8 @@ install_fba_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list, if (boot_init_fba_stage1b(stage1b, stage2_list, stage2_count)) goto out_free_stage1b; *stage1b_count = disk_write_block_buffer(mfd, 1, stage1b, stage1b_size, - stage1b_list, info); + stage1b_list, fs_block_size, + info); if (*stage1b_count == 0) goto out_free_stage1b; rc = 0; @@ -1030,7 +1050,8 @@ out: } static int -install_svdump_fba(struct misc_fd *mfd, struct disk_info *info, +install_svdump_fba(struct misc_fd *mfd, int fs_block_size, + struct disk_info *info, const struct stage2dump_parm_tail *stage2dump_parms) { blocknum_t stage1b_count, stage2_count, blk; @@ -1055,7 +1076,8 @@ install_svdump_fba(struct misc_fd *mfd, struct disk_info *info, if (misc_seek(mfd->fd, blk * info->phy_block_size)) goto out_free_stage2; stage2_count = disk_write_block_buffer(mfd, 1, stage2, stage2_size, - &stage2_list, info); + &stage2_list, fs_block_size, + info); if (stage2_count == 0) goto out_free_stage2; /* Install stage 1b in front of stage 2 */ @@ -1063,7 +1085,7 @@ install_svdump_fba(struct misc_fd *mfd, struct disk_info *info, if (misc_seek(mfd->fd, blk * info->phy_block_size)) goto out_free_stage2_list; if (install_fba_stage1b(mfd, &stage1b_list, &stage1b_count, - stage2_list, stage2_count, info)) + stage2_list, stage2_count, fs_block_size, info)) goto out_free_stage2_list; /* Install stage 0/1 fill in dump partition parameter */ if (boot_init_fba_stage0(&stage0, stage1b_list, stage1b_count)) @@ -1111,7 +1133,8 @@ install_dump(const char *device, struct job_target_data *target, uint64_t mem, { struct stage2dump_parm_tail stage2dump_parms = {0}; struct misc_fd mfd = {0}; - struct disk_info* info; + struct device_info *dev_info; + struct disk_info *info; uint64_t part_size; char *tempdev; int rc; @@ -1151,32 +1174,33 @@ install_dump(const char *device, struct job_target_data *target, uint64_t mem, } close(mfd.fd); /* This is a disk device */ - rc = disk_get_info(device, target, &info); + rc = device_get_info(device, target, &dev_info); if (rc) { error_text("Could not get information for dump target " "'%s'", device); return rc; } + info = &dev_info->base[0]; if (info->partnum == 0) { error_reason("Dump target '%s' is not a disk partition", device); - disk_free_info(info); + device_free_info(dev_info); return -1; } if (verbose) { printf("Target device information\n"); - disk_print_info(info, target->source); + device_print_info(dev_info, target->source); } - rc = misc_temp_dev(info->device, 1, &tempdev); + rc = misc_temp_dev(dev_info->device, 1, &tempdev); if (rc) { - disk_free_info(info); + device_free_info(dev_info); return -1; } if (misc_open_device(tempdev, &mfd, dry_run) == -1) { error_text("Could not open temporary device node '%s'", tempdev); misc_free_temp_dev(tempdev); - disk_free_info(info); + device_free_info(dev_info); return -1; } switch (info->type) { @@ -1203,11 +1227,16 @@ install_dump(const char *device, struct job_target_data *target, uint64_t mem, disk_get_type_name(info->type)); } if (info->type == disk_type_eckd_ldl) - rc = install_svdump_eckd_ldl(&mfd, info, &stage2dump_parms); + rc = install_svdump_eckd_ldl(&mfd, + dev_info->fs_block_size, + info, &stage2dump_parms); else if (info->type == disk_type_eckd_cdl) - rc = install_svdump_eckd_cdl(&mfd, info, &stage2dump_parms); + rc = install_svdump_eckd_cdl(&mfd, + dev_info->fs_block_size, + info, &stage2dump_parms); else - rc = install_svdump_fba(&mfd, info, &stage2dump_parms); + rc = install_svdump_fba(&mfd, dev_info->fs_block_size, + info, &stage2dump_parms); break; case disk_type_scsi: error_reason("%s: Unsupported disk type '%s' (try --dumptofs)", @@ -1221,7 +1250,7 @@ install_dump(const char *device, struct job_target_data *target, uint64_t mem, break; } misc_free_temp_dev(tempdev); - disk_free_info(info); + device_free_info(dev_info); if (fsync(mfd.fd)) error_text("Could not sync device file '%s'", device); if (close(mfd.fd)) @@ -1234,8 +1263,9 @@ int install_mvdump(char* const device[], struct job_target_data* target, int count, uint64_t mem, uint8_t force) { - struct disk_info *info[MAX_DUMP_VOLUMES] = {0}; + struct device_info *dev_info[MAX_DUMP_VOLUMES] = {0}; struct stage2dump_parm_tail stage2dump_parms = {0}; + struct disk_info *info[MAX_DUMP_VOLUMES] = {0}; struct mvdump_parm_table mvdump_parms; uint64_t total_size = 0; struct timeval time; @@ -1269,12 +1299,13 @@ install_mvdump(char* const device[], struct job_target_data* target, int count, } close(mfd.fd); /* This is a disk device */ - rc = disk_get_info(device[i], target, &info[i]); + rc = device_get_info(device[i], target, &dev_info[i]); if (rc) { error_text("Could not get information for dump target " "'%s'", device[i]); goto out; } + info[i] = &dev_info[i]->base[0]; if (info[i]->partnum == 0) { error_reason("Dump target '%s' is not a disk partition", device[i]); @@ -1323,7 +1354,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); - disk_print_info(info[i], target->source); + device_print_info(dev_info[i], target->source); printf("-------------------------------------------\n"); } } @@ -1345,7 +1376,7 @@ install_mvdump(char* const device[], struct job_target_data* target, int count, for (i = 0; i < count; i++) { struct misc_fd mfd = {0}; - rc = misc_temp_dev(info[i]->device, 1, &tempdev); + rc = misc_temp_dev(dev_info[i]->device, 1, &tempdev); if (rc) { rc = -1; goto out; @@ -1360,7 +1391,9 @@ install_mvdump(char* const device[], struct job_target_data* target, int count, if (verbose) printf("Installing dump record on target partition " "'%s'\n", device[i]); - rc = install_mvdump_eckd_cdl(&mfd, info[i], &stage2dump_parms, &mvdump_parms); + rc = install_mvdump_eckd_cdl(&mfd, dev_info[i]->fs_block_size, + info[i], &stage2dump_parms, + &mvdump_parms); misc_free_temp_dev(tempdev); if (fsync(mfd.fd)) @@ -1374,6 +1407,6 @@ install_mvdump(char* const device[], struct job_target_data* target, int count, out: for (i = 0; i < count; i++) if (info[i] != NULL) - disk_free_info(info[i]); + device_free_info(dev_info[i]); return rc; } diff --git a/zipl/src/zipl.c b/zipl/src/zipl.c index 9f6d64a4..ac4775fb 100644 --- a/zipl/src/zipl.c +++ b/zipl/src/zipl.c @@ -174,7 +174,8 @@ main(int argc, char* argv[]) /* Do it */ switch (job->id) { case job_dump_partition: - rc = disk_get_ext_type(job->data.dump.device, &ext_type); + rc = disk_get_ext_type(job->data.dump.device, &ext_type, + 0 /* disk index */); if (rc) break; job_dump_check_set_ngdump(job, &ext_type);