Annotation of src/sys/miscfs/genfs/layer_subr.c, Revision 1.31
1.31 ! hannken 1: /* $NetBSD: layer_subr.c,v 1.30 2010/07/02 03:16:00 rmind Exp $ */
1.1 wrstuden 2:
3: /*
4: * Copyright (c) 1999 National Aeronautics & Space Administration
5: * All rights reserved.
6: *
7: * This software was written by William Studenmund of the
1.8 wiz 8: * Numerical Aerospace Simulation Facility, NASA Ames Research Center.
1.1 wrstuden 9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
1.5 soren 18: * 3. Neither the name of the National Aeronautics & Space Administration
1.1 wrstuden 19: * nor the names of its contributors may be used to endorse or promote
20: * products derived from this software without specific prior written
21: * permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE NATIONAL AERONAUTICS & SPACE ADMINISTRATION
24: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ADMINISTRATION OR CONTRIB-
27: * UTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
28: * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
1.30 rmind 35:
1.1 wrstuden 36: /*
37: * Copyright (c) 1992, 1993
38: * The Regents of the University of California. All rights reserved.
39: *
40: * This code is derived from software donated to Berkeley by
41: * Jan-Simon Pendry.
42: *
43: * Redistribution and use in source and binary forms, with or without
44: * modification, are permitted provided that the following conditions
45: * are met:
46: * 1. Redistributions of source code must retain the above copyright
47: * notice, this list of conditions and the following disclaimer.
48: * 2. Redistributions in binary form must reproduce the above copyright
49: * notice, this list of conditions and the following disclaimer in the
50: * documentation and/or other materials provided with the distribution.
1.15 agc 51: * 3. Neither the name of the University nor the names of its contributors
1.1 wrstuden 52: * may be used to endorse or promote products derived from this software
53: * without specific prior written permission.
54: *
55: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65: * SUCH DAMAGE.
66: *
67: * from: Id: lofs_subr.c,v 1.11 1992/05/30 10:05:43 jsp Exp
68: * @(#)null_subr.c 8.7 (Berkeley) 5/14/95
69: */
1.9 lukem 70:
71: #include <sys/cdefs.h>
1.31 ! hannken 72: __KERNEL_RCSID(0, "$NetBSD: layer_subr.c,v 1.30 2010/07/02 03:16:00 rmind Exp $");
1.1 wrstuden 73:
74: #include <sys/param.h>
75: #include <sys/systm.h>
76: #include <sys/proc.h>
77: #include <sys/time.h>
78: #include <sys/vnode.h>
79: #include <sys/mount.h>
80: #include <sys/namei.h>
1.23 ad 81: #include <sys/kmem.h>
1.1 wrstuden 82: #include <sys/malloc.h>
1.23 ad 83:
1.1 wrstuden 84: #include <miscfs/specfs/specdev.h>
85: #include <miscfs/genfs/layer.h>
86: #include <miscfs/genfs/layer_extern.h>
87:
1.16 erh 88: #ifdef LAYERFS_DIAGNOSTIC
89: int layerfs_debug = 1;
90: #endif
91:
1.1 wrstuden 92: /*
93: * layer cache:
94: * Each cache entry holds a reference to the lower vnode
95: * along with a pointer to the alias vnode. When an
96: * entry is added the lower vnode is VREF'd. When the
97: * alias is removed the lower vnode is vrele'd.
98: */
99:
100: void
1.27 cegger 101: layerfs_init(void)
1.1 wrstuden 102: {
1.30 rmind 103: /* Nothing. */
1.6 jdolecek 104: }
1.1 wrstuden 105:
1.6 jdolecek 106: void
1.27 cegger 107: layerfs_done(void)
1.6 jdolecek 108: {
1.30 rmind 109: /* Nothing. */
1.1 wrstuden 110: }
111:
112: /*
1.30 rmind 113: * layer_node_find: find and return alias for lower vnode or NULL.
114: *
115: * => Return alias vnode locked and referenced. if already exists.
116: * => The layermp's hashlock must be held on entry, we will unlock on success.
1.1 wrstuden 117: */
118: struct vnode *
1.26 dsl 119: layer_node_find(struct mount *mp, struct vnode *lowervp)
1.1 wrstuden 120: {
121: struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
122: struct layer_node_hashhead *hd;
123: struct layer_node *a;
124: struct vnode *vp;
1.21 chs 125: int error;
1.1 wrstuden 126:
127: /*
1.30 rmind 128: * Find hash bucket and search the (two-way) linked list looking
129: * for a layerfs node structure which is referencing the lower vnode.
130: * If found, the increment the layer_node reference count, but NOT
131: * the lower vnode's reference counter. Return vnode locked.
1.1 wrstuden 132: */
1.30 rmind 133: KASSERT(mutex_owned(&lmp->layerm_hashlock));
1.1 wrstuden 134: hd = LAYER_NHASH(lmp, lowervp);
135: loop:
1.21 chs 136: LIST_FOREACH(a, hd, layer_hash) {
1.30 rmind 137: if (a->layer_lowervp != lowervp) {
138: continue;
139: }
140: vp = LAYERTOV(a);
141: if (vp->v_mount != mp) {
142: continue;
143: }
144: mutex_enter(&vp->v_interlock);
145: /*
146: * If we find a node being cleaned out, then ignore it and
147: * continue. A thread trying to clean out the extant layer
148: * vnode needs to acquire the shared lock (i.e. the lower
149: * vnode's lock), which our caller already holds. To allow
150: * the cleaning to succeed the current thread must make
151: * progress. So, for a brief time more than one vnode in a
152: * layered file system may refer to a single vnode in the
153: * lower file system.
154: */
155: if ((vp->v_iflag & VI_XLOCK) != 0) {
156: mutex_exit(&vp->v_interlock);
157: continue;
158: }
159: mutex_exit(&lmp->layerm_hashlock);
160: /*
161: * We must not let vget() try to lock the layer vp, since
162: * the lower vp is already locked and locking the layer vp
163: * will involve locking the lower vp.
164: */
1.31 ! hannken 165: error = vget(vp, LK_NOWAIT);
1.30 rmind 166: if (error) {
167: kpause("layerfs", false, 1, NULL);
168: mutex_enter(&lmp->layerm_hashlock);
169: goto loop;
1.1 wrstuden 170: }
1.30 rmind 171: return vp;
1.1 wrstuden 172: }
173: return NULL;
174: }
175:
176: /*
1.30 rmind 177: * layer_node_alloc: make a new layerfs vnode.
178: *
179: * => vp is the alias vnode, lowervp is the lower vnode.
180: * => We will hold a reference to lowervp.
1.1 wrstuden 181: */
182: int
1.26 dsl 183: layer_node_alloc(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)
1.1 wrstuden 184: {
185: struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
186: struct layer_node_hashhead *hd;
187: struct layer_node *xp;
188: struct vnode *vp, *nvp;
189: int error;
1.17 xtraeme 190: extern int (**dead_vnodeop_p)(void *);
1.1 wrstuden 191:
1.23 ad 192: error = getnewvnode(lmp->layerm_tag, mp, lmp->layerm_vnodeop_p, &vp);
1.30 rmind 193: if (error) {
194: return error;
195: }
1.1 wrstuden 196: vp->v_type = lowervp->v_type;
1.23 ad 197: mutex_enter(&vp->v_interlock);
1.22 ad 198: vp->v_iflag |= VI_LAYER;
1.23 ad 199: mutex_exit(&vp->v_interlock);
1.1 wrstuden 200:
1.23 ad 201: xp = kmem_alloc(lmp->layerm_size, KM_SLEEP);
202: if (xp == NULL) {
203: ungetnewvnode(vp);
204: return ENOMEM;
205: }
1.1 wrstuden 206: if (vp->v_type == VBLK || vp->v_type == VCHR) {
1.25 ad 207: spec_node_init(vp, lowervp->v_rdev);
1.1 wrstuden 208: }
209:
210: vp->v_data = xp;
1.23 ad 211: vp->v_vflag = (vp->v_vflag & ~VV_MPSAFE) |
212: (lowervp->v_vflag & VV_MPSAFE);
1.1 wrstuden 213: xp->layer_vnode = vp;
214: xp->layer_lowervp = lowervp;
215: xp->layer_flags = 0;
1.21 chs 216:
1.1 wrstuden 217: /*
1.30 rmind 218: * Before inserting the node into the hash, check if other thread
219: * did not race with us. If so - return that node, destroy ours.
1.1 wrstuden 220: */
1.22 ad 221: mutex_enter(&lmp->layerm_hashlock);
1.1 wrstuden 222: if ((nvp = layer_node_find(mp, lowervp)) != NULL) {
1.30 rmind 223: /* Free the structures we have created. */
1.1 wrstuden 224: if (vp->v_type == VBLK || vp->v_type == VCHR)
1.25 ad 225: spec_node_destroy(vp);
1.1 wrstuden 226:
227: vp->v_type = VBAD; /* node is discarded */
228: vp->v_op = dead_vnodeop_p; /* so ops will still work */
229: vrele(vp); /* get rid of it. */
1.30 rmind 230: kmem_free(xp, lmp->layerm_size);
231: *vpp = nvp;
232: return 0;
1.1 wrstuden 233: }
234:
235: /*
1.21 chs 236: * Insert the new node into the hash.
237: * Add a reference to the lower node.
1.1 wrstuden 238: */
1.28 pooka 239: vref(lowervp);
1.1 wrstuden 240: hd = LAYER_NHASH(lmp, lowervp);
241: LIST_INSERT_HEAD(hd, xp, layer_hash);
1.7 chs 242: uvm_vnp_setsize(vp, 0);
1.22 ad 243: mutex_exit(&lmp->layerm_hashlock);
1.30 rmind 244:
245: *vpp = vp;
246: return 0;
1.1 wrstuden 247: }
248:
249: /*
1.30 rmind 250: * layer_node_create: try to find an existing layerfs vnode refering to it,
251: * otherwise make a new vnode which contains a reference to the lower vnode.
1.1 wrstuden 252: *
1.30 rmind 253: * => Caller should lock the lower node.
1.1 wrstuden 254: */
255: int
1.30 rmind 256: layer_node_create(struct mount *mp, struct vnode *lowervp, struct vnode **nvpp)
1.1 wrstuden 257: {
258: struct vnode *aliasvp;
259: struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
260:
1.30 rmind 261: KASSERT(VOP_ISLOCKED(lowervp));
262:
1.22 ad 263: mutex_enter(&lmp->layerm_hashlock);
1.21 chs 264: aliasvp = layer_node_find(mp, lowervp);
265: if (aliasvp != NULL) {
1.1 wrstuden 266: /*
1.30 rmind 267: * Note: layer_node_find() has taken another reference to
268: * the alias vnode and moved the lock holding to aliasvp.
1.1 wrstuden 269: */
270: #ifdef LAYERFS_DIAGNOSTIC
1.16 erh 271: if (layerfs_debug)
272: vprint("layer_node_create: exists", aliasvp);
1.1 wrstuden 273: #endif
274: } else {
275: int error;
276:
1.22 ad 277: mutex_exit(&lmp->layerm_hashlock);
1.1 wrstuden 278: /*
1.30 rmind 279: * Get a new vnode. Make it to reference the layer_node.
280: * Note: aliasvp will be return with the reference held.
1.1 wrstuden 281: */
1.30 rmind 282: error = (lmp->layerm_alloc)(mp, lowervp, &aliasvp);
283: if (error)
284: return error;
1.1 wrstuden 285: #ifdef LAYERFS_DIAGNOSTIC
1.16 erh 286: if (layerfs_debug)
287: printf("layer_node_create: create new alias vnode\n");
1.1 wrstuden 288: #endif
289: }
290:
291: /*
1.30 rmind 292: * Now that we acquired a reference on the upper vnode, release one
293: * on the lower node. The existence of the layer_node retains one
1.1 wrstuden 294: * reference to the lower node.
295: */
296: vrele(lowervp);
1.30 rmind 297: KASSERT(lowervp->v_usecount > 0);
1.1 wrstuden 298:
299: #ifdef LAYERFS_DIAGNOSTIC
1.16 erh 300: if (layerfs_debug)
301: vprint("layer_node_create: alias", aliasvp);
1.1 wrstuden 302: #endif
1.30 rmind 303: *nvpp = aliasvp;
304: return 0;
1.1 wrstuden 305: }
306:
1.16 erh 307: #ifdef LAYERFS_DIAGNOSTIC
1.1 wrstuden 308: struct vnode *
1.26 dsl 309: layer_checkvp(struct vnode *vp, const char *fil, int lno)
1.1 wrstuden 310: {
311: struct layer_node *a = VTOLAYER(vp);
312: #ifdef notyet
313: /*
314: * Can't do this check because vop_reclaim runs
315: * with a funny vop vector.
316: *
317: * WRS - no it doesnt...
318: */
319: if (vp->v_op != layer_vnodeop_p) {
320: printf ("layer_checkvp: on non-layer-node\n");
321: #ifdef notyet
322: while (layer_checkvp_barrier) /*WAIT*/ ;
323: #endif
324: panic("layer_checkvp");
325: };
326: #endif
327: if (a->layer_lowervp == NULL) {
328: /* Should never happen */
329: int i; u_long *p;
330: printf("vp = %p, ZERO ptr\n", vp);
331: for (p = (u_long *) a, i = 0; i < 8; i++)
332: printf(" %lx", p[i]);
333: printf("\n");
334: /* wait for debugger */
335: panic("layer_checkvp");
336: }
337: if (a->layer_lowervp->v_usecount < 1) {
338: int i; u_long *p;
339: printf("vp = %p, unref'ed lowervp\n", vp);
340: for (p = (u_long *) a, i = 0; i < 8; i++)
341: printf(" %lx", p[i]);
342: printf("\n");
343: /* wait for debugger */
344: panic ("layer with unref'ed lowervp");
345: };
346: #ifdef notnow
347: printf("layer %p/%d -> %p/%d [%s, %d]\n",
348: LAYERTOV(a), LAYERTOV(a)->v_usecount,
349: a->layer_lowervp, a->layer_lowervp->v_usecount,
350: fil, lno);
351: #endif
352: return a->layer_lowervp;
353: }
1.16 erh 354: #endif
CVSweb <webmaster@jp.NetBSD.org>