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