diff options
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r-- | fs/xfs/xfs_icache.c | 58 |
1 files changed, 49 insertions, 9 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index d7a490f24ead..adbc1f59969a 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c | |||
@@ -210,14 +210,17 @@ xfs_iget_cache_hit( | |||
210 | 210 | ||
211 | error = inode_init_always(mp->m_super, inode); | 211 | error = inode_init_always(mp->m_super, inode); |
212 | if (error) { | 212 | if (error) { |
213 | bool wake; | ||
213 | /* | 214 | /* |
214 | * Re-initializing the inode failed, and we are in deep | 215 | * Re-initializing the inode failed, and we are in deep |
215 | * trouble. Try to re-add it to the reclaim list. | 216 | * trouble. Try to re-add it to the reclaim list. |
216 | */ | 217 | */ |
217 | rcu_read_lock(); | 218 | rcu_read_lock(); |
218 | spin_lock(&ip->i_flags_lock); | 219 | spin_lock(&ip->i_flags_lock); |
219 | 220 | wake = !!__xfs_iflags_test(ip, XFS_INEW); | |
220 | ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM); | 221 | ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM); |
222 | if (wake) | ||
223 | wake_up_bit(&ip->i_flags, __XFS_INEW_BIT); | ||
221 | ASSERT(ip->i_flags & XFS_IRECLAIMABLE); | 224 | ASSERT(ip->i_flags & XFS_IRECLAIMABLE); |
222 | trace_xfs_iget_reclaim_fail(ip); | 225 | trace_xfs_iget_reclaim_fail(ip); |
223 | goto out_error; | 226 | goto out_error; |
@@ -363,6 +366,22 @@ out_destroy: | |||
363 | return error; | 366 | return error; |
364 | } | 367 | } |
365 | 368 | ||
369 | static void | ||
370 | xfs_inew_wait( | ||
371 | struct xfs_inode *ip) | ||
372 | { | ||
373 | wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_INEW_BIT); | ||
374 | DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_INEW_BIT); | ||
375 | |||
376 | do { | ||
377 | prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE); | ||
378 | if (!xfs_iflags_test(ip, XFS_INEW)) | ||
379 | break; | ||
380 | schedule(); | ||
381 | } while (true); | ||
382 | finish_wait(wq, &wait.wait); | ||
383 | } | ||
384 | |||
366 | /* | 385 | /* |
367 | * Look up an inode by number in the given file system. | 386 | * Look up an inode by number in the given file system. |
368 | * The inode is looked up in the cache held in each AG. | 387 | * The inode is looked up in the cache held in each AG. |
@@ -467,9 +486,11 @@ out_error_or_again: | |||
467 | 486 | ||
468 | STATIC int | 487 | STATIC int |
469 | xfs_inode_ag_walk_grab( | 488 | xfs_inode_ag_walk_grab( |
470 | struct xfs_inode *ip) | 489 | struct xfs_inode *ip, |
490 | int flags) | ||
471 | { | 491 | { |
472 | struct inode *inode = VFS_I(ip); | 492 | struct inode *inode = VFS_I(ip); |
493 | bool newinos = !!(flags & XFS_AGITER_INEW_WAIT); | ||
473 | 494 | ||
474 | ASSERT(rcu_read_lock_held()); | 495 | ASSERT(rcu_read_lock_held()); |
475 | 496 | ||
@@ -487,7 +508,8 @@ xfs_inode_ag_walk_grab( | |||
487 | goto out_unlock_noent; | 508 | goto out_unlock_noent; |
488 | 509 | ||
489 | /* avoid new or reclaimable inodes. Leave for reclaim code to flush */ | 510 | /* avoid new or reclaimable inodes. Leave for reclaim code to flush */ |
490 | if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM)) | 511 | if ((!newinos && __xfs_iflags_test(ip, XFS_INEW)) || |
512 | __xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM)) | ||
491 | goto out_unlock_noent; | 513 | goto out_unlock_noent; |
492 | spin_unlock(&ip->i_flags_lock); | 514 | spin_unlock(&ip->i_flags_lock); |
493 | 515 | ||
@@ -515,7 +537,8 @@ xfs_inode_ag_walk( | |||
515 | void *args), | 537 | void *args), |
516 | int flags, | 538 | int flags, |
517 | void *args, | 539 | void *args, |
518 | int tag) | 540 | int tag, |
541 | int iter_flags) | ||
519 | { | 542 | { |
520 | uint32_t first_index; | 543 | uint32_t first_index; |
521 | int last_error = 0; | 544 | int last_error = 0; |
@@ -557,7 +580,7 @@ restart: | |||
557 | for (i = 0; i < nr_found; i++) { | 580 | for (i = 0; i < nr_found; i++) { |
558 | struct xfs_inode *ip = batch[i]; | 581 | struct xfs_inode *ip = batch[i]; |
559 | 582 | ||
560 | if (done || xfs_inode_ag_walk_grab(ip)) | 583 | if (done || xfs_inode_ag_walk_grab(ip, iter_flags)) |
561 | batch[i] = NULL; | 584 | batch[i] = NULL; |
562 | 585 | ||
563 | /* | 586 | /* |
@@ -585,6 +608,9 @@ restart: | |||
585 | for (i = 0; i < nr_found; i++) { | 608 | for (i = 0; i < nr_found; i++) { |
586 | if (!batch[i]) | 609 | if (!batch[i]) |
587 | continue; | 610 | continue; |
611 | if ((iter_flags & XFS_AGITER_INEW_WAIT) && | ||
612 | xfs_iflags_test(batch[i], XFS_INEW)) | ||
613 | xfs_inew_wait(batch[i]); | ||
588 | error = execute(batch[i], flags, args); | 614 | error = execute(batch[i], flags, args); |
589 | IRELE(batch[i]); | 615 | IRELE(batch[i]); |
590 | if (error == -EAGAIN) { | 616 | if (error == -EAGAIN) { |
@@ -637,12 +663,13 @@ xfs_eofblocks_worker( | |||
637 | } | 663 | } |
638 | 664 | ||
639 | int | 665 | int |
640 | xfs_inode_ag_iterator( | 666 | xfs_inode_ag_iterator_flags( |
641 | struct xfs_mount *mp, | 667 | struct xfs_mount *mp, |
642 | int (*execute)(struct xfs_inode *ip, int flags, | 668 | int (*execute)(struct xfs_inode *ip, int flags, |
643 | void *args), | 669 | void *args), |
644 | int flags, | 670 | int flags, |
645 | void *args) | 671 | void *args, |
672 | int iter_flags) | ||
646 | { | 673 | { |
647 | struct xfs_perag *pag; | 674 | struct xfs_perag *pag; |
648 | int error = 0; | 675 | int error = 0; |
@@ -652,7 +679,8 @@ xfs_inode_ag_iterator( | |||
652 | ag = 0; | 679 | ag = 0; |
653 | while ((pag = xfs_perag_get(mp, ag))) { | 680 | while ((pag = xfs_perag_get(mp, ag))) { |
654 | ag = pag->pag_agno + 1; | 681 | ag = pag->pag_agno + 1; |
655 | error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1); | 682 | error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1, |
683 | iter_flags); | ||
656 | xfs_perag_put(pag); | 684 | xfs_perag_put(pag); |
657 | if (error) { | 685 | if (error) { |
658 | last_error = error; | 686 | last_error = error; |
@@ -664,6 +692,17 @@ xfs_inode_ag_iterator( | |||
664 | } | 692 | } |
665 | 693 | ||
666 | int | 694 | int |
695 | xfs_inode_ag_iterator( | ||
696 | struct xfs_mount *mp, | ||
697 | int (*execute)(struct xfs_inode *ip, int flags, | ||
698 | void *args), | ||
699 | int flags, | ||
700 | void *args) | ||
701 | { | ||
702 | return xfs_inode_ag_iterator_flags(mp, execute, flags, args, 0); | ||
703 | } | ||
704 | |||
705 | int | ||
667 | xfs_inode_ag_iterator_tag( | 706 | xfs_inode_ag_iterator_tag( |
668 | struct xfs_mount *mp, | 707 | struct xfs_mount *mp, |
669 | int (*execute)(struct xfs_inode *ip, int flags, | 708 | int (*execute)(struct xfs_inode *ip, int flags, |
@@ -680,7 +719,8 @@ xfs_inode_ag_iterator_tag( | |||
680 | ag = 0; | 719 | ag = 0; |
681 | while ((pag = xfs_perag_get_tag(mp, ag, tag))) { | 720 | while ((pag = xfs_perag_get_tag(mp, ag, tag))) { |
682 | ag = pag->pag_agno + 1; | 721 | ag = pag->pag_agno + 1; |
683 | error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag); | 722 | error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag, |
723 | 0); | ||
684 | xfs_perag_put(pag); | 724 | xfs_perag_put(pag); |
685 | if (error) { | 725 | if (error) { |
686 | last_error = error; | 726 | last_error = error; |