1 /* $NetBSD: kernfs_vfsops.c,v 1.53 2003/08/07 16:32:37 agc Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993, 1995 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software donated to Berkeley by 8 * Jan-Simon Pendry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)kernfs_vfsops.c 8.10 (Berkeley) 5/14/95 35 */ 36 37 /* 38 * Kernel params Filesystem 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: kernfs_vfsops.c,v 1.53 2003/08/07 16:32:37 agc Exp $"); 43 44 #if defined(_KERNEL_OPT) 45 #include "opt_compat_netbsd.h" 46 #endif 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/conf.h> 51 #include <sys/proc.h> 52 #include <sys/vnode.h> 53 #include <sys/mount.h> 54 #include <sys/namei.h> 55 #include <sys/malloc.h> 56 57 #include <miscfs/specfs/specdev.h> 58 #include <miscfs/kernfs/kernfs.h> 59 60 MALLOC_DEFINE(M_KERNFSMNT, "kernfs mount", "kernfs mount structures"); 61 62 dev_t rrootdev = NODEV; 63 64 void kernfs_init __P((void)); 65 void kernfs_done __P((void)); 66 void kernfs_get_rrootdev __P((void)); 67 int kernfs_mount __P((struct mount *, const char *, void *, 68 struct nameidata *, struct proc *)); 69 int kernfs_start __P((struct mount *, int, struct proc *)); 70 int kernfs_unmount __P((struct mount *, int, struct proc *)); 71 int kernfs_root __P((struct mount *, struct vnode **)); 72 int kernfs_statfs __P((struct mount *, struct statfs *, struct proc *)); 73 int kernfs_quotactl __P((struct mount *, int, uid_t, caddr_t, 74 struct proc *)); 75 int kernfs_sync __P((struct mount *, int, struct ucred *, struct proc *)); 76 int kernfs_vget __P((struct mount *, ino_t, struct vnode **)); 77 int kernfs_fhtovp __P((struct mount *, struct fid *, struct vnode **)); 78 int kernfs_checkexp __P((struct mount *, struct mbuf *, int *, 79 struct ucred **)); 80 int kernfs_vptofh __P((struct vnode *, struct fid *)); 81 int kernfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t, 82 struct proc *)); 83 84 void 85 kernfs_init() 86 { 87 #ifdef _LKM 88 malloc_type_attach(M_KERNFSMNT); 89 #endif 90 } 91 92 void 93 kernfs_done() 94 { 95 #ifdef _LKM 96 malloc_type_detach(M_KERNFSMNT); 97 #endif 98 } 99 100 void 101 kernfs_get_rrootdev() 102 { 103 static int tried = 0; 104 105 if (tried) { 106 /* Already did it once. */ 107 return; 108 } 109 tried = 1; 110 111 if (rootdev == NODEV) 112 return; 113 rrootdev = devsw_blk2chr(rootdev); 114 if (rrootdev != NODEV) { 115 #ifdef KERNFS_DIAGNOSTIC 116 printf("kernfs_mount: rootdev = %u.%u; rrootdev = %u.%u\n", 117 major(rootdev), minor(rootdev), major(rrootdev), minor(rrootdev)); 118 #endif 119 return; 120 } 121 rrootdev = NODEV; 122 printf("kernfs_get_rrootdev: no raw root device\n"); 123 } 124 125 /* 126 * Mount the Kernel params filesystem 127 */ 128 int 129 kernfs_mount(mp, path, data, ndp, p) 130 struct mount *mp; 131 const char *path; 132 void *data; 133 struct nameidata *ndp; 134 struct proc *p; 135 { 136 int error = 0; 137 struct kernfs_mount *fmp; 138 struct vnode *rvp; 139 140 #ifdef KERNFS_DIAGNOSTIC 141 printf("kernfs_mount(mp = %p)\n", mp); 142 #endif 143 144 if (mp->mnt_flag & MNT_GETARGS) 145 return 0; 146 /* 147 * Update is a no-op 148 */ 149 if (mp->mnt_flag & MNT_UPDATE) 150 return (EOPNOTSUPP); 151 152 error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp); 153 if (error) 154 return (error); 155 156 MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount), 157 M_KERNFSMNT, M_WAITOK); 158 rvp->v_type = VDIR; 159 rvp->v_flag |= VROOT; 160 #ifdef KERNFS_DIAGNOSTIC 161 printf("kernfs_mount: root vp = %p\n", rvp); 162 #endif 163 fmp->kf_root = rvp; 164 mp->mnt_flag |= MNT_LOCAL; 165 mp->mnt_data = fmp; 166 vfs_getnewfsid(mp); 167 168 error = set_statfs_info(path, UIO_USERSPACE, "kernfs", UIO_SYSSPACE, 169 mp, p); 170 #ifdef KERNFS_DIAGNOSTIC 171 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname); 172 #endif 173 174 kernfs_get_rrootdev(); 175 return error; 176 } 177 178 int 179 kernfs_start(mp, flags, p) 180 struct mount *mp; 181 int flags; 182 struct proc *p; 183 { 184 185 return (0); 186 } 187 188 int 189 kernfs_unmount(mp, mntflags, p) 190 struct mount *mp; 191 int mntflags; 192 struct proc *p; 193 { 194 int error; 195 int flags = 0; 196 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; 197 198 #ifdef KERNFS_DIAGNOSTIC 199 printf("kernfs_unmount(mp = %p)\n", mp); 200 #endif 201 202 if (mntflags & MNT_FORCE) 203 flags |= FORCECLOSE; 204 205 /* 206 * Clear out buffer cache. I don't think we 207 * ever get anything cached at this level at the 208 * moment, but who knows... 209 */ 210 if (rootvp->v_usecount > 1) 211 return (EBUSY); 212 #ifdef KERNFS_DIAGNOSTIC 213 printf("kernfs_unmount: calling vflush\n"); 214 #endif 215 if ((error = vflush(mp, rootvp, flags)) != 0) 216 return (error); 217 218 #ifdef KERNFS_DIAGNOSTIC 219 vprint("kernfs root", rootvp); 220 #endif 221 /* 222 * Clean out the old root vnode for reuse. 223 */ 224 vrele(rootvp); 225 vgone(rootvp); 226 /* 227 * Finally, throw away the kernfs_mount structure 228 */ 229 free(mp->mnt_data, M_KERNFSMNT); 230 mp->mnt_data = 0; 231 return (0); 232 } 233 234 int 235 kernfs_root(mp, vpp) 236 struct mount *mp; 237 struct vnode **vpp; 238 { 239 struct vnode *vp; 240 241 #ifdef KERNFS_DIAGNOSTIC 242 printf("kernfs_root(mp = %p)\n", mp); 243 #endif 244 245 /* 246 * Return locked reference to root. 247 */ 248 vp = VFSTOKERNFS(mp)->kf_root; 249 VREF(vp); 250 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 251 *vpp = vp; 252 return (0); 253 } 254 255 int 256 kernfs_quotactl(mp, cmd, uid, arg, p) 257 struct mount *mp; 258 int cmd; 259 uid_t uid; 260 caddr_t arg; 261 struct proc *p; 262 { 263 264 return (EOPNOTSUPP); 265 } 266 267 int 268 kernfs_statfs(mp, sbp, p) 269 struct mount *mp; 270 struct statfs *sbp; 271 struct proc *p; 272 { 273 274 #ifdef KERNFS_DIAGNOSTIC 275 printf("kernfs_statfs(mp = %p)\n", mp); 276 #endif 277 278 sbp->f_bsize = DEV_BSIZE; 279 sbp->f_iosize = DEV_BSIZE; 280 sbp->f_blocks = 2; /* 1K to keep df happy */ 281 sbp->f_bfree = 0; 282 sbp->f_bavail = 0; 283 sbp->f_files = 0; 284 sbp->f_ffree = 0; 285 #ifdef COMPAT_09 286 sbp->f_type = 7; 287 #else 288 sbp->f_type = 0; 289 #endif 290 copy_statfs_info(sbp, mp); 291 return (0); 292 } 293 294 /*ARGSUSED*/ 295 int 296 kernfs_sync(mp, waitfor, uc, p) 297 struct mount *mp; 298 int waitfor; 299 struct ucred *uc; 300 struct proc *p; 301 { 302 303 return (0); 304 } 305 306 /* 307 * Kernfs flat namespace lookup. 308 * Currently unsupported. 309 */ 310 int 311 kernfs_vget(mp, ino, vpp) 312 struct mount *mp; 313 ino_t ino; 314 struct vnode **vpp; 315 { 316 317 return (EOPNOTSUPP); 318 } 319 320 /*ARGSUSED*/ 321 int 322 kernfs_fhtovp(mp, fhp, vpp) 323 struct mount *mp; 324 struct fid *fhp; 325 struct vnode **vpp; 326 { 327 328 return (EOPNOTSUPP); 329 } 330 331 /*ARGSUSED*/ 332 int 333 kernfs_checkexp(mp, mb, what, anon) 334 struct mount *mp; 335 struct mbuf *mb; 336 int *what; 337 struct ucred **anon; 338 { 339 340 return (EOPNOTSUPP); 341 } 342 343 /*ARGSUSED*/ 344 int 345 kernfs_vptofh(vp, fhp) 346 struct vnode *vp; 347 struct fid *fhp; 348 { 349 350 return (EOPNOTSUPP); 351 } 352 353 int 354 kernfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 355 int *name; 356 u_int namelen; 357 void *oldp; 358 size_t *oldlenp; 359 void *newp; 360 size_t newlen; 361 struct proc *p; 362 { 363 return (EOPNOTSUPP); 364 } 365 366 extern const struct vnodeopv_desc kernfs_vnodeop_opv_desc; 367 368 const struct vnodeopv_desc * const kernfs_vnodeopv_descs[] = { 369 &kernfs_vnodeop_opv_desc, 370 NULL, 371 }; 372 373 struct vfsops kernfs_vfsops = { 374 MOUNT_KERNFS, 375 kernfs_mount, 376 kernfs_start, 377 kernfs_unmount, 378 kernfs_root, 379 kernfs_quotactl, 380 kernfs_statfs, 381 kernfs_sync, 382 kernfs_vget, 383 kernfs_fhtovp, 384 kernfs_vptofh, 385 kernfs_init, 386 NULL, 387 kernfs_done, 388 kernfs_sysctl, 389 NULL, /* vfs_mountroot */ 390 kernfs_checkexp, 391 kernfs_vnodeopv_descs, 392 }; 393