diff options
Diffstat (limited to 'fs/xfs/xfs_iget.c')
-rw-r--r-- | fs/xfs/xfs_iget.c | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index b73d216ecaf9..c1c89dac19cc 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -215,7 +215,7 @@ again: | |||
215 | * If INEW is set this inode is being set up | 215 | * If INEW is set this inode is being set up |
216 | * we need to pause and try again. | 216 | * we need to pause and try again. |
217 | */ | 217 | */ |
218 | if (ip->i_flags & XFS_INEW) { | 218 | if (xfs_iflags_test(ip, XFS_INEW)) { |
219 | read_unlock(&ih->ih_lock); | 219 | read_unlock(&ih->ih_lock); |
220 | delay(1); | 220 | delay(1); |
221 | XFS_STATS_INC(xs_ig_frecycle); | 221 | XFS_STATS_INC(xs_ig_frecycle); |
@@ -230,22 +230,50 @@ again: | |||
230 | * on its way out of the system, | 230 | * on its way out of the system, |
231 | * we need to pause and try again. | 231 | * we need to pause and try again. |
232 | */ | 232 | */ |
233 | if (ip->i_flags & XFS_IRECLAIM) { | 233 | if (xfs_iflags_test(ip, XFS_IRECLAIM)) { |
234 | read_unlock(&ih->ih_lock); | 234 | read_unlock(&ih->ih_lock); |
235 | delay(1); | 235 | delay(1); |
236 | XFS_STATS_INC(xs_ig_frecycle); | 236 | XFS_STATS_INC(xs_ig_frecycle); |
237 | 237 | ||
238 | goto again; | 238 | goto again; |
239 | } | 239 | } |
240 | ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE)); | ||
241 | |||
242 | /* | ||
243 | * If lookup is racing with unlink, then we | ||
244 | * should return an error immediately so we | ||
245 | * don't remove it from the reclaim list and | ||
246 | * potentially leak the inode. | ||
247 | */ | ||
248 | if ((ip->i_d.di_mode == 0) && | ||
249 | !(flags & XFS_IGET_CREATE)) { | ||
250 | read_unlock(&ih->ih_lock); | ||
251 | return ENOENT; | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * There may be transactions sitting in the | ||
256 | * incore log buffers or being flushed to disk | ||
257 | * at this time. We can't clear the | ||
258 | * XFS_IRECLAIMABLE flag until these | ||
259 | * transactions have hit the disk, otherwise we | ||
260 | * will void the guarantee the flag provides | ||
261 | * xfs_iunpin() | ||
262 | */ | ||
263 | if (xfs_ipincount(ip)) { | ||
264 | read_unlock(&ih->ih_lock); | ||
265 | xfs_log_force(mp, 0, | ||
266 | XFS_LOG_FORCE|XFS_LOG_SYNC); | ||
267 | XFS_STATS_INC(xs_ig_frecycle); | ||
268 | goto again; | ||
269 | } | ||
240 | 270 | ||
241 | vn_trace_exit(vp, "xfs_iget.alloc", | 271 | vn_trace_exit(vp, "xfs_iget.alloc", |
242 | (inst_t *)__return_address); | 272 | (inst_t *)__return_address); |
243 | 273 | ||
244 | XFS_STATS_INC(xs_ig_found); | 274 | XFS_STATS_INC(xs_ig_found); |
245 | 275 | ||
246 | spin_lock(&ip->i_flags_lock); | 276 | xfs_iflags_clear(ip, XFS_IRECLAIMABLE); |
247 | ip->i_flags &= ~XFS_IRECLAIMABLE; | ||
248 | spin_unlock(&ip->i_flags_lock); | ||
249 | version = ih->ih_version; | 277 | version = ih->ih_version; |
250 | read_unlock(&ih->ih_lock); | 278 | read_unlock(&ih->ih_lock); |
251 | xfs_ihash_promote(ih, ip, version); | 279 | xfs_ihash_promote(ih, ip, version); |
@@ -299,10 +327,7 @@ finish_inode: | |||
299 | if (lock_flags != 0) | 327 | if (lock_flags != 0) |
300 | xfs_ilock(ip, lock_flags); | 328 | xfs_ilock(ip, lock_flags); |
301 | 329 | ||
302 | spin_lock(&ip->i_flags_lock); | 330 | xfs_iflags_clear(ip, XFS_ISTALE); |
303 | ip->i_flags &= ~XFS_ISTALE; | ||
304 | spin_unlock(&ip->i_flags_lock); | ||
305 | |||
306 | vn_trace_exit(vp, "xfs_iget.found", | 331 | vn_trace_exit(vp, "xfs_iget.found", |
307 | (inst_t *)__return_address); | 332 | (inst_t *)__return_address); |
308 | goto return_ip; | 333 | goto return_ip; |
@@ -371,10 +396,7 @@ finish_inode: | |||
371 | ih->ih_next = ip; | 396 | ih->ih_next = ip; |
372 | ip->i_udquot = ip->i_gdquot = NULL; | 397 | ip->i_udquot = ip->i_gdquot = NULL; |
373 | ih->ih_version++; | 398 | ih->ih_version++; |
374 | spin_lock(&ip->i_flags_lock); | 399 | xfs_iflags_set(ip, XFS_INEW); |
375 | ip->i_flags |= XFS_INEW; | ||
376 | spin_unlock(&ip->i_flags_lock); | ||
377 | |||
378 | write_unlock(&ih->ih_lock); | 400 | write_unlock(&ih->ih_lock); |
379 | 401 | ||
380 | /* | 402 | /* |
@@ -625,7 +647,7 @@ xfs_iput_new(xfs_inode_t *ip, | |||
625 | vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); | 647 | vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); |
626 | 648 | ||
627 | if ((ip->i_d.di_mode == 0)) { | 649 | if ((ip->i_d.di_mode == 0)) { |
628 | ASSERT(!(ip->i_flags & XFS_IRECLAIMABLE)); | 650 | ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE)); |
629 | vn_mark_bad(vp); | 651 | vn_mark_bad(vp); |
630 | } | 652 | } |
631 | if (inode->i_state & I_NEW) | 653 | if (inode->i_state & I_NEW) |
@@ -683,6 +705,7 @@ xfs_ireclaim(xfs_inode_t *ip) | |||
683 | /* | 705 | /* |
684 | * Free all memory associated with the inode. | 706 | * Free all memory associated with the inode. |
685 | */ | 707 | */ |
708 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
686 | xfs_idestroy(ip); | 709 | xfs_idestroy(ip); |
687 | } | 710 | } |
688 | 711 | ||