Hardware RAID volume bootpaths are similar to Fibre channel ones in that
they use the disk's WWID (lower 16 bit only) as SCSI target, e.g.

        /pci@400/pci@2/pci@0/pci@e/scsi@0/disk@w3aa32290d5dcd16c,0:a

Currently device_register() does recognise devices with their WWN as
target but only continues to nail_bootdev() them if their lun and port
match as well.

Diff below makes device_register() look at the bootpath's partition and
--in lack of a better criterium-- the device name as well to test for
hardware RAIDs.

But to be able to match the partition, partition index calculation must
be deferred from bootpath_build() to diskconf() so it becomes possible
to check whether partition "a" (index 0) has been specified in the
bootpath - this is currently not possible because the partition gets
turned into an index right away which makes it indistinguishable from
val[2]'s default initialised value.

As a bonus, this now makes also makes the kernel print back the bootpath
correctly with regard to "a" partitions:

        bootpath: 
/pci@400,0/pci@2,0/pci@0,0/pci@e,0/scsi@0,0/disk@3aa32290d5dcd16c,0:a
        root on sd0a (5eb46f4312eeecb7.a) swap on sd0b dump on sd0b


Is there a better way to detect hardware RAIDs as such?


Index: sparc64/autoconf.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/sparc64/autoconf.c,v
retrieving revision 1.133
diff -u -p -r1.133 autoconf.c
--- sparc64/autoconf.c  15 Oct 2019 05:21:16 -0000      1.133
+++ sparc64/autoconf.c  26 Dec 2019 05:56:20 -0000
@@ -525,7 +525,7 @@ bootpath_build(void)
                                 * be an ethernet media specification, so be
                                 * sure to skip all letters.
                                 */
-                               bp->val[2] = *++cp - 'a';
+                               bp->val[2] = *++cp;
                                while (*cp != '\0' && *cp != '/')
                                        cp++;
                        }
@@ -611,7 +611,7 @@ bootpath_print(struct bootpath *bp)
                else
                        printf("/%s@%lx,%lx", bp->name, bp->val[0], bp->val[1]);
                if (bp->val[2] != 0)
-                       printf(":%c", (int)bp->val[2] + 'a');
+                       printf(":%c", (int)bp->val[2]);
                bp++;
        }
        printf("\n");
@@ -813,7 +813,7 @@ diskconf(void)
                bootdv = mpath_bootdv(bootdv);
 #endif
 
-       setroot(bootdv, bp->val[2], RB_USERREQ | RB_HALT);
+       setroot(bootdv, bp->val[2] - 'a', RB_USERREQ | RB_HALT);
        dumpconf();
 }
 
@@ -1453,7 +1453,9 @@ device_register(struct device *dev, void
                    (struct scsibus_softc *)dev->dv_parent;
                u_int target = bp->val[0];
                u_int lun = bp->val[1];
+               int partition = bp->val[2];
 
+               /* Is target a full WWN/WWID? */
                if (bp->val[0] & 0xffffffff00000000 && bp->val[0] != -1) {
                        /* Fibre channel? */
                        if (bp->val[0] == sl->port_wwn && lun == sl->lun) {
@@ -1468,6 +1470,12 @@ device_register(struct device *dev, void
                            sl->id->d_type == DEVID_NAA &&
                            memcmp(sl->id + 1, &bp->val[0], 8) == 0)
                                nail_bootdev(dev, bp);
+
+                       /* Hardware RAID? */
+                       /* XXX: how to detect properly? */
+                       if (strcmp(devname, "sd") == 0 && partition != 0) {
+                               nail_bootdev(dev, bp);
+                       }
                        return;
                }
 

Reply via email to