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
This commit is contained in:
parent
0479585a9d
commit
7dd1d04ac0
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user