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

1.92.4.3! ad          1: /*     $NetBSD: nfs_node.c,v 1.92.4.2 2007/07/15 13:28:06 ad 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.
1.70      agc        18:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        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:  *
1.16      fvdl       34:  *     @(#)nfs_node.c  8.6 (Berkeley) 5/22/95
1.1       cgd        35:  */
1.47      lukem      36:
                     37: #include <sys/cdefs.h>
1.92.4.3! ad         38: __KERNEL_RCSID(0, "$NetBSD: nfs_node.c,v 1.92.4.2 2007/07/15 13:28:06 ad Exp $");
1.1       cgd        39:
1.35      bjh21      40: #include "opt_nfs.h"
1.16      fvdl       41:
1.4       mycroft    42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/proc.h>
                     45: #include <sys/mount.h>
                     46: #include <sys/namei.h>
                     47: #include <sys/vnode.h>
                     48: #include <sys/kernel.h>
                     49: #include <sys/malloc.h>
1.28      thorpej    50: #include <sys/pool.h>
1.22      fvdl       51: #include <sys/lock.h>
1.48      lukem      52: #include <sys/hash.h>
1.84      elad       53: #include <sys/kauth.h>
1.1       cgd        54:
1.9       mycroft    55: #include <nfs/rpcv2.h>
1.16      fvdl       56: #include <nfs/nfsproto.h>
1.4       mycroft    57: #include <nfs/nfs.h>
                     58: #include <nfs/nfsnode.h>
                     59: #include <nfs/nfsmount.h>
1.15      christos   60: #include <nfs/nfs_var.h>
1.1       cgd        61:
1.56      matt       62: struct nfsnodehashhead *nfsnodehashtbl;
1.13      mycroft    63: u_long nfsnodehash;
1.22      fvdl       64: struct lock nfs_hashlock;
1.1       cgd        65:
1.77      simonb     66: POOL_INIT(nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, "nfsnodepl",
1.92.4.1  ad         67:     &pool_allocator_nointr, IPL_NONE);
1.77      simonb     68: POOL_INIT(nfs_vattr_pool, sizeof(struct vattr), 0, 0, 0, "nfsvapl",
1.92.4.1  ad         69:     &pool_allocator_nointr, IPL_NONE);
1.57      thorpej    70:
                     71: MALLOC_DEFINE(M_NFSBIGFH, "NFS bigfh", "NFS big filehandle");
                     72: MALLOC_DEFINE(M_NFSNODE, "NFS node", "NFS vnode private part");
1.28      thorpej    73:
1.41      tsutsui    74: extern int prtactive;
1.1       cgd        75:
1.48      lukem      76: #define        nfs_hash(x,y)   hash32_buf((x), (y), HASH32_BUF_INIT)
                     77:
1.61      perseant   78: void nfs_gop_size(struct vnode *, off_t, off_t *, int);
1.84      elad       79: int nfs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t);
1.53      chs        80: int nfs_gop_write(struct vnode *, struct vm_page **, int, int);
1.46      chs        81:
1.80      yamt       82: static const struct genfs_ops nfs_genfsops = {
                     83:        .gop_size = nfs_gop_size,
                     84:        .gop_alloc = nfs_gop_alloc,
                     85:        .gop_write = nfs_gop_write,
1.46      chs        86: };
                     87:
1.1       cgd        88: /*
                     89:  * Initialize hash links for nfsnodes
                     90:  * and build nfsnode free list.
                     91:  */
1.15      christos   92: void
1.1       cgd        93: nfs_nhinit()
                     94: {
                     95:
1.37      ad         96:        nfsnodehashtbl = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE,
                     97:            M_WAITOK, &nfsnodehash);
1.22      fvdl       98:        lockinit(&nfs_hashlock, PINOD, "nfs_hashlock", 0, 0);
1.31      jdolecek   99: }
                    100:
                    101: /*
1.45      chs       102:  * Reinitialize inode hash table.
                    103:  */
                    104:
                    105: void
                    106: nfs_nhreinit()
                    107: {
                    108:        struct nfsnode *np;
                    109:        struct nfsnodehashhead *oldhash, *hash;
                    110:        u_long oldmask, mask, val;
                    111:        int i;
                    112:
                    113:        hash = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE, M_WAITOK,
                    114:            &mask);
1.79      perry     115:
1.45      chs       116:        lockmgr(&nfs_hashlock, LK_EXCLUSIVE, NULL);
                    117:        oldhash = nfsnodehashtbl;
                    118:        oldmask = nfsnodehash;
                    119:        nfsnodehashtbl = hash;
                    120:        nfsnodehash = mask;
                    121:        for (i = 0; i <= oldmask; i++) {
                    122:                while ((np = LIST_FIRST(&oldhash[i])) != NULL) {
                    123:                        LIST_REMOVE(np, n_hash);
                    124:                        val = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
                    125:                        LIST_INSERT_HEAD(&hash[val], np, n_hash);
                    126:                }
                    127:        }
                    128:        lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
                    129:        hashdone(oldhash, M_NFSNODE);
                    130: }
                    131:
                    132: /*
1.31      jdolecek  133:  * Free resources previoslu allocated in nfs_nhinit().
                    134:  */
                    135: void
                    136: nfs_nhdone()
                    137: {
                    138:        hashdone(nfsnodehashtbl, M_NFSNODE);
                    139:        pool_destroy(&nfs_node_pool);
                    140:        pool_destroy(&nfs_vattr_pool);
1.1       cgd       141: }
                    142:
                    143: /*
                    144:  * Look up a vnode/nfsnode by file handle.
                    145:  * Callers must check for mount points!!
                    146:  * In all cases, a pointer to a
                    147:  * nfsnode structure is returned.
                    148:  */
1.15      christos  149: int
1.75      yamt      150: nfs_nget1(mntp, fhp, fhsize, npp, lkflags)
1.1       cgd       151:        struct mount *mntp;
1.33      augustss  152:        nfsfh_t *fhp;
1.16      fvdl      153:        int fhsize;
1.1       cgd       154:        struct nfsnode **npp;
1.75      yamt      155:        int lkflags;
1.1       cgd       156: {
1.33      augustss  157:        struct nfsnode *np;
1.13      mycroft   158:        struct nfsnodehashhead *nhpp;
1.33      augustss  159:        struct vnode *vp;
1.1       cgd       160:        int error;
                    161:
1.45      chs       162:        nhpp = &nfsnodehashtbl[NFSNOHASH(nfs_hash(fhp, fhsize))];
1.1       cgd       163: loop:
1.45      chs       164:        LIST_FOREACH(np, nhpp, n_hash) {
1.16      fvdl      165:                if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
1.38      chs       166:                    memcmp(fhp, np->n_fhp, fhsize))
1.1       cgd       167:                        continue;
                    168:                vp = NFSTOV(np);
1.75      yamt      169:                error = vget(vp, LK_EXCLUSIVE | lkflags);
                    170:                if (error == EBUSY)
                    171:                        return error;
                    172:                if (error)
1.1       cgd       173:                        goto loop;
                    174:                *npp = np;
                    175:                return(0);
                    176:        }
1.26      fvdl      177:        if (lockmgr(&nfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0))
1.22      fvdl      178:                goto loop;
1.73      yamt      179:        error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &vp);
1.15      christos  180:        if (error) {
1.1       cgd       181:                *npp = 0;
1.26      fvdl      182:                lockmgr(&nfs_hashlock, LK_RELEASE, 0);
1.1       cgd       183:                return (error);
                    184:        }
1.28      thorpej   185:        np = pool_get(&nfs_node_pool, PR_WAITOK);
1.38      chs       186:        memset(np, 0, sizeof *np);
1.9       mycroft   187:        vp->v_data = np;
1.1       cgd       188:        np->n_vnode = vp;
1.46      chs       189:        genfs_node_init(vp, &nfs_genfsops);
1.38      chs       190:
1.1       cgd       191:        /*
                    192:         * Insert the nfsnode in the hash queue for its new file handle
                    193:         */
1.46      chs       194:
1.13      mycroft   195:        LIST_INSERT_HEAD(nhpp, np, n_hash);
1.16      fvdl      196:        if (fhsize > NFS_SMALLFH) {
1.34      thorpej   197:                np->n_fhp = malloc(fhsize, M_NFSBIGFH, M_WAITOK);
1.16      fvdl      198:        } else
                    199:                np->n_fhp = &np->n_fh;
1.38      chs       200:        memcpy(np->n_fhp, fhp, fhsize);
1.16      fvdl      201:        np->n_fhsize = fhsize;
1.30      fvdl      202:        np->n_accstamp = -1;
1.28      thorpej   203:        np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK);
1.71      fvdl      204:
                    205:        /*
                    206:         * Initalize read/write creds to useful values. VOP_OPEN will
                    207:         * overwrite these.
                    208:         */
1.85      ad        209:        np->n_rcred = curlwp->l_cred;
1.84      elad      210:        kauth_cred_hold(np->n_rcred);
1.85      ad        211:        np->n_wcred = curlwp->l_cred;
1.84      elad      212:        kauth_cred_hold(np->n_wcred);
1.45      chs       213:        lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL);
1.46      chs       214:        lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
1.74      yamt      215:        NFS_INVALIDATE_ATTRCACHE(np);
                    216:        uvm_vnp_setsize(vp, 0);
1.1       cgd       217:        *npp = np;
                    218:        return (0);
                    219: }
                    220:
1.15      christos  221: int
                    222: nfs_inactive(v)
                    223:        void *v;
                    224: {
1.9       mycroft   225:        struct vop_inactive_args /* {
                    226:                struct vnode *a_vp;
1.81      christos  227:                struct lwp *a_l;
1.15      christos  228:        } */ *ap = v;
1.33      augustss  229:        struct nfsnode *np;
                    230:        struct sillyrename *sp;
1.81      christos  231:        struct lwp *l = ap->a_l;
1.40      fvdl      232:        struct vnode *vp = ap->a_vp;
1.92      thorpej   233:        bool removed;
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.81      christos  244:                nfs_vinvalbuf(vp, 0, sp->s_cred, l, 1);
1.69      yamt      245:        removed = (np->n_flag & NREMOVED) != 0;
1.92.4.2  ad        246:        np->n_flag &=
                    247:            (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NEOFVALID | NTRUNCDELAYED);
1.76      yamt      248:
                    249:        if (vp->v_type == VDIR && np->n_dircache)
1.78      yamt      250:                nfs_invaldircache(vp,
                    251:                    NFS_INVALDIRCACHE_FORCE | NFS_INVALDIRCACHE_KEEPEOF);
1.76      yamt      252:
1.44      fvdl      253:        VOP_UNLOCK(vp, 0);
1.76      yamt      254:
                    255:        /* XXXMP only kernel_lock protects vp */
                    256:        if (removed)
1.81      christos  257:                vrecycle(vp, NULL, l);
1.76      yamt      258:
1.44      fvdl      259:        if (sp != NULL) {
1.82      yamt      260:                int error;
1.19      fvdl      261:
                    262:                /*
1.1       cgd       263:                 * Remove the silly file that was rename'd earlier
1.72      wrstuden  264:                 *
                    265:                 * Just in case our thread also has the parent node locked,
1.82      yamt      266:                 * we use LK_CANRECURSE.
1.1       cgd       267:                 */
1.40      fvdl      268:
1.82      yamt      269:                error = vn_lock(sp->s_dvp, LK_EXCLUSIVE | LK_CANRECURSE);
                    270:                if (error || sp->s_dvp->v_data == NULL) {
                    271:                        /* XXX should recover */
1.92.4.3! ad        272:                        printf("%s: vp=%p error=%d\n",
        !           273:                            __func__, sp->s_dvp, error);
        !           274:                } else {
        !           275:                        nfs_removeit(sp);
1.82      yamt      276:                }
1.84      elad      277:                kauth_cred_free(sp->s_cred);
1.82      yamt      278:                vput(sp->s_dvp);
1.38      chs       279:                FREE(sp, M_NFSREQ);
1.1       cgd       280:        }
1.59      fvdl      281:
1.1       cgd       282:        return (0);
                    283: }
                    284:
                    285: /*
                    286:  * Reclaim an nfsnode so that it can be used for other purposes.
                    287:  */
1.15      christos  288: int
                    289: nfs_reclaim(v)
                    290:        void *v;
                    291: {
1.9       mycroft   292:        struct vop_reclaim_args /* {
                    293:                struct vnode *a_vp;
1.15      christos  294:        } */ *ap = v;
1.33      augustss  295:        struct vnode *vp = ap->a_vp;
                    296:        struct nfsnode *np = VTONFS(vp);
1.1       cgd       297:
                    298:        if (prtactive && vp->v_usecount != 0)
                    299:                vprint("nfs_reclaim: pushing active", vp);
1.60      drochner  300:
                    301:        LIST_REMOVE(np, n_hash);
1.16      fvdl      302:
                    303:        /*
                    304:         * Free up any directory cookie structures and
                    305:         * large file handle structures that might be associated with
                    306:         * this nfs node.
                    307:         */
1.59      fvdl      308:        if (vp->v_type == VDIR && np->n_dircache)
1.63      yamt      309:                hashdone(np->n_dircache, M_NFSDIROFF);
1.65      yamt      310:        KASSERT(np->n_dirgens == NULL);
1.59      fvdl      311:
                    312:        if (np->n_fhsize > NFS_SMALLFH)
1.38      chs       313:                free(np->n_fhp, M_NFSBIGFH);
1.16      fvdl      314:
1.28      thorpej   315:        pool_put(&nfs_vattr_pool, np->n_vattr);
1.59      fvdl      316:        if (np->n_rcred)
1.84      elad      317:                kauth_cred_free(np->n_rcred);
1.59      fvdl      318:
                    319:        if (np->n_wcred)
1.84      elad      320:                kauth_cred_free(np->n_wcred);
1.59      fvdl      321:
1.1       cgd       322:        cache_purge(vp);
1.90      yamt      323:        if (vp->v_type == VREG) {
                    324:                mutex_destroy(&np->n_commitlock);
                    325:        }
1.91      ad        326:        genfs_node_destroy(vp);
1.90      yamt      327:        pool_put(&nfs_node_pool, np);
1.38      chs       328:        vp->v_data = NULL;
1.1       cgd       329:        return (0);
1.46      chs       330: }
                    331:
                    332: void
1.87      yamt      333: nfs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
1.46      chs       334: {
1.83      yamt      335:
1.46      chs       336:        *eobp = MAX(size, vp->v_size);
                    337: }
                    338:
                    339: int
1.87      yamt      340: nfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
                    341:     kauth_cred_t cred)
1.46      chs       342: {
1.87      yamt      343:
1.46      chs       344:        return 0;
1.53      chs       345: }
                    346:
                    347: int
                    348: nfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
                    349: {
                    350:        int i;
                    351:
                    352:        for (i = 0; i < npages; i++) {
                    353:                pmap_page_protect(pgs[i], VM_PROT_READ);
                    354:        }
                    355:        return genfs_gop_write(vp, pgs, npages, flags);
1.1       cgd       356: }

CVSweb <webmaster@jp.NetBSD.org>