aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r--fs/xfs/xfs_icache.c58
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
369static void
370xfs_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
468STATIC int 487STATIC int
469xfs_inode_ag_walk_grab( 488xfs_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
639int 665int
640xfs_inode_ag_iterator( 666xfs_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
666int 694int
695xfs_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
705int
667xfs_inode_ag_iterator_tag( 706xfs_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;