Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Jul 2023 21:37:45 -0500
From:      Mike Karels <mike@karels.net>
To:        Mateusz Guzik <mjguzik@gmail.com>
Cc:        Current FreeBSD <freebsd-current@freebsd.org>
Subject:   Re: confusion about root partition causes panic during startup
Message-ID:  <202307210237.36L2bjqk049891@mail2.karels.net>
In-Reply-To: Your message of Thu, 20 Jul 2023 23:13:31 %2B0200. <CAGudoHEgVf6=kFrrCQjce0wjVRQgWJZyZ-bWDz87gse9qFgJQA@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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 man=
aged
> > 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 te=
st.
> > Probably the NDFREE_PNBUF() shouldn't happen if namei() returned an er=
ror.
> >

> 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, fsp=
ath);
>                 error =3D namei(&nd);
>                 if (error) {
> -                       NDFREE_PNBUF(&nd);
>                         fspath =3D "/mnt";
>                         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSP=
ACE,
>                             fspath);
>                         error =3D namei(&nd);
>                 }
>                 if (!error) {
> +                       NDFREE_PNBUF(&nd);
>                         vp =3D nd.ni_vp;
>                         error =3D (vp->v_type =3D=3D 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 ro=
ot "
> @@ -387,6 +386,7 @@ vfs_mountroot_shuffle(struct thread *td, struct
> mount *mpdevfs)
>         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev");
>         error =3D namei(&nd);
>         if (!error) {
> +               NDFREE_PNBUF(&nd);
>                 vp =3D nd.ni_vp;
>                 error =3D (vp->v_type =3D=3D 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 moun=
t *mpdevfs)
 		NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath);
 		error =3D namei(&nd);
 		if (error) {
-			NDFREE_PNBUF(&nd);
 			fspath =3D "/mnt";
 			NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
 			    fspath);
 			error =3D namei(&nd);
 		}
 		if (!error) {
+			NDFREE_PNBUF(&nd);
 			vp =3D nd.ni_vp;
 			error =3D (vp->v_type =3D=3D 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 =3D namei(&nd);
 	if (!error) {
+		NDFREE_PNBUF(&nd);
 		vp =3D nd.ni_vp;
 		error =3D (vp->v_type =3D=3D 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 =3D=3D mpdevfs) {
 		vfs_unbusy(mpdevfs);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202307210237.36L2bjqk049891>