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 | * |
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 */ | |
28 | extern 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 | 37 | union 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 | */ | |
49 | nfs_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 | */ | |
67 | union nhead * | |
68 | nfs_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 | */ | |
88 | nfs_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 | 101 | loop: |
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 |
140 | nfs_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 | */ | |
196 | nfs_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 | */ | |
219 | nfs_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 | */ | |
240 | nfs_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 | */ | |
259 | nfs_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 | */ | |
273 | nfs_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 | 288 | nfs_abortop(ndp) |
66955caf | 289 | struct nameidata *ndp; |
a2907882 | 290 | { |
a2907882 | 291 | |
66955caf | 292 | return (0); |
a2907882 | 293 | } |