From: Alex Hornung Date: Sun, 14 Mar 2010 08:57:36 +0000 (+0000) Subject: vfs_synth - rewrite X-Git-Tag: v2.7.0~82^2~3 X-Git-Url: https://repo.or.cz/w/dragonfly.git/commitdiff_plain/4c83c1d38c3f000618b4d9d46f6e5a50a1655af8 vfs_synth - rewrite * Rewrite the whole vfs_synth mess to be compatible with devfs. Now we create a synthetic mountpoint and mount devfs on it. We then just nlookup() whatever device we need on that mountpoint. * This also fixes vinum rootmount. To use vinum as a root, vfs.root.mountfrom in /boot/loader.conf has to be set to ":vinum/vinumroot" where can be ufs or hammer. Reported-by: Rumko, tuxillo Dragonfly-bug: http://bugs.dragonflybsd.org/issue1565 --- diff --git a/sys/kern/vfs_synth.c b/sys/kern/vfs_synth.c index 64173f7f26..3bc1eb476d 100644 --- a/sys/kern/vfs_synth.c +++ b/sys/kern/vfs_synth.c @@ -1,13 +1,13 @@ /* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * + * Copyright (c) 2010 The DragonFly Project. All rights reserved. + * * This code is derived from software contributed to The DragonFly Project - * by Matthew Dillon - * + * by Alex Hornung + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -17,7 +17,7 @@ * 3. Neither the name of The DragonFly Project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific, prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -30,15 +30,6 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $DragonFly: src/sys/kern/vfs_synth.c,v 1.1 2007/07/30 08:02:38 dillon Exp $ - */ - -/* - * Synthesize vnodes for devices. Devices have certain requirements and - * limitations with regards to opening and closing, and physical I/O - * limits. This module allows you to synthesize a specfs-backed vnode - * for a device. */ #include @@ -48,129 +39,100 @@ #include #include #include - +#include +#include +#include #include +#include -static struct mount *synth_mount; +struct mount *synth_mp; +struct vnode *synth_vp; +static int synth_inited = 0; +static int synth_synced = 0; -/* - * getsynthvnode() - return a vnode representing a device. - * - * The caller must VOP_OPEN() the vnode as appropriate before using it for - * I/O, and VOP_CLOSE() it when finished. - * - * The returned vnode will be referenced and locked. The caller must - * vrele() the vnode when finished with it. - */ struct vnode * getsynthvnode(const char *devname) { struct vnode *vp; + struct nchandle nch; + struct nlookupdata nd; + struct ucred *cred = proc0.p_ucred; int error; - cdev_t dev; - - dev = disk_locate(devname); - if (dev == NULL) - return(NULL); - - error = getnewvnode(VT_SYNTH, synth_mount, &vp, 0, 0); - if (error) - panic("getsynthvnode: unable to get new vnode"); - vp->v_type = VCHR; - addaliasu(vp, dev->si_umajor, dev->si_uminor); - return(vp); -} - -/* - * VOP support - use specfs and dummy up the mount. - */ - -static int synth_inactive(struct vop_inactive_args *ap); -static int synth_reclaim(struct vop_reclaim_args *ap); - -struct vop_ops synth_vnode_vops = { - .vop_default = vop_defaultop, - .vop_inactive = synth_inactive, - .vop_reclaim = synth_reclaim -}; - -VNODEOP_SET(synth_vnode_vops); -static -int -synth_inactive(struct vop_inactive_args *ap) -{ - vrecycle(ap->a_vp); - return (0); -} - -static -int -synth_reclaim(struct vop_reclaim_args *ap) -{ - ap->a_vp->v_data = NULL; - return(0); -} - -/* - * Create a dummy mount structure and VFS. This VFS is not currently - * mountable. - */ -static int synth_vfs_mount(struct mount *, char *, caddr_t, struct ucred *); -static int synth_vfs_unmount(struct mount *, int mntflags); -static int synth_vfs_root(struct mount *mp, struct vnode **vpp); - -static struct vfsops synth_vfsops = { - .vfs_mount = synth_vfs_mount, - .vfs_root = synth_vfs_root, - .vfs_unmount = synth_vfs_unmount -}; - -static struct vfsconf synth_vfsconf = { - .vfc_vfsops = &synth_vfsops, - .vfc_name = { "synth" }, - .vfc_typenum = VT_SYNTH -}; - -static -int -synth_vfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) -{ - return (EINVAL); + KKASSERT(synth_inited != 0); + KKASSERT(synth_mp != NULL); + KKASSERT(synth_mp->mnt_ncmountpt.mount != NULL); + + /* Sync devfs/disks twice to make sure all devices are around */ + if (synth_synced < 2) { + sync_devs(); + ++synth_synced; + } + + error = nlookup_init_root(&nd, + devname, UIO_SYSSPACE, NLC_FOLLOW, + cred, &synth_mp->mnt_ncmountpt, + &synth_mp->mnt_ncmountpt); + + if (error) { + panic("synth: nlookup_init_root failed with %d\n", error); + /* NOTREACHED */ + } + + error = nlookup(&nd); + if (error == 0) { + if (nd.nl_nch.ncp->nc_vp == NULL) { + kprintf("synth: nc_vp == NULL\n"); + return (NULL); + } + nch = nd.nl_nch; + cache_zero(&nd.nl_nch); + } + + nlookup_done(&nd); + if (error) { + if (error != ENOENT) { /* Don't bother warning about ENOENT */ + kprintf("synth: nlookup of %s failed with %d\n", + devname, error); + } + return (NULL); + } + + vp = nch.ncp->nc_vp; + /* A VX locked & refd vnode must be returned. */ + error = vget(vp, LK_EXCLUSIVE); + cache_unlock(&nch); + + if (error) { + kprintf("synth: could not vget vnode\n"); + return (NULL); + } + + return (vp); } -static -int -synth_vfs_unmount(struct mount *mp, int mntflags) -{ - return (0); -} - -static -int -synth_vfs_root(struct mount *mp, struct vnode **vpp) -{ - *vpp = NULL; - return (EINVAL); -} - -/* - * We have to register our VFS and create our dummy mount structure before - * devices configure or vinum will not be able to configure at boot. The - * standard usage via VFS_SET() is registered too late. - */ -static -void +static void synthinit(void *arg __unused) { int error; - error = vfs_register(&synth_vfsconf); - KKASSERT(error == 0); - error = vfs_rootmountalloc("synth", "dummy", &synth_mount); - KKASSERT(error == 0); - synth_mount->mnt_vn_use_ops = &synth_vnode_vops; + if ((error = vfs_rootmountalloc("devfs", "dummy", &synth_mp))) { + panic("synth: vfs_rootmountalloc failed with %d\n", error); + /* NOTREACHED */ + } + if ((error = VFS_MOUNT(synth_mp, NULL, NULL, proc0.p_ucred))) { + panic("synth: vfs_mount failed with %d\n", error); + /* NOTREACHED */ + } + if ((error = VFS_ROOT(synth_mp, &synth_vp))) { + panic("synth: vfs_root failed with %d\n", error); + /* NOTREACHED */ + } + cache_allocroot(&synth_mp->mnt_ncmountpt, synth_mp, synth_vp); + cache_unlock(&synth_mp->mnt_ncmountpt); /* leave ref intact */ + vput(synth_vp); + + synth_inited = 1; } -SYSINIT(synthinit, SI_SUB_CREATE_INIT, SI_ORDER_ANY, synthinit, NULL) - +SYSINIT(synthinit, SI_SUB_VFS, SI_ORDER_ANY, synthinit, NULL)