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