1 /* 2 * Copyright (c) 1990, 1992 Jan-Simon Pendry 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Jan-Simon Pendry. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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 the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * $Id: kernfs_vfsops.c,v 1.7 1993/06/07 05:25:24 cgd Exp $ 37 */ 38 39 /* 40 * Kernel params Filesystem 41 */ 42 43 #include "param.h" 44 #include "systm.h" 45 #include "time.h" 46 #include "types.h" 47 #include "proc.h" 48 #include "vnode.h" 49 #include "mount.h" 50 #include "namei.h" 51 #include "malloc.h" 52 #include "conf.h" 53 #include "miscfs/kernfs/kernfs.h" 54 55 /* bring in the spec vnodeops for cdevvp */ 56 extern struct vnodeops spec_vnodeops; 57 58 struct vnode *rrootdevvp; 59 60 /* 61 * cdevvp: 62 * get a character device node. 63 * this is used a few places in the miscfs routines. 64 * 65 * copied from the bdevvp in kern/vfs_subr.c 66 */ 67 cdevvp(dev, vpp) 68 dev_t dev; 69 struct vnode **vpp; 70 { 71 register struct vnode *vp; 72 struct vnode *nvp; 73 int error; 74 75 if (dev == NODEV) 76 return (0); 77 error = getnewvnode(VT_NON, (struct mount *)0, &spec_vnodeops, &nvp); 78 if (error) { 79 *vpp = 0; 80 return (error); 81 } 82 vp = nvp; 83 vp->v_type = VCHR; 84 if (nvp = checkalias(vp, dev, (struct mount *)0)) { 85 vput(vp); 86 vp = nvp; 87 } 88 *vpp = vp; 89 return (0); 90 } 91 92 kernfs_init() 93 { 94 int error, bmaj, cmaj; 95 96 #ifdef KERNFS_DIAGNOSTIC 97 printf("kernfs_init\n"); /* printed during system boot */ 98 #endif 99 100 bmaj = major(rootdev); 101 102 /* hunt for the raw root device by looking in cdevsw for a matching 103 * open routine... 104 */ 105 for (cmaj = 0; cmaj < nchrdev; cmaj++) { 106 if (cdevsw[cmaj].d_open == bdevsw[bmaj].d_open) { 107 dev_t cdev = makedev(cmaj, minor(rootdev)); 108 error = cdevvp(cdev, &rrootdevvp); 109 if (error == 0) 110 break; 111 } 112 } 113 114 /* this isn't fatal... */ 115 if (error) { 116 printf("kernfs: no raw root device\n"); 117 rrootdevvp = 0; 118 } 119 } 120 121 /* 122 * Mount the kernel parameter filesystem 123 */ 124 kernfs_mount(mp, path, data, ndp, p) 125 struct mount *mp; 126 char *path; 127 caddr_t data; 128 struct nameidata *ndp; 129 struct proc *p; 130 { 131 int error = 0; 132 u_int size; 133 struct kernfs_mount *fmp; 134 struct vnode *rvp; 135 136 #ifdef KERNFS_DIAGNOSTIC 137 printf("kernfs_mount(mp = %x)\n", mp); 138 #endif 139 140 /* 141 * Update is a no-op 142 */ 143 if (mp->mnt_flag & MNT_UPDATE) 144 return (EOPNOTSUPP); 145 146 error = getnewvnode(VT_KERNFS, mp, &kernfs_vnodeops, &rvp); 147 if (error) 148 return (error); 149 150 fmp = (struct kernfs_mount *) malloc(sizeof(struct kernfs_mount), 151 M_MISCFSMNT, M_WAITOK); 152 rvp->v_type = VDIR; 153 rvp->v_flag |= VROOT; 154 VTOKERN(rvp)->kf_kt = &kernfs_targets[KERNFS_TARGET_ROOT]; 155 #ifdef KERNFS_DIAGNOSTIC 156 printf("kernfs_mount: root vp = %x\n", rvp); 157 #endif 158 fmp->kf_root = rvp; 159 mp->mnt_flag |= MNT_LOCAL; 160 mp->mnt_data = (qaddr_t) fmp; 161 getnewfsid(mp, MOUNT_KERNFS); 162 163 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 164 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 165 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 166 bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs")); 167 #ifdef KERNFS_DIAGNOSTIC 168 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname); 169 #endif 170 return (0); 171 } 172 173 kernfs_start(mp, flags, p) 174 struct mount *mp; 175 int flags; 176 struct proc *p; 177 { 178 return (0); 179 } 180 181 kernfs_unmount(mp, mntflags, p) 182 struct mount *mp; 183 int mntflags; 184 struct proc *p; 185 { 186 int error; 187 int flags = 0; 188 extern int doforce; 189 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; 190 191 #ifdef KERNFS_DIAGNOSTIC 192 printf("kernfs_unmount(mp = %x)\n", mp); 193 #endif 194 195 if (mntflags & MNT_FORCE) { 196 /* kernfs can never be rootfs so don't check for it */ 197 if (!doforce) 198 return (EINVAL); 199 flags |= FORCECLOSE; 200 } 201 202 /* 203 * Clear out buffer cache. I don't think we 204 * ever get anything cached at this level at the 205 * moment, but who knows... 206 */ 207 #ifdef KERNFS_DIAGNOSTIC 208 printf("kernfs_unmount: calling mntflushbuf\n"); 209 #endif 210 mntflushbuf(mp, 0); 211 #ifdef KERNFS_DIAGNOSTIC 212 printf("kernfs_unmount: calling mntinvalbuf\n"); 213 #endif 214 if (mntinvalbuf(mp, 1)) 215 return (EBUSY); 216 if (rootvp->v_usecount > 1) 217 return (EBUSY); 218 #ifdef KERNFS_DIAGNOSTIC 219 printf("kernfs_unmount: calling vflush\n"); 220 #endif 221 if (error = vflush(mp, rootvp, flags)) 222 return (error); 223 224 #ifdef KERNFS_DIAGNOSTIC 225 vprint("kernfs root", rootvp); 226 #endif 227 /* 228 * Release reference on underlying root vnode 229 */ 230 vrele(rootvp); 231 /* 232 * And blow it away for future re-use 233 */ 234 vgone(rootvp); 235 /* 236 * Finally, throw away the kernfs_mount structure 237 */ 238 free(mp->mnt_data, M_MISCFSMNT); 239 mp->mnt_data = 0; 240 return 0; 241 } 242 243 kernfs_root(mp, vpp) 244 struct mount *mp; 245 struct vnode **vpp; 246 { 247 struct vnode *vp; 248 int error; 249 250 #ifdef KERNFS_DIAGNOSTIC 251 printf("kernfs_root(mp = %x)\n", mp); 252 #endif 253 254 /* 255 * Return locked reference to root. 256 */ 257 vp = VFSTOKERNFS(mp)->kf_root; 258 VREF(vp); 259 VOP_LOCK(vp); 260 *vpp = vp; 261 return (0); 262 } 263 264 kernfs_quotactl(mp, cmd, uid, arg, p) 265 struct mount *mp; 266 int cmd; 267 uid_t uid; 268 caddr_t arg; 269 struct proc *p; 270 { 271 return (EOPNOTSUPP); 272 } 273 274 kernfs_statfs(mp, sbp, p) 275 struct mount *mp; 276 struct statfs *sbp; 277 struct proc *p; 278 { 279 struct filedesc *fdp; 280 int lim; 281 int i; 282 int last; 283 int freefd; 284 285 #ifdef KERNFS_DIAGNOSTIC 286 printf("kernfs_statfs(mp = %x)\n", mp); 287 #endif 288 289 sbp->f_type = MOUNT_KERNFS; 290 sbp->f_flags = 0; 291 sbp->f_fsize = DEV_BSIZE; 292 sbp->f_bsize = DEV_BSIZE; 293 sbp->f_blocks = 2; /* 1K to keep df happy */ 294 sbp->f_bfree = 0; 295 sbp->f_bavail = 0; 296 sbp->f_files = 0; /* Allow for "." */ 297 sbp->f_ffree = 0; /* See comments above */ 298 if (sbp != &mp->mnt_stat) { 299 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 300 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 301 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 302 } 303 return (0); 304 } 305 306 kernfs_sync(mp, waitfor) 307 struct mount *mp; 308 int waitfor; 309 { 310 return (0); 311 } 312 313 kernfs_fhtovp(mp, fhp, vpp) 314 struct mount *mp; 315 struct fid *fhp; 316 struct vnode **vpp; 317 { 318 return (EOPNOTSUPP); 319 } 320 321 kernfs_vptofh(vp, fhp) 322 struct vnode *vp; 323 struct fid *fhp; 324 { 325 return (EOPNOTSUPP); 326 } 327 328 struct vfsops kernfs_vfsops = { 329 kernfs_mount, 330 kernfs_start, 331 kernfs_unmount, 332 kernfs_root, 333 kernfs_quotactl, 334 kernfs_statfs, 335 kernfs_sync, 336 kernfs_fhtovp, 337 kernfs_vptofh, 338 kernfs_init, 339 }; 340