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