|
|
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.