[BACK]Return to kernfs_subr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / miscfs / kernfs

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>