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

1.63    ! yamt        1: /*     $NetBSD: nfs_node.c,v 1.62 2003/04/02 15:14:19 yamt 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.63    ! yamt       42: __KERNEL_RCSID(0, "$NetBSD: nfs_node.c,v 1.62 2003/04/02 15:14:19 yamt 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 */
1.57      thorpej    72:
                     73: MALLOC_DEFINE(M_NFSBIGFH, "NFS bigfh", "NFS big filehandle");
                     74: MALLOC_DEFINE(M_NFSNODE, "NFS node", "NFS vnode private part");
1.28      thorpej    75:
1.41      tsutsui    76: extern int prtactive;
                     77:
1.1       cgd        78: #define TRUE   1
                     79: #define        FALSE   0
                     80:
1.48      lukem      81: #define        nfs_hash(x,y)   hash32_buf((x), (y), HASH32_BUF_INIT)
                     82:
1.61      perseant   83: void nfs_gop_size(struct vnode *, off_t, off_t *, int);
1.46      chs        84: int nfs_gop_alloc(struct vnode *, off_t, off_t, int, struct ucred *);
1.53      chs        85: int nfs_gop_write(struct vnode *, struct vm_page **, int, int);
1.46      chs        86:
                     87: struct genfs_ops nfs_genfsops = {
                     88:        nfs_gop_size,
                     89:        nfs_gop_alloc,
1.53      chs        90:        nfs_gop_write,
1.46      chs        91: };
                     92:
1.1       cgd        93: /*
                     94:  * Initialize hash links for nfsnodes
                     95:  * and build nfsnode free list.
                     96:  */
1.15      christos   97: void
1.1       cgd        98: nfs_nhinit()
                     99: {
                    100:
1.37      ad        101:        nfsnodehashtbl = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE,
                    102:            M_WAITOK, &nfsnodehash);
1.22      fvdl      103:        lockinit(&nfs_hashlock, PINOD, "nfs_hashlock", 0, 0);
1.28      thorpej   104:
                    105:        pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, "nfsnodepl",
1.52      thorpej   106:            &pool_allocator_nointr);
1.28      thorpej   107:        pool_init(&nfs_vattr_pool, sizeof(struct vattr), 0, 0, 0, "nfsvapl",
1.52      thorpej   108:            &pool_allocator_nointr);
1.31      jdolecek  109: }
                    110:
                    111: /*
1.45      chs       112:  * Reinitialize inode hash table.
                    113:  */
                    114:
                    115: void
                    116: nfs_nhreinit()
                    117: {
                    118:        struct nfsnode *np;
                    119:        struct nfsnodehashhead *oldhash, *hash;
                    120:        u_long oldmask, mask, val;
                    121:        int i;
                    122:
                    123:        hash = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE, M_WAITOK,
                    124:            &mask);
                    125:
                    126:        lockmgr(&nfs_hashlock, LK_EXCLUSIVE, NULL);
                    127:        oldhash = nfsnodehashtbl;
                    128:        oldmask = nfsnodehash;
                    129:        nfsnodehashtbl = hash;
                    130:        nfsnodehash = mask;
                    131:        for (i = 0; i <= oldmask; i++) {
                    132:                while ((np = LIST_FIRST(&oldhash[i])) != NULL) {
                    133:                        LIST_REMOVE(np, n_hash);
                    134:                        val = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
                    135:                        LIST_INSERT_HEAD(&hash[val], np, n_hash);
                    136:                }
                    137:        }
                    138:        lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
                    139:        hashdone(oldhash, M_NFSNODE);
                    140: }
                    141:
                    142: /*
1.31      jdolecek  143:  * Free resources previoslu allocated in nfs_nhinit().
                    144:  */
                    145: void
                    146: nfs_nhdone()
                    147: {
                    148:        hashdone(nfsnodehashtbl, M_NFSNODE);
                    149:        pool_destroy(&nfs_node_pool);
                    150:        pool_destroy(&nfs_vattr_pool);
1.1       cgd       151: }
                    152:
                    153: /*
                    154:  * Look up a vnode/nfsnode by file handle.
                    155:  * Callers must check for mount points!!
                    156:  * In all cases, a pointer to a
                    157:  * nfsnode structure is returned.
                    158:  */
1.15      christos  159: int
1.16      fvdl      160: nfs_nget(mntp, fhp, fhsize, npp)
1.1       cgd       161:        struct mount *mntp;
1.33      augustss  162:        nfsfh_t *fhp;
1.16      fvdl      163:        int fhsize;
1.1       cgd       164:        struct nfsnode **npp;
                    165: {
1.33      augustss  166:        struct nfsnode *np;
1.13      mycroft   167:        struct nfsnodehashhead *nhpp;
1.33      augustss  168:        struct vnode *vp;
1.1       cgd       169:        struct vnode *nvp;
                    170:        int error;
                    171:
1.45      chs       172:        nhpp = &nfsnodehashtbl[NFSNOHASH(nfs_hash(fhp, fhsize))];
1.1       cgd       173: loop:
1.45      chs       174:        LIST_FOREACH(np, nhpp, n_hash) {
1.16      fvdl      175:                if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
1.38      chs       176:                    memcmp(fhp, np->n_fhp, fhsize))
1.1       cgd       177:                        continue;
                    178:                vp = NFSTOV(np);
1.26      fvdl      179:                if (vget(vp, LK_EXCLUSIVE))
1.1       cgd       180:                        goto loop;
                    181:                *npp = np;
                    182:                return(0);
                    183:        }
1.26      fvdl      184:        if (lockmgr(&nfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0))
1.22      fvdl      185:                goto loop;
1.15      christos  186:        error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp);
                    187:        if (error) {
1.1       cgd       188:                *npp = 0;
1.26      fvdl      189:                lockmgr(&nfs_hashlock, LK_RELEASE, 0);
1.1       cgd       190:                return (error);
                    191:        }
                    192:        vp = nvp;
1.28      thorpej   193:        np = pool_get(&nfs_node_pool, PR_WAITOK);
1.38      chs       194:        memset(np, 0, sizeof *np);
1.36      fvdl      195:        lockinit(&np->n_commitlock, PINOD, "nfsclock", 0, 0);
1.9       mycroft   196:        vp->v_data = np;
1.1       cgd       197:        np->n_vnode = vp;
1.46      chs       198:        genfs_node_init(vp, &nfs_genfsops);
1.38      chs       199:
1.1       cgd       200:        /*
                    201:         * Insert the nfsnode in the hash queue for its new file handle
                    202:         */
1.46      chs       203:
1.13      mycroft   204:        LIST_INSERT_HEAD(nhpp, np, n_hash);
1.16      fvdl      205:        if (fhsize > NFS_SMALLFH) {
1.34      thorpej   206:                np->n_fhp = malloc(fhsize, M_NFSBIGFH, M_WAITOK);
1.16      fvdl      207:        } else
                    208:                np->n_fhp = &np->n_fh;
1.38      chs       209:        memcpy(np->n_fhp, fhp, fhsize);
1.16      fvdl      210:        np->n_fhsize = fhsize;
1.30      fvdl      211:        np->n_accstamp = -1;
1.28      thorpej   212:        np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK);
1.45      chs       213:        lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL);
1.46      chs       214:        lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
1.38      chs       215:        error = VOP_GETATTR(vp, np->n_vattr, curproc->p_ucred, curproc);
                    216:        if (error) {
1.50      fvdl      217:                vput(vp);
1.38      chs       218:                return error;
                    219:        }
                    220:        uvm_vnp_setsize(vp, np->n_vattr->va_size);
1.1       cgd       221:        *npp = np;
                    222:        return (0);
                    223: }
                    224:
1.15      christos  225: int
                    226: nfs_inactive(v)
                    227:        void *v;
                    228: {
1.9       mycroft   229:        struct vop_inactive_args /* {
                    230:                struct vnode *a_vp;
1.16      fvdl      231:                struct proc *a_p;
1.15      christos  232:        } */ *ap = v;
1.33      augustss  233:        struct nfsnode *np;
                    234:        struct sillyrename *sp;
1.26      fvdl      235:        struct proc *p = ap->a_p;
1.40      fvdl      236:        struct vnode *vp = ap->a_vp;
1.59      fvdl      237:        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1.1       cgd       238:
1.40      fvdl      239:        np = VTONFS(vp);
                    240:        if (prtactive && vp->v_usecount != 0)
                    241:                vprint("nfs_inactive: pushing active", vp);
                    242:        if (vp->v_type != VDIR) {
1.16      fvdl      243:                sp = np->n_sillyrename;
1.18      fvdl      244:                np->n_sillyrename = (struct sillyrename *)0;
                    245:        } else
1.44      fvdl      246:                sp = NULL;
                    247:        if (sp != NULL)
1.40      fvdl      248:                nfs_vinvalbuf(vp, 0, sp->s_cred, p, 1);
1.44      fvdl      249:        np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
                    250:                NQNFSNONCACHE | NQNFSWRITE);
                    251:        VOP_UNLOCK(vp, 0);
                    252:        if (sp != NULL) {
1.19      fvdl      253:
                    254:                /*
1.1       cgd       255:                 * Remove the silly file that was rename'd earlier
                    256:                 */
1.40      fvdl      257:
1.39      fvdl      258:                vn_lock(sp->s_dvp, LK_EXCLUSIVE | LK_RETRY);
1.9       mycroft   259:                nfs_removeit(sp);
1.1       cgd       260:                crfree(sp->s_cred);
1.39      fvdl      261:                vput(sp->s_dvp);
1.38      chs       262:                FREE(sp, M_NFSREQ);
1.1       cgd       263:        }
1.59      fvdl      264:
1.62      yamt      265:        if ((nmp->nm_flag & NFSMNT_NQNFS) && CIRCLEQ_NEXT(np, n_timer) != 0) {
1.59      fvdl      266:                CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
                    267:        }
                    268:
                    269:        if (vp->v_type == VDIR && np->n_dircache)
                    270:                nfs_invaldircache(vp, 1);
                    271:
1.1       cgd       272:        return (0);
                    273: }
                    274:
                    275: /*
                    276:  * Reclaim an nfsnode so that it can be used for other purposes.
                    277:  */
1.15      christos  278: int
                    279: nfs_reclaim(v)
                    280:        void *v;
                    281: {
1.9       mycroft   282:        struct vop_reclaim_args /* {
                    283:                struct vnode *a_vp;
1.15      christos  284:        } */ *ap = v;
1.33      augustss  285:        struct vnode *vp = ap->a_vp;
                    286:        struct nfsnode *np = VTONFS(vp);
1.1       cgd       287:
                    288:        if (prtactive && vp->v_usecount != 0)
                    289:                vprint("nfs_reclaim: pushing active", vp);
1.60      drochner  290:
                    291:        LIST_REMOVE(np, n_hash);
1.16      fvdl      292:
                    293:        /*
                    294:         * Free up any directory cookie structures and
                    295:         * large file handle structures that might be associated with
                    296:         * this nfs node.
                    297:         */
1.59      fvdl      298:        if (vp->v_type == VDIR && np->n_dircache)
1.63    ! yamt      299:                hashdone(np->n_dircache, M_NFSDIROFF);
1.59      fvdl      300:
                    301:        if (np->n_fhsize > NFS_SMALLFH)
1.38      chs       302:                free(np->n_fhp, M_NFSBIGFH);
1.16      fvdl      303:
1.28      thorpej   304:        pool_put(&nfs_vattr_pool, np->n_vattr);
1.59      fvdl      305:        if (np->n_rcred)
1.38      chs       306:                crfree(np->n_rcred);
1.59      fvdl      307:
                    308:        if (np->n_wcred)
1.38      chs       309:                crfree(np->n_wcred);
1.59      fvdl      310:
1.1       cgd       311:        cache_purge(vp);
1.28      thorpej   312:        pool_put(&nfs_node_pool, vp->v_data);
1.38      chs       313:        vp->v_data = NULL;
1.1       cgd       314:        return (0);
1.46      chs       315: }
                    316:
                    317: void
1.61      perseant  318: nfs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
1.46      chs       319: {
1.61      perseant  320:        KASSERT(flags & (GOP_SIZE_READ | GOP_SIZE_WRITE));
                    321:        KASSERT((flags & (GOP_SIZE_READ | GOP_SIZE_WRITE))
                    322:                != (GOP_SIZE_READ | GOP_SIZE_WRITE));
1.46      chs       323:        *eobp = MAX(size, vp->v_size);
                    324: }
                    325:
                    326: int
                    327: nfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
                    328:     struct ucred *cred)
                    329: {
                    330:        return 0;
1.53      chs       331: }
                    332:
                    333: int
                    334: nfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
                    335: {
                    336:        int i;
                    337:
                    338:        for (i = 0; i < npages; i++) {
                    339:                pmap_page_protect(pgs[i], VM_PROT_READ);
                    340:        }
                    341:        return genfs_gop_write(vp, pgs, npages, flags);
1.1       cgd       342: }

CVSweb <webmaster@jp.NetBSD.org>