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;
 };

Reply via email to