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.4 1993/03/27 02:00:45 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 boot 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_UFS, mp, &kernfs_vnodeops, &rvp); /* XXX */ 147 if (error) 148 return (error); 149 150 fmp = (struct kernfs_mount *) malloc(sizeof(struct kernfs_mount), 151 M_UFSMNT, M_WAITOK); /* XXX */ 152 rvp->v_type = VDIR; 153 rvp->v_flag |= VROOT; 154 #ifdef KERNFS_DIAGNOSTIC 155 printf("kernfs_mount: root vp = %x\n", rvp); 156 #endif 157 fmp->kf_root = rvp; 158 mp->mnt_flag |= MNT_LOCAL; 159 mp->mnt_data = (qaddr_t) fmp; 160 getnewfsid(mp, MOUNT_KERNFS); 161 162 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 163 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 164 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 165 bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs")); 166 #ifdef KERNFS_DIAGNOSTIC 167 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname); 168 #endif 169 return (0); 170 } 171 172 kernfs_start(mp, flags, p) 173 struct mount *mp; 174 int flags; 175 struct proc *p; 176 { 177 return (0); 178 } 179 180 kernfs_unmount(mp, mntflags, p) 181 struct mount *mp; 182 int mntflags; 183 struct proc *p; 184 { 185 int error; 186 int flags = 0; 187 extern int doforce; 188 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; 189 190 #ifdef KERNFS_DIAGNOSTIC 191 printf("kernfs_unmount(mp = %x)\n", mp); 192 #endif 193 194 if (mntflags & MNT_FORCE) { 195 /* kernfs can never be rootfs so don't check for it */ 196 if (!doforce) 197 return (EINVAL); 198 flags |= FORCECLOSE; 199 } 200 201 /* 202 * Clear out buffer cache. I don't think we 203 * ever get anything cached at this level at the 204 * moment, but who knows... 205 */ 206 #ifdef KERNFS_DIAGNOSTIC 207 printf("kernfs_unmount: calling mntflushbuf\n"); 208 #endif 209 mntflushbuf(mp, 0); 210 #ifdef KERNFS_DIAGNOSTIC 211 printf("kernfs_unmount: calling mntinvalbuf\n"); 212 #endif 213 if (mntinvalbuf(mp, 1)) 214 return (EBUSY); 215 if (rootvp->v_usecount > 1) 216 return (EBUSY); 217 #ifdef KERNFS_DIAGNOSTIC 218 printf("kernfs_unmount: calling vflush\n"); 219 #endif 220 if (error = vflush(mp, rootvp, flags)) 221 return (error); 222 223 #ifdef KERNFS_DIAGNOSTIC 224 vprint("kernfs root", rootvp); 225 #endif 226 /* 227 * Release reference on underlying root vnode 228 */ 229 vrele(rootvp); 230 /* 231 * And blow it away for future re-use 232 */ 233 vgone(rootvp); 234 /* 235 * Finally, throw away the kernfs_mount structure 236 */ 237 free(mp->mnt_data, M_UFSMNT); /* XXX */ 238 mp->mnt_data = 0; 239 return 0; 240 } 241 242 kernfs_root(mp, vpp) 243 struct mount *mp; 244 struct vnode **vpp; 245 { 246 struct vnode *vp; 247 int error; 248 249 #ifdef KERNFS_DIAGNOSTIC 250 printf("kernfs_root(mp = %x)\n", mp); 251 #endif 252 253 /* 254 * Return locked reference to root. 255 */ 256 vp = VFSTOKERNFS(mp)->kf_root; 257 VREF(vp); 258 VOP_LOCK(vp); 259 *vpp = vp; 260 return (0); 261 } 262 263 kernfs_quotactl(mp, cmd, uid, arg, p) 264 struct mount *mp; 265 int cmd; 266 uid_t uid; 267 caddr_t arg; 268 struct proc *p; 269 { 270 return (EOPNOTSUPP); 271 } 272 273 kernfs_statfs(mp, sbp, p) 274 struct mount *mp; 275 struct statfs *sbp; 276 struct proc *p; 277 { 278 struct filedesc *fdp; 279 int lim; 280 int i; 281 int last; 282 int freefd; 283 284 #ifdef KERNFS_DIAGNOSTIC 285 printf("kernfs_statfs(mp = %x)\n", mp); 286 #endif 287 288 sbp->f_type = MOUNT_KERNFS; 289 sbp->f_flags = 0; 290 sbp->f_fsize = DEV_BSIZE; 291 sbp->f_bsize = DEV_BSIZE; 292 sbp->f_blocks = 2; /* 1K to keep df happy */ 293 sbp->f_bfree = 0; 294 sbp->f_bavail = 0; 295 sbp->f_files = 0; /* Allow for "." */ 296 sbp->f_ffree = 0; /* See comments above */ 297 if (sbp != &mp->mnt_stat) { 298 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 299 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 300 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 301 } 302 return (0); 303 } 304 305 kernfs_sync(mp, waitfor) 306 struct mount *mp; 307 int waitfor; 308 { 309 return (0); 310 } 311 312 kernfs_fhtovp(mp, fhp, vpp) 313 struct mount *mp; 314 struct fid *fhp; 315 struct vnode **vpp; 316 { 317 return (EOPNOTSUPP); 318 } 319 320 kernfs_vptofh(vp, fhp) 321 struct vnode *vp; 322 struct fid *fhp; 323 { 324 return (EOPNOTSUPP); 325 } 326 327 struct vfsops kernfs_vfsops = { 328 kernfs_mount, 329 kernfs_start, 330 kernfs_unmount, 331 kernfs_root, 332 kernfs_quotactl, 333 kernfs_statfs, 334 kernfs_sync, 335 kernfs_fhtovp, 336 kernfs_vptofh, 337 kernfs_init, 338 }; 339