zipl/src: Fix alignment of componets location in bootmap file

Calculate the alignment value as maximum of physical block sizes of
disks participating in the mirrored setup. Earlier the alignment was
calculated as a physical block size of the first disk of a mirrored
setup.

Without this change, the assertion in disk_get_blocklist_from_file()
'assert(reg->offset % info->phy_block_size == 0)' is triggered in case
when blocksize of base disk #J > blocksize of base disk #I && (J>I).
To reproduce the problem, build a mixed mirrored setup with first SCSI
disk, second DASD disk and prepare it for IPL.

Fixes: 731f00202c ("zipl/src: Enable heterogeneous mirrors support")
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Eduard Shishkin
2026-06-10 18:05:55 +02:00
committed by Jan Höppner
parent 9882aabe44
commit f2902a1990
5 changed files with 69 additions and 44 deletions
+5 -4
View File
@@ -93,6 +93,7 @@ struct device_info {
* as retrieved from "/proc/devices", or evaluated
*/
int fs_block_size;
int align; /* alignment of component location in bootmap */
struct disk_info base[MAX_TARGETS]; /* array of physical disks for
* bootstrap blocks recording
*/
@@ -133,13 +134,13 @@ int disk_write_block_aligned(struct misc_fd *mfd, const void *data,
blocknum_t disk_write_block_buffer(struct misc_fd *fd, int fd_is_basedisk,
const void* buffer, size_t bytecount,
disk_blockptr_t** blocklist,
int fs_block_size, struct disk_info *info);
int fs_block_size, int align,
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);
int fs_block_size, int align,
struct disk_info *info, 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);
+2 -2
View File
@@ -160,13 +160,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, int fs_block_size,
blocknum_t stage2_count, int fs_block_size, int align,
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, int fs_block_size,
struct disk_info *info);
int align, struct disk_info *info);
int rewind_tape(int fd);
#endif /* INSTALL_H */
+13 -8
View File
@@ -383,8 +383,8 @@ static int add_component_file_range(struct install_set *bis,
0 /* not a base disk */,
buffer, size, list,
bis->info->fs_block_size,
bis->info->align,
info,
info->phy_block_size,
/*
* save component offset
*/
@@ -478,7 +478,7 @@ static int add_component_buffer_base(struct install_set *bis, void *buffer,
align = fs_block_aligned_by_id(comp_id) ?
bis->info->fs_block_size :
info->phy_block_size;
bis->info->align;
if (bis->skip_prepare_device &&
bis->mirrors[mirror_id].skip_prepare_blocklist)
@@ -486,8 +486,8 @@ static int add_component_buffer_base(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->fs_block_size,
info, align, &offset);
bis->info->fs_block_size, align,
info, &offset);
if (*count == 0) {
error_text("Could not write to bootmap file");
return -1;
@@ -1265,7 +1265,7 @@ write_empty_block(struct misc_fd *mfd, disk_blockptr_t *block,
static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename,
struct job_data *job,
int fs_block_size,
int fs_block_size, int align,
struct disk_info *info,
disk_blockptr_t **stage1b_list,
blocknum_t *stage1b_count,
@@ -1289,6 +1289,7 @@ static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename,
stage2_size,
&stage2_list,
fs_block_size,
align,
info);
free(stage2_data);
if (stage2_count == 0) {
@@ -1297,7 +1298,7 @@ static int install_stages_dasd_fba(struct misc_fd *mfd, char *filename,
}
if (install_fba_stage1b(mfd, stage1b_list, stage1b_count,
stage2_list, stage2_count,
fs_block_size, info))
fs_block_size, align, info))
return -1;
free(stage2_list);
break;
@@ -1317,7 +1318,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,
int fs_block_size, int align,
struct disk_info *info,
disk_blockptr_t *program_table,
disk_blockptr_t **stage1b_list,
@@ -1341,6 +1342,7 @@ static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename,
stage2b_size,
&stage2b_list,
fs_block_size,
align,
info);
free(stage2b_data);
if (stage2b_count == 0) {
@@ -1349,7 +1351,7 @@ static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename,
}
if (install_eckd_stage1b(mfd, stage1b_list, stage1b_count,
stage2b_list, stage2b_count,
fs_block_size, info))
fs_block_size, align, info))
return -1;
free(stage2b_list);
break;
@@ -1367,6 +1369,7 @@ static int install_stages_eckd_dasd(struct misc_fd *mfd, char *filename,
stage2b_size,
stage1b_list,
fs_block_size,
align,
info);
free(stage2b_data);
if (stage2b_count == 0) {
@@ -1395,6 +1398,7 @@ static int bootmap_install_stages(struct job_data *job, struct install_set *bis,
case disk_type_fba:
rc = install_stages_dasd_fba(&bis->mfd, bis->filename, job,
bis->info->fs_block_size,
bis->info->align,
info,
&pt->stage1b_list,
&pt->stage1b_count,
@@ -1404,6 +1408,7 @@ static int bootmap_install_stages(struct job_data *job, struct install_set *bis,
case disk_type_eckd_cdl:
rc = install_stages_eckd_dasd(&bis->mfd, bis->filename, job,
bis->info->fs_block_size,
bis->info->align,
info,
&pt->table,
&pt->stage1b_list,
+21 -6
View File
@@ -575,7 +575,21 @@ static int disk_set_info_complete(struct job_target_data *td,
return 0;
}
static int device_set_info_complete(struct device_info *dev_info)
static void device_get_alignment(struct device_info *dev_info,
struct job_target_data *td)
{
struct disk_info *base;
int i;
for (i = 0; i < td->nr_targets; i++) {
base = &dev_info->base[i];
if (dev_info->align < base->phy_block_size)
dev_info->align = base->phy_block_size;
}
}
static int device_set_info_complete(struct device_info *dev_info,
struct job_target_data *td)
{
struct util_proc_part_entry part_entry;
@@ -588,6 +602,7 @@ static int device_set_info_complete(struct device_info *dev_info)
}
/* Initialize file system block size with invalid value */
dev_info->fs_block_size = -1;
device_get_alignment(dev_info, td);
return 0;
}
@@ -689,7 +704,7 @@ int device_get_info(const char *device, struct job_target_data *td,
if (disk_set_info_complete(td, &data->base[i], &stats, fd))
goto error;
}
if (device_set_info_complete(data))
if (device_set_info_complete(data, td))
goto error;
free(script_file);
close(fd);
@@ -1017,7 +1032,7 @@ 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)
int align, struct disk_info *info, off_t *offset)
{
blocknum_t count;
blocknum_t i;
@@ -1058,12 +1073,12 @@ blocknum_t
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)
int align, struct disk_info *info)
{
return disk_write_block_buffer_align(mfd, fd_is_basedisk, buffer,
bytecount, blocklist,
fs_block_size, info,
info->phy_block_size, NULL);
fs_block_size, align, info,
NULL);
}
/* Print device node. */
+28 -24
View File
@@ -172,7 +172,7 @@ 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, int fs_block_size,
blocknum_t stage2_count, int fs_block_size, int align,
struct disk_info *info)
{
struct boot_eckd_stage1b *stage1b;
@@ -189,7 +189,7 @@ install_eckd_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list,
goto out_free_stage1b;
*stage1b_count = disk_write_block_buffer(mfd, 1, stage1b, stage1b_size,
stage1b_list, fs_block_size,
info);
align, info);
if (*stage1b_count == 0)
goto out_free_stage1b;
rc = 0;
@@ -855,7 +855,7 @@ static void eckd_dump_store_param(struct eckd_dump_param *param,
static int
install_svdump_eckd_ldl(struct misc_fd *mfd, int fs_block_size,
struct disk_info *info,
int align, struct disk_info *info,
const struct stage2dump_parm_tail *stage2dump_parms)
{
disk_blockptr_t *stage2_list, *stage1b_list;
@@ -879,13 +879,13 @@ install_svdump_eckd_ldl(struct misc_fd *mfd, int fs_block_size,
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,
fs_block_size, info);
&stage2_list, fs_block_size,
align, info);
if (stage2_count == 0)
goto out_free_stage2_list;
if (install_eckd_stage1b(mfd, &stage1b_list, &stage1b_count,
stage2_list, stage2_count, fs_block_size,
info))
align, info))
goto out_free_stage2_list;
/* Install stage 0 - afterwards we are at stage 1 position*/
boot_init_eckd_ldl_stage0(&stage0);
@@ -913,8 +913,8 @@ out:
}
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 align, struct disk_info *info,
void *stage2, size_t stage2_size, int mvdump,
int force)
{
blocknum_t count, stage2_count, stage1b_count;
@@ -939,13 +939,13 @@ static int install_dump_eckd_cdl(struct misc_fd *mfd, int fs_block_size,
goto out;
stage2_count = disk_write_block_buffer(mfd, 1, stage2, stage2_size,
&stage2_list, fs_block_size,
info);
align, 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, fs_block_size,
info))
align, info))
goto out_free_stage2_list;
/* Install stage 0 */
boot_init_eckd_cdl_stage0(&stage0_cdl);
@@ -973,7 +973,7 @@ out:
static int
install_svdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size,
struct disk_info *info,
int align, struct disk_info *info,
const struct stage2dump_parm_tail *stage2dump_parms)
{
size_t stage2_size;
@@ -982,7 +982,7 @@ install_svdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size,
if (boot_get_eckd_dump_stage2(&stage2, &stage2_size, stage2dump_parms))
return -1;
rc = install_dump_eckd_cdl(mfd, fs_block_size,
rc = install_dump_eckd_cdl(mfd, fs_block_size, align,
info, stage2, stage2_size, 0, 0);
free(stage2);
return rc;
@@ -990,7 +990,7 @@ install_svdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size,
static int
install_mvdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size,
struct disk_info *info,
int align, struct disk_info *info,
const struct stage2dump_parm_tail *stage2dump_parms,
const struct mvdump_parm_table *mv_parm_table)
{
@@ -1002,7 +1002,7 @@ install_mvdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size,
if (boot_get_eckd_mvdump_stage2(&stage2, &stage2_size, stage2dump_parms,
mv_parm_table))
return -1;
rc = install_dump_eckd_cdl(mfd, fs_block_size, info, stage2,
rc = install_dump_eckd_cdl(mfd, fs_block_size, align, info, stage2,
stage2_size, 1,
stage2dump_parms->mvdump_force);
free(stage2);
@@ -1012,7 +1012,7 @@ install_mvdump_eckd_cdl(struct misc_fd *mfd, int fs_block_size,
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, int fs_block_size,
blocknum_t stage2_count, int fs_block_size, int align,
struct disk_info *info)
{
struct boot_fba_stage1b *stage1b;
@@ -1029,7 +1029,7 @@ install_fba_stage1b(struct misc_fd *mfd, disk_blockptr_t **stage1b_list,
goto out_free_stage1b;
*stage1b_count = disk_write_block_buffer(mfd, 1, stage1b, stage1b_size,
stage1b_list, fs_block_size,
info);
align, info);
if (*stage1b_count == 0)
goto out_free_stage1b;
rc = 0;
@@ -1041,7 +1041,7 @@ out:
static int
install_svdump_fba(struct misc_fd *mfd, int fs_block_size,
struct disk_info *info,
int align, struct disk_info *info,
const struct stage2dump_parm_tail *stage2dump_parms)
{
blocknum_t stage1b_count, stage2_count, blk;
@@ -1067,7 +1067,7 @@ install_svdump_fba(struct misc_fd *mfd, int fs_block_size,
goto out_free_stage2;
stage2_count = disk_write_block_buffer(mfd, 1, stage2, stage2_size,
&stage2_list, fs_block_size,
info);
align, info);
if (stage2_count == 0)
goto out_free_stage2;
/* Install stage 1b in front of stage 2 */
@@ -1075,7 +1075,8 @@ install_svdump_fba(struct misc_fd *mfd, int fs_block_size,
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, fs_block_size, info))
stage2_list, stage2_count, fs_block_size,
align, 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))
@@ -1219,14 +1220,17 @@ install_dump(const char *device, struct job_target_data *target, uint64_t mem,
if (info->type == disk_type_eckd_ldl)
rc = install_svdump_eckd_ldl(&mfd,
dev_info->fs_block_size,
info, &stage2dump_parms);
dev_info->align, info,
&stage2dump_parms);
else if (info->type == disk_type_eckd_cdl)
rc = install_svdump_eckd_cdl(&mfd,
dev_info->fs_block_size,
info, &stage2dump_parms);
dev_info->align, info,
&stage2dump_parms);
else
rc = install_svdump_fba(&mfd, dev_info->fs_block_size,
info, &stage2dump_parms);
dev_info->align, info,
&stage2dump_parms);
break;
case disk_type_scsi:
error_reason("%s: Unsupported disk type '%s' (try --dumptofs)",
@@ -1382,8 +1386,8 @@ install_mvdump(char* const device[], struct job_target_data* target, int count,
printf("Installing dump record on target partition "
"'%s'\n", device[i]);
rc = install_mvdump_eckd_cdl(&mfd, dev_info[i]->fs_block_size,
info[i], &stage2dump_parms,
&mvdump_parms);
dev_info[i]->align, info[i],
&stage2dump_parms, &mvdump_parms);
misc_free_temp_dev(tempdev);
if (fsync(mfd.fd))