|
|
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 };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.