|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /*- ! 23: * Copyright 1997,1998 Julian Elischer. All rights reserved. ! 24: * [email protected] ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions are ! 28: * met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright notice, ! 32: * this list of conditions and the following disclaimer in the documentation ! 33: * and/or other materials provided with the distribution. ! 34: * ! 35: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS ! 36: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 37: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 38: * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR ! 39: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 40: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 41: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ! 42: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 43: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 44: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 45: * SUCH DAMAGE. ! 46: * ! 47: * devfs_vfsops.c ! 48: * ! 49: */ ! 50: /* ! 51: * HISTORY ! 52: * Dieter Siegmund ([email protected]) Wed Jul 14 13:37:59 PDT 1999 ! 53: * - modified devfs_statfs() to use devfs_stats to calculate the ! 54: * amount of memory used by devfs ! 55: */ ! 56: ! 57: ! 58: #include <sys/param.h> ! 59: #include <sys/systm.h> ! 60: #include <sys/kernel.h> ! 61: #include <sys/vnode.h> ! 62: #include <sys/proc.h> ! 63: #include <sys/mount.h> ! 64: #include <sys/malloc.h> ! 65: ! 66: #include "devfs.h" ! 67: #include "devfsdefs.h" ! 68: ! 69: static int devfs_statfs( struct mount *mp, struct statfs *sbp, struct proc *p); ! 70: ! 71: static struct vfsconf * devfs_vfsp = 0; ! 72: static int kernel_mount = 0; ! 73: ! 74: ! 75: /*- ! 76: * Called from the generic VFS startups. ! 77: * This is the second stage of DEVFS initialisation. ! 78: * The probed devices have already been loaded and the ! 79: * basic structure of the DEVFS created. ! 80: * We take the oportunity to mount the hidden DEVFS layer, so that ! 81: * devices from devfs get sync'd. ! 82: */ ! 83: static int ! 84: devfs_init(struct vfsconf *vfsp) ! 85: { ! 86: devfs_vfsp = vfsp; /* remember this for devfs_kernel_mount below */ ! 87: ! 88: if (devfs_sinit()) ! 89: return (EOPNOTSUPP); ! 90: printf("devfs enabled\n"); ! 91: devfs_make_node(makedev(0, 0), DEVFS_CHAR, ! 92: UID_ROOT, GID_WHEEL, 0622, "console"); ! 93: devfs_make_node(makedev(2, 0), DEVFS_CHAR, ! 94: UID_ROOT, GID_WHEEL, 0666, "tty"); ! 95: devfs_make_node(makedev(3, 0), DEVFS_CHAR, ! 96: UID_ROOT, GID_KMEM, 0640, "mem"); ! 97: devfs_make_node(makedev(3, 1), DEVFS_CHAR, ! 98: UID_ROOT, GID_KMEM, 0640, "kmem"); ! 99: devfs_make_node(makedev(3, 2), DEVFS_CHAR, ! 100: UID_ROOT, GID_WHEEL, 0666, "null"); ! 101: devfs_make_node(makedev(6, 0), DEVFS_CHAR, ! 102: UID_ROOT, GID_WHEEL, 0600, "klog"); ! 103: devfs_make_node(makedev(37, 0), DEVFS_CHAR, ! 104: UID_ROOT, GID_WHEEL, 0600, "nvram"); ! 105: return 0; ! 106: } ! 107: ! 108: /*- ! 109: * mp - pointer to 'mount' structure ! 110: * path - addr in user space of mount point (ie /usr or whatever) ! 111: * data - addr in user space of mount params including the ! 112: * name of the block special file to treat as a filesystem. ! 113: * (NOT USED) ! 114: * ndp - namei data pointer (NOT USED) ! 115: * p - proc pointer ! 116: * devfs is special in that it doesn't require any device to be mounted.. ! 117: * It makes up its data as it goes along. ! 118: * it must be mounted during single user.. until it is, only std{in/out/err} ! 119: * and the root filesystem are available. ! 120: */ ! 121: /*proto*/ ! 122: int ! 123: devfs_mount(struct mount *mp, char *path, caddr_t data, ! 124: struct nameidata *ndp, struct proc *p) ! 125: { ! 126: struct devfsmount *devfs_mp_p; /* devfs specific mount info */ ! 127: int error; ! 128: size_t size; ! 129: ! 130: /*- ! 131: * If they just want to update, we don't need to do anything. ! 132: */ ! 133: if (mp->mnt_flag & MNT_UPDATE) ! 134: { ! 135: return 0; ! 136: } ! 137: ! 138: /*- ! 139: * Well, it's not an update, it's a real mount request. ! 140: * Time to get dirty. ! 141: * HERE we should check to see if we are already mounted here. ! 142: */ ! 143: ! 144: MALLOC(devfs_mp_p, struct devfsmount *, sizeof(struct devfsmount), ! 145: M_DEVFSMNT, M_WAITOK); ! 146: if (devfs_mp_p == NULL) ! 147: return (ENOMEM); ! 148: bzero(devfs_mp_p,sizeof(*devfs_mp_p)); ! 149: devfs_mp_p->mount = mp; ! 150: ! 151: /*- ! 152: * Fill out some fields ! 153: */ ! 154: mp->mnt_data = (qaddr_t)devfs_mp_p; ! 155: mp->mnt_stat.f_type = mp->mnt_vfc->vfc_typenum; ! 156: mp->mnt_stat.f_fsid.val[0] = (int32_t)(void *)devfs_mp_p; ! 157: mp->mnt_stat.f_fsid.val[1] = mp->mnt_stat.f_type; ! 158: mp->mnt_flag |= MNT_LOCAL; ! 159: ! 160: DEVFS_LOCK(p); ! 161: error = dev_dup_plane(devfs_mp_p); ! 162: DEVFS_UNLOCK(p); ! 163: if (error) { ! 164: mp->mnt_data = (qaddr_t)0; ! 165: FREE((caddr_t)devfs_mp_p, M_DEVFSMNT); ! 166: return (error); ! 167: } ! 168: ! 169: /*- ! 170: * Copy in the name of the directory the filesystem ! 171: * is to be mounted on. ! 172: * And we clear the remainder of the character strings ! 173: * to be tidy. ! 174: */ ! 175: ! 176: if (!kernel_mount) { ! 177: copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname, ! 178: sizeof(mp->mnt_stat.f_mntonname)-1, &size); ! 179: bzero(mp->mnt_stat.f_mntonname + size, ! 180: sizeof(mp->mnt_stat.f_mntonname) - size); ! 181: } ! 182: bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); ! 183: bcopy("devfs",mp->mnt_stat.f_mntfromname, 5); ! 184: DEVFS_INCR_MOUNTS(); ! 185: (void)devfs_statfs(mp, &mp->mnt_stat, p); ! 186: return 0; ! 187: } ! 188: ! 189: ! 190: static int ! 191: devfs_start(struct mount *mp, int flags, struct proc *p) ! 192: { ! 193: return 0; ! 194: } ! 195: ! 196: /*- ! 197: * Unmount the filesystem described by mp. ! 198: */ ! 199: static int ! 200: devfs_unmount( struct mount *mp, int mntflags, struct proc *p) ! 201: { ! 202: struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data; ! 203: int flags = 0; ! 204: int error; ! 205: ! 206: if (mntflags & MNT_FORCE) { ! 207: flags |= FORCECLOSE; ! 208: } ! 209: error = vflush(mp, NULLVP, flags); ! 210: if (error) ! 211: return error; ! 212: ! 213: DEVFS_LOCK(p); ! 214: devfs_free_plane(devfs_mp_p); ! 215: DEVFS_UNLOCK(p); ! 216: FREE((caddr_t)devfs_mp_p, M_DEVFSMNT); ! 217: DEVFS_DECR_MOUNTS(); ! 218: mp->mnt_data = (qaddr_t)0; ! 219: mp->mnt_flag &= ~MNT_LOCAL; ! 220: ! 221: return 0; ! 222: } ! 223: ! 224: /* return the address of the root vnode in *vpp */ ! 225: static int ! 226: devfs_root(struct mount *mp, struct vnode **vpp) ! 227: { ! 228: struct devfsmount *devfs_mp_p = (struct devfsmount *)(mp->mnt_data); ! 229: int error; ! 230: ! 231: error = devfs_dntovn(devfs_mp_p->plane_root->de_dnp,vpp, ! 232: current_proc()); ! 233: return error; ! 234: } ! 235: ! 236: static int ! 237: devfs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, ! 238: struct proc *p) ! 239: { ! 240: return EOPNOTSUPP; ! 241: } ! 242: ! 243: static int ! 244: devfs_statfs( struct mount *mp, struct statfs *sbp, struct proc *p) ! 245: { ! 246: struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data; ! 247: ! 248: /*- ! 249: * Fill in the stat block. ! 250: */ ! 251: sbp->f_type = mp->mnt_stat.f_type; ! 252: sbp->f_flags = 0; /* XXX */ ! 253: sbp->f_bsize = 512; ! 254: sbp->f_iosize = 512; ! 255: sbp->f_blocks = (devfs_stats.mounts * sizeof(struct devfsmount) ! 256: + devfs_stats.nodes * sizeof(devnode_t) ! 257: + devfs_stats.entries * sizeof(devdirent_t) ! 258: + devfs_stats.stringspace ! 259: ) / sbp->f_bsize; ! 260: sbp->f_bfree = 0; ! 261: sbp->f_bavail = 0; ! 262: sbp->f_files = devfs_stats.nodes; ! 263: sbp->f_ffree = 0; ! 264: sbp->f_fsid.val[0] = (int32_t)(void *)devfs_mp_p; ! 265: sbp->f_fsid.val[1] = mp->mnt_stat.f_type; ! 266: ! 267: /*- ! 268: * Copy the mounted on and mounted from names into ! 269: * the passed in stat block, if it is not the one ! 270: * in the mount structure. ! 271: */ ! 272: if (sbp != &mp->mnt_stat) { ! 273: bcopy((caddr_t)mp->mnt_stat.f_mntonname, ! 274: (caddr_t)&sbp->f_mntonname[0], MNAMELEN); ! 275: bcopy((caddr_t)mp->mnt_stat.f_mntfromname, ! 276: (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); ! 277: } ! 278: return 0; ! 279: } ! 280: ! 281: static int ! 282: devfs_sync(struct mount *mp, int waitfor,struct ucred *cred,struct proc *p) ! 283: { ! 284: return (0); ! 285: } ! 286: ! 287: ! 288: static int ! 289: devfs_vget(struct mount *mp, void * ino,struct vnode **vpp) ! 290: { ! 291: return EOPNOTSUPP; ! 292: } ! 293: ! 294: /************************************************************* ! 295: * The concept of exporting a kernel generated devfs is stupid ! 296: * So don't handle filehandles ! 297: */ ! 298: ! 299: static int ! 300: devfs_fhtovp (struct mount *mp, struct fid *fhp, struct mbuf *nam, ! 301: struct vnode **vpp, int *exflagsp, struct ucred **credanonp) ! 302: { ! 303: return (EINVAL); ! 304: } ! 305: ! 306: ! 307: static int ! 308: devfs_vptofh (struct vnode *vp, struct fid *fhp) ! 309: { ! 310: return (EINVAL); ! 311: } ! 312: ! 313: static int ! 314: devfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) ! 315: int *name; ! 316: u_int namelen; ! 317: void *oldp; ! 318: size_t *oldlenp; ! 319: void *newp; ! 320: size_t newlen; ! 321: struct proc *p; ! 322: { ! 323: return (EOPNOTSUPP); ! 324: } ! 325: ! 326: #include <sys/namei.h> ! 327: ! 328: /* ! 329: * Function: devfs_kernel_mount ! 330: * Purpose: ! 331: * Mount devfs at the given mount point from within the kernel. ! 332: */ ! 333: int ! 334: devfs_kernel_mount(char * mntname) ! 335: { ! 336: struct mount *mp; ! 337: int error; ! 338: struct proc *procp; ! 339: struct nameidata nd; ! 340: struct vnode * vp; ! 341: ! 342: if (devfs_vfsp == NULL) { ! 343: printf("devfs_kernel_mount: devfs_vfsp is NULL\n"); ! 344: return (EINVAL); ! 345: } ! 346: procp = current_proc(); ! 347: ! 348: /* ! 349: * Get vnode to be covered ! 350: */ ! 351: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, ! 352: mntname, procp); ! 353: if ((error = namei(&nd))) { ! 354: printf("devfs_kernel_mount: failed to find directory '%s', %d", ! 355: mntname, error); ! 356: return (error); ! 357: } ! 358: vp = nd.ni_vp; ! 359: if ((error = vinvalbuf(vp, V_SAVE, procp->p_ucred, procp, 0, 0))) { ! 360: printf("devfs_kernel_mount: vinval failed: %d\n", error); ! 361: vput(vp); ! 362: return (error); ! 363: } ! 364: if (vp->v_type != VDIR) { ! 365: printf("devfs_kernel_mount: '%s' is not a directory\n", mntname); ! 366: vput(vp); ! 367: return (ENOTDIR); ! 368: } ! 369: if (vp->v_mountedhere != NULL) { ! 370: vput(vp); ! 371: return (EBUSY); ! 372: } ! 373: ! 374: /* ! 375: * Allocate and initialize the filesystem. ! 376: */ ! 377: mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); ! 378: lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); ! 379: (void)vfs_busy(mp, LK_NOWAIT, 0, procp); ! 380: LIST_INIT(&mp->mnt_vnodelist); ! 381: mp->mnt_op = devfs_vfsp->vfc_vfsops; ! 382: mp->mnt_vfc = devfs_vfsp; ! 383: devfs_vfsp->vfc_refcount++; ! 384: mp->mnt_flag = 0; ! 385: mp->mnt_flag |= devfs_vfsp->vfc_flags & MNT_VISFLAGMASK; ! 386: strncpy(mp->mnt_stat.f_fstypename, devfs_vfsp->vfc_name, MFSNAMELEN); ! 387: vp->v_mountedhere = mp; ! 388: mp->mnt_vnodecovered = vp; ! 389: mp->mnt_stat.f_owner = procp->p_ucred->cr_uid; ! 390: (void) copystr(mntname, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0); ! 391: ! 392: kernel_mount = 1; ! 393: error = devfs_mount(mp, mntname, NULL, NULL, procp); ! 394: kernel_mount = 0; ! 395: if (error) { ! 396: printf("devfs_kernel_mount: mount %s failed: %d", mntname, error); ! 397: mp->mnt_vfc->vfc_refcount--; ! 398: vfs_unbusy(mp, procp); ! 399: _FREE_ZONE(mp, sizeof (struct mount), M_MOUNT); ! 400: return (error); ! 401: } ! 402: printf("devfs on %s\n", mntname); ! 403: simple_lock(&mountlist_slock); ! 404: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); ! 405: simple_unlock(&mountlist_slock); ! 406: VOP_UNLOCK(vp, 0, procp); ! 407: vfs_unbusy(mp, procp); ! 408: return (0); ! 409: } ! 410: ! 411: struct vfsops devfs_vfsops = { ! 412: devfs_mount, ! 413: devfs_start, ! 414: devfs_unmount, ! 415: devfs_root, ! 416: devfs_quotactl, ! 417: devfs_statfs, ! 418: devfs_sync, ! 419: devfs_vget, ! 420: devfs_fhtovp, ! 421: devfs_vptofh, ! 422: devfs_init, ! 423: devfs_sysctl, ! 424: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.