From Bruce:
[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
8fd6bef6 37 * $Id: nfs_node.c,v 1.3 1993/11/25 01:36:48 wollman 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;
8fd6bef6 165 np->n_lockf = 0;
15637ed4
RG
166 *npp = np;
167 return (0);
168}
169
a8599e88 170int
15637ed4
RG
171nfs_inactive(vp, p)
172 struct vnode *vp;
173 struct proc *p;
174{
175 register struct nfsnode *np;
176 register struct sillyrename *sp;
177 struct nfsnode *dnp;
178 extern int prtactive;
179
180 np = VTONFS(vp);
181 if (prtactive && vp->v_usecount != 0)
182 vprint("nfs_inactive: pushing active", vp);
183 nfs_lock(vp);
184 sp = np->n_sillyrename;
185 np->n_sillyrename = (struct sillyrename *)0;
186 if (sp) {
187 /*
188 * Remove the silly file that was rename'd earlier
189 */
190 if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) {
191 sp->s_dvp = NFSTOV(dnp);
192 nfs_removeit(sp, p);
193 nfs_nput(sp->s_dvp);
194 }
195 crfree(sp->s_cred);
196 vrele(sp->s_dvp);
197 free((caddr_t)sp, M_NFSREQ);
198 }
199 nfs_unlock(vp);
200 np->n_flag &= NMODIFIED;
201#ifdef notdef
202 /*
203 * Scan the request list for any requests left hanging about
204 */
205 s = splnet();
206 rep = nfsreqh.r_next;
207 while (rep && rep != &nfsreqh) {
208 if (rep->r_vp == vp) {
209 rep->r_prev->r_next = rep2 = rep->r_next;
210 rep->r_next->r_prev = rep->r_prev;
211 m_freem(rep->r_mreq);
212 if (rep->r_mrep != NULL)
213 m_freem(rep->r_mrep);
214 free((caddr_t)rep, M_NFSREQ);
215 rep = rep2;
216 } else
217 rep = rep->r_next;
218 }
219 splx(s);
220#endif
221 return (0);
222}
223
224/*
225 * Reclaim an nfsnode so that it can be used for other purposes.
226 */
a8599e88 227int
15637ed4
RG
228nfs_reclaim(vp)
229 register struct vnode *vp;
230{
231 register struct nfsnode *np = VTONFS(vp);
232 extern int prtactive;
233
234 if (prtactive && vp->v_usecount != 0)
235 vprint("nfs_reclaim: pushing active", vp);
236 /*
237 * Remove the nfsnode from its hash chain.
238 */
239 remque(np);
240 np->n_forw = np;
241 np->n_back = np;
242 cache_purge(vp);
243 np->n_flag = 0;
244 np->n_direofoffset = 0;
245 return (0);
246}
247
248/*
249 * In theory, NFS does not need locking, but we make provision
250 * for doing it just in case it is needed.
251 */
252int donfslocking = 0;
4c45483e 253
15637ed4
RG
254/*
255 * Lock an nfsnode
256 */
a8599e88 257int
15637ed4
RG
258nfs_lock(vp)
259 struct vnode *vp;
260{
261 register struct nfsnode *np = VTONFS(vp);
262
263 if (!donfslocking)
4c45483e 264 return 0;
15637ed4
RG
265 while (np->n_flag & NLOCKED) {
266 np->n_flag |= NWANT;
267 if (np->n_lockholder == curproc->p_pid)
268 panic("locking against myself");
269 np->n_lockwaiter = curproc->p_pid;
270 (void) tsleep((caddr_t)np, PINOD, "nfslock", 0);
271 }
272 np->n_lockwaiter = 0;
273 np->n_lockholder = curproc->p_pid;
274 np->n_flag |= NLOCKED;
a8599e88 275 return(0);
15637ed4
RG
276}
277
278/*
279 * Unlock an nfsnode
280 */
a8599e88 281int
15637ed4
RG
282nfs_unlock(vp)
283 struct vnode *vp;
284{
285 register struct nfsnode *np = VTONFS(vp);
286
287 np->n_lockholder = 0;
288 np->n_flag &= ~NLOCKED;
289 if (np->n_flag & NWANT) {
290 np->n_flag &= ~NWANT;
291 wakeup((caddr_t)np);
292 }
a8599e88 293 return(0);
15637ed4
RG
294}
295
296/*
297 * Check for a locked nfsnode
298 */
a8599e88 299int
15637ed4
RG
300nfs_islocked(vp)
301 struct vnode *vp;
302{
303
304 if (VTONFS(vp)->n_flag & NLOCKED)
305 return (1);
306 return (0);
307}
308
309/*
310 * Unlock and vrele()
311 * since I can't decide if dirs. should be locked, I will check for
312 * the lock and be flexible
313 */
a8599e88 314void
15637ed4
RG
315nfs_nput(vp)
316 struct vnode *vp;
317{
318 register struct nfsnode *np = VTONFS(vp);
319
320 if (np->n_flag & NLOCKED)
321 nfs_unlock(vp);
322 vrele(vp);
323}
324
325/*
326 * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
327 * done. Currently nothing to do.
328 */
329/* ARGSUSED */
a8599e88 330int
15637ed4
RG
331nfs_abortop(ndp)
332 struct nameidata *ndp;
333{
334
335 if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
336 FREE(ndp->ni_pnbuf, M_NAMEI);
337 return (0);
338}