> Date: Thu, 26 Dec 2019 07:38:47 +0100
> From: Klemens Nanni <k...@openbsd.org>
> 
> 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;

What happens if the bootpath doesn't specify a partition?  Currently
we end up with bp->val[2] being zero in that case, which means we end
up booting from 'a' which is the default partition.  So I think you
need to check for that case when you call setroot().

However, that means the partition != 0 check is probably meaningless...

Also note that booting by WWWN isn't just for fibre-channel and
hardware RAID.  It works for single disks as well on some controllers.

Why does matching the LUN fail?  If I read the code correctly, you'll
end up with bp->val[1] = 0.  What is the value of sl->lun?

Reply via email to