Annotation of src/sys/miscfs/kernfs/kernfs_subr.c, Revision 1.7.4.3
1.7.4.3 ! yamt 1: /* $NetBSD: kernfs_subr.c,v 1.7.4.2 2007/02/26 09:11:28 yamt Exp $ */
1.1 itojun 2:
3: /*
4: * Copyright (c) 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley by
8: * Jan-Simon Pendry.
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.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: * @(#)kernfs_subr.c 8.6 (Berkeley) 5/14/95
35: */
36:
37: /*
38: * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved.
39: * Copyright (c) 1993 Jan-Simon Pendry
40: *
41: * This code is derived from software contributed to Berkeley by
42: * Jan-Simon Pendry.
43: *
44: * Redistribution and use in source and binary forms, with or without
45: * modification, are permitted provided that the following conditions
46: * are met:
47: * 1. Redistributions of source code must retain the above copyright
48: * notice, this list of conditions and the following disclaimer.
49: * 2. Redistributions in binary form must reproduce the above copyright
50: * notice, this list of conditions and the following disclaimer in the
51: * documentation and/or other materials provided with the distribution.
52: * 3. All advertising materials mentioning features or use of this software
53: * must display the following acknowledgement:
54: * This product includes software developed by the University of
55: * California, Berkeley and its contributors.
56: * 4. Neither the name of the University nor the names of its contributors
57: * may be used to endorse or promote products derived from this software
58: * without specific prior written permission.
59: *
60: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70: * SUCH DAMAGE.
71: *
72: * @(#)kernfs_subr.c 8.6 (Berkeley) 5/14/95
73: */
74:
75: #include <sys/cdefs.h>
1.7.4.3 ! yamt 76: __KERNEL_RCSID(0, "$NetBSD: kernfs_subr.c,v 1.7.4.2 2007/02/26 09:11:28 yamt Exp $");
1.1 itojun 77:
78: #ifdef _KERNEL_OPT
79: #include "opt_ipsec.h"
80: #endif
81:
82: #include <sys/param.h>
83: #include <sys/systm.h>
84: #include <sys/time.h>
85: #include <sys/kernel.h>
86: #include <sys/proc.h>
87: #include <sys/vnode.h>
88: #include <sys/malloc.h>
89: #include <sys/stat.h>
90: #include <sys/file.h>
91: #include <sys/filedesc.h>
92: #include <sys/mount.h>
93:
94: #include <miscfs/kernfs/kernfs.h>
95:
96: #ifdef IPSEC
97: #include <sys/mbuf.h>
98: #include <net/route.h>
99: #include <netinet/in.h>
100: #include <netinet6/ipsec.h>
101: #include <netkey/keydb.h>
102: #include <netkey/key.h>
103: #endif
104:
1.7.4.1 yamt 105: void kernfs_hashins(struct kernfs_node *);
106: void kernfs_hashrem(struct kernfs_node *);
107: struct vnode *kernfs_hashget(kfstype, struct mount *,
108: const struct kern_target *, u_int32_t);
1.1 itojun 109:
110: static LIST_HEAD(kfs_hashhead, kernfs_node) *kfs_hashtbl;
111: static u_long kfs_ihash; /* size of hash table - 1 */
112: #define KFSVALUEHASH(v) ((v) & kfs_ihash)
113:
1.7.4.2 yamt 114: static kmutex_t kfs_hashlock;
115: static kmutex_t kfs_ihash_lock;
1.1 itojun 116:
117: #define ISSET(t, f) ((t) & (f))
118:
119: /*
120: * allocate a kfsnode/vnode pair. the vnode is
121: * referenced, and locked.
122: *
123: * the kfs_type, kfs_value and mount point uniquely
124: * identify a kfsnode. the mount point is needed
125: * because someone might mount this filesystem
126: * twice.
127: *
128: * all kfsnodes are maintained on a singly-linked
129: * list. new nodes are only allocated when they cannot
130: * be found on this list. entries on the list are
131: * removed when the vfs reclaim entry is called.
132: *
133: * a single lock is kept for the entire list. this is
134: * needed because the getnewvnode() function can block
135: * waiting for a vnode to become free, in which case there
136: * may be more than one process trying to get the same
137: * vnode. this lock is only taken if we are going to
138: * call getnewvnode, since the kernel itself is single-threaded.
139: *
140: * if an entry is found on the list, then call vget() to
141: * take a reference. this is done because there may be
142: * zero references to it and so it needs to removed from
143: * the vnode free list.
144: */
145: int
146: kernfs_allocvp(mp, vpp, kfs_type, kt, value)
147: struct mount *mp;
148: struct vnode **vpp;
149: kfstype kfs_type;
150: const struct kern_target *kt;
151: u_int32_t value;
152: {
153: struct kernfs_node *kfs = NULL, *kfsp;
154: struct vnode *vp = NULL;
155: int error;
156: long *cookie;
157:
1.7.4.2 yamt 158: if ((*vpp = kernfs_hashget(kfs_type, mp, kt, value)) != NULL)
159: return (0);
160:
161: mutex_enter(&kfs_hashlock);
162: if ((*vpp = kernfs_hashget(kfs_type, mp, kt, value)) != NULL) {
163: mutex_exit(&kfs_hashlock);
164: return (0);
165: }
1.1 itojun 166:
1.5 darcy 167: if (kfs_type == KFSdevice) {
1.1 itojun 168: /* /kern/rootdev = look for device and obey */
169: /* /kern/rrootdev = look for device and obey */
170: dev_t *dp;
171: struct vnode *fvp;
172:
173: #ifdef DIAGNOSTIC
174: if (!kt)
1.5 darcy 175: panic("kernfs: kt == NULL for KFSdevice");
1.1 itojun 176: #endif
177: dp = kt->kt_data;
178: loop:
179: if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) {
1.7.4.2 yamt 180: mutex_exit(&kfs_hashlock);
1.1 itojun 181: return (ENOENT);
182: }
183: vp = fvp;
184: if (vget(fvp, LK_EXCLUSIVE))
185: goto loop;
186: *vpp = vp;
1.7.4.2 yamt 187: mutex_exit(&kfs_hashlock);
1.1 itojun 188: return (0);
189: }
190:
191: if ((error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &vp)) != 0) {
192: *vpp = NULL;
1.7.4.2 yamt 193: mutex_exit(&kfs_hashlock);
1.1 itojun 194: return (error);
195: }
196:
197: MALLOC(kfs, void *, sizeof(struct kernfs_node), M_TEMP, M_WAITOK);
198: memset(kfs, 0, sizeof(*kfs));
199: vp->v_data = kfs;
1.7 perry 200: cookie = &(VFSTOKERNFS(mp)->fileno_cookie);
1.1 itojun 201: again:
202: TAILQ_FOREACH(kfsp, &VFSTOKERNFS(mp)->nodelist, kfs_list) {
203: if (kfsp->kfs_cookie == *cookie) {
204: (*cookie) ++;
205: goto again;
206: }
207: if (TAILQ_NEXT(kfsp, kfs_list)) {
208: if (kfsp->kfs_cookie < *cookie &&
209: *cookie < TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie)
210: break;
211: if (kfsp->kfs_cookie + 1 <
212: TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie) {
213: *cookie = kfsp->kfs_cookie + 1;
214: break;
215: }
216: }
217: }
218:
219: kfs->kfs_cookie = *cookie;
220:
221: if (kfsp)
222: TAILQ_INSERT_AFTER(&VFSTOKERNFS(mp)->nodelist, kfsp, kfs,
223: kfs_list);
224: else
225: TAILQ_INSERT_TAIL(&VFSTOKERNFS(mp)->nodelist, kfs, kfs_list);
226:
227: kfs->kfs_type = kfs_type;
228: kfs->kfs_vnode = vp;
229: kfs->kfs_fileno = KERNFS_FILENO(kt, kfs_type, kfs->kfs_cookie);
230: kfs->kfs_value = value;
231: kfs->kfs_kt = kt;
1.6 cl 232: kfs->kfs_mode = kt->kt_mode;
233: vp->v_type = kt->kt_vtype;
1.1 itojun 234:
1.6 cl 235: if (kfs_type == KFSkern)
1.1 itojun 236: vp->v_flag = VROOT;
237:
238: kernfs_hashins(kfs);
239: uvm_vnp_setsize(vp, 0);
1.7.4.2 yamt 240: mutex_exit(&kfs_hashlock);
1.1 itojun 241:
242: *vpp = vp;
243: return (0);
244: }
245:
246: int
247: kernfs_freevp(vp)
248: struct vnode *vp;
249: {
250: struct kernfs_node *kfs = VTOKERN(vp);
251:
252: kernfs_hashrem(kfs);
253: TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list);
254:
255: FREE(vp->v_data, M_TEMP);
256: vp->v_data = 0;
257: return (0);
258: }
259:
260: /*
261: * Initialize kfsnode hash table.
262: */
263: void
264: kernfs_hashinit()
265: {
266:
1.7.4.2 yamt 267: mutex_init(&kfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
268: mutex_init(&kfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE);
1.1 itojun 269: kfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT,
270: M_WAITOK, &kfs_ihash);
271: }
272:
273: void
274: kernfs_hashreinit()
275: {
276: struct kernfs_node *pp;
277: struct kfs_hashhead *oldhash, *hash;
278: u_long i, oldmask, mask, val;
279:
280: hash = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT, M_WAITOK,
281: &mask);
282:
1.7.4.2 yamt 283: mutex_enter(&kfs_ihash_lock);
1.1 itojun 284: oldhash = kfs_hashtbl;
285: oldmask = kfs_ihash;
286: kfs_hashtbl = hash;
287: kfs_ihash = mask;
288: for (i = 0; i <= oldmask; i++) {
289: while ((pp = LIST_FIRST(&oldhash[i])) != NULL) {
290: LIST_REMOVE(pp, kfs_hash);
291: val = KFSVALUEHASH(pp->kfs_value);
292: LIST_INSERT_HEAD(&hash[val], pp, kfs_hash);
293: }
294: }
1.7.4.2 yamt 295: mutex_exit(&kfs_ihash_lock);
1.1 itojun 296: hashdone(oldhash, M_UFSMNT);
297: }
298:
299: /*
300: * Free kfsnode hash table.
301: */
302: void
303: kernfs_hashdone()
304: {
305:
306: hashdone(kfs_hashtbl, M_UFSMNT);
1.7.4.3 ! yamt 307: mutex_destroy(&kfs_hashlock);
! 308: mutex_destroy(&kfs_ihash_lock);
1.1 itojun 309: }
310:
311: struct vnode *
1.2 dan 312: kernfs_hashget(type, mp, kt, value)
1.1 itojun 313: kfstype type;
314: struct mount *mp;
1.2 dan 315: const struct kern_target *kt;
1.1 itojun 316: u_int32_t value;
317: {
318: struct kfs_hashhead *ppp;
319: struct kernfs_node *pp;
320: struct vnode *vp;
321:
1.7.4.2 yamt 322: loop:
323: mutex_enter(&kfs_ihash_lock);
1.1 itojun 324: ppp = &kfs_hashtbl[KFSVALUEHASH(value)];
325: LIST_FOREACH(pp, ppp, kfs_hash) {
326: vp = KERNFSTOV(pp);
327: if (pp->kfs_type == type && vp->v_mount == mp &&
1.2 dan 328: pp->kfs_kt == kt && pp->kfs_value == value) {
1.1 itojun 329: simple_lock(&vp->v_interlock);
1.7.4.2 yamt 330: mutex_exit(&kfs_ihash_lock);
1.1 itojun 331: if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
332: goto loop;
333: return (vp);
334: }
335: }
1.7.4.2 yamt 336: mutex_exit(&kfs_ihash_lock);
1.1 itojun 337: return (NULL);
338: }
339:
340: /*
341: * Insert the kfsnode into the hash table and lock it.
342: */
343: void
344: kernfs_hashins(pp)
345: struct kernfs_node *pp;
346: {
347: struct kfs_hashhead *ppp;
348:
349: /* lock the kfsnode, then put it on the appropriate hash list */
1.7.4.3 ! yamt 350: lockmgr(&pp->kfs_vnode->v_lock, LK_EXCLUSIVE, NULL);
1.1 itojun 351:
1.7.4.2 yamt 352: mutex_enter(&kfs_ihash_lock);
1.1 itojun 353: ppp = &kfs_hashtbl[KFSVALUEHASH(pp->kfs_value)];
354: LIST_INSERT_HEAD(ppp, pp, kfs_hash);
1.7.4.2 yamt 355: mutex_exit(&kfs_ihash_lock);
1.1 itojun 356: }
357:
358: /*
359: * Remove the kfsnode from the hash table.
360: */
361: void
362: kernfs_hashrem(pp)
363: struct kernfs_node *pp;
364: {
1.7.4.2 yamt 365: mutex_enter(&kfs_ihash_lock);
1.1 itojun 366: LIST_REMOVE(pp, kfs_hash);
1.7.4.2 yamt 367: mutex_exit(&kfs_ihash_lock);
1.1 itojun 368: }
369:
370: #ifdef IPSEC
371: void
372: kernfs_revoke_sa(sav)
373: struct secasvar *sav;
374: {
375: struct kernfs_node *kfs, *pnext;
376: struct vnode *vp;
377: struct kfs_hashhead *ppp;
378: struct mbuf *m;
379:
380: ppp = &kfs_hashtbl[KFSVALUEHASH(ntohl(sav->spi))];
381: for (kfs = LIST_FIRST(ppp); kfs; kfs = pnext) {
382: vp = KERNFSTOV(kfs);
383: pnext = LIST_NEXT(kfs, kfs_hash);
1.5 darcy 384: if (vp->v_usecount > 0 && kfs->kfs_type == KFSipsecsa &&
1.1 itojun 385: kfs->kfs_value == ntohl(sav->spi)) {
386: m = key_setdumpsa_spi(sav->spi);
387: if (!m)
388: VOP_REVOKE(vp, REVOKEALL);
389: else
390: m_freem(m);
391: break;
392: }
393: }
394: }
395:
396: void
397: kernfs_revoke_sp(sp)
398: struct secpolicy *sp;
399: {
400: struct kernfs_node *kfs, *pnext;
401: struct vnode *vp;
402: struct kfs_hashhead *ppp;
403:
404: ppp = &kfs_hashtbl[KFSVALUEHASH(sp->id)];
405: for (kfs = LIST_FIRST(ppp); kfs; kfs = pnext) {
406: vp = KERNFSTOV(kfs);
407: pnext = LIST_NEXT(kfs, kfs_hash);
1.5 darcy 408: if (vp->v_usecount > 0 && kfs->kfs_type == KFSipsecsa &&
1.1 itojun 409: kfs->kfs_value == sp->id)
410: VOP_REVOKE(vp, REVOKEALL);
411: }
412: }
413: #endif
CVSweb <webmaster@jp.NetBSD.org>