diff options
Diffstat (limited to 'fs/xfs/xfs_iget.c')
-rw-r--r-- | fs/xfs/xfs_iget.c | 185 |
1 files changed, 73 insertions, 112 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index fb69ef180b2..f01b07687fa 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -65,7 +65,7 @@ | |||
65 | */ | 65 | */ |
66 | STATIC int | 66 | STATIC int |
67 | xfs_iget_core( | 67 | xfs_iget_core( |
68 | bhv_vnode_t *vp, | 68 | struct inode *inode, |
69 | xfs_mount_t *mp, | 69 | xfs_mount_t *mp, |
70 | xfs_trans_t *tp, | 70 | xfs_trans_t *tp, |
71 | xfs_ino_t ino, | 71 | xfs_ino_t ino, |
@@ -74,9 +74,9 @@ xfs_iget_core( | |||
74 | xfs_inode_t **ipp, | 74 | xfs_inode_t **ipp, |
75 | xfs_daddr_t bno) | 75 | xfs_daddr_t bno) |
76 | { | 76 | { |
77 | struct inode *old_inode; | ||
77 | xfs_inode_t *ip; | 78 | xfs_inode_t *ip; |
78 | xfs_inode_t *iq; | 79 | xfs_inode_t *iq; |
79 | bhv_vnode_t *inode_vp; | ||
80 | int error; | 80 | int error; |
81 | xfs_icluster_t *icl, *new_icl = NULL; | 81 | xfs_icluster_t *icl, *new_icl = NULL; |
82 | unsigned long first_index, mask; | 82 | unsigned long first_index, mask; |
@@ -111,8 +111,8 @@ again: | |||
111 | goto again; | 111 | goto again; |
112 | } | 112 | } |
113 | 113 | ||
114 | inode_vp = XFS_ITOV_NULL(ip); | 114 | old_inode = ip->i_vnode; |
115 | if (inode_vp == NULL) { | 115 | if (old_inode == NULL) { |
116 | /* | 116 | /* |
117 | * If IRECLAIM is set this inode is | 117 | * If IRECLAIM is set this inode is |
118 | * on its way out of the system, | 118 | * on its way out of the system, |
@@ -140,28 +140,9 @@ again: | |||
140 | return ENOENT; | 140 | return ENOENT; |
141 | } | 141 | } |
142 | 142 | ||
143 | /* | 143 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); |
144 | * There may be transactions sitting in the | ||
145 | * incore log buffers or being flushed to disk | ||
146 | * at this time. We can't clear the | ||
147 | * XFS_IRECLAIMABLE flag until these | ||
148 | * transactions have hit the disk, otherwise we | ||
149 | * will void the guarantee the flag provides | ||
150 | * xfs_iunpin() | ||
151 | */ | ||
152 | if (xfs_ipincount(ip)) { | ||
153 | read_unlock(&pag->pag_ici_lock); | ||
154 | xfs_log_force(mp, 0, | ||
155 | XFS_LOG_FORCE|XFS_LOG_SYNC); | ||
156 | XFS_STATS_INC(xs_ig_frecycle); | ||
157 | goto again; | ||
158 | } | ||
159 | |||
160 | vn_trace_exit(ip, "xfs_iget.alloc", | ||
161 | (inst_t *)__return_address); | ||
162 | 144 | ||
163 | XFS_STATS_INC(xs_ig_found); | 145 | XFS_STATS_INC(xs_ig_found); |
164 | |||
165 | xfs_iflags_clear(ip, XFS_IRECLAIMABLE); | 146 | xfs_iflags_clear(ip, XFS_IRECLAIMABLE); |
166 | read_unlock(&pag->pag_ici_lock); | 147 | read_unlock(&pag->pag_ici_lock); |
167 | 148 | ||
@@ -171,13 +152,11 @@ again: | |||
171 | 152 | ||
172 | goto finish_inode; | 153 | goto finish_inode; |
173 | 154 | ||
174 | } else if (vp != inode_vp) { | 155 | } else if (inode != old_inode) { |
175 | struct inode *inode = vn_to_inode(inode_vp); | ||
176 | |||
177 | /* The inode is being torn down, pause and | 156 | /* The inode is being torn down, pause and |
178 | * try again. | 157 | * try again. |
179 | */ | 158 | */ |
180 | if (inode->i_state & (I_FREEING | I_CLEAR)) { | 159 | if (old_inode->i_state & (I_FREEING | I_CLEAR)) { |
181 | read_unlock(&pag->pag_ici_lock); | 160 | read_unlock(&pag->pag_ici_lock); |
182 | delay(1); | 161 | delay(1); |
183 | XFS_STATS_INC(xs_ig_frecycle); | 162 | XFS_STATS_INC(xs_ig_frecycle); |
@@ -190,7 +169,7 @@ again: | |||
190 | */ | 169 | */ |
191 | cmn_err(CE_PANIC, | 170 | cmn_err(CE_PANIC, |
192 | "xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p", | 171 | "xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p", |
193 | inode_vp, vp); | 172 | old_inode, inode); |
194 | } | 173 | } |
195 | 174 | ||
196 | /* | 175 | /* |
@@ -200,20 +179,16 @@ again: | |||
200 | XFS_STATS_INC(xs_ig_found); | 179 | XFS_STATS_INC(xs_ig_found); |
201 | 180 | ||
202 | finish_inode: | 181 | finish_inode: |
203 | if (ip->i_d.di_mode == 0) { | 182 | if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) { |
204 | if (!(flags & XFS_IGET_CREATE)) { | 183 | xfs_put_perag(mp, pag); |
205 | xfs_put_perag(mp, pag); | 184 | return ENOENT; |
206 | return ENOENT; | ||
207 | } | ||
208 | xfs_iocore_inode_reinit(ip); | ||
209 | } | 185 | } |
210 | 186 | ||
211 | if (lock_flags != 0) | 187 | if (lock_flags != 0) |
212 | xfs_ilock(ip, lock_flags); | 188 | xfs_ilock(ip, lock_flags); |
213 | 189 | ||
214 | xfs_iflags_clear(ip, XFS_ISTALE); | 190 | xfs_iflags_clear(ip, XFS_ISTALE); |
215 | vn_trace_exit(ip, "xfs_iget.found", | 191 | xfs_itrace_exit_tag(ip, "xfs_iget.found"); |
216 | (inst_t *)__return_address); | ||
217 | goto return_ip; | 192 | goto return_ip; |
218 | } | 193 | } |
219 | 194 | ||
@@ -234,10 +209,16 @@ finish_inode: | |||
234 | return error; | 209 | return error; |
235 | } | 210 | } |
236 | 211 | ||
237 | vn_trace_exit(ip, "xfs_iget.alloc", (inst_t *)__return_address); | 212 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); |
213 | |||
214 | |||
215 | mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, | ||
216 | "xfsino", ip->i_ino); | ||
217 | mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); | ||
218 | init_waitqueue_head(&ip->i_ipin_wait); | ||
219 | atomic_set(&ip->i_pincount, 0); | ||
220 | initnsema(&ip->i_flock, 1, "xfsfino"); | ||
238 | 221 | ||
239 | xfs_inode_lock_init(ip, vp); | ||
240 | xfs_iocore_inode_init(ip); | ||
241 | if (lock_flags) | 222 | if (lock_flags) |
242 | xfs_ilock(ip, lock_flags); | 223 | xfs_ilock(ip, lock_flags); |
243 | 224 | ||
@@ -333,9 +314,6 @@ finish_inode: | |||
333 | ASSERT(ip->i_df.if_ext_max == | 314 | ASSERT(ip->i_df.if_ext_max == |
334 | XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t)); | 315 | XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t)); |
335 | 316 | ||
336 | ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) == | ||
337 | ((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0)); | ||
338 | |||
339 | xfs_iflags_set(ip, XFS_IMODIFIED); | 317 | xfs_iflags_set(ip, XFS_IMODIFIED); |
340 | *ipp = ip; | 318 | *ipp = ip; |
341 | 319 | ||
@@ -343,7 +321,7 @@ finish_inode: | |||
343 | * If we have a real type for an on-disk inode, we can set ops(&unlock) | 321 | * If we have a real type for an on-disk inode, we can set ops(&unlock) |
344 | * now. If it's a new inode being created, xfs_ialloc will handle it. | 322 | * now. If it's a new inode being created, xfs_ialloc will handle it. |
345 | */ | 323 | */ |
346 | xfs_initialize_vnode(mp, vp, ip); | 324 | xfs_initialize_vnode(mp, inode, ip); |
347 | return 0; | 325 | return 0; |
348 | } | 326 | } |
349 | 327 | ||
@@ -363,69 +341,58 @@ xfs_iget( | |||
363 | xfs_daddr_t bno) | 341 | xfs_daddr_t bno) |
364 | { | 342 | { |
365 | struct inode *inode; | 343 | struct inode *inode; |
366 | bhv_vnode_t *vp = NULL; | 344 | xfs_inode_t *ip; |
367 | int error; | 345 | int error; |
368 | 346 | ||
369 | XFS_STATS_INC(xs_ig_attempts); | 347 | XFS_STATS_INC(xs_ig_attempts); |
370 | 348 | ||
371 | retry: | 349 | retry: |
372 | inode = iget_locked(mp->m_super, ino); | 350 | inode = iget_locked(mp->m_super, ino); |
373 | if (inode) { | 351 | if (!inode) |
374 | xfs_inode_t *ip; | 352 | /* If we got no inode we are out of memory */ |
375 | 353 | return ENOMEM; | |
376 | vp = vn_from_inode(inode); | 354 | |
377 | if (inode->i_state & I_NEW) { | 355 | if (inode->i_state & I_NEW) { |
378 | vn_initialize(inode); | 356 | XFS_STATS_INC(vn_active); |
379 | error = xfs_iget_core(vp, mp, tp, ino, flags, | 357 | XFS_STATS_INC(vn_alloc); |
380 | lock_flags, ipp, bno); | 358 | |
381 | if (error) { | 359 | error = xfs_iget_core(inode, mp, tp, ino, flags, |
382 | vn_mark_bad(vp); | 360 | lock_flags, ipp, bno); |
383 | if (inode->i_state & I_NEW) | 361 | if (error) { |
384 | unlock_new_inode(inode); | 362 | make_bad_inode(inode); |
385 | iput(inode); | 363 | if (inode->i_state & I_NEW) |
386 | } | 364 | unlock_new_inode(inode); |
387 | } else { | 365 | iput(inode); |
388 | /* | ||
389 | * If the inode is not fully constructed due to | ||
390 | * filehandle mismatches wait for the inode to go | ||
391 | * away and try again. | ||
392 | * | ||
393 | * iget_locked will call __wait_on_freeing_inode | ||
394 | * to wait for the inode to go away. | ||
395 | */ | ||
396 | if (is_bad_inode(inode) || | ||
397 | ((ip = xfs_vtoi(vp)) == NULL)) { | ||
398 | iput(inode); | ||
399 | delay(1); | ||
400 | goto retry; | ||
401 | } | ||
402 | |||
403 | if (lock_flags != 0) | ||
404 | xfs_ilock(ip, lock_flags); | ||
405 | XFS_STATS_INC(xs_ig_found); | ||
406 | *ipp = ip; | ||
407 | error = 0; | ||
408 | } | 366 | } |
409 | } else | 367 | return error; |
410 | error = ENOMEM; /* If we got no inode we are out of memory */ | 368 | } |
411 | 369 | ||
412 | return error; | 370 | /* |
413 | } | 371 | * If the inode is not fully constructed due to |
372 | * filehandle mismatches wait for the inode to go | ||
373 | * away and try again. | ||
374 | * | ||
375 | * iget_locked will call __wait_on_freeing_inode | ||
376 | * to wait for the inode to go away. | ||
377 | */ | ||
378 | if (is_bad_inode(inode)) { | ||
379 | iput(inode); | ||
380 | delay(1); | ||
381 | goto retry; | ||
382 | } | ||
414 | 383 | ||
415 | /* | 384 | ip = XFS_I(inode); |
416 | * Do the setup for the various locks within the incore inode. | 385 | if (!ip) { |
417 | */ | 386 | iput(inode); |
418 | void | 387 | delay(1); |
419 | xfs_inode_lock_init( | 388 | goto retry; |
420 | xfs_inode_t *ip, | 389 | } |
421 | bhv_vnode_t *vp) | 390 | |
422 | { | 391 | if (lock_flags != 0) |
423 | mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, | 392 | xfs_ilock(ip, lock_flags); |
424 | "xfsino", ip->i_ino); | 393 | XFS_STATS_INC(xs_ig_found); |
425 | mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); | 394 | *ipp = ip; |
426 | init_waitqueue_head(&ip->i_ipin_wait); | 395 | return 0; |
427 | atomic_set(&ip->i_pincount, 0); | ||
428 | initnsema(&ip->i_flock, 1, "xfsfino"); | ||
429 | } | 396 | } |
430 | 397 | ||
431 | /* | 398 | /* |
@@ -465,11 +432,9 @@ void | |||
465 | xfs_iput(xfs_inode_t *ip, | 432 | xfs_iput(xfs_inode_t *ip, |
466 | uint lock_flags) | 433 | uint lock_flags) |
467 | { | 434 | { |
468 | bhv_vnode_t *vp = XFS_ITOV(ip); | 435 | xfs_itrace_entry(ip); |
469 | |||
470 | vn_trace_entry(ip, "xfs_iput", (inst_t *)__return_address); | ||
471 | xfs_iunlock(ip, lock_flags); | 436 | xfs_iunlock(ip, lock_flags); |
472 | VN_RELE(vp); | 437 | IRELE(ip); |
473 | } | 438 | } |
474 | 439 | ||
475 | /* | 440 | /* |
@@ -479,20 +444,19 @@ void | |||
479 | xfs_iput_new(xfs_inode_t *ip, | 444 | xfs_iput_new(xfs_inode_t *ip, |
480 | uint lock_flags) | 445 | uint lock_flags) |
481 | { | 446 | { |
482 | bhv_vnode_t *vp = XFS_ITOV(ip); | 447 | struct inode *inode = ip->i_vnode; |
483 | struct inode *inode = vn_to_inode(vp); | ||
484 | 448 | ||
485 | vn_trace_entry(ip, "xfs_iput_new", (inst_t *)__return_address); | 449 | xfs_itrace_entry(ip); |
486 | 450 | ||
487 | if ((ip->i_d.di_mode == 0)) { | 451 | if ((ip->i_d.di_mode == 0)) { |
488 | ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE)); | 452 | ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE)); |
489 | vn_mark_bad(vp); | 453 | make_bad_inode(inode); |
490 | } | 454 | } |
491 | if (inode->i_state & I_NEW) | 455 | if (inode->i_state & I_NEW) |
492 | unlock_new_inode(inode); | 456 | unlock_new_inode(inode); |
493 | if (lock_flags) | 457 | if (lock_flags) |
494 | xfs_iunlock(ip, lock_flags); | 458 | xfs_iunlock(ip, lock_flags); |
495 | VN_RELE(vp); | 459 | IRELE(ip); |
496 | } | 460 | } |
497 | 461 | ||
498 | 462 | ||
@@ -505,8 +469,6 @@ xfs_iput_new(xfs_inode_t *ip, | |||
505 | void | 469 | void |
506 | xfs_ireclaim(xfs_inode_t *ip) | 470 | xfs_ireclaim(xfs_inode_t *ip) |
507 | { | 471 | { |
508 | bhv_vnode_t *vp; | ||
509 | |||
510 | /* | 472 | /* |
511 | * Remove from old hash list and mount list. | 473 | * Remove from old hash list and mount list. |
512 | */ | 474 | */ |
@@ -535,9 +497,8 @@ xfs_ireclaim(xfs_inode_t *ip) | |||
535 | /* | 497 | /* |
536 | * Pull our behavior descriptor from the vnode chain. | 498 | * Pull our behavior descriptor from the vnode chain. |
537 | */ | 499 | */ |
538 | vp = XFS_ITOV_NULL(ip); | 500 | if (ip->i_vnode) { |
539 | if (vp) { | 501 | ip->i_vnode->i_private = NULL; |
540 | vn_to_inode(vp)->i_private = NULL; | ||
541 | ip->i_vnode = NULL; | 502 | ip->i_vnode = NULL; |
542 | } | 503 | } |
543 | 504 | ||