Annotation of kernel/bsd/miscfs/umapfs/umap_vnops.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*     $NetBSD: umap_vnops.c,v 1.3 1994/08/19 11:25:42 mycroft Exp $   */
                     26: 
                     27: /*
                     28:  * Copyright (c) 1992, 1993
                     29:  *     The Regents of the University of California.  All rights reserved.
                     30:  *
                     31:  * This code is derived from software donated to Berkeley by
                     32:  * the UCLA Ficus project.
                     33:  *
                     34:  * Redistribution and use in source and binary forms, with or without
                     35:  * modification, are permitted provided that the following conditions
                     36:  * are met:
                     37:  * 1. Redistributions of source code must retain the above copyright
                     38:  *    notice, this list of conditions and the following disclaimer.
                     39:  * 2. Redistributions in binary form must reproduce the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer in the
                     41:  *    documentation and/or other materials provided with the distribution.
                     42:  * 3. All advertising materials mentioning features or use of this software
                     43:  *    must display the following acknowledgement:
                     44:  *     This product includes software developed by the University of
                     45:  *     California, Berkeley and its contributors.
                     46:  * 4. Neither the name of the University nor the names of its contributors
                     47:  *    may be used to endorse or promote products derived from this software
                     48:  *    without specific prior written permission.
                     49:  *
                     50:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     51:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     52:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     53:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     54:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     55:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     56:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     57:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     58:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     59:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     60:  * SUCH DAMAGE.
                     61:  *
                     62:  *     @(#)umap_vnops.c        8.3 (Berkeley) 1/5/94
                     63:  */
                     64: 
                     65: /*
                     66:  * Umap Layer
                     67:  */
                     68: 
                     69: #include <sys/param.h>
                     70: #include <sys/systm.h>
                     71: #include <sys/time.h>
                     72: #include <sys/types.h>
                     73: #include <sys/vnode.h>
                     74: #include <sys/mount.h>
                     75: #include <sys/namei.h>
                     76: #include <sys/malloc.h>
                     77: #include <sys/buf.h>
                     78: #include <miscfs/umapfs/umap.h>
                     79: 
                     80: 
                     81: int umap_bug_bypass = 0;   /* for debugging: enables bypass printf'ing */
                     82: 
                     83: /*
                     84:  * This is the 10-Apr-92 bypass routine.
                     85:  * See null_vnops.c:null_bypass for more details.
                     86:  */ 
                     87: int
                     88: umap_bypass(ap)
                     89:        struct vop_generic_args /* {
                     90:                struct vnodeop_desc *a_desc;
                     91:                <other random data follows, presumably>
                     92:        } */ *ap;
                     93: {
                     94:        extern int (**umap_vnodeop_p)();  /* not extern, really "forward" */
                     95:        struct ucred **credpp = 0, *credp = 0;
                     96:        struct ucred *savecredp, *savecompcredp = 0;
                     97:        struct ucred *compcredp = 0;
                     98:        struct vnode **this_vp_p;
                     99:        int error;
                    100:        struct vnode *old_vps[VDESC_MAX_VPS];
                    101:        struct vnode *vp1 = 0;
                    102:        struct vnode **vps_p[VDESC_MAX_VPS];
                    103:        struct vnode ***vppp;
                    104:        struct vnodeop_desc *descp = ap->a_desc;
                    105:        int reles, i;
                    106:        struct componentname **compnamepp = 0;
                    107: 
                    108:        if (umap_bug_bypass)
                    109:                printf ("umap_bypass: %s\n", descp->vdesc_name);
                    110: 
                    111: #ifdef SAFETY
                    112:        /*
                    113:         * We require at least one vp.
                    114:         */
                    115:        if (descp->vdesc_vp_offsets == NULL ||
                    116:            descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
                    117:                panic ("umap_bypass: no vp's in map.\n");
                    118: #endif
                    119: 
                    120:        /*
                    121:         * Map the vnodes going in.
                    122:         * Later, we'll invoke the operation based on
                    123:         * the first mapped vnode's operation vector.
                    124:         */
                    125:        reles = descp->vdesc_flags;
                    126:        for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
                    127:                if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
                    128:                        break;   /* bail out at end of list */
                    129:                vps_p[i] = this_vp_p = 
                    130:                        VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[i], ap);
                    131: 
                    132:                if (i == 0) {
                    133:                        vp1 = *vps_p[0];
                    134:                }
                    135: 
                    136:                /*
                    137:                 * We're not guaranteed that any but the first vnode
                    138:                 * are of our type.  Check for and don't map any
                    139:                 * that aren't.  (Must map first vp or vclean fails.)
                    140:                 */
                    141: 
                    142:                if (i && (*this_vp_p)->v_op != umap_vnodeop_p) {
                    143:                        old_vps[i] = NULL;
                    144:                } else {
                    145:                        old_vps[i] = *this_vp_p;
                    146:                        *(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
                    147:                        if (reles & 1)
                    148:                                VREF(*this_vp_p);
                    149:                }
                    150:                        
                    151:        }
                    152: 
                    153:        /*
                    154:         * Fix the credentials.  (That's the purpose of this layer.)
                    155:         */
                    156: 
                    157:        if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
                    158: 
                    159:                credpp = VOPARG_OFFSETTO(struct ucred**, 
                    160:                    descp->vdesc_cred_offset, ap);
                    161: 
                    162:                /* Save old values */
                    163: 
                    164:                savecredp = *credpp;
                    165:                if (savecredp != NOCRED)
                    166:                        *credpp = crdup(savecredp);
                    167:                credp = *credpp;
                    168: 
                    169:                if (umap_bug_bypass && credp->cr_uid != 0)
                    170:                        printf("umap_bypass: user was %d, group %d\n", 
                    171:                            credp->cr_uid, credp->cr_gid);
                    172: 
                    173:                /* Map all ids in the credential structure. */
                    174: 
                    175:                umap_mapids(vp1->v_mount, credp);
                    176: 
                    177:                if (umap_bug_bypass && credp->cr_uid != 0)
                    178:                        printf("umap_bypass: user now %d, group %d\n", 
                    179:                            credp->cr_uid, credp->cr_gid);
                    180:        }
                    181: 
                    182:        /* BSD often keeps a credential in the componentname structure
                    183:         * for speed.  If there is one, it better get mapped, too. 
                    184:         */
                    185: 
                    186:        if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
                    187: 
                    188:                compnamepp = VOPARG_OFFSETTO(struct componentname**, 
                    189:                    descp->vdesc_componentname_offset, ap);
                    190: 
                    191:                savecompcredp = (*compnamepp)->cn_cred;
                    192:                if (savecompcredp != NOCRED)
                    193:                        (*compnamepp)->cn_cred = crdup(savecompcredp);
                    194:                compcredp = (*compnamepp)->cn_cred;
                    195: 
                    196:                if (umap_bug_bypass && compcredp->cr_uid != 0)
                    197:                        printf("umap_bypass: component credit user was %d, group %d\n", 
                    198:                            compcredp->cr_uid, compcredp->cr_gid);
                    199: 
                    200:                /* Map all ids in the credential structure. */
                    201: 
                    202:                umap_mapids(vp1->v_mount, compcredp);
                    203: 
                    204:                if (umap_bug_bypass && compcredp->cr_uid != 0)
                    205:                        printf("umap_bypass: component credit user now %d, group %d\n", 
                    206:                            compcredp->cr_uid, compcredp->cr_gid);
                    207:        }
                    208: 
                    209:        /*
                    210:         * Call the operation on the lower layer
                    211:         * with the modified argument structure.
                    212:         */
                    213:        error = VCALL(*(vps_p[0]), descp->vdesc_offset, ap);
                    214: 
                    215:        /*
                    216:         * Maintain the illusion of call-by-value
                    217:         * by restoring vnodes in the argument structure
                    218:         * to their original value.
                    219:         */
                    220:        reles = descp->vdesc_flags;
                    221:        for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
                    222:                if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
                    223:                        break;   /* bail out at end of list */
                    224:                if (old_vps[i]) {
                    225:                        *(vps_p[i]) = old_vps[i];
                    226:                        if (reles & 1)
                    227:                                vrele(*(vps_p[i]));
                    228:                };
                    229:        };
                    230: 
                    231:        /*
                    232:         * Map the possible out-going vpp
                    233:         * (Assumes that the lower layer always returns
                    234:         * a VREF'ed vpp unless it gets an error.)
                    235:         */
                    236:        if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
                    237:            !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
                    238:            !error) {
                    239:                if (descp->vdesc_flags & VDESC_VPP_WILLRELE)
                    240:                        goto out;
                    241:                vppp = VOPARG_OFFSETTO(struct vnode***,
                    242:                                 descp->vdesc_vpp_offset, ap);
                    243:                error = umap_node_create(old_vps[0]->v_mount, **vppp, *vppp);
                    244:        };
                    245: 
                    246:  out:
                    247:        /* 
                    248:         * Free duplicate cred structure and restore old one.
                    249:         */
                    250:        if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
                    251:                if (umap_bug_bypass && credp && credp->cr_uid != 0)
                    252:                        printf("umap_bypass: returning-user was %d\n",
                    253:                                        credp->cr_uid);
                    254: 
                    255:                if (savecredp != NOCRED) {
                    256:                        if (credp != NOCRED)
                    257:                                crfree(credp);
                    258:                        *credpp = savecredp;
                    259:                        if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0)
                    260:                                printf("umap_bypass: returning-user now %d\n\n", 
                    261:                                    savecredp->cr_uid);
                    262:                }
                    263:        }
                    264: 
                    265:        if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
                    266:                if (umap_bug_bypass && compcredp && compcredp->cr_uid != 0)
                    267:                        printf("umap_bypass: returning-component-user was %d\n", 
                    268:                                compcredp->cr_uid);
                    269: 
                    270:                if (savecompcredp != NOCRED) {
                    271:                        if (compcredp != NOCRED)
                    272:                                crfree(compcredp);
                    273:                        (*compnamepp)->cn_cred = savecompcredp;
                    274:                        if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0)
                    275:                                printf("umap_bypass: returning-component-user now %d\n", 
                    276:                                    savecompcredp->cr_uid);
                    277:                }
                    278:        }
                    279: 
                    280:        return (error);
                    281: }
                    282: 
                    283: 
                    284: /*
                    285:  *  We handle getattr to change the fsid.
                    286:  */
                    287: int
                    288: umap_getattr(ap)
                    289:        struct vop_getattr_args /* {
                    290:                struct vnode *a_vp;
                    291:                struct vattr *a_vap;
                    292:                struct ucred *a_cred;
                    293:                struct proc *a_p;
                    294:        } */ *ap;
                    295: {
                    296:        uid_t uid;
                    297:        gid_t gid;
                    298:        int error, tmpid, nentries, gnentries;
                    299:        uid_t (*mapdata)[2];
                    300:        gid_t (*gmapdata)[2];
                    301:        struct vnode **vp1p;
                    302:        struct vnodeop_desc *descp = ap->a_desc;
                    303: 
                    304:        if (error = umap_bypass(ap))
                    305:                return (error);
                    306:        /* Requires that arguments be restored. */
                    307:        ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
                    308: 
                    309:        /*
                    310:         * Umap needs to map the uid and gid returned by a stat
                    311:         * into the proper values for this site.  This involves
                    312:         * finding the returned uid in the mapping information,
                    313:         * translating it into the uid on the other end,
                    314:         * and filling in the proper field in the vattr
                    315:         * structure pointed to by ap->a_vap.  The group
                    316:         * is easier, since currently all groups will be
                    317:         * translate to the NULLGROUP.
                    318:         */
                    319: 
                    320:        /* Find entry in map */
                    321: 
                    322:        uid = ap->a_vap->va_uid;
                    323:        gid = ap->a_vap->va_gid;
                    324:        if (umap_bug_bypass)
                    325:                printf("umap_getattr: mapped uid = %d, mapped gid = %d\n", uid, 
                    326:                    gid);
                    327: 
                    328:        vp1p = VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[0], ap);
                    329:        nentries =  MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_nentries;
                    330:        mapdata =  (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_mapdata);
                    331:        gnentries =  MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gnentries;
                    332:        gmapdata =  (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gmapdata);
                    333: 
                    334:        /* Reverse map the uid for the vnode.  Since it's a reverse
                    335:                map, we can't use umap_mapids() to do it. */
                    336: 
                    337:        tmpid = umap_reverse_findid(uid, mapdata, nentries);
                    338: 
                    339:        if (tmpid != -1) {
                    340:                ap->a_vap->va_uid = (uid_t) tmpid;
                    341:                if (umap_bug_bypass)
                    342:                        printf("umap_getattr: original uid = %d\n", uid);
                    343:        } else 
                    344:                ap->a_vap->va_uid = (uid_t) NOBODY;
                    345: 
                    346:        /* Reverse map the gid for the vnode. */
                    347: 
                    348:        tmpid = umap_reverse_findid(gid, gmapdata, gnentries);
                    349: 
                    350:        if (tmpid != -1) {
                    351:                ap->a_vap->va_gid = (gid_t) tmpid;
                    352:                if (umap_bug_bypass)
                    353:                        printf("umap_getattr: original gid = %d\n", gid);
                    354:        } else
                    355:                ap->a_vap->va_gid = (gid_t) NULLGROUP;
                    356:        
                    357:        return (0);
                    358: }
                    359: 
                    360: int
                    361: umap_inactive(ap)
                    362:        struct vop_inactive_args /* {
                    363:                struct vnode *a_vp;
                    364:        } */ *ap;
                    365: {
                    366:        /*
                    367:         * Do nothing (and _don't_ bypass).
                    368:         * Wait to vrele lowervp until reclaim,
                    369:         * so that until then our umap_node is in the
                    370:         * cache and reusable.
                    371:         *
                    372:         */
                    373:        return (0);
                    374: }
                    375: 
                    376: int
                    377: umap_reclaim(ap)
                    378:        struct vop_reclaim_args /* {
                    379:                struct vnode *a_vp;
                    380:        } */ *ap;
                    381: {
                    382:        struct vnode *vp = ap->a_vp;
                    383:        struct umap_node *xp = VTOUMAP(vp);
                    384:        struct vnode *lowervp = xp->umap_lowervp;
                    385:        
                    386:        /* After this assignment, this node will not be re-used. */
                    387:        xp->umap_lowervp = NULL;
                    388:        LIST_REMOVE(xp, umap_hash);
                    389:        FREE(vp->v_data, M_TEMP);
                    390:        vp->v_data = NULL;
                    391:        vrele(lowervp);
                    392:        return (0);
                    393: }
                    394: 
                    395: int
                    396: umap_strategy(ap)
                    397:        struct vop_strategy_args /* {
                    398:                struct buf *a_bp;
                    399:        } */ *ap;
                    400: {
                    401:        struct buf *bp = ap->a_bp;
                    402:        int error;
                    403:        struct vnode *savedvp;
                    404: 
                    405:        savedvp = bp->b_vp;
                    406:        bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp);
                    407: 
                    408:        error = VOP_STRATEGY(ap->a_bp);
                    409: 
                    410:        bp->b_vp = savedvp;
                    411: 
                    412:        return (error);
                    413: }
                    414: 
                    415: int
                    416: umap_bwrite(ap)
                    417:        struct vop_bwrite_args /* {
                    418:                struct buf *a_bp;
                    419:        } */ *ap;
                    420: {
                    421:        struct buf *bp = ap->a_bp;
                    422:        int error;
                    423:        struct vnode *savedvp;
                    424: 
                    425:        savedvp = bp->b_vp;
                    426:        bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp);
                    427: 
                    428:        error = VOP_BWRITE(ap->a_bp);
                    429: 
                    430:        bp->b_vp = savedvp;
                    431: 
                    432:        return (error);
                    433: }
                    434: 
                    435: 
                    436: int
                    437: umap_print(ap)
                    438:        struct vop_print_args /* {
                    439:                struct vnode *a_vp;
                    440:        } */ *ap;
                    441: {
                    442:        struct vnode *vp = ap->a_vp;
                    443:        printf("\ttag VT_UMAPFS, vp=%x, lowervp=%x\n", vp, UMAPVPTOLOWERVP(vp));
                    444:        return (0);
                    445: }
                    446: 
                    447: int
                    448: umap_rename(ap)
                    449:        struct vop_rename_args  /* {
                    450:                struct vnode *a_fdvp;
                    451:                struct vnode *a_fvp;
                    452:                struct componentname *a_fcnp;
                    453:                struct vnode *a_tdvp;
                    454:                struct vnode *a_tvp;
                    455:                struct componentname *a_tcnp;
                    456:        } */ *ap;
                    457: {
                    458:        int error;
                    459:        struct componentname *compnamep;
                    460:        struct ucred *compcredp, *savecompcredp;
                    461:        struct vnode *vp;
                    462: 
                    463:        /*
                    464:         * Rename is irregular, having two componentname structures.
                    465:         * We need to map the cre in the second structure,
                    466:         * and then bypass takes care of the rest.
                    467:         */
                    468: 
                    469:        vp = ap->a_fdvp;
                    470:        compnamep = ap->a_tcnp;
                    471:        compcredp = compnamep->cn_cred;
                    472: 
                    473:        savecompcredp = compcredp;
                    474:        compcredp = compnamep->cn_cred = crdup(savecompcredp);
                    475: 
                    476:        if (umap_bug_bypass && compcredp->cr_uid != 0)
                    477:                printf("umap_rename: rename component credit user was %d, group %d\n", 
                    478:                    compcredp->cr_uid, compcredp->cr_gid);
                    479: 
                    480:        /* Map all ids in the credential structure. */
                    481: 
                    482:        umap_mapids(vp->v_mount, compcredp);
                    483: 
                    484:        if (umap_bug_bypass && compcredp->cr_uid != 0)
                    485:                printf("umap_rename: rename component credit user now %d, group %d\n", 
                    486:                    compcredp->cr_uid, compcredp->cr_gid);
                    487: 
                    488:        error = umap_bypass(ap);
                    489:        
                    490:        /* Restore the additional mapped componentname cred structure. */
                    491: 
                    492:        crfree(compcredp);
                    493:        compnamep->cn_cred = savecompcredp;
                    494: 
                    495:        return error;
                    496: }
                    497: 
                    498: /*
                    499:  * Global vfs data structures
                    500:  */
                    501: /*
                    502:  * XXX - strategy, bwrite are hand coded currently.  They should
                    503:  * go away with a merged buffer/block cache.
                    504:  *
                    505:  */
                    506: int (**umap_vnodeop_p)();
                    507: struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
                    508:        { &vop_default_desc, umap_bypass },
                    509: 
                    510:        { &vop_getattr_desc, umap_getattr },
                    511:        { &vop_inactive_desc, umap_inactive },
                    512:        { &vop_reclaim_desc, umap_reclaim },
                    513:        { &vop_print_desc, umap_print },
                    514:        { &vop_rename_desc, umap_rename },
                    515: 
                    516:        { &vop_strategy_desc, umap_strategy },
                    517:        { &vop_bwrite_desc, umap_bwrite },
                    518: 
                    519:        { (struct vnodeop_desc*) NULL, (int(*)()) NULL }
                    520: };
                    521: struct vnodeopv_desc umap_vnodeop_opv_desc =
                    522:        { &umap_vnodeop_p, umap_vnodeop_entries };

unix.superglobalmegacorp.com

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