file descriptors are now allocated dynamically
[unix-history] / usr / src / sys / nfs / nfs_node.c
CommitLineData
a2907882
KM
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 *
dbf0c423 8 * %sccs.include.redist.c%
a2907882 9 *
dbf0c423 10 * @(#)nfs_node.c 7.29 (Berkeley) %G%
a2907882
KM
11 */
12
13#include "param.h"
14#include "systm.h"
15#include "user.h"
16#include "proc.h"
17#include "mount.h"
18#include "vnode.h"
a2907882
KM
19#include "errno.h"
20#include "nfsv2.h"
21#include "nfs.h"
22#include "nfsnode.h"
23#include "nfsmount.h"
24#include "kernel.h"
25#include "malloc.h"
26
27/* The request list head */
28extern struct nfsreq nfsreqh;
29
a2907882
KM
30#define NFSNOHSZ 512
31#if ((NFSNOHSZ&(NFSNOHSZ-1)) == 0)
32#define NFSNOHASH(fhsum) ((fhsum)&(NFSNOHSZ-1))
33#else
34#define NFSNOHASH(fhsum) (((unsigned)(fhsum))%NFSNOHSZ)
35#endif
36
bfb2d643 37union nhead {
a2907882
KM
38 union nhead *nh_head[2];
39 struct nfsnode *nh_chain[2];
40} nhead[NFSNOHSZ];
41
9238aa59
RM
42#define TRUE 1
43#define FALSE 0
44
a2907882
KM
45/*
46 * Initialize hash links for nfsnodes
47 * and build nfsnode free list.
48 */
49nfs_nhinit()
50{
51 register int i;
a2907882
KM
52 register union nhead *nh = nhead;
53
0bd503ad 54#ifndef lint
bfb2d643
KM
55 if (VN_MAXPRIVATE < sizeof(struct nfsnode))
56 panic("nfs_nhinit: too small");
0bd503ad 57#endif /* not lint */
a2907882
KM
58 for (i = NFSNOHSZ; --i >= 0; nh++) {
59 nh->nh_head[0] = nh;
60 nh->nh_head[1] = nh;
61 }
a2907882
KM
62}
63
7f79aa94
KM
64/*
65 * Compute an entry in the NFS hash table structure
66 */
67union nhead *
68nfs_hash(fhp)
69 register nfsv2fh_t *fhp;
70{
71 register u_char *fhpp;
72 register u_long fhsum;
73 int i;
74
75 fhpp = &fhp->fh_bytes[0];
76 fhsum = 0;
77 for (i = 0; i < NFSX_FH; i++)
78 fhsum += *fhpp++;
79 return (&nhead[NFSNOHASH(fhsum)]);
80}
81
a2907882 82/*
bfb2d643 83 * Look up a vnode/nfsnode by file handle.
a2907882
KM
84 * Callers must check for mount points!!
85 * In all cases, a pointer to a
86 * nfsnode structure is returned.
87 */
88nfs_nget(mntp, fhp, npp)
89 struct mount *mntp;
90 register nfsv2fh_t *fhp;
91 struct nfsnode **npp;
92{
93 register struct nfsnode *np;
94 register struct vnode *vp;
7f79aa94 95 extern struct vnodeops nfsv2_vnodeops;
bfb2d643
KM
96 struct vnode *nvp;
97 union nhead *nh;
7f79aa94 98 int error;
a2907882 99
7f79aa94 100 nh = nfs_hash(fhp);
a2907882 101loop:
9238aa59 102 for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) {
bfb2d643
KM
103 if (mntp != NFSTOV(np)->v_mount ||
104 bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
105 continue;
bfb2d643
KM
106 if ((np->n_flag & NLOCKED) != 0) {
107 np->n_flag |= NWANT;
170bfd05 108 (void) tsleep((caddr_t)np, PINOD, "nfsnode", 0);
bfb2d643 109 goto loop;
a2907882 110 }
bfb2d643 111 vp = NFSTOV(np);
7f79aa94
KM
112 if (vget(vp))
113 goto loop;
bfb2d643
KM
114 *npp = np;
115 return(0);
9238aa59 116 }
bfb2d643 117 if (error = getnewvnode(VT_NFS, mntp, &nfsv2_vnodeops, &nvp)) {
a2907882 118 *npp = 0;
bfb2d643 119 return (error);
9238aa59 120 }
bfb2d643
KM
121 vp = nvp;
122 np = VTONFS(vp);
123 np->n_vnode = vp;
9238aa59
RM
124 /*
125 * Insert the nfsnode in the hash queue for its new file handle
126 */
226812f6 127 np->n_flag = 0;
a2907882 128 insque(np, nh);
226812f6 129 nfs_lock(vp);
a2907882 130 bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
a2907882 131 np->n_attrstamp = 0;
f0f1cbaa 132 np->n_direofoffset = 0;
a2907882 133 np->n_sillyrename = (struct sillyrename *)0;
9238aa59
RM
134 np->n_size = 0;
135 np->n_mtime = 0;
a2907882
KM
136 *npp = np;
137 return (0);
138}
139
a2907882
KM
140nfs_inactive(vp)
141 struct vnode *vp;
142{
143 register struct nfsnode *np;
144 register struct nameidata *ndp;
145 register struct sillyrename *sp;
a2907882 146 struct nfsnode *dnp;
7efae46b 147 extern int prtactive;
a2907882 148
bfb2d643 149 np = VTONFS(vp);
1f7e9641 150 if (prtactive && vp->v_usecount != 0)
b2870bc0 151 vprint("nfs_inactive: pushing active", vp);
bfb2d643
KM
152 nfs_lock(vp);
153 sp = np->n_sillyrename;
154 np->n_sillyrename = (struct sillyrename *)0;
155 if (sp) {
a2907882 156 /*
bfb2d643 157 * Remove the silly file that was rename'd earlier
a2907882 158 */
bfb2d643
KM
159 ndp = &sp->s_namei;
160 if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) {
161 ndp->ni_dvp = NFSTOV(dnp);
162 nfs_removeit(ndp);
163 nfs_nput(ndp->ni_dvp);
a2907882 164 }
bfb2d643
KM
165 crfree(ndp->ni_cred);
166 free((caddr_t)sp, M_TEMP);
167 }
168 nfs_unlock(vp);
f0f1cbaa 169 np->n_flag &= NMODIFIED;
bfb2d643
KM
170#ifdef notdef
171 /*
172 * Scan the request list for any requests left hanging about
173 */
174 s = splnet();
175 rep = nfsreqh.r_next;
176 while (rep && rep != &nfsreqh) {
177 if (rep->r_vp == vp) {
178 rep->r_prev->r_next = rep2 = rep->r_next;
179 rep->r_next->r_prev = rep->r_prev;
180 m_freem(rep->r_mreq);
181 if (rep->r_mrep != NULL)
182 m_freem(rep->r_mrep);
183 free((caddr_t)rep, M_NFSREQ);
184 rep = rep2;
185 } else
186 rep = rep->r_next;
187 }
188 splx(s);
9238aa59 189#endif
bfb2d643
KM
190 return (0);
191}
192
193/*
194 * Reclaim an nfsnode so that it can be used for other purposes.
195 */
196nfs_reclaim(vp)
197 register struct vnode *vp;
198{
199 register struct nfsnode *np = VTONFS(vp);
7efae46b 200 extern int prtactive;
bfb2d643 201
1f7e9641 202 if (prtactive && vp->v_usecount != 0)
b2870bc0 203 vprint("nfs_reclaim: pushing active", vp);
bfb2d643
KM
204 /*
205 * Remove the nfsnode from its hash chain.
206 */
207 remque(np);
208 np->n_forw = np;
209 np->n_back = np;
210 cache_purge(vp);
e8540f59 211 np->n_flag = 0;
f0f1cbaa 212 np->n_direofoffset = 0;
a2907882
KM
213 return (0);
214}
215
a2907882
KM
216/*
217 * Lock an nfsnode
218 */
219nfs_lock(vp)
220 struct vnode *vp;
221{
222 register struct nfsnode *np = VTONFS(vp);
223
a2907882
KM
224 while (np->n_flag & NLOCKED) {
225 np->n_flag |= NWANT;
90285725
KM
226 if (np->n_lockholder == u.u_procp->p_pid)
227 panic("locking against myself");
228 np->n_lockwaiter = u.u_procp->p_pid;
170bfd05 229 (void) tsleep((caddr_t)np, PINOD, "nfslock", 0);
a2907882 230 }
90285725
KM
231 np->n_lockwaiter = 0;
232 np->n_lockholder = u.u_procp->p_pid;
233 u.u_spare[0]++;
a2907882
KM
234 np->n_flag |= NLOCKED;
235}
236
237/*
238 * Unlock an nfsnode
239 */
240nfs_unlock(vp)
241 struct vnode *vp;
242{
243 register struct nfsnode *np = VTONFS(vp);
244
90285725
KM
245 if ((np->n_flag & NLOCKED) == 0)
246 vprint("nfs_unlock: unlocked nfsnode", vp);
247 np->n_lockholder = 0;
248 u.u_spare[0]--;
a2907882
KM
249 np->n_flag &= ~NLOCKED;
250 if (np->n_flag & NWANT) {
251 np->n_flag &= ~NWANT;
252 wakeup((caddr_t)np);
253 }
254}
255
226812f6
KM
256/*
257 * Check for a locked nfsnode
258 */
259nfs_islocked(vp)
260 struct vnode *vp;
261{
262
263 if (VTONFS(vp)->n_flag & NLOCKED)
264 return (1);
265 return (0);
266}
267
a2907882
KM
268/*
269 * Unlock and vrele()
270 * since I can't decide if dirs. should be locked, I will check for
271 * the lock and be flexible
272 */
273nfs_nput(vp)
274 struct vnode *vp;
275{
276 register struct nfsnode *np = VTONFS(vp);
277
278 if (np->n_flag & NLOCKED)
279 nfs_unlock(vp);
280 vrele(vp);
281}
282
66955caf
KM
283/*
284 * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
285 * done. Currently nothing to do.
286 */
287/* ARGSUSED */
a2907882 288nfs_abortop(ndp)
66955caf 289 struct nameidata *ndp;
a2907882 290{
a2907882 291
66955caf 292 return (0);
a2907882 293}