On Sun, Jan 13, 2019 at 08:45:31AM -0000, Michael van Elst wrote:
> b...@bsd.de (Christoph Badura) writes:
> >> So, assuming 'raid0' has a component 'dk0' which is based on 'wd0', it
> >> should work to specify 'wd0' as bootdev.
> 
> >That does work.  However, that is besides the point  bootdev=raid0 is
> >supposed to work but it doesn't.
> 
> Which is of course is unrelated to the raid autoconfig I talked about
> and which is flawed too.
> 
> >The reason for that is in the code that overrides rootspec with bootspec.
> 
> Not really, read below.

> >rootspec gets initialized by config(8) like so:
> 
> >For "config <name> root on ?":
> >const char *rootspec = NULL;
> >dev_t   rootdev = NODEV;        /* wildcarded */
> 
> >And for, e.g., "config <name> root on sd0e":
> >const char *rootspec = "sd0e";
> >dev_t   rootdev = makedev(4, 4);        /* sd0e */
> 
> 
> rootspec is set by config(1) for three cases:
> 
> config <name> root on major 4 minor 4
> - sets rootspec to "sd0e" (or maybe "<4/4>") and rootdev to makedev(4,4)
> 
> config <name> root on sd0e
> - sets rootspec to "sd0e" and rootdev to makedev(4,4)
> 
> config <name> root on "some string constant"
> - sets rootspec to "some string constant" and rootdev to NODEV.

There is also:

config <name> root on ?
- sets rootspec to NULL and rootdev to NODEV

and the interesting case of a network device:

config <name> on wm0
- sets rootspec to "wm0" and rootdev to NODEV explicitly.

Also, one has to use a spec string to put root on dk(4) or a wedge name.
The former case is because dk(4)s don't exist at config(1) time.

> If rootspec is set the kernel checks for
> - rootspec specifying a network interface -> network boot
> - rootdev == NODEV -> resolve rootspec (as a wedge name)
> - rootdev != NODEV -> Use rootdev, ignore rootspec but which is same as 
> rootdev

Can you give me the line numbers in kern_subr.c where you think those
decisions are made?  I can't find the code in question.  rootdev is never
used in a comparison in kern_subr.c.

> The intention is to resolve the 3 cases (network interface, disk device,
> wedge name), and rootspec basically overrides rootdev (in the second case
> they specify the same device, so nothing is "overridden" even when the
> code takes the rootdev value).

I'm unclear what the you mean by "in the second case".

> >I.e. rootspec and rootdev need to be set in pairs.
> 
> If rootspec isn't set by config(1), we talk about a wildcard boot and
> rootdev is already set to NODEV. So that's exactly the third case provided
> by config(1). And if I'm not mistaken then
> config <name> root on "raid0"
> doesn't work either.

Probably.  My proposed change makes that work, though.
The idea in that change is that if parsedisk() can resolve the device in
bootspec, that we simulate what "config <name> root on bootspec" would
have done.  That does handle the dk(4) and wedge name cases too, because
these devices now exist.

> So we could
> - explicitely clear rootdev to NODEV to not rely on config(1) defaults
>   when using bootspec.

That doesn't work because then rootdev would never get set and it has to
be set after you get to haveroot:.

> - make the code that resolves rootspec also handle regular disks and
>   not just dk (and flash) devices. This also keeps that logic in a
>   single place.

I have thought about why

                if (dv != NULL && device_class(dv) == DV_DISK &&
                    !DEV_USES_PARTITIONS(dv) &&
                    (majdev = devsw_name2blk(device_xname(dv), NULL, 0)) >= 0) {
                        rootdv = dv;
                        rootdev = makedev(majdev, device_unit(dv));
                        goto haveroot;
                }

doesn't do the same thing as 

                        if (DEV_USES_PARTITIONS(bootdv))
                                rootdev = MAKEDISKDEV(majdev,
                                                      device_unit(bootdv),
                                                      bootpartition);
                        else
                                rootdev = makedev(majdev, device_unit(bootdv));
in the rootspec == NULL case.

That is another candidate for a likely fix.

But I can't easily test any longer as the machine I was testing on had to
leave the house 10 days ago.

Anyway, I see nothing wrong on a technical level with my change.
There's a lot to clean up and actually factor out related to setroot()
anyway.

--chris

Reply via email to