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