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.8 1993/08/23 05:02:14 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 kernfs_init() 61 { 62 int error, bmaj, cmaj; 63 64 #ifdef KERNFS_DIAGNOSTIC 65 printf("kernfs_init\n"); /* printed during system boot */ 66 #endif 67 68 bmaj = major(rootdev); 69 70 /* hunt for the raw root device by looking in cdevsw for a matching 71 * open routine... 72 */ 73 for (cmaj = 0; cmaj < nchrdev; cmaj++) { 74 if (cdevsw[cmaj].d_open == bdevsw[bmaj].d_open) { 75 dev_t cdev = makedev(cmaj, minor(rootdev)); 76 error = cdevvp(cdev, &rrootdevvp); 77 if (error == 0) 78 break; 79 } 80 } 81 82 /* this isn't fatal... */ 83 if (error) { 84 printf("kernfs: no raw root device\n"); 85 rrootdevvp = 0; 86 } 87 } 88 89 /* 90 * Mount the kernel parameter filesystem 91 */ 92 kernfs_mount(mp, path, data, ndp, p) 93 struct mount *mp; 94 char *path; 95 caddr_t data; 96 struct nameidata *ndp; 97 struct proc *p; 98 { 99 int error = 0; 100 u_int size; 101 struct kernfs_mount *fmp; 102 struct vnode *rvp; 103 104 #ifdef KERNFS_DIAGNOSTIC 105 printf("kernfs_mount(mp = %x)\n", mp); 106 #endif 107 108 /* 109 * Update is a no-op 110 */ 111 if (mp->mnt_flag & MNT_UPDATE) 112 return (EOPNOTSUPP); 113 114 error = getnewvnode(VT_KERNFS, mp, &kernfs_vnodeops, &rvp); 115 if (error) 116 return (error); 117 118 fmp = (struct kernfs_mount *) malloc(sizeof(struct kernfs_mount), 119 M_MISCFSMNT, M_WAITOK); 120 rvp->v_type = VDIR; 121 rvp->v_flag |= VROOT; 122 VTOKERN(rvp)->kf_kt = &kernfs_targets[KERNFS_TARGET_ROOT]; 123 #ifdef KERNFS_DIAGNOSTIC 124 printf("kernfs_mount: root vp = %x\n", rvp); 125 #endif 126 fmp->kf_root = rvp; 127 mp->mnt_flag |= MNT_LOCAL; 128 mp->mnt_data = (qaddr_t) fmp; 129 getnewfsid(mp, MOUNT_KERNFS); 130 131 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 132 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 133 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 134 bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs")); 135 #ifdef KERNFS_DIAGNOSTIC 136 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname); 137 #endif 138 return (0); 139 } 140 141 kernfs_start(mp, flags, p) 142 struct mount *mp; 143 int flags; 144 struct proc *p; 145 { 146 return (0); 147 } 148 149 kernfs_unmount(mp, mntflags, p) 150 struct mount *mp; 151 int mntflags; 152 struct proc *p; 153 { 154 int error; 155 int flags = 0; 156 extern int doforce; 157 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; 158 159 #ifdef KERNFS_DIAGNOSTIC 160 printf("kernfs_unmount(mp = %x)\n", mp); 161 #endif 162 163 if (mntflags & MNT_FORCE) { 164 /* kernfs can never be rootfs so don't check for it */ 165 if (!doforce) 166 return (EINVAL); 167 flags |= FORCECLOSE; 168 } 169 170 /* 171 * Clear out buffer cache. I don't think we 172 * ever get anything cached at this level at the 173 * moment, but who knows... 174 */ 175 #ifdef KERNFS_DIAGNOSTIC 176 printf("kernfs_unmount: calling mntflushbuf\n"); 177 #endif 178 mntflushbuf(mp, 0); 179 #ifdef KERNFS_DIAGNOSTIC 180 printf("kernfs_unmount: calling mntinvalbuf\n"); 181 #endif 182 if (mntinvalbuf(mp, 1)) 183 return (EBUSY); 184 if (rootvp->v_usecount > 1) 185 return (EBUSY); 186 #ifdef KERNFS_DIAGNOSTIC 187 printf("kernfs_unmount: calling vflush\n"); 188 #endif 189 if (error = vflush(mp, rootvp, flags)) 190 return (error); 191 192 #ifdef KERNFS_DIAGNOSTIC 193 vprint("kernfs root", rootvp); 194 #endif 195 /* 196 * Release reference on underlying root vnode 197 */ 198 vrele(rootvp); 199 /* 200 * And blow it away for future re-use 201 */ 202 vgone(rootvp); 203 /* 204 * Finally, throw away the kernfs_mount structure 205 */ 206 free(mp->mnt_data, M_MISCFSMNT); 207 mp->mnt_data = 0; 208 return 0; 209 } 210 211 kernfs_root(mp, vpp) 212 struct mount *mp; 213 struct vnode **vpp; 214 { 215 struct vnode *vp; 216 int error; 217 218 #ifdef KERNFS_DIAGNOSTIC 219 printf("kernfs_root(mp = %x)\n", mp); 220 #endif 221 222 /* 223 * Return locked reference to root. 224 */ 225 vp = VFSTOKERNFS(mp)->kf_root; 226 VREF(vp); 227 VOP_LOCK(vp); 228 *vpp = vp; 229 return (0); 230 } 231 232 kernfs_quotactl(mp, cmd, uid, arg, p) 233 struct mount *mp; 234 int cmd; 235 uid_t uid; 236 caddr_t arg; 237 struct proc *p; 238 { 239 return (EOPNOTSUPP); 240 } 241 242 kernfs_statfs(mp, sbp, p) 243 struct mount *mp; 244 struct statfs *sbp; 245 struct proc *p; 246 { 247 struct filedesc *fdp; 248 int lim; 249 int i; 250 int last; 251 int freefd; 252 253 #ifdef KERNFS_DIAGNOSTIC 254 printf("kernfs_statfs(mp = %x)\n", mp); 255 #endif 256 257 sbp->f_type = MOUNT_KERNFS; 258 sbp->f_flags = 0; 259 sbp->f_fsize = DEV_BSIZE; 260 sbp->f_bsize = DEV_BSIZE; 261 sbp->f_blocks = 2; /* 1K to keep df happy */ 262 sbp->f_bfree = 0; 263 sbp->f_bavail = 0; 264 sbp->f_files = 0; /* Allow for "." */ 265 sbp->f_ffree = 0; /* See comments above */ 266 if (sbp != &mp->mnt_stat) { 267 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 268 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 269 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 270 } 271 return (0); 272 } 273 274 kernfs_sync(mp, waitfor) 275 struct mount *mp; 276 int waitfor; 277 { 278 return (0); 279 } 280 281 kernfs_fhtovp(mp, fhp, vpp) 282 struct mount *mp; 283 struct fid *fhp; 284 struct vnode **vpp; 285 { 286 return (EOPNOTSUPP); 287 } 288 289 kernfs_vptofh(vp, fhp) 290 struct vnode *vp; 291 struct fid *fhp; 292 { 293 return (EOPNOTSUPP); 294 } 295 296 struct vfsops kernfs_vfsops = { 297 kernfs_mount, 298 kernfs_start, 299 kernfs_unmount, 300 kernfs_root, 301 kernfs_quotactl, 302 kernfs_statfs, 303 kernfs_sync, 304 kernfs_fhtovp, 305 kernfs_vptofh, 306 kernfs_init, 307 }; 308