LCOV - code coverage report
Current view: top level - nfs - nfs_node.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 96 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: nfs_node.c,v 1.70 2018/05/27 06:02:15 visa Exp $      */
       2             : /*      $NetBSD: nfs_node.c,v 1.16 1996/02/18 11:53:42 fvdl Exp $       */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1989, 1993
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to Berkeley by
       9             :  * Rick Macklem at The University of Guelph.
      10             :  *
      11             :  * Redistribution and use in source and binary forms, with or without
      12             :  * modification, are permitted provided that the following conditions
      13             :  * are met:
      14             :  * 1. Redistributions of source code must retain the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer.
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in the
      18             :  *    documentation and/or other materials provided with the distribution.
      19             :  * 3. Neither the name of the University nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  *
      35             :  *      @(#)nfs_node.c  8.6 (Berkeley) 5/22/95
      36             :  */
      37             : 
      38             : 
      39             : #include <sys/param.h>
      40             : #include <sys/systm.h>
      41             : #include <sys/timeout.h>
      42             : #include <sys/mount.h>
      43             : #include <sys/namei.h>
      44             : #include <sys/vnode.h>
      45             : #include <sys/lock.h>
      46             : #include <sys/kernel.h>
      47             : #include <sys/malloc.h>
      48             : #include <sys/pool.h>
      49             : #include <sys/rwlock.h>
      50             : #include <sys/queue.h>
      51             : 
      52             : #include <nfs/rpcv2.h>
      53             : #include <nfs/nfsproto.h>
      54             : #include <nfs/nfsnode.h>
      55             : #include <nfs/nfsmount.h>
      56             : #include <nfs/nfs_var.h>
      57             : 
      58             : struct pool nfs_node_pool;
      59             : extern int prtactive;
      60             : 
      61             : /* XXX */
      62             : extern struct vops nfs_vops;
      63             : 
      64             : /* filehandle to node lookup. */
      65             : static __inline int
      66           0 : nfsnode_cmp(const struct nfsnode *a, const struct nfsnode *b)
      67             : {
      68           0 :         if (a->n_fhsize != b->n_fhsize)
      69           0 :                 return (a->n_fhsize - b->n_fhsize);
      70           0 :         return (memcmp(a->n_fhp, b->n_fhp, a->n_fhsize));
      71           0 : }
      72             : 
      73           0 : RBT_PROTOTYPE(nfs_nodetree, nfsnode, n_entry, nfsnode_cmp);
      74           0 : RBT_GENERATE(nfs_nodetree, nfsnode, n_entry, nfsnode_cmp);
      75             : 
      76             : void
      77           0 : nfs_ninit(struct nfsmount *nmp)
      78             : {
      79           0 :         RBT_INIT(nfs_nodetree, &nmp->nm_ntree);
      80           0 : }
      81             : 
      82             : /*
      83             :  * Look up a vnode/nfsnode by file handle and store the pointer in *npp.
      84             :  * Callers must check for mount points!!
      85             :  * An error number is returned.
      86             :  */
      87             : int
      88           0 : nfs_nget(struct mount *mnt, nfsfh_t *fh, int fhsize, struct nfsnode **npp)
      89             : {
      90             :         struct nfsmount         *nmp;
      91           0 :         struct nfsnode          *np, find, *np2;
      92           0 :         struct vnode            *vp, *nvp;
      93             :         int                      error;
      94             : 
      95           0 :         nmp = VFSTONFS(mnt);
      96             : 
      97             : loop:
      98           0 :         find.n_fhp = fh;
      99           0 :         find.n_fhsize = fhsize;
     100           0 :         np = RBT_FIND(nfs_nodetree, &nmp->nm_ntree, &find);
     101           0 :         if (np != NULL) {
     102           0 :                 vp = NFSTOV(np);
     103           0 :                 error = vget(vp, LK_EXCLUSIVE);
     104           0 :                 if (error)
     105           0 :                         goto loop;
     106           0 :                 *npp = np;
     107           0 :                 return (0);
     108             :         }
     109             : 
     110             :         /*
     111             :          * getnewvnode() could recycle a vnode, potentially formerly
     112             :          * owned by NFS. This will cause a VOP_RECLAIM() to happen,
     113             :          * which will cause recursive locking, so we unlock before
     114             :          * calling getnewvnode() lock again afterwards, but must check
     115             :          * to see if this nfsnode has been added while we did not hold
     116             :          * the lock.
     117             :          */
     118           0 :         error = getnewvnode(VT_NFS, mnt, &nfs_vops, &nvp);
     119             :         /* note that we don't have this vnode set up completely yet */
     120           0 :         if (error) {
     121           0 :                 *npp = NULL;
     122           0 :                 return (error);
     123             :         }
     124           0 :         nvp->v_flag |= VLARVAL;
     125           0 :         np = pool_get(&nfs_node_pool, PR_WAITOK | PR_ZERO);
     126             :         /*
     127             :          * getnewvnode() and pool_get() can sleep, check for race.
     128             :          */
     129           0 :         if (RBT_FIND(nfs_nodetree, &nmp->nm_ntree, &find) != NULL) {
     130           0 :                 pool_put(&nfs_node_pool, np);
     131           0 :                 vgone(nvp);
     132           0 :                 goto loop;
     133             :         }
     134             : 
     135           0 :         vp = nvp;
     136             : #ifdef VFSLCKDEBUG
     137             :         vp->v_flag |= VLOCKSWORK;
     138             : #endif
     139           0 :         rrw_init_flags(&np->n_lock, "nfsnode", RWL_DUPOK | RWL_IS_VNODE);
     140           0 :         vp->v_data = np;
     141             :         /* we now have an nfsnode on this vnode */
     142           0 :         vp->v_flag &= ~VLARVAL;
     143           0 :         np->n_vnode = vp;
     144           0 :         rw_init(&np->n_commitlock, "nfs_commitlk");
     145           0 :         np->n_fhp = &np->n_fh;
     146           0 :         bcopy(fh, np->n_fhp, fhsize);
     147           0 :         np->n_fhsize = fhsize;
     148             :         /* lock the nfsnode, then put it on the rbtree */
     149           0 :         rrw_enter(&np->n_lock, RW_WRITE);
     150           0 :         np2 = RBT_INSERT(nfs_nodetree, &nmp->nm_ntree, np);
     151           0 :         KASSERT(np2 == NULL);
     152           0 :         np->n_accstamp = -1;
     153           0 :         *npp = np;
     154             : 
     155           0 :         return (0);
     156           0 : }
     157             : 
     158             : int
     159           0 : nfs_inactive(void *v)
     160             : {
     161           0 :         struct vop_inactive_args        *ap = v;
     162             :         struct nfsnode                  *np;
     163             :         struct sillyrename              *sp;
     164             : 
     165             : #ifdef DIAGNOSTIC
     166           0 :         if (prtactive && ap->a_vp->v_usecount != 0)
     167           0 :                 vprint("nfs_inactive: pushing active", ap->a_vp);
     168             : #endif
     169           0 :         if (ap->a_vp->v_flag & VLARVAL)
     170             :                 /*
     171             :                  * vnode was incompletely set up, just return
     172             :                  * as we are throwing it away.
     173             :                  */
     174           0 :                 return(0);
     175             : #ifdef DIAGNOSTIC
     176           0 :         if (ap->a_vp->v_data == NULL)
     177           0 :                 panic("NULL v_data (no nfsnode set up?) in vnode %p",
     178             :                     ap->a_vp);
     179             : #endif
     180           0 :         np = VTONFS(ap->a_vp);
     181           0 :         if (ap->a_vp->v_type != VDIR) {
     182           0 :                 sp = np->n_sillyrename;
     183           0 :                 np->n_sillyrename = NULL;
     184           0 :         } else
     185             :                 sp = NULL;
     186           0 :         if (sp) {
     187             :                 /*
     188             :                  * Remove the silly file that was rename'd earlier
     189             :                  */
     190           0 :                 nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, curproc);
     191           0 :                 vn_lock(sp->s_dvp, LK_EXCLUSIVE | LK_RETRY);
     192           0 :                 nfs_removeit(sp);
     193           0 :                 crfree(sp->s_cred);
     194           0 :                 vput(sp->s_dvp);
     195           0 :                 free(sp, M_NFSREQ, sizeof(*sp));
     196           0 :         }
     197           0 :         np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT);
     198             : 
     199           0 :         VOP_UNLOCK(ap->a_vp);
     200           0 :         return (0);
     201           0 : }
     202             : 
     203             : /*
     204             :  * Reclaim an nfsnode so that it can be used for other purposes.
     205             :  */
     206             : int
     207           0 : nfs_reclaim(void *v)
     208             : {
     209           0 :         struct vop_reclaim_args *ap = v;
     210           0 :         struct vnode            *vp = ap->a_vp;
     211             :         struct nfsmount         *nmp;
     212           0 :         struct nfsnode          *np = VTONFS(vp);
     213             : 
     214             : #ifdef DIAGNOSTIC
     215           0 :         if (prtactive && vp->v_usecount != 0)
     216           0 :                 vprint("nfs_reclaim: pushing active", vp);
     217             : #endif
     218           0 :         if (ap->a_vp->v_flag & VLARVAL)
     219             :                 /*
     220             :                  * vnode was incompletely set up, just return
     221             :                  * as we are throwing it away.
     222             :                  */
     223           0 :                 return(0);
     224             : #ifdef DIAGNOSTIC
     225           0 :         if (ap->a_vp->v_data == NULL)
     226           0 :                 panic("NULL v_data (no nfsnode set up?) in vnode %p",
     227             :                     ap->a_vp);
     228             : #endif
     229           0 :         nmp = VFSTONFS(vp->v_mount);
     230           0 :         RBT_REMOVE(nfs_nodetree, &nmp->nm_ntree, np);
     231             : 
     232           0 :         if (np->n_rcred)
     233           0 :                 crfree(np->n_rcred);
     234           0 :         if (np->n_wcred)
     235           0 :                 crfree(np->n_wcred);
     236             : 
     237           0 :         cache_purge(vp);
     238           0 :         pool_put(&nfs_node_pool, vp->v_data);
     239           0 :         vp->v_data = NULL;
     240             : 
     241           0 :         return (0);
     242           0 : }

Generated by: LCOV version 1.13