Commit | Line | Data |
---|---|---|
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 */ | |
27 | extern 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 | 36 | union 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 | */ | |
48 | nfs_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 | */ | |
66 | union nhead * | |
67 | nfs_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 | */ | |
87 | nfs_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 | 100 | loop: |
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 |
139 | nfs_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 | */ | |
195 | nfs_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 | */ | |
218 | nfs_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 | */ | |
238 | nfs_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 | */ | |
256 | nfs_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 | */ | |
270 | nfs_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 | 285 | nfs_abortop(ndp) |
66955caf | 286 | struct nameidata *ndp; |
a2907882 | 287 | { |
a2907882 | 288 | |
66955caf | 289 | return (0); |
a2907882 | 290 | } |