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