home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / nfs / nfs_node.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-20  |  7.4 KB  |  326 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Rick Macklem at The University of Guelph.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  *    @(#)nfs_node.c    7.34 (Berkeley) 5/15/91
  37.  */
  38.  
  39. #include "param.h"
  40. #include "systm.h"
  41. #include "proc.h"
  42. #include "mount.h"
  43. #include "namei.h"
  44. #include "vnode.h"
  45. #include "kernel.h"
  46. #include "malloc.h"
  47.  
  48. #include "nfsv2.h"
  49. #include "nfs.h"
  50. #include "nfsnode.h"
  51. #include "nfsmount.h"
  52.  
  53. /* The request list head */
  54. extern struct nfsreq nfsreqh;
  55.  
  56. #define    NFSNOHSZ    512
  57. #if    ((NFSNOHSZ&(NFSNOHSZ-1)) == 0)
  58. #define    NFSNOHASH(fhsum)    ((fhsum)&(NFSNOHSZ-1))
  59. #else
  60. #define    NFSNOHASH(fhsum)    (((unsigned)(fhsum))%NFSNOHSZ)
  61. #endif
  62.  
  63. union nhead {
  64.     union  nhead *nh_head[2];
  65.     struct nfsnode *nh_chain[2];
  66. } nhead[NFSNOHSZ];
  67.  
  68. #define TRUE    1
  69. #define    FALSE    0
  70.  
  71. /*
  72.  * Initialize hash links for nfsnodes
  73.  * and build nfsnode free list.
  74.  */
  75. nfs_nhinit()
  76. {
  77.     register int i;
  78.     register union  nhead *nh = nhead;
  79.  
  80. #ifndef lint
  81.     if (VN_MAXPRIVATE < sizeof(struct nfsnode))
  82.         panic("nfs_nhinit: too small");
  83. #endif /* not lint */
  84.     for (i = NFSNOHSZ; --i >= 0; nh++) {
  85.         nh->nh_head[0] = nh;
  86.         nh->nh_head[1] = nh;
  87.     }
  88. }
  89.  
  90. /*
  91.  * Compute an entry in the NFS hash table structure
  92.  */
  93. union nhead *
  94. nfs_hash(fhp)
  95.     register nfsv2fh_t *fhp;
  96. {
  97.     register u_char *fhpp;
  98.     register u_long fhsum;
  99.     int i;
  100.  
  101.     fhpp = &fhp->fh_bytes[0];
  102.     fhsum = 0;
  103.     for (i = 0; i < NFSX_FH; i++)
  104.         fhsum += *fhpp++;
  105.     return (&nhead[NFSNOHASH(fhsum)]);
  106. }
  107.  
  108. /*
  109.  * Look up a vnode/nfsnode by file handle.
  110.  * Callers must check for mount points!!
  111.  * In all cases, a pointer to a
  112.  * nfsnode structure is returned.
  113.  */
  114. nfs_nget(mntp, fhp, npp)
  115.     struct mount *mntp;
  116.     register nfsv2fh_t *fhp;
  117.     struct nfsnode **npp;
  118. {
  119.     register struct nfsnode *np;
  120.     register struct vnode *vp;
  121.     extern struct vnodeops nfsv2_vnodeops;
  122.     struct vnode *nvp;
  123.     union nhead *nh;
  124.     int error;
  125.  
  126.     nh = nfs_hash(fhp);
  127. loop:
  128.     for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) {
  129.         if (mntp != NFSTOV(np)->v_mount ||
  130.             bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
  131.             continue;
  132.         if ((np->n_flag & NLOCKED) != 0) {
  133.             np->n_flag |= NWANT;
  134.             (void) tsleep((caddr_t)np, PINOD, "nfsnode", 0);
  135.             goto loop;
  136.         }
  137.         vp = NFSTOV(np);
  138.         if (vget(vp))
  139.             goto loop;
  140.         *npp = np;
  141.         return(0);
  142.     }
  143.     if (error = getnewvnode(VT_NFS, mntp, &nfsv2_vnodeops, &nvp)) {
  144.         *npp = 0;
  145.         return (error);
  146.     }
  147.     vp = nvp;
  148.     np = VTONFS(vp);
  149.     np->n_vnode = vp;
  150.     /*
  151.      * Insert the nfsnode in the hash queue for its new file handle
  152.      */
  153.     np->n_flag = 0;
  154.     insque(np, nh);
  155.     nfs_lock(vp);
  156.     bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
  157.     np->n_attrstamp = 0;
  158.     np->n_direofoffset = 0;
  159.     np->n_sillyrename = (struct sillyrename *)0;
  160.     np->n_size = 0;
  161.     np->n_mtime = 0;
  162.     *npp = np;
  163.     return (0);
  164. }
  165.  
  166. nfs_inactive(vp, p)
  167.     struct vnode *vp;
  168.     struct proc *p;
  169. {
  170.     register struct nfsnode *np;
  171.     register struct sillyrename *sp;
  172.     struct nfsnode *dnp;
  173.     extern int prtactive;
  174.  
  175.     np = VTONFS(vp);
  176.     if (prtactive && vp->v_usecount != 0)
  177.         vprint("nfs_inactive: pushing active", vp);
  178.     nfs_lock(vp);
  179.     sp = np->n_sillyrename;
  180.     np->n_sillyrename = (struct sillyrename *)0;
  181.     if (sp) {
  182.         /*
  183.          * Remove the silly file that was rename'd earlier
  184.          */
  185.         if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) {
  186.             sp->s_dvp = NFSTOV(dnp);
  187.             nfs_removeit(sp, p);
  188.             nfs_nput(sp->s_dvp);
  189.         }
  190.         crfree(sp->s_cred);
  191.         vrele(sp->s_dvp);
  192.         free((caddr_t)sp, M_NFSREQ);
  193.     }
  194.     nfs_unlock(vp);
  195.     np->n_flag &= NMODIFIED;
  196. #ifdef notdef
  197.     /*
  198.      * Scan the request list for any requests left hanging about
  199.      */
  200.     s = splnet();
  201.     rep = nfsreqh.r_next;
  202.     while (rep && rep != &nfsreqh) {
  203.         if (rep->r_vp == vp) {
  204.             rep->r_prev->r_next = rep2 = rep->r_next;
  205.             rep->r_next->r_prev = rep->r_prev;
  206.             m_freem(rep->r_mreq);
  207.             if (rep->r_mrep != NULL)
  208.                 m_freem(rep->r_mrep);
  209.             free((caddr_t)rep, M_NFSREQ);
  210.             rep = rep2;
  211.         } else
  212.             rep = rep->r_next;
  213.     }
  214.     splx(s);
  215. #endif
  216.     return (0);
  217. }
  218.  
  219. /*
  220.  * Reclaim an nfsnode so that it can be used for other purposes.
  221.  */
  222. nfs_reclaim(vp)
  223.     register struct vnode *vp;
  224. {
  225.     register struct nfsnode *np = VTONFS(vp);
  226.     extern int prtactive;
  227.  
  228.     if (prtactive && vp->v_usecount != 0)
  229.         vprint("nfs_reclaim: pushing active", vp);
  230.     /*
  231.      * Remove the nfsnode from its hash chain.
  232.      */
  233.     remque(np);
  234.     np->n_forw = np;
  235.     np->n_back = np;
  236.     cache_purge(vp);
  237.     np->n_flag = 0;
  238.     np->n_direofoffset = 0;
  239.     return (0);
  240. }
  241.  
  242. /*
  243.  * In theory, NFS does not need locking, but we make provision
  244.  * for doing it just in case it is needed.
  245.  */
  246. int donfslocking = 0;
  247. /*
  248.  * Lock an nfsnode
  249.  */
  250.  
  251. nfs_lock(vp)
  252.     struct vnode *vp;
  253. {
  254.     register struct nfsnode *np = VTONFS(vp);
  255.  
  256.     if (!donfslocking)
  257.         return;
  258.     while (np->n_flag & NLOCKED) {
  259.         np->n_flag |= NWANT;
  260.         if (np->n_lockholder == curproc->p_pid)
  261.             panic("locking against myself");
  262.         np->n_lockwaiter = curproc->p_pid;
  263.         (void) tsleep((caddr_t)np, PINOD, "nfslock", 0);
  264.     }
  265.     np->n_lockwaiter = 0;
  266.     np->n_lockholder = curproc->p_pid;
  267.     np->n_flag |= NLOCKED;
  268. }
  269.  
  270. /*
  271.  * Unlock an nfsnode
  272.  */
  273. nfs_unlock(vp)
  274.     struct vnode *vp;
  275. {
  276.     register struct nfsnode *np = VTONFS(vp);
  277.  
  278.     np->n_lockholder = 0;
  279.     np->n_flag &= ~NLOCKED;
  280.     if (np->n_flag & NWANT) {
  281.         np->n_flag &= ~NWANT;
  282.         wakeup((caddr_t)np);
  283.     }
  284. }
  285.  
  286. /*
  287.  * Check for a locked nfsnode
  288.  */
  289. nfs_islocked(vp)
  290.     struct vnode *vp;
  291. {
  292.  
  293.     if (VTONFS(vp)->n_flag & NLOCKED)
  294.         return (1);
  295.     return (0);
  296. }
  297.  
  298. /*
  299.  * Unlock and vrele()
  300.  * since I can't decide if dirs. should be locked, I will check for
  301.  * the lock and be flexible
  302.  */
  303. nfs_nput(vp)
  304.     struct vnode *vp;
  305. {
  306.     register struct nfsnode *np = VTONFS(vp);
  307.  
  308.     if (np->n_flag & NLOCKED)
  309.         nfs_unlock(vp);
  310.     vrele(vp);
  311. }
  312.  
  313. /*
  314.  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
  315.  * done. Currently nothing to do.
  316.  */
  317. /* ARGSUSED */
  318. nfs_abortop(ndp)
  319.     struct nameidata *ndp;
  320. {
  321.  
  322.     if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
  323.         FREE(ndp->ni_pnbuf, M_NAMEI);
  324.     return (0);
  325. }
  326.