summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2004-06-17 21:24:13 +0000
committerphk <phk@FreeBSD.org>2004-06-17 21:24:13 +0000
commit7dd1d04ac065be210014388f240f045441efd820 (patch)
treef40b1612e107469fa7fe45ff6a9e1f36d26bb2f4 /sys
parent0479585a9d87cc726cd2b3cdb44ebebafe406c84 (diff)
downloadFreeBSD-src-7dd1d04ac065be210014388f240f045441efd820.zip
FreeBSD-src-7dd1d04ac065be210014388f240f045441efd820.tar.gz
Reduce the thaumaturgical level of root filesystem mounts: Instead of using
an otherwise redundant clone routine in geom_disk.c, mount a temporary DEVFS and do a proper lookup. Submitted by: thomas
Diffstat (limited to 'sys')
-rw-r--r--sys/geom/geom_dev.c43
-rw-r--r--sys/kern/vfs_mount.c60
2 files changed, 51 insertions, 52 deletions
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index 5c16763..f24400a 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -91,49 +91,6 @@ g_dev_print(void)
printf("\n");
}
-/*
- * XXX: This is disgusting and wrong in every way imaginable: The only reason
- * XXX: we have a clone function is because of the root-mount hack we currently
- * XXX: employ. An improvment would be to unregister this cloner once we know
- * XXX: we no longer need it. Ideally, root-fs would be mounted through DEVFS
- * XXX: eliminating the need for this hack.
- */
-static void
-g_dev_clone(void *arg __unused, char *name, int namelen __unused, struct cdev **dev)
-{
- struct g_geom *gp;
-
- if (*dev != NULL)
- return;
-
- g_waitidle();
-
- /* g_topology_lock(); */
- LIST_FOREACH(gp, &g_dev_class.geom, geom) {
- if (strcmp(gp->name, name))
- continue;
- *dev = gp->softc;
- g_trace(G_T_TOPOLOGY, "g_dev_clone(%s) = %p", name, *dev);
- return;
- }
- /* g_topology_unlock(); */
- return;
-}
-
-static void
-g_dev_register_cloner(void *foo __unused)
-{
- static int once;
-
- /* XXX: why would this happen more than once ?? */
- if (!once) {
- EVENTHANDLER_REGISTER(dev_clone, g_dev_clone, 0, 1000);
- once++;
- }
-}
-
-SYSINIT(geomdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,g_dev_register_cloner,NULL);
-
struct g_provider *
g_dev_getprovider(struct cdev *dev)
{
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 82086ad..57220ba 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1445,21 +1445,63 @@ gets(char *cp)
}
/*
- * Convert a given name to the struct cdev *of the disk-like device
- * it refers to.
+ * Convert a given name to the cdev pointer of the device, which is probably
+ * but not by definition, a disk. Mount a DEVFS (on nothing), look the name
+ * up, extract the cdev from the vnode and unmount it again. Unfortunately
+ * we cannot use the vnode directly (because we unmount the DEVFS again)
+ * so the filesystems still have to do the bdevvp() stunt.
*/
struct cdev *
-getdiskbyname(char *name) {
- char *cp;
- struct cdev *dev;
+getdiskbyname(char *name)
+{
+ char *cp = name;
+ struct cdev *dev = NULL;
+ struct thread *td = curthread;
+ struct vfsconf *vfsp;
+ struct mount *mp = NULL;
+ struct vnode *vroot = NULL;
+ struct nameidata nid;
+ int error;
- cp = name;
if (!bcmp(cp, "/dev/", 5))
cp += 5;
- dev = NULL;
- EVENTHANDLER_INVOKE(dev_clone, cp, strlen(cp), &dev);
- return (dev);
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (!strcmp(vfsp->vfc_name, "devfs"))
+ break;
+ do {
+ if (vfsp == NULL)
+ break;
+ error = vfs_mount_alloc(NULLVP, vfsp, "/dev", td, &mp);
+ if (error)
+ break;
+ mp->mnt_flag |= MNT_RDONLY;
+
+ error = VFS_NMOUNT(mp, NULL, curthread);
+ if (error)
+ break;
+ 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)
+ break;
+ dev = vn_todev (nid.ni_vp);
+ NDFREE(&nid, 0);
+ } while (0);
+
+ if (vroot != NULL)
+ VFS_UNMOUNT(mp, 0, td);
+ if (mp != NULL)
+ vfs_mount_destroy(mp, td);
+ return (dev);
}
/*
OpenPOWER on IntegriCloud