|
|
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 is only permitted until one year after the first shipment ! 9: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 10: * binary forms are permitted provided that: (1) source distributions retain ! 11: * this entire copyright notice and comment, and (2) distributions including ! 12: * binaries display the following acknowledgement: This product includes ! 13: * software developed by the University of California, Berkeley and its ! 14: * contributors'' in the documentation or other materials provided with the ! 15: * distribution and in all advertising materials mentioning features or use ! 16: * of this software. Neither the name of the University nor the names of ! 17: * its contributors may be used to endorse or promote products derived from ! 18: * this software without specific prior written permission. ! 19: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 22: * ! 23: * @(#)nfs_node.c 7.29 (Berkeley) 6/28/90 ! 24: */ ! 25: ! 26: #include "param.h" ! 27: #include "systm.h" ! 28: #include "user.h" ! 29: #include "proc.h" ! 30: #include "mount.h" ! 31: #include "vnode.h" ! 32: #include "errno.h" ! 33: #include "nfsv2.h" ! 34: #include "nfs.h" ! 35: #include "nfsnode.h" ! 36: #include "nfsmount.h" ! 37: #include "kernel.h" ! 38: #include "malloc.h" ! 39: ! 40: /* The request list head */ ! 41: extern struct nfsreq nfsreqh; ! 42: ! 43: #define NFSNOHSZ 512 ! 44: #if ((NFSNOHSZ&(NFSNOHSZ-1)) == 0) ! 45: #define NFSNOHASH(fhsum) ((fhsum)&(NFSNOHSZ-1)) ! 46: #else ! 47: #define NFSNOHASH(fhsum) (((unsigned)(fhsum))%NFSNOHSZ) ! 48: #endif ! 49: ! 50: union nhead { ! 51: union nhead *nh_head[2]; ! 52: struct nfsnode *nh_chain[2]; ! 53: } nhead[NFSNOHSZ]; ! 54: ! 55: #define TRUE 1 ! 56: #define FALSE 0 ! 57: ! 58: /* ! 59: * Initialize hash links for nfsnodes ! 60: * and build nfsnode free list. ! 61: */ ! 62: nfs_nhinit() ! 63: { ! 64: register int i; ! 65: register union nhead *nh = nhead; ! 66: ! 67: #ifndef lint ! 68: if (VN_MAXPRIVATE < sizeof(struct nfsnode)) ! 69: panic("nfs_nhinit: too small"); ! 70: #endif /* not lint */ ! 71: for (i = NFSNOHSZ; --i >= 0; nh++) { ! 72: nh->nh_head[0] = nh; ! 73: nh->nh_head[1] = nh; ! 74: } ! 75: } ! 76: ! 77: /* ! 78: * Compute an entry in the NFS hash table structure ! 79: */ ! 80: union nhead * ! 81: nfs_hash(fhp) ! 82: register nfsv2fh_t *fhp; ! 83: { ! 84: register u_char *fhpp; ! 85: register u_long fhsum; ! 86: int i; ! 87: ! 88: fhpp = &fhp->fh_bytes[0]; ! 89: fhsum = 0; ! 90: for (i = 0; i < NFSX_FH; i++) ! 91: fhsum += *fhpp++; ! 92: return (&nhead[NFSNOHASH(fhsum)]); ! 93: } ! 94: ! 95: /* ! 96: * Look up a vnode/nfsnode by file handle. ! 97: * Callers must check for mount points!! ! 98: * In all cases, a pointer to a ! 99: * nfsnode structure is returned. ! 100: */ ! 101: nfs_nget(mntp, fhp, npp) ! 102: struct mount *mntp; ! 103: register nfsv2fh_t *fhp; ! 104: struct nfsnode **npp; ! 105: { ! 106: register struct nfsnode *np; ! 107: register struct vnode *vp; ! 108: extern struct vnodeops nfsv2_vnodeops; ! 109: struct vnode *nvp; ! 110: union nhead *nh; ! 111: int error; ! 112: ! 113: nh = nfs_hash(fhp); ! 114: loop: ! 115: for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) { ! 116: if (mntp != NFSTOV(np)->v_mount || ! 117: bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH)) ! 118: continue; ! 119: if ((np->n_flag & NLOCKED) != 0) { ! 120: np->n_flag |= NWANT; ! 121: (void) tsleep((caddr_t)np, PINOD, "nfsnode", 0); ! 122: goto loop; ! 123: } ! 124: vp = NFSTOV(np); ! 125: if (vget(vp)) ! 126: goto loop; ! 127: *npp = np; ! 128: return(0); ! 129: } ! 130: if (error = getnewvnode(VT_NFS, mntp, &nfsv2_vnodeops, &nvp)) { ! 131: *npp = 0; ! 132: return (error); ! 133: } ! 134: vp = nvp; ! 135: np = VTONFS(vp); ! 136: np->n_vnode = vp; ! 137: /* ! 138: * Insert the nfsnode in the hash queue for its new file handle ! 139: */ ! 140: np->n_flag = 0; ! 141: insque(np, nh); ! 142: nfs_lock(vp); ! 143: bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH); ! 144: np->n_attrstamp = 0; ! 145: np->n_direofoffset = 0; ! 146: np->n_sillyrename = (struct sillyrename *)0; ! 147: np->n_size = 0; ! 148: np->n_mtime = 0; ! 149: *npp = np; ! 150: return (0); ! 151: } ! 152: ! 153: nfs_inactive(vp) ! 154: struct vnode *vp; ! 155: { ! 156: register struct nfsnode *np; ! 157: register struct nameidata *ndp; ! 158: register struct sillyrename *sp; ! 159: struct nfsnode *dnp; ! 160: extern int prtactive; ! 161: ! 162: np = VTONFS(vp); ! 163: if (prtactive && vp->v_usecount != 0) ! 164: vprint("nfs_inactive: pushing active", vp); ! 165: nfs_lock(vp); ! 166: sp = np->n_sillyrename; ! 167: np->n_sillyrename = (struct sillyrename *)0; ! 168: if (sp) { ! 169: /* ! 170: * Remove the silly file that was rename'd earlier ! 171: */ ! 172: ndp = &sp->s_namei; ! 173: if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) { ! 174: ndp->ni_dvp = NFSTOV(dnp); ! 175: nfs_removeit(ndp); ! 176: nfs_nput(ndp->ni_dvp); ! 177: } ! 178: crfree(ndp->ni_cred); ! 179: free((caddr_t)sp, M_TEMP); ! 180: } ! 181: nfs_unlock(vp); ! 182: np->n_flag &= NMODIFIED; ! 183: #ifdef notdef ! 184: /* ! 185: * Scan the request list for any requests left hanging about ! 186: */ ! 187: s = splnet(); ! 188: rep = nfsreqh.r_next; ! 189: while (rep && rep != &nfsreqh) { ! 190: if (rep->r_vp == vp) { ! 191: rep->r_prev->r_next = rep2 = rep->r_next; ! 192: rep->r_next->r_prev = rep->r_prev; ! 193: m_freem(rep->r_mreq); ! 194: if (rep->r_mrep != NULL) ! 195: m_freem(rep->r_mrep); ! 196: free((caddr_t)rep, M_NFSREQ); ! 197: rep = rep2; ! 198: } else ! 199: rep = rep->r_next; ! 200: } ! 201: splx(s); ! 202: #endif ! 203: return (0); ! 204: } ! 205: ! 206: /* ! 207: * Reclaim an nfsnode so that it can be used for other purposes. ! 208: */ ! 209: nfs_reclaim(vp) ! 210: register struct vnode *vp; ! 211: { ! 212: register struct nfsnode *np = VTONFS(vp); ! 213: extern int prtactive; ! 214: ! 215: if (prtactive && vp->v_usecount != 0) ! 216: vprint("nfs_reclaim: pushing active", vp); ! 217: /* ! 218: * Remove the nfsnode from its hash chain. ! 219: */ ! 220: remque(np); ! 221: np->n_forw = np; ! 222: np->n_back = np; ! 223: cache_purge(vp); ! 224: np->n_flag = 0; ! 225: np->n_direofoffset = 0; ! 226: return (0); ! 227: } ! 228: ! 229: /* ! 230: * Lock an nfsnode ! 231: */ ! 232: nfs_lock(vp) ! 233: struct vnode *vp; ! 234: { ! 235: register struct nfsnode *np = VTONFS(vp); ! 236: ! 237: while (np->n_flag & NLOCKED) { ! 238: np->n_flag |= NWANT; ! 239: if (np->n_lockholder == u.u_procp->p_pid) ! 240: panic("locking against myself"); ! 241: np->n_lockwaiter = u.u_procp->p_pid; ! 242: (void) tsleep((caddr_t)np, PINOD, "nfslock", 0); ! 243: } ! 244: np->n_lockwaiter = 0; ! 245: np->n_lockholder = u.u_procp->p_pid; ! 246: u.u_spare[0]++; ! 247: np->n_flag |= NLOCKED; ! 248: } ! 249: ! 250: /* ! 251: * Unlock an nfsnode ! 252: */ ! 253: nfs_unlock(vp) ! 254: struct vnode *vp; ! 255: { ! 256: register struct nfsnode *np = VTONFS(vp); ! 257: ! 258: if ((np->n_flag & NLOCKED) == 0) ! 259: vprint("nfs_unlock: unlocked nfsnode", vp); ! 260: np->n_lockholder = 0; ! 261: u.u_spare[0]--; ! 262: np->n_flag &= ~NLOCKED; ! 263: if (np->n_flag & NWANT) { ! 264: np->n_flag &= ~NWANT; ! 265: wakeup((caddr_t)np); ! 266: } ! 267: } ! 268: ! 269: /* ! 270: * Check for a locked nfsnode ! 271: */ ! 272: nfs_islocked(vp) ! 273: struct vnode *vp; ! 274: { ! 275: ! 276: if (VTONFS(vp)->n_flag & NLOCKED) ! 277: return (1); ! 278: return (0); ! 279: } ! 280: ! 281: /* ! 282: * Unlock and vrele() ! 283: * since I can't decide if dirs. should be locked, I will check for ! 284: * the lock and be flexible ! 285: */ ! 286: nfs_nput(vp) ! 287: struct vnode *vp; ! 288: { ! 289: register struct nfsnode *np = VTONFS(vp); ! 290: ! 291: if (np->n_flag & NLOCKED) ! 292: nfs_unlock(vp); ! 293: vrele(vp); ! 294: } ! 295: ! 296: /* ! 297: * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually ! 298: * done. Currently nothing to do. ! 299: */ ! 300: /* ARGSUSED */ ! 301: nfs_abortop(ndp) ! 302: struct nameidata *ndp; ! 303: { ! 304: ! 305: return (0); ! 306: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.