diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_vnode.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.c | 251 |
1 files changed, 15 insertions, 236 deletions
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 250cad54e892..268f45bf6a9a 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c | |||
@@ -42,93 +42,33 @@ DEFINE_SPINLOCK(vnumber_lock); | |||
42 | */ | 42 | */ |
43 | #define NVSYNC 37 | 43 | #define NVSYNC 37 |
44 | #define vptosync(v) (&vsync[((unsigned long)v) % NVSYNC]) | 44 | #define vptosync(v) (&vsync[((unsigned long)v) % NVSYNC]) |
45 | sv_t vsync[NVSYNC]; | 45 | STATIC wait_queue_head_t vsync[NVSYNC]; |
46 | |||
47 | /* | ||
48 | * Translate stat(2) file types to vnode types and vice versa. | ||
49 | * Aware of numeric order of S_IFMT and vnode type values. | ||
50 | */ | ||
51 | enum vtype iftovt_tab[] = { | ||
52 | VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, | ||
53 | VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON | ||
54 | }; | ||
55 | |||
56 | u_short vttoif_tab[] = { | ||
57 | 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO, 0, S_IFSOCK | ||
58 | }; | ||
59 | 46 | ||
60 | 47 | ||
61 | void | 48 | void |
62 | vn_init(void) | 49 | vn_init(void) |
63 | { | 50 | { |
64 | register sv_t *svp; | 51 | int i; |
65 | register int i; | ||
66 | 52 | ||
67 | for (svp = vsync, i = 0; i < NVSYNC; i++, svp++) | 53 | for (i = 0; i < NVSYNC; i++) |
68 | init_sv(svp, SV_DEFAULT, "vsy", i); | 54 | init_waitqueue_head(&vsync[i]); |
69 | } | 55 | } |
70 | 56 | ||
71 | /* | 57 | void |
72 | * Clean a vnode of filesystem-specific data and prepare it for reuse. | 58 | vn_iowait( |
73 | */ | ||
74 | STATIC int | ||
75 | vn_reclaim( | ||
76 | struct vnode *vp) | 59 | struct vnode *vp) |
77 | { | 60 | { |
78 | int error; | 61 | wait_queue_head_t *wq = vptosync(vp); |
79 | 62 | ||
80 | XFS_STATS_INC(vn_reclaim); | 63 | wait_event(*wq, (atomic_read(&vp->v_iocount) == 0)); |
81 | vn_trace_entry(vp, "vn_reclaim", (inst_t *)__return_address); | ||
82 | |||
83 | /* | ||
84 | * Only make the VOP_RECLAIM call if there are behaviors | ||
85 | * to call. | ||
86 | */ | ||
87 | if (vp->v_fbhv) { | ||
88 | VOP_RECLAIM(vp, error); | ||
89 | if (error) | ||
90 | return -error; | ||
91 | } | ||
92 | ASSERT(vp->v_fbhv == NULL); | ||
93 | |||
94 | VN_LOCK(vp); | ||
95 | vp->v_flag &= (VRECLM|VWAIT); | ||
96 | VN_UNLOCK(vp, 0); | ||
97 | |||
98 | vp->v_type = VNON; | ||
99 | vp->v_fbhv = NULL; | ||
100 | |||
101 | #ifdef XFS_VNODE_TRACE | ||
102 | ktrace_free(vp->v_trace); | ||
103 | vp->v_trace = NULL; | ||
104 | #endif | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | STATIC void | ||
110 | vn_wakeup( | ||
111 | struct vnode *vp) | ||
112 | { | ||
113 | VN_LOCK(vp); | ||
114 | if (vp->v_flag & VWAIT) | ||
115 | sv_broadcast(vptosync(vp)); | ||
116 | vp->v_flag &= ~(VRECLM|VWAIT|VMODIFIED); | ||
117 | VN_UNLOCK(vp, 0); | ||
118 | } | 64 | } |
119 | 65 | ||
120 | int | 66 | void |
121 | vn_wait( | 67 | vn_iowake( |
122 | struct vnode *vp) | 68 | struct vnode *vp) |
123 | { | 69 | { |
124 | VN_LOCK(vp); | 70 | if (atomic_dec_and_test(&vp->v_iocount)) |
125 | if (vp->v_flag & (VINACT | VRECLM)) { | 71 | wake_up(vptosync(vp)); |
126 | vp->v_flag |= VWAIT; | ||
127 | sv_wait(vptosync(vp), PINOD, &vp->v_lock, 0); | ||
128 | return 1; | ||
129 | } | ||
130 | VN_UNLOCK(vp, 0); | ||
131 | return 0; | ||
132 | } | 72 | } |
133 | 73 | ||
134 | struct vnode * | 74 | struct vnode * |
@@ -154,6 +94,8 @@ vn_initialize( | |||
154 | /* Initialize the first behavior and the behavior chain head. */ | 94 | /* Initialize the first behavior and the behavior chain head. */ |
155 | vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode"); | 95 | vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode"); |
156 | 96 | ||
97 | atomic_set(&vp->v_iocount, 0); | ||
98 | |||
157 | #ifdef XFS_VNODE_TRACE | 99 | #ifdef XFS_VNODE_TRACE |
158 | vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP); | 100 | vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP); |
159 | #endif /* XFS_VNODE_TRACE */ | 101 | #endif /* XFS_VNODE_TRACE */ |
@@ -163,30 +105,6 @@ vn_initialize( | |||
163 | } | 105 | } |
164 | 106 | ||
165 | /* | 107 | /* |
166 | * Get a reference on a vnode. | ||
167 | */ | ||
168 | vnode_t * | ||
169 | vn_get( | ||
170 | struct vnode *vp, | ||
171 | vmap_t *vmap) | ||
172 | { | ||
173 | struct inode *inode; | ||
174 | |||
175 | XFS_STATS_INC(vn_get); | ||
176 | inode = LINVFS_GET_IP(vp); | ||
177 | if (inode->i_state & I_FREEING) | ||
178 | return NULL; | ||
179 | |||
180 | inode = ilookup(vmap->v_vfsp->vfs_super, vmap->v_ino); | ||
181 | if (!inode) /* Inode not present */ | ||
182 | return NULL; | ||
183 | |||
184 | vn_trace_exit(vp, "vn_get", (inst_t *)__return_address); | ||
185 | |||
186 | return vp; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Revalidate the Linux inode from the vattr. | 108 | * Revalidate the Linux inode from the vattr. |
191 | * Note: i_size _not_ updated; we must hold the inode | 109 | * Note: i_size _not_ updated; we must hold the inode |
192 | * semaphore when doing that - callers responsibility. | 110 | * semaphore when doing that - callers responsibility. |
@@ -198,7 +116,7 @@ vn_revalidate_core( | |||
198 | { | 116 | { |
199 | struct inode *inode = LINVFS_GET_IP(vp); | 117 | struct inode *inode = LINVFS_GET_IP(vp); |
200 | 118 | ||
201 | inode->i_mode = VTTOIF(vap->va_type) | vap->va_mode; | 119 | inode->i_mode = vap->va_mode; |
202 | inode->i_nlink = vap->va_nlink; | 120 | inode->i_nlink = vap->va_nlink; |
203 | inode->i_uid = vap->va_uid; | 121 | inode->i_uid = vap->va_uid; |
204 | inode->i_gid = vap->va_gid; | 122 | inode->i_gid = vap->va_gid; |
@@ -247,71 +165,6 @@ vn_revalidate( | |||
247 | } | 165 | } |
248 | 166 | ||
249 | /* | 167 | /* |
250 | * purge a vnode from the cache | ||
251 | * At this point the vnode is guaranteed to have no references (vn_count == 0) | ||
252 | * The caller has to make sure that there are no ways someone could | ||
253 | * get a handle (via vn_get) on the vnode (usually done via a mount/vfs lock). | ||
254 | */ | ||
255 | void | ||
256 | vn_purge( | ||
257 | struct vnode *vp, | ||
258 | vmap_t *vmap) | ||
259 | { | ||
260 | vn_trace_entry(vp, "vn_purge", (inst_t *)__return_address); | ||
261 | |||
262 | again: | ||
263 | /* | ||
264 | * Check whether vp has already been reclaimed since our caller | ||
265 | * sampled its version while holding a filesystem cache lock that | ||
266 | * its VOP_RECLAIM function acquires. | ||
267 | */ | ||
268 | VN_LOCK(vp); | ||
269 | if (vp->v_number != vmap->v_number) { | ||
270 | VN_UNLOCK(vp, 0); | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * If vp is being reclaimed or inactivated, wait until it is inert, | ||
276 | * then proceed. Can't assume that vnode is actually reclaimed | ||
277 | * just because the reclaimed flag is asserted -- a vn_alloc | ||
278 | * reclaim can fail. | ||
279 | */ | ||
280 | if (vp->v_flag & (VINACT | VRECLM)) { | ||
281 | ASSERT(vn_count(vp) == 0); | ||
282 | vp->v_flag |= VWAIT; | ||
283 | sv_wait(vptosync(vp), PINOD, &vp->v_lock, 0); | ||
284 | goto again; | ||
285 | } | ||
286 | |||
287 | /* | ||
288 | * Another process could have raced in and gotten this vnode... | ||
289 | */ | ||
290 | if (vn_count(vp) > 0) { | ||
291 | VN_UNLOCK(vp, 0); | ||
292 | return; | ||
293 | } | ||
294 | |||
295 | XFS_STATS_DEC(vn_active); | ||
296 | vp->v_flag |= VRECLM; | ||
297 | VN_UNLOCK(vp, 0); | ||
298 | |||
299 | /* | ||
300 | * Call VOP_RECLAIM and clean vp. The FSYNC_INVAL flag tells | ||
301 | * vp's filesystem to flush and invalidate all cached resources. | ||
302 | * When vn_reclaim returns, vp should have no private data, | ||
303 | * either in a system cache or attached to v_data. | ||
304 | */ | ||
305 | if (vn_reclaim(vp) != 0) | ||
306 | panic("vn_purge: cannot reclaim"); | ||
307 | |||
308 | /* | ||
309 | * Wakeup anyone waiting for vp to be reclaimed. | ||
310 | */ | ||
311 | vn_wakeup(vp); | ||
312 | } | ||
313 | |||
314 | /* | ||
315 | * Add a reference to a referenced vnode. | 168 | * Add a reference to a referenced vnode. |
316 | */ | 169 | */ |
317 | struct vnode * | 170 | struct vnode * |
@@ -330,80 +183,6 @@ vn_hold( | |||
330 | return vp; | 183 | return vp; |
331 | } | 184 | } |
332 | 185 | ||
333 | /* | ||
334 | * Call VOP_INACTIVE on last reference. | ||
335 | */ | ||
336 | void | ||
337 | vn_rele( | ||
338 | struct vnode *vp) | ||
339 | { | ||
340 | int vcnt; | ||
341 | int cache; | ||
342 | |||
343 | XFS_STATS_INC(vn_rele); | ||
344 | |||
345 | VN_LOCK(vp); | ||
346 | |||
347 | vn_trace_entry(vp, "vn_rele", (inst_t *)__return_address); | ||
348 | vcnt = vn_count(vp); | ||
349 | |||
350 | /* | ||
351 | * Since we always get called from put_inode we know | ||
352 | * that i_count won't be decremented after we | ||
353 | * return. | ||
354 | */ | ||
355 | if (!vcnt) { | ||
356 | /* | ||
357 | * As soon as we turn this on, noone can find us in vn_get | ||
358 | * until we turn off VINACT or VRECLM | ||
359 | */ | ||
360 | vp->v_flag |= VINACT; | ||
361 | VN_UNLOCK(vp, 0); | ||
362 | |||
363 | /* | ||
364 | * Do not make the VOP_INACTIVE call if there | ||
365 | * are no behaviors attached to the vnode to call. | ||
366 | */ | ||
367 | if (vp->v_fbhv) | ||
368 | VOP_INACTIVE(vp, NULL, cache); | ||
369 | |||
370 | VN_LOCK(vp); | ||
371 | if (vp->v_flag & VWAIT) | ||
372 | sv_broadcast(vptosync(vp)); | ||
373 | |||
374 | vp->v_flag &= ~(VINACT|VWAIT|VRECLM|VMODIFIED); | ||
375 | } | ||
376 | |||
377 | VN_UNLOCK(vp, 0); | ||
378 | |||
379 | vn_trace_exit(vp, "vn_rele", (inst_t *)__return_address); | ||
380 | } | ||
381 | |||
382 | /* | ||
383 | * Finish the removal of a vnode. | ||
384 | */ | ||
385 | void | ||
386 | vn_remove( | ||
387 | struct vnode *vp) | ||
388 | { | ||
389 | vmap_t vmap; | ||
390 | |||
391 | /* Make sure we don't do this to the same vnode twice */ | ||
392 | if (!(vp->v_fbhv)) | ||
393 | return; | ||
394 | |||
395 | XFS_STATS_INC(vn_remove); | ||
396 | vn_trace_exit(vp, "vn_remove", (inst_t *)__return_address); | ||
397 | |||
398 | /* | ||
399 | * After the following purge the vnode | ||
400 | * will no longer exist. | ||
401 | */ | ||
402 | VMAP(vp, vmap); | ||
403 | vn_purge(vp, &vmap); | ||
404 | } | ||
405 | |||
406 | |||
407 | #ifdef XFS_VNODE_TRACE | 186 | #ifdef XFS_VNODE_TRACE |
408 | 187 | ||
409 | #define KTRACE_ENTER(vp, vk, s, line, ra) \ | 188 | #define KTRACE_ENTER(vp, vk, s, line, ra) \ |