|
|
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: *
1.1.1.2 ! root 36: * from: @(#)nfs_node.c 7.34 (Berkeley) 5/15/91
! 37: * nfs_node.c,v 1.2.2.1 1993/07/24 20:26:40 cgd Exp
1.1 root 38: */
39:
40: #include "param.h"
41: #include "systm.h"
42: #include "proc.h"
43: #include "mount.h"
44: #include "namei.h"
45: #include "vnode.h"
46: #include "kernel.h"
47: #include "malloc.h"
48:
49: #include "nfsv2.h"
50: #include "nfs.h"
51: #include "nfsnode.h"
52: #include "nfsmount.h"
53:
54: /* The request list head */
55: extern struct nfsreq nfsreqh;
56:
57: #define NFSNOHSZ 512
58: #if ((NFSNOHSZ&(NFSNOHSZ-1)) == 0)
59: #define NFSNOHASH(fhsum) ((fhsum)&(NFSNOHSZ-1))
60: #else
61: #define NFSNOHASH(fhsum) (((unsigned)(fhsum))%NFSNOHSZ)
62: #endif
63:
64: union nhead {
65: union nhead *nh_head[2];
66: struct nfsnode *nh_chain[2];
67: } nhead[NFSNOHSZ];
68:
69: #define TRUE 1
70: #define FALSE 0
71:
72: /*
73: * Initialize hash links for nfsnodes
74: * and build nfsnode free list.
75: */
76: nfs_nhinit()
77: {
78: register int i;
79: register union nhead *nh = nhead;
80:
81: #ifndef lint
82: if (VN_MAXPRIVATE < sizeof(struct nfsnode))
83: panic("nfs_nhinit: too small");
84: #endif /* not lint */
85: for (i = NFSNOHSZ; --i >= 0; nh++) {
86: nh->nh_head[0] = nh;
87: nh->nh_head[1] = nh;
88: }
89: }
90:
91: /*
92: * Compute an entry in the NFS hash table structure
93: */
94: union nhead *
95: nfs_hash(fhp)
96: register nfsv2fh_t *fhp;
97: {
98: register u_char *fhpp;
99: register u_long fhsum;
100: int i;
101:
102: fhpp = &fhp->fh_bytes[0];
103: fhsum = 0;
104: for (i = 0; i < NFSX_FH; i++)
105: fhsum += *fhpp++;
106: return (&nhead[NFSNOHASH(fhsum)]);
107: }
108:
109: /*
110: * Look up a vnode/nfsnode by file handle.
111: * Callers must check for mount points!!
112: * In all cases, a pointer to a
113: * nfsnode structure is returned.
114: */
115: nfs_nget(mntp, fhp, npp)
116: struct mount *mntp;
117: register nfsv2fh_t *fhp;
118: struct nfsnode **npp;
119: {
120: register struct nfsnode *np;
121: register struct vnode *vp;
122: extern struct vnodeops nfsv2_vnodeops;
123: struct vnode *nvp;
124: union nhead *nh;
125: int error;
126:
127: nh = nfs_hash(fhp);
128: loop:
129: for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) {
130: if (mntp != NFSTOV(np)->v_mount ||
131: bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
132: continue;
133: if ((np->n_flag & NLOCKED) != 0) {
134: np->n_flag |= NWANT;
135: (void) tsleep((caddr_t)np, PINOD, "nfsnode", 0);
136: goto loop;
137: }
138: vp = NFSTOV(np);
139: if (vget(vp))
140: goto loop;
141: *npp = np;
142: return(0);
143: }
144: if (error = getnewvnode(VT_NFS, mntp, &nfsv2_vnodeops, &nvp)) {
145: *npp = 0;
146: return (error);
147: }
148: vp = nvp;
149: np = VTONFS(vp);
150: np->n_vnode = vp;
151: /*
152: * Insert the nfsnode in the hash queue for its new file handle
153: */
154: np->n_flag = 0;
155: insque(np, nh);
156: nfs_lock(vp);
157: bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
158: np->n_attrstamp = 0;
159: np->n_direofoffset = 0;
160: np->n_sillyrename = (struct sillyrename *)0;
161: np->n_size = 0;
162: np->n_mtime = 0;
1.1.1.2 ! root 163: np->n_lockf = 0;
1.1 root 164: *npp = np;
165: return (0);
166: }
167:
168: nfs_inactive(vp, p)
169: struct vnode *vp;
170: struct proc *p;
171: {
172: register struct nfsnode *np;
173: register struct sillyrename *sp;
174: struct nfsnode *dnp;
175: extern int prtactive;
176:
177: np = VTONFS(vp);
178: if (prtactive && vp->v_usecount != 0)
179: vprint("nfs_inactive: pushing active", vp);
180: nfs_lock(vp);
181: sp = np->n_sillyrename;
182: np->n_sillyrename = (struct sillyrename *)0;
183: if (sp) {
184: /*
185: * Remove the silly file that was rename'd earlier
186: */
187: if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) {
188: sp->s_dvp = NFSTOV(dnp);
189: nfs_removeit(sp, p);
190: nfs_nput(sp->s_dvp);
191: }
192: crfree(sp->s_cred);
193: vrele(sp->s_dvp);
194: free((caddr_t)sp, M_NFSREQ);
195: }
196: nfs_unlock(vp);
197: np->n_flag &= NMODIFIED;
198: #ifdef notdef
199: /*
200: * Scan the request list for any requests left hanging about
201: */
202: s = splnet();
203: rep = nfsreqh.r_next;
204: while (rep && rep != &nfsreqh) {
205: if (rep->r_vp == vp) {
206: rep->r_prev->r_next = rep2 = rep->r_next;
207: rep->r_next->r_prev = rep->r_prev;
208: m_freem(rep->r_mreq);
209: if (rep->r_mrep != NULL)
210: m_freem(rep->r_mrep);
211: free((caddr_t)rep, M_NFSREQ);
212: rep = rep2;
213: } else
214: rep = rep->r_next;
215: }
216: splx(s);
217: #endif
218: return (0);
219: }
220:
221: /*
222: * Reclaim an nfsnode so that it can be used for other purposes.
223: */
224: nfs_reclaim(vp)
225: register struct vnode *vp;
226: {
227: register struct nfsnode *np = VTONFS(vp);
228: extern int prtactive;
229:
230: if (prtactive && vp->v_usecount != 0)
231: vprint("nfs_reclaim: pushing active", vp);
232: /*
233: * Remove the nfsnode from its hash chain.
234: */
235: remque(np);
236: np->n_forw = np;
237: np->n_back = np;
238: cache_purge(vp);
239: np->n_flag = 0;
240: np->n_direofoffset = 0;
241: return (0);
242: }
243:
244: /*
245: * In theory, NFS does not need locking, but we make provision
246: * for doing it just in case it is needed.
247: */
248: int donfslocking = 0;
249: /*
250: * Lock an nfsnode
251: */
252:
253: nfs_lock(vp)
254: struct vnode *vp;
255: {
256: register struct nfsnode *np = VTONFS(vp);
257:
258: if (!donfslocking)
259: return;
260: while (np->n_flag & NLOCKED) {
261: np->n_flag |= NWANT;
262: if (np->n_lockholder == curproc->p_pid)
263: panic("locking against myself");
264: np->n_lockwaiter = curproc->p_pid;
265: (void) tsleep((caddr_t)np, PINOD, "nfslock", 0);
266: }
267: np->n_lockwaiter = 0;
268: np->n_lockholder = curproc->p_pid;
269: np->n_flag |= NLOCKED;
270: }
271:
272: /*
273: * Unlock an nfsnode
274: */
275: nfs_unlock(vp)
276: struct vnode *vp;
277: {
278: register struct nfsnode *np = VTONFS(vp);
279:
280: np->n_lockholder = 0;
281: np->n_flag &= ~NLOCKED;
282: if (np->n_flag & NWANT) {
283: np->n_flag &= ~NWANT;
284: wakeup((caddr_t)np);
285: }
286: }
287:
288: /*
289: * Check for a locked nfsnode
290: */
291: nfs_islocked(vp)
292: struct vnode *vp;
293: {
294:
295: if (VTONFS(vp)->n_flag & NLOCKED)
296: return (1);
297: return (0);
298: }
299:
300: /*
301: * Unlock and vrele()
302: * since I can't decide if dirs. should be locked, I will check for
303: * the lock and be flexible
304: */
305: nfs_nput(vp)
306: struct vnode *vp;
307: {
308: register struct nfsnode *np = VTONFS(vp);
309:
310: if (np->n_flag & NLOCKED)
311: nfs_unlock(vp);
312: vrele(vp);
313: }
314:
315: /*
316: * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
317: * done. Currently nothing to do.
318: */
319: /* ARGSUSED */
320: nfs_abortop(ndp)
321: struct nameidata *ndp;
322: {
323:
324: if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
325: FREE(ndp->ni_pnbuf, M_NAMEI);
326: return (0);
327: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.