|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.