Re: confusion about root partition causes panic during startup
Date: Fri, 21 Jul 2023 02:37:45 UTC
Mateusz Guzik <mjguzik@gmail.com> wrote: > On 7/20/23, Mike Karels <mike@karels.net> wrote: > > I installed an additional NVME drive on a system, and then booted. It > > turns > > out that the new drive became nda0, renumbering the other drives. The > > loader > > found the correct partition to boot (the only choice), and loaded the > > kernel > > correctly. However, /etc/fstab still had the old name (nvd1p2), which is > > now drive 2. I expected it to drop into single user, but instead the > > system > > panicked in vfs_mountroot_shuffle trying to switch root devices (see > > below). > > It doesn't seem that having the wrong root device in /etc/fstab should > > cause > > a panic; it makes it harder to patch the system. I was unable to get the > > system to boot using boot-to-single-user or setting currdev, but I managed > > to remember doing "boot -a" from a loader prompt to get the system to ask > > the root device before mounting it. I can easily reproduce this to test. > > Probably the NDFREE_PNBUF() shouldn't happen if namei() returned an error. > > > ye, this should do it (untested): > diff --git a/sys/kern/vfs_mountroot.c b/sys/kern/vfs_mountroot.c > index 956d29e3f084..85398ff781e4 100644 > --- a/sys/kern/vfs_mountroot.c > +++ b/sys/kern/vfs_mountroot.c > @@ -352,13 +352,13 @@ vfs_mountroot_shuffle(struct thread *td, struct > mount *mpdevfs) > NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath); > error = namei(&nd); > if (error) { > - NDFREE_PNBUF(&nd); > fspath = "/mnt"; > NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, > fspath); > error = namei(&nd); > } > if (!error) { > + NDFREE_PNBUF(&nd); > vp = nd.ni_vp; > error = (vp->v_type == VDIR) ? 0 : ENOTDIR; > if (!error) > @@ -376,7 +376,6 @@ vfs_mountroot_shuffle(struct thread *td, struct > mount *mpdevfs) > } else > vput(vp); > } > - NDFREE_PNBUF(&nd); > if (error) > printf("mountroot: unable to remount previous root " > @@ -387,6 +386,7 @@ vfs_mountroot_shuffle(struct thread *td, struct > mount *mpdevfs) > NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev"); > error = namei(&nd); > if (!error) { > + NDFREE_PNBUF(&nd); > vp = nd.ni_vp; > error = (vp->v_type == VDIR) ? 0 : ENOTDIR; > if (!error) That was missing the last change, and tabs were expanded. I put it in by hand, and the patch works, at least to avoid this panic. It still insisted on remounting root on nda1p2, which is not a root file system. Remounting /dev still failed without panicking, then it panicked because there was no /sbin/init. Apparently it is necessary to use "boot -a" in this situation. Too bad the loader option menu doesn't include that. Just to be clear what I tested, my patch follows. Mike diff --git a/sys/kern/vfs_mountroot.c b/sys/kern/vfs_mountroot.c index 956d29e3f084..b08b2a3200f8 100644 --- a/sys/kern/vfs_mountroot.c +++ b/sys/kern/vfs_mountroot.c @@ -352,13 +352,13 @@ vfs_mountroot_shuffle(struct thread *td, struct mount *mpdevfs) NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath); error = namei(&nd); if (error) { - NDFREE_PNBUF(&nd); fspath = "/mnt"; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath); error = namei(&nd); } if (!error) { + NDFREE_PNBUF(&nd); vp = nd.ni_vp; error = (vp->v_type == VDIR) ? 0 : ENOTDIR; if (!error) @@ -376,7 +376,6 @@ vfs_mountroot_shuffle(struct thread *td, struct mount *mpdevfs) } else vput(vp); } - NDFREE_PNBUF(&nd); if (error) printf("mountroot: unable to remount previous root " @@ -387,6 +386,7 @@ vfs_mountroot_shuffle(struct thread *td, struct mount *mpdevfs) NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev"); error = namei(&nd); if (!error) { + NDFREE_PNBUF(&nd); vp = nd.ni_vp; error = (vp->v_type == VDIR) ? 0 : ENOTDIR; if (!error) @@ -413,7 +413,6 @@ vfs_mountroot_shuffle(struct thread *td, struct mount *mpdevfs) if (error) printf("mountroot: unable to remount devfs under /dev " "(error %d)\n", error); - NDFREE_PNBUF(&nd); if (mporoot == mpdevfs) { vfs_unbusy(mpdevfs);