[BACK]Return to nfs_node.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / nfs

Annotation of src/sys/nfs/nfs_node.c, Revision 1.56

1.56    ! matt        1: /*     $NetBSD: nfs_node.c,v 1.55 2002/10/01 14:59:21 christos Exp $   */
1.12      cgd         2:
1.1       cgd         3: /*
1.9       mycroft     4:  * Copyright (c) 1989, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Rick Macklem at The University of Guelph.
                      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. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the University of
                     21:  *     California, Berkeley and its contributors.
                     22:  * 4. Neither the name of the University nor the names of its contributors
                     23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  *
1.16      fvdl       38:  *     @(#)nfs_node.c  8.6 (Berkeley) 5/22/95
1.1       cgd        39:  */
1.47      lukem      40:
                     41: #include <sys/cdefs.h>
1.56    ! matt       42: __KERNEL_RCSID(0, "$NetBSD: nfs_node.c,v 1.55 2002/10/01 14:59:21 christos Exp $");
1.1       cgd        43:
1.35      bjh21      44: #include "opt_nfs.h"
1.16      fvdl       45:
1.4       mycroft    46: #include <sys/param.h>
                     47: #include <sys/systm.h>
                     48: #include <sys/proc.h>
                     49: #include <sys/mount.h>
                     50: #include <sys/namei.h>
                     51: #include <sys/vnode.h>
                     52: #include <sys/kernel.h>
                     53: #include <sys/malloc.h>
1.28      thorpej    54: #include <sys/pool.h>
1.22      fvdl       55: #include <sys/lock.h>
1.48      lukem      56: #include <sys/hash.h>
1.1       cgd        57:
1.9       mycroft    58: #include <nfs/rpcv2.h>
1.16      fvdl       59: #include <nfs/nfsproto.h>
1.4       mycroft    60: #include <nfs/nfs.h>
                     61: #include <nfs/nfsnode.h>
                     62: #include <nfs/nfsmount.h>
1.9       mycroft    63: #include <nfs/nqnfs.h>
1.15      christos   64: #include <nfs/nfs_var.h>
1.1       cgd        65:
1.56    ! matt       66: struct nfsnodehashhead *nfsnodehashtbl;
1.13      mycroft    67: u_long nfsnodehash;
1.22      fvdl       68: struct lock nfs_hashlock;
1.1       cgd        69:
1.28      thorpej    70: struct pool nfs_node_pool;             /* memory pool for nfs nodes */
                     71: struct pool nfs_vattr_pool;            /* memory pool for nfs vattrs */
                     72:
1.41      tsutsui    73: extern int prtactive;
                     74:
1.1       cgd        75: #define TRUE   1
                     76: #define        FALSE   0
                     77:
1.48      lukem      78: #define        nfs_hash(x,y)   hash32_buf((x), (y), HASH32_BUF_INIT)
                     79:
1.46      chs        80: void nfs_gop_size(struct vnode *, off_t, off_t *);
                     81: int nfs_gop_alloc(struct vnode *, off_t, off_t, int, struct ucred *);
1.53      chs        82: int nfs_gop_write(struct vnode *, struct vm_page **, int, int);
1.46      chs        83:
                     84: struct genfs_ops nfs_genfsops = {
                     85:        nfs_gop_size,
                     86:        nfs_gop_alloc,
1.53      chs        87:        nfs_gop_write,
1.46      chs        88: };
                     89:
1.1       cgd        90: /*
                     91:  * Initialize hash links for nfsnodes
                     92:  * and build nfsnode free list.
                     93:  */
1.15      christos   94: void
1.1       cgd        95: nfs_nhinit()
                     96: {
                     97:
1.37      ad         98:        nfsnodehashtbl = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE,
                     99:            M_WAITOK, &nfsnodehash);
1.22      fvdl      100:        lockinit(&nfs_hashlock, PINOD, "nfs_hashlock", 0, 0);
1.28      thorpej   101:
                    102:        pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, "nfsnodepl",
1.52      thorpej   103:            &pool_allocator_nointr);
1.28      thorpej   104:        pool_init(&nfs_vattr_pool, sizeof(struct vattr), 0, 0, 0, "nfsvapl",
1.52      thorpej   105:            &pool_allocator_nointr);
1.31      jdolecek  106: }
                    107:
                    108: /*
1.45      chs       109:  * Reinitialize inode hash table.
                    110:  */
                    111:
                    112: void
                    113: nfs_nhreinit()
                    114: {
                    115:        struct nfsnode *np;
                    116:        struct nfsnodehashhead *oldhash, *hash;
                    117:        u_long oldmask, mask, val;
                    118:        int i;
                    119:
                    120:        hash = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE, M_WAITOK,
                    121:            &mask);
                    122:
                    123:        lockmgr(&nfs_hashlock, LK_EXCLUSIVE, NULL);
                    124:        oldhash = nfsnodehashtbl;
                    125:        oldmask = nfsnodehash;
                    126:        nfsnodehashtbl = hash;
                    127:        nfsnodehash = mask;
                    128:        for (i = 0; i <= oldmask; i++) {
                    129:                while ((np = LIST_FIRST(&oldhash[i])) != NULL) {
                    130:                        LIST_REMOVE(np, n_hash);
                    131:                        val = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
                    132:                        LIST_INSERT_HEAD(&hash[val], np, n_hash);
                    133:                }
                    134:        }
                    135:        lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
                    136:        hashdone(oldhash, M_NFSNODE);
                    137: }
                    138:
                    139: /*
1.31      jdolecek  140:  * Free resources previoslu allocated in nfs_nhinit().
                    141:  */
                    142: void
                    143: nfs_nhdone()
                    144: {
                    145:        hashdone(nfsnodehashtbl, M_NFSNODE);
                    146:        pool_destroy(&nfs_node_pool);
                    147:        pool_destroy(&nfs_vattr_pool);
1.1       cgd       148: }
                    149:
                    150: /*
                    151:  * Look up a vnode/nfsnode by file handle.
                    152:  * Callers must check for mount points!!
                    153:  * In all cases, a pointer to a
                    154:  * nfsnode structure is returned.
                    155:  */
1.15      christos  156: int
1.16      fvdl      157: nfs_nget(mntp, fhp, fhsize, npp)
1.1       cgd       158:        struct mount *mntp;
1.33      augustss  159:        nfsfh_t *fhp;
1.16      fvdl      160:        int fhsize;
1.1       cgd       161:        struct nfsnode **npp;
                    162: {
1.33      augustss  163:        struct nfsnode *np;
1.13      mycroft   164:        struct nfsnodehashhead *nhpp;
1.33      augustss  165:        struct vnode *vp;
1.1       cgd       166:        struct vnode *nvp;
                    167:        int error;
                    168:
1.45      chs       169:        nhpp = &nfsnodehashtbl[NFSNOHASH(nfs_hash(fhp, fhsize))];
1.1       cgd       170: loop:
1.45      chs       171:        LIST_FOREACH(np, nhpp, n_hash) {
1.16      fvdl      172:                if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
1.38      chs       173:                    memcmp(fhp, np->n_fhp, fhsize))
1.1       cgd       174:                        continue;
                    175:                vp = NFSTOV(np);
1.26      fvdl      176:                if (vget(vp, LK_EXCLUSIVE))
1.1       cgd       177:                        goto loop;
                    178:                *npp = np;
                    179:                return(0);
                    180:        }
1.26      fvdl      181:        if (lockmgr(&nfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0))
1.22      fvdl      182:                goto loop;
1.15      christos  183:        error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp);
                    184:        if (error) {
1.1       cgd       185:                *npp = 0;
1.26      fvdl      186:                lockmgr(&nfs_hashlock, LK_RELEASE, 0);
1.1       cgd       187:                return (error);
                    188:        }
                    189:        vp = nvp;
1.28      thorpej   190:        np = pool_get(&nfs_node_pool, PR_WAITOK);
1.38      chs       191:        memset(np, 0, sizeof *np);
1.36      fvdl      192:        lockinit(&np->n_commitlock, PINOD, "nfsclock", 0, 0);
1.9       mycroft   193:        vp->v_data = np;
1.1       cgd       194:        np->n_vnode = vp;
1.46      chs       195:        genfs_node_init(vp, &nfs_genfsops);
1.38      chs       196:
1.1       cgd       197:        /*
                    198:         * Insert the nfsnode in the hash queue for its new file handle
                    199:         */
1.46      chs       200:
1.13      mycroft   201:        LIST_INSERT_HEAD(nhpp, np, n_hash);
1.16      fvdl      202:        if (fhsize > NFS_SMALLFH) {
1.34      thorpej   203:                np->n_fhp = malloc(fhsize, M_NFSBIGFH, M_WAITOK);
1.16      fvdl      204:        } else
                    205:                np->n_fhp = &np->n_fh;
1.38      chs       206:        memcpy(np->n_fhp, fhp, fhsize);
1.16      fvdl      207:        np->n_fhsize = fhsize;
1.30      fvdl      208:        np->n_accstamp = -1;
1.28      thorpej   209:        np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK);
1.45      chs       210:        lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL);
1.46      chs       211:        lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
1.38      chs       212:        error = VOP_GETATTR(vp, np->n_vattr, curproc->p_ucred, curproc);
                    213:        if (error) {
1.50      fvdl      214:                vput(vp);
1.38      chs       215:                return error;
                    216:        }
                    217:        uvm_vnp_setsize(vp, np->n_vattr->va_size);
1.1       cgd       218:        *npp = np;
                    219:        return (0);
                    220: }
                    221:
1.15      christos  222: int
                    223: nfs_inactive(v)
                    224:        void *v;
                    225: {
1.9       mycroft   226:        struct vop_inactive_args /* {
                    227:                struct vnode *a_vp;
1.16      fvdl      228:                struct proc *a_p;
1.15      christos  229:        } */ *ap = v;
1.33      augustss  230:        struct nfsnode *np;
                    231:        struct sillyrename *sp;
1.26      fvdl      232:        struct proc *p = ap->a_p;
1.40      fvdl      233:        struct vnode *vp = ap->a_vp;
1.1       cgd       234:
1.40      fvdl      235:        np = VTONFS(vp);
                    236:        if (prtactive && vp->v_usecount != 0)
                    237:                vprint("nfs_inactive: pushing active", vp);
                    238:        if (vp->v_type != VDIR) {
1.16      fvdl      239:                sp = np->n_sillyrename;
1.18      fvdl      240:                np->n_sillyrename = (struct sillyrename *)0;
                    241:        } else
1.44      fvdl      242:                sp = NULL;
                    243:        if (sp != NULL)
1.40      fvdl      244:                nfs_vinvalbuf(vp, 0, sp->s_cred, p, 1);
1.44      fvdl      245:        np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
                    246:                NQNFSNONCACHE | NQNFSWRITE);
                    247:        VOP_UNLOCK(vp, 0);
                    248:        if (sp != NULL) {
1.19      fvdl      249:
                    250:                /*
1.1       cgd       251:                 * Remove the silly file that was rename'd earlier
                    252:                 */
1.40      fvdl      253:
1.39      fvdl      254:                vn_lock(sp->s_dvp, LK_EXCLUSIVE | LK_RETRY);
1.9       mycroft   255:                nfs_removeit(sp);
1.1       cgd       256:                crfree(sp->s_cred);
1.39      fvdl      257:                vput(sp->s_dvp);
1.38      chs       258:                FREE(sp, M_NFSREQ);
1.1       cgd       259:        }
                    260:        return (0);
                    261: }
                    262:
                    263: /*
                    264:  * Reclaim an nfsnode so that it can be used for other purposes.
                    265:  */
1.15      christos  266: int
                    267: nfs_reclaim(v)
                    268:        void *v;
                    269: {
1.9       mycroft   270:        struct vop_reclaim_args /* {
                    271:                struct vnode *a_vp;
1.15      christos  272:        } */ *ap = v;
1.33      augustss  273:        struct vnode *vp = ap->a_vp;
                    274:        struct nfsnode *np = VTONFS(vp);
                    275:        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1.1       cgd       276:
                    277:        if (prtactive && vp->v_usecount != 0)
                    278:                vprint("nfs_reclaim: pushing active", vp);
1.16      fvdl      279:
1.13      mycroft   280:        LIST_REMOVE(np, n_hash);
1.9       mycroft   281:
1.55      christos  282:        if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
1.13      mycroft   283:                CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
1.9       mycroft   284:        }
1.16      fvdl      285:
                    286:        /*
                    287:         * Free up any directory cookie structures and
                    288:         * large file handle structures that might be associated with
                    289:         * this nfs node.
                    290:         */
1.23      fvdl      291:        if (vp->v_type == VDIR && np->n_dircache) {
1.24      fvdl      292:                nfs_invaldircache(vp, 1);
1.23      fvdl      293:                FREE(np->n_dircache, M_NFSDIROFF);
1.16      fvdl      294:        }
                    295:        if (np->n_fhsize > NFS_SMALLFH) {
1.38      chs       296:                free(np->n_fhp, M_NFSBIGFH);
1.16      fvdl      297:        }
                    298:
1.28      thorpej   299:        pool_put(&nfs_vattr_pool, np->n_vattr);
1.38      chs       300:        if (np->n_rcred) {
                    301:                crfree(np->n_rcred);
                    302:        }
                    303:        if (np->n_wcred) {
                    304:                crfree(np->n_wcred);
                    305:        }
1.1       cgd       306:        cache_purge(vp);
1.28      thorpej   307:        pool_put(&nfs_node_pool, vp->v_data);
1.38      chs       308:        vp->v_data = NULL;
1.1       cgd       309:        return (0);
1.46      chs       310: }
                    311:
                    312: void
                    313: nfs_gop_size(struct vnode *vp, off_t size, off_t *eobp)
                    314: {
                    315:        *eobp = MAX(size, vp->v_size);
                    316: }
                    317:
                    318: int
                    319: nfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
                    320:     struct ucred *cred)
                    321: {
                    322:        return 0;
1.53      chs       323: }
                    324:
                    325: int
                    326: nfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
                    327: {
                    328:        int i;
                    329:
                    330:        for (i = 0; i < npages; i++) {
                    331:                pmap_page_protect(pgs[i], VM_PROT_READ);
                    332:        }
                    333:        return genfs_gop_write(vp, pgs, npages, flags);
1.1       cgd       334: }

CVSweb <webmaster@jp.NetBSD.org>