Mounting root through devfs

Thomas Quinot thomas at FreeBSD.ORG
Sat May 1 15:30:29 PDT 2004


Hi all,

The attached patch defines a new platform-independant kernel option,
DEVFS_ROOTDEV, which allows devfs to be used by the kernel to look up
the root filesystem.

An interesting use of this option is to mount a root file system by
FFS volume label (using GEOM_VOL), without needing to know what hardware
identifier will be assigned to it.

I have tested this patch successfully on a Soekris 4801 box mounting its
root fs from a CompactFlash card. In such a situation, it is convenient
to mount devices using volume names, because some flash media behave as
ATA masters, and get identified as ad0, whereas others behave as slaves
and are, of course, ad1.

Review, testing and comments would be very much appreciated.

If I understand the comment just above the definition of g_dev_clone,
integration of this patch would allow removal of a questionable hack.

Thanks,
Thomas.

Index: kern/vfs_mount.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_mount.c,v
retrieving revision 1.125
diff -u -r1.125 vfs_mount.c
--- kern/vfs_mount.c	5 Apr 2004 21:03:36 -0000	1.125
+++ kern/vfs_mount.c	1 May 2004 22:18:26 -0000
@@ -1446,19 +1446,65 @@
 
 /*
  * Convert a given name to the dev_t of the disk-like device
- * it refers to.
+ * it refers to. If DEVFS_ROOTDEV is defined, a temporary mount
+ * of devfs is performed, and a lookup is done therein.
  */
 dev_t
 getdiskbyname(char *name) {
-	char *cp;
-	dev_t dev;
+	char *cp = name;
+	dev_t dev = NODEV;
+
+#ifdef DEVFS_ROOTDEV
+	struct thread *td = curthread;
+	struct vfsconf *vfsp;
+	struct mount *mp = NULL;
+	struct vnode *vroot = NULL;
+	struct nameidata nid;
+	int error;
+#endif
 
-	cp = name;
 	if (!bcmp(cp, "/dev/", 5))
 		cp += 5;
 
-	dev = NODEV;
+#ifdef DEVFS_ROOTDEV
+	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+		if (!strcmp(vfsp->vfc_name, "devfs"))
+			break;
+	if (vfsp == NULL)
+		goto devfs_rootdev_cleanup;
+	error = vfs_mount_alloc(NULLVP, vfsp, "/dev", td, &mp);
+	if (error)
+		goto devfs_rootdev_cleanup;
+	mp->mnt_flag |= MNT_RDONLY;
+
+	error = VFS_NMOUNT(mp, NULL, curthread);
+	if (error)
+		goto devfs_rootdev_cleanup;
+	VFS_START(mp, 0, td);
+	VFS_ROOT(mp, &vroot);
+	VOP_UNLOCK(vroot, 0, td);
+
+	NDINIT(&nid, LOOKUP, NOCACHE|FOLLOW, UIO_SYSSPACE, cp, curthread);
+	nid.ni_startdir = vroot;
+	nid.ni_pathlen = strlen(cp);
+	nid.ni_cnd.cn_nameptr = cp;
+
+	error = lookup(&nid);
+	if (error)
+		goto devfs_rootdev_cleanup;
+	dev = vn_todev (nid.ni_vp);
+	NDFREE(&nid, 0);
+
+devfs_rootdev_cleanup:
+	if (vroot != NULL) {
+		VFS_UNMOUNT(mp, 0, td);
+	}
+	if (mp != NULL) {
+		vfs_mount_destroy(mp, td);
+	}
+#else
 	EVENTHANDLER_INVOKE(dev_clone, cp, strlen(cp), &dev);
+#endif
 	return (dev);
 }
 
Index: conf/options
===================================================================
RCS file: /home/ncvs/src/sys/conf/options,v
retrieving revision 1.446
diff -u -r1.446 options
--- conf/options	30 Apr 2004 21:16:51 -0000	1.446
+++ conf/options	1 May 2004 22:03:58 -0000
@@ -543,6 +543,7 @@
 INIT_PATH		opt_init_path.h
 
 ROOTDEVNAME		opt_rootdevname.h
+DEVFS_ROOTDEV		opt_rootdevname.h
 
 FDC_DEBUG		opt_fdc.h
 PCFCLOCK_VERBOSE	opt_pcfclock.h
Index: conf/NOTES
===================================================================
RCS file: /home/ncvs/src/sys/conf/NOTES,v
retrieving revision 1.1223
diff -u -r1.1223 NOTES
--- conf/NOTES	30 Apr 2004 21:16:51 -0000	1.1223
+++ conf/NOTES	1 May 2004 22:05:11 -0000
@@ -136,6 +136,11 @@
 #
 options 	ROOTDEVNAME=\"ufs:da0s2e\"
 
+#
+# The kernel can use the devfs information provided by driver to loo
+# up the root device name, if this option is set.
+options		DEVFS_ROOTDEV
+
 
 #####################################################################
 # Scheduler options:

-- 
    Thomas.Quinot at Cuivre.FR.EU.ORG


More information about the freebsd-current mailing list