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