Annotation of XNU/bsd/miscfs/devfs/devfs_vfsops.c, revision 1.1.1.1

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: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.