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