The diff below is a first cut at making softraid usable on today's larger and larger disks which use 4096-byte sectors.
It allows building softraid volumes with such devices, and even building volumes that mix 'classic' 512-byte sector devices with 'avante garde' 4k-sector devices. Unlikely to be completely final, but lots of testing would be appreciated. And I mean testing -current with existing 512-byte sector softraid volumes! A significant amount of cleanup was committed to prepare for this diff. If you want to ensure a surprise-free upgrade to 5.8, now is the time to test. NEEDED: a machine with a BIOS that can boot from a 4K device. Apparently very rare still. But it would be nice to test with. CAVEAT: The metadata version has changed so new volumes you create will not be loadable on boxes running older versions of OpenBSD. CAVEAT: You can't rebuild a volume created with *only* 512-byte devices onto a 4K-sector device. The volume must be created with at least one 4K device to start with. .... Ken Index: softraid.c =================================================================== RCS file: /cvs/src/sys/dev/softraid.c,v retrieving revision 1.360 diff -u -p -r1.360 softraid.c --- softraid.c 21 Jul 2015 03:30:51 -0000 1.360 +++ softraid.c 21 Jul 2015 04:02:14 -0000 @@ -944,6 +944,7 @@ sr_meta_validate(struct sr_discipline *s */ if (sm->ssd_data_blkno == 0) sm->ssd_data_blkno = SR_META_V3_DATA_OFFSET; + sm->ssdi.ssd_secsize = DEV_BSIZE; } else if (sm->ssdi.ssd_version == 4) { @@ -953,14 +954,22 @@ sr_meta_validate(struct sr_discipline *s */ if (sm->ssd_data_blkno == 0) sm->ssd_data_blkno = SR_DATA_OFFSET; + sm->ssdi.ssd_secsize = DEV_BSIZE; - } else if (sm->ssdi.ssd_version == SR_META_VERSION) { + } else if (sm->ssdi.ssd_version == 5) { /* * Version 5 - variable length optional metadata. Migration * from earlier fixed length optional metadata is handled * in sr_meta_read(). */ + sm->ssdi.ssd_secsize = DEV_BSIZE; + + } else if (sm->ssdi.ssd_version == SR_META_VERSION) { + + /* + * Version 6 - store & report a sector size. + */ } else { @@ -1052,13 +1061,6 @@ sr_meta_native_bootprobe(struct sr_softc } vput(vn); - /* Make sure this is a DEV_BSIZE byte/sector device. */ - if (label.d_secsize != DEV_BSIZE) { - DNPRINTF(SR_D_META, "%s: %s has unsupported sector size (%d)", - DEVNAME(sc), devname, label.d_secsize); - goto done; - } - md = malloc(SR_META_SIZE * DEV_BSIZE, M_DEVBUF, M_ZERO | M_NOWAIT); if (md == NULL) { sr_error(sc, "not enough memory for metadata buffer"); @@ -1568,13 +1570,6 @@ sr_meta_native_probe(struct sr_softc *sc } memcpy(ch_entry->src_duid, label.d_uid, sizeof(ch_entry->src_duid)); - /* Make sure this is a DEV_BSIZE byte/sector device. */ - if (label.d_secsize != DEV_BSIZE) { - sr_error(sc, "%s has unsupported sector size (%u)", - devname, label.d_secsize); - goto unwind; - } - /* make sure the partition is of the right type */ if (label.d_partitions[part].p_fstype != FS_RAID) { DNPRINTF(SR_D_META, @@ -1597,6 +1592,7 @@ sr_meta_native_probe(struct sr_softc *sc goto unwind; } ch_entry->src_size = size; + ch_entry->src_secsize = label.d_secsize; DNPRINTF(SR_D_META, "%s: probe found %s size %lld\n", DEVNAME(sc), devname, (long long)size); @@ -2879,11 +2875,6 @@ sr_hotspare(struct sr_softc *sc, dev_t d vput(vn); goto fail; } - if (label.d_secsize != DEV_BSIZE) { - sr_error(sc, "%s has unsupported sector size (%u)", - devname, label.d_secsize); - goto fail; - } if (label.d_partitions[part].p_fstype != FS_RAID) { sr_error(sc, "%s partition not of type RAID (%d)", devname, label.d_partitions[part].p_fstype); @@ -2943,6 +2934,7 @@ sr_hotspare(struct sr_softc *sc, dev_t d sm->ssdi.ssd_volid = SR_HOTSPARE_VOLID; sm->ssdi.ssd_level = SR_HOTSPARE_LEVEL; sm->ssdi.ssd_size = size; + sm->ssdi.ssd_secsize = label.d_secsize; strlcpy(sm->ssdi.ssd_vendor, "OPENBSD", sizeof(sm->ssdi.ssd_vendor)); snprintf(sm->ssdi.ssd_product, sizeof(sm->ssdi.ssd_product), "SR %s", "HOTSPARE"); @@ -3193,11 +3185,6 @@ sr_rebuild_init(struct sr_discipline *sd DEVNAME(sc)); goto done; } - if (label.d_secsize != DEV_BSIZE) { - sr_error(sc, "%s has unsupported sector size (%u)", - devname, label.d_secsize); - goto done; - } if (label.d_partitions[part].p_fstype != FS_RAID) { sr_error(sc, "%s partition not of type RAID (%d)", devname, label.d_partitions[part].p_fstype); @@ -3672,7 +3659,7 @@ sr_ioctl_installboot(struct sr_softc *sc struct sr_meta_opt_item *omi; struct sr_meta_boot *sbm; struct disk *dk; - u_int32_t bbs, bls; + u_int32_t bbs, bls, secsize; u_char duid[8]; int rv = EINVAL; int i; @@ -3716,14 +3703,16 @@ sr_ioctl_installboot(struct sr_softc *sc if (bb->bb_bootldr_size > SR_BOOT_LOADER_SIZE * DEV_BSIZE) goto done; + secsize = sd->sd_meta->ssdi.ssd_secsize; + /* Copy in boot block. */ - bbs = howmany(bb->bb_bootblk_size, DEV_BSIZE) * DEV_BSIZE; + bbs = howmany(bb->bb_bootblk_size, secsize) * secsize; bootblk = malloc(bbs, M_DEVBUF, M_WAITOK | M_ZERO); if (copyin(bb->bb_bootblk, bootblk, bb->bb_bootblk_size) != 0) goto done; /* Copy in boot loader. */ - bls = howmany(bb->bb_bootldr_size, DEV_BSIZE) * DEV_BSIZE; + bls = howmany(bb->bb_bootldr_size, secsize) * secsize; bootldr = malloc(bls, M_DEVBUF, M_WAITOK | M_ZERO); if (copyin(bb->bb_bootldr, bootldr, bb->bb_bootldr_size) != 0) goto done; @@ -4047,25 +4036,28 @@ sr_raid_read_cap(struct sr_workunit *wu) struct scsi_xfer *xs = wu->swu_xs; struct scsi_read_cap_data rcd; struct scsi_read_cap_data_16 rcd16; - int64_t addr; + u_int64_t addr; int rv = 1; + u_int32_t secsize; DNPRINTF(SR_D_DIS, "%s: sr_raid_read_cap\n", DEVNAME(sd->sd_sc)); - addr = sd->sd_meta->ssdi.ssd_size - 1; + secsize = sd->sd_meta->ssdi.ssd_secsize; + + addr = ((sd->sd_meta->ssdi.ssd_size * DEV_BSIZE) / secsize) - 1; if (xs->cmd->opcode == READ_CAPACITY) { bzero(&rcd, sizeof(rcd)); if (addr > 0xffffffffllu) _lto4b(0xffffffff, rcd.addr); else _lto4b(addr, rcd.addr); - _lto4b(DEV_BSIZE, rcd.length); + _lto4b(secsize, rcd.length); sr_copy_internal_data(xs, &rcd, sizeof(rcd)); rv = 0; } else if (xs->cmd->opcode == READ_CAPACITY_16) { bzero(&rcd16, sizeof(rcd16)); _lto8b(addr, rcd16.addr); - _lto4b(DEV_BSIZE, rcd16.length); + _lto4b(secsize, rcd16.length); sr_copy_internal_data(xs, &rcd16, sizeof(rcd16)); rv = 0; } @@ -4591,6 +4583,8 @@ sr_validate_io(struct sr_workunit *wu, d DEVNAME(sd->sd_sc), func, sd->sd_meta->ssd_devname); goto bad; } + + *blkno *= (sd->sd_meta->ssdi.ssd_secsize / DEV_BSIZE); wu->swu_blk_start = *blkno; wu->swu_blk_end = *blkno + (xs->datalen >> DEV_BSHIFT) - 1; Index: softraid_concat.c =================================================================== RCS file: /cvs/src/sys/dev/softraid_concat.c,v retrieving revision 1.23 diff -u -p -r1.23 softraid_concat.c --- softraid_concat.c 21 Jul 2015 03:30:51 -0000 1.23 +++ softraid_concat.c 21 Jul 2015 04:02:14 -0000 @@ -61,6 +61,7 @@ sr_concat_create(struct sr_discipline *s int no_chunk, int64_t coerced_size) { int i; + u_int32_t secsize; if (no_chunk < 2) { sr_error(sd->sd_sc, "%s requires two or more chunks", @@ -69,9 +70,14 @@ sr_concat_create(struct sr_discipline *s } sd->sd_meta->ssdi.ssd_size = 0; - for (i = 0; i < no_chunk; i++) + secsize = 0; + for (i = 0; i < no_chunk; i++) { + if (sd->sd_vol.sv_chunks[i]->src_secsize > secsize) + secsize = sd->sd_vol.sv_chunks[i]->src_secsize; sd->sd_meta->ssdi.ssd_size += sd->sd_vol.sv_chunks[i]->src_size; + } + sd->sd_meta->ssdi.ssd_secsize = secsize; return sr_concat_init(sd); } Index: softraid_crypto.c =================================================================== RCS file: /cvs/src/sys/dev/softraid_crypto.c,v retrieving revision 1.121 diff -u -p -r1.121 softraid_crypto.c --- softraid_crypto.c 21 Jul 2015 03:30:51 -0000 1.121 +++ softraid_crypto.c 21 Jul 2015 04:02:14 -0000 @@ -179,6 +179,7 @@ sr_crypto_create(struct sr_discipline *s goto done; sd->sd_meta->ssdi.ssd_size = coerced_size; + sd->sd_meta->ssdi.ssd_secsize = sd->sd_vol.sv_chunks[0]->src_secsize; sr_crypto_create_keys(sd); @@ -649,11 +650,6 @@ sr_crypto_create_key_disk(struct sr_disc vput(vn); goto fail; } - if (label.d_secsize != DEV_BSIZE) { - sr_error(sc, "%s has unsupported sector size (%d)", - devname, label.d_secsize); - goto fail; - } if (label.d_partitions[part].p_fstype != FS_RAID) { sr_error(sc, "%s partition not of type RAID (%d)\n", devname, label.d_partitions[part].p_fstype); @@ -817,11 +813,6 @@ sr_crypto_read_key_disk(struct sr_discip "failed\n", DEVNAME(sc)); VOP_CLOSE(vn, FREAD | FWRITE, NOCRED, curproc); vput(vn); - goto done; - } - if (label.d_secsize != DEV_BSIZE) { - sr_error(sc, "%s has unsupported sector size (%d)", - devname, label.d_secsize); goto done; } if (label.d_partitions[part].p_fstype != FS_RAID) { Index: softraid_raid0.c =================================================================== RCS file: /cvs/src/sys/dev/softraid_raid0.c,v retrieving revision 1.50 diff -u -p -r1.50 softraid_raid0.c --- softraid_raid0.c 21 Jul 2015 03:30:51 -0000 1.50 +++ softraid_raid0.c 21 Jul 2015 04:02:14 -0000 @@ -69,11 +69,21 @@ int sr_raid0_create(struct sr_discipline *sd, struct bioc_createraid *bc, int no_chunk, int64_t coerced_size) { + int i; + u_int32_t secsize; + if (no_chunk < 2) { sr_error(sd->sd_sc, "%s requires two or more chunks", sd->sd_name); return EINVAL; } + + secsize = 0; + for (i = 0; i < no_chunk; i++) { + if (sd->sd_vol.sv_chunks[i]->src_secsize > secsize) + secsize = sd->sd_vol.sv_chunks[i]->src_secsize; + } + sd->sd_meta->ssdi.ssd_secsize = secsize; /* * XXX add variable strip size later even though MAXPHYS is really Index: softraid_raid1.c =================================================================== RCS file: /cvs/src/sys/dev/softraid_raid1.c,v retrieving revision 1.63 diff -u -p -r1.63 softraid_raid1.c --- softraid_raid1.c 21 Jul 2015 03:30:51 -0000 1.63 +++ softraid_raid1.c 21 Jul 2015 04:02:14 -0000 @@ -76,12 +76,21 @@ int sr_raid1_create(struct sr_discipline *sd, struct bioc_createraid *bc, int no_chunk, int64_t coerced_size) { + int i; + u_int32_t secsize; + if (no_chunk < 2) { sr_error(sd->sd_sc, "%s requires two or more chunks", sd->sd_name); return EINVAL; } + secsize = 0; + for (i = 0; i < no_chunk; i++) { + if (sd->sd_vol.sv_chunks[i]->src_secsize > secsize) + secsize = sd->sd_vol.sv_chunks[i]->src_secsize; + } + sd->sd_meta->ssdi.ssd_secsize = secsize; sd->sd_meta->ssdi.ssd_size = coerced_size; return sr_raid1_init(sd); Index: softraid_raid5.c =================================================================== RCS file: /cvs/src/sys/dev/softraid_raid5.c,v retrieving revision 1.23 diff -u -p -r1.23 softraid_raid5.c --- softraid_raid5.c 21 Jul 2015 03:30:51 -0000 1.23 +++ softraid_raid5.c 21 Jul 2015 04:02:14 -0000 @@ -96,11 +96,21 @@ int sr_raid5_create(struct sr_discipline *sd, struct bioc_createraid *bc, int no_chunk, int64_t coerced_size) { + int i; + u_int32_t secsize; + if (no_chunk < 3) { sr_error(sd->sd_sc, "%s requires three or more chunks", sd->sd_name); return EINVAL; } + + secsize = sd->sd_vol.sv_chunks[0]->src_secsize; + for (i = 0; i < no_chunk; i++) { + if (sd->sd_vol.sv_chunks[i]->src_secsize > secsize) + secsize = sd->sd_vol.sv_chunks[i]->src_secsize; + } + sd->sd_meta->ssdi.ssd_secsize = secsize; /* * XXX add variable strip size later even though MAXPHYS is really Index: softraid_raid6.c =================================================================== RCS file: /cvs/src/sys/dev/softraid_raid6.c,v retrieving revision 1.69 diff -u -p -r1.69 softraid_raid6.c --- softraid_raid6.c 21 Jul 2015 03:30:51 -0000 1.69 +++ softraid_raid6.c 21 Jul 2015 04:02:14 -0000 @@ -112,11 +112,21 @@ int sr_raid6_create(struct sr_discipline *sd, struct bioc_createraid *bc, int no_chunk, int64_t coerced_size) { + int i; + u_int32_t secsize; + if (no_chunk < 4) { sr_error(sd->sd_sc, "%s requires four or more chunks", sd->sd_name); return EINVAL; } + + secsize = 0; + for (i = 0; i < no_chunk; i++) { + if (sd->sd_vol.sv_chunks[i]->src_secsize > secsize) + secsize = sd->sd_vol.sv_chunks[i]->src_secsize; + } + sd->sd_meta->ssdi.ssd_secsize = secsize; /* * XXX add variable strip size later even though MAXPHYS is really Index: softraidvar.h =================================================================== RCS file: /cvs/src/sys/dev/softraidvar.h,v retrieving revision 1.161 diff -u -p -r1.161 softraidvar.h --- softraidvar.h 21 Jul 2015 03:30:51 -0000 1.161 +++ softraidvar.h 21 Jul 2015 04:02:14 -0000 @@ -19,7 +19,7 @@ #ifndef SOFTRAIDVAR_H #define SOFTRAIDVAR_H -#define SR_META_VERSION 5 /* bump when sr_metadata changes */ +#define SR_META_VERSION 6 /* bump when sr_metadata changes */ #define SR_META_SIZE 64 /* save space at chunk beginning */ #define SR_META_OFFSET 16 /* skip 8192 bytes at chunk beginning */ @@ -135,7 +135,7 @@ struct sr_metadata { /* optional */ u_int32_t ssd_opt_no; /* nr of optional md elements */ - u_int32_t ssd_pad; + u_int32_t ssd_secsize; /* volume metadata */ u_int32_t ssd_volid; /* volume id */ @@ -473,6 +473,7 @@ struct sr_chunk { char src_devname[32]; u_char src_duid[8]; /* Chunk disklabel UID. */ int64_t src_size; /* in blocks */ + u_int32_t src_secsize; SLIST_ENTRY(sr_chunk) src_link; };