1 /* 2 * Copyright (c) 2007 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/sys/kern/vfs_synth.c,v 1.1 2007/07/30 08:02:38 dillon Exp $ 35 */ 36 37 /* 38 * Synthesize vnodes for devices. Devices have certain requirements and 39 * limitations with regards to opening and closing, and physical I/O 40 * limits. This module allows you to synthesize a specfs-backed vnode 41 * for a device. 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/vnode.h> 48 #include <sys/lock.h> 49 #include <sys/disk.h> 50 #include <sys/mount.h> 51 52 #include <sys/thread2.h> 53 54 static struct mount *synth_mount; 55 56 /* 57 * getsynthvnode() - return a vnode representing a device. 58 * 59 * The caller must VOP_OPEN() the vnode as appropriate before using it for 60 * I/O, and VOP_CLOSE() it when finished. 61 * 62 * The returned vnode will be referenced and locked. The caller must 63 * vrele() the vnode when finished with it. 64 */ 65 struct vnode * 66 getsynthvnode(const char *devname) 67 { 68 struct vnode *vp; 69 int error; 70 cdev_t dev; 71 72 dev = disk_locate(devname); 73 if (dev == NULL) 74 return(NULL); 75 76 error = getnewvnode(VT_SYNTH, synth_mount, &vp, 0, 0); 77 if (error) 78 panic("getsynthvnode: unable to get new vnode"); 79 vp->v_type = VCHR; 80 addaliasu(vp, dev->si_umajor, dev->si_uminor); 81 return(vp); 82 } 83 84 /* 85 * VOP support - use specfs and dummy up the mount. 86 */ 87 88 static int synth_inactive(struct vop_inactive_args *ap); 89 static int synth_reclaim(struct vop_reclaim_args *ap); 90 91 struct vop_ops synth_vnode_vops = { 92 .vop_default = vop_defaultop, 93 .vop_inactive = synth_inactive, 94 .vop_reclaim = synth_reclaim 95 }; 96 97 VNODEOP_SET(synth_vnode_vops); 98 99 static 100 int 101 synth_inactive(struct vop_inactive_args *ap) 102 { 103 vrecycle(ap->a_vp); 104 return (0); 105 } 106 107 static 108 int 109 synth_reclaim(struct vop_reclaim_args *ap) 110 { 111 ap->a_vp->v_data = NULL; 112 return(0); 113 } 114 115 /* 116 * Create a dummy mount structure and VFS. This VFS is not currently 117 * mountable. 118 */ 119 static int synth_vfs_mount(struct mount *, char *, caddr_t, struct ucred *); 120 static int synth_vfs_unmount(struct mount *, int mntflags); 121 static int synth_vfs_root(struct mount *mp, struct vnode **vpp); 122 123 static struct vfsops synth_vfsops = { 124 .vfs_mount = synth_vfs_mount, 125 .vfs_root = synth_vfs_root, 126 .vfs_unmount = synth_vfs_unmount 127 }; 128 129 static struct vfsconf synth_vfsconf = { 130 .vfc_vfsops = &synth_vfsops, 131 .vfc_name = { "synth" }, 132 .vfc_typenum = VT_SYNTH 133 }; 134 135 static 136 int 137 synth_vfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) 138 { 139 return (EINVAL); 140 } 141 142 static 143 int 144 synth_vfs_unmount(struct mount *mp, int mntflags) 145 { 146 return (0); 147 } 148 149 static 150 int 151 synth_vfs_root(struct mount *mp, struct vnode **vpp) 152 { 153 *vpp = NULL; 154 return (EINVAL); 155 } 156 157 /* 158 * We have to register our VFS and create our dummy mount structure before 159 * devices configure or vinum will not be able to configure at boot. The 160 * standard usage via VFS_SET() is registered too late. 161 */ 162 static 163 void 164 synthinit(void *arg __unused) 165 { 166 int error; 167 168 error = vfs_register(&synth_vfsconf); 169 KKASSERT(error == 0); 170 error = vfs_rootmountalloc("synth", "dummy", &synth_mount); 171 KKASSERT(error == 0); 172 synth_mount->mnt_vn_use_ops = &synth_vnode_vops; 173 } 174 175 SYSINIT(synthinit, SI_SUB_CREATE_INIT, SI_ORDER_ANY, synthinit, NULL) 176 177