diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.c | 69 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 1 |
2 files changed, 67 insertions, 3 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index af3275965c77..debe2822c930 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
@@ -461,7 +461,6 @@ xfs_sync_worker( | |||
461 | error = xfs_fs_log_dummy(mp); | 461 | error = xfs_fs_log_dummy(mp); |
462 | else | 462 | else |
463 | xfs_log_force(mp, 0); | 463 | xfs_log_force(mp, 0); |
464 | xfs_reclaim_inodes(mp, 0); | ||
465 | error = xfs_qm_sync(mp, SYNC_TRYLOCK); | 464 | error = xfs_qm_sync(mp, SYNC_TRYLOCK); |
466 | } | 465 | } |
467 | 466 | ||
@@ -470,6 +469,52 @@ xfs_sync_worker( | |||
470 | } | 469 | } |
471 | 470 | ||
472 | /* | 471 | /* |
472 | * Queue a new inode reclaim pass if there are reclaimable inodes and there | ||
473 | * isn't a reclaim pass already in progress. By default it runs every 5s based | ||
474 | * on the xfs syncd work default of 30s. Perhaps this should have it's own | ||
475 | * tunable, but that can be done if this method proves to be ineffective or too | ||
476 | * aggressive. | ||
477 | */ | ||
478 | static void | ||
479 | xfs_syncd_queue_reclaim( | ||
480 | struct xfs_mount *mp) | ||
481 | { | ||
482 | |||
483 | /* | ||
484 | * We can have inodes enter reclaim after we've shut down the syncd | ||
485 | * workqueue during unmount, so don't allow reclaim work to be queued | ||
486 | * during unmount. | ||
487 | */ | ||
488 | if (!(mp->m_super->s_flags & MS_ACTIVE)) | ||
489 | return; | ||
490 | |||
491 | rcu_read_lock(); | ||
492 | if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) { | ||
493 | queue_delayed_work(xfs_syncd_wq, &mp->m_reclaim_work, | ||
494 | msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10)); | ||
495 | } | ||
496 | rcu_read_unlock(); | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | * This is a fast pass over the inode cache to try to get reclaim moving on as | ||
501 | * many inodes as possible in a short period of time. It kicks itself every few | ||
502 | * seconds, as well as being kicked by the inode cache shrinker when memory | ||
503 | * goes low. It scans as quickly as possible avoiding locked inodes or those | ||
504 | * already being flushed, and once done schedules a future pass. | ||
505 | */ | ||
506 | STATIC void | ||
507 | xfs_reclaim_worker( | ||
508 | struct work_struct *work) | ||
509 | { | ||
510 | struct xfs_mount *mp = container_of(to_delayed_work(work), | ||
511 | struct xfs_mount, m_reclaim_work); | ||
512 | |||
513 | xfs_reclaim_inodes(mp, SYNC_TRYLOCK); | ||
514 | xfs_syncd_queue_reclaim(mp); | ||
515 | } | ||
516 | |||
517 | /* | ||
473 | * Flush delayed allocate data, attempting to free up reserved space | 518 | * Flush delayed allocate data, attempting to free up reserved space |
474 | * from existing allocations. At this point a new allocation attempt | 519 | * from existing allocations. At this point a new allocation attempt |
475 | * has failed with ENOSPC and we are in the process of scratching our | 520 | * has failed with ENOSPC and we are in the process of scratching our |
@@ -508,7 +553,10 @@ xfs_syncd_init( | |||
508 | { | 553 | { |
509 | INIT_WORK(&mp->m_flush_work, xfs_flush_worker); | 554 | INIT_WORK(&mp->m_flush_work, xfs_flush_worker); |
510 | INIT_DELAYED_WORK(&mp->m_sync_work, xfs_sync_worker); | 555 | INIT_DELAYED_WORK(&mp->m_sync_work, xfs_sync_worker); |
556 | INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker); | ||
557 | |||
511 | xfs_syncd_queue_sync(mp); | 558 | xfs_syncd_queue_sync(mp); |
559 | xfs_syncd_queue_reclaim(mp); | ||
512 | 560 | ||
513 | return 0; | 561 | return 0; |
514 | } | 562 | } |
@@ -518,6 +566,7 @@ xfs_syncd_stop( | |||
518 | struct xfs_mount *mp) | 566 | struct xfs_mount *mp) |
519 | { | 567 | { |
520 | cancel_delayed_work_sync(&mp->m_sync_work); | 568 | cancel_delayed_work_sync(&mp->m_sync_work); |
569 | cancel_delayed_work_sync(&mp->m_reclaim_work); | ||
521 | cancel_work_sync(&mp->m_flush_work); | 570 | cancel_work_sync(&mp->m_flush_work); |
522 | } | 571 | } |
523 | 572 | ||
@@ -537,6 +586,10 @@ __xfs_inode_set_reclaim_tag( | |||
537 | XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), | 586 | XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), |
538 | XFS_ICI_RECLAIM_TAG); | 587 | XFS_ICI_RECLAIM_TAG); |
539 | spin_unlock(&ip->i_mount->m_perag_lock); | 588 | spin_unlock(&ip->i_mount->m_perag_lock); |
589 | |||
590 | /* schedule periodic background inode reclaim */ | ||
591 | xfs_syncd_queue_reclaim(ip->i_mount); | ||
592 | |||
540 | trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno, | 593 | trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno, |
541 | -1, _RET_IP_); | 594 | -1, _RET_IP_); |
542 | } | 595 | } |
@@ -953,7 +1006,13 @@ xfs_reclaim_inodes( | |||
953 | } | 1006 | } |
954 | 1007 | ||
955 | /* | 1008 | /* |
956 | * Shrinker infrastructure. | 1009 | * Inode cache shrinker. |
1010 | * | ||
1011 | * When called we make sure that there is a background (fast) inode reclaim in | ||
1012 | * progress, while we will throttle the speed of reclaim via doiing synchronous | ||
1013 | * reclaim of inodes. That means if we come across dirty inodes, we wait for | ||
1014 | * them to be cleaned, which we hope will not be very long due to the | ||
1015 | * background walker having already kicked the IO off on those dirty inodes. | ||
957 | */ | 1016 | */ |
958 | static int | 1017 | static int |
959 | xfs_reclaim_inode_shrink( | 1018 | xfs_reclaim_inode_shrink( |
@@ -968,10 +1027,14 @@ xfs_reclaim_inode_shrink( | |||
968 | 1027 | ||
969 | mp = container_of(shrink, struct xfs_mount, m_inode_shrink); | 1028 | mp = container_of(shrink, struct xfs_mount, m_inode_shrink); |
970 | if (nr_to_scan) { | 1029 | if (nr_to_scan) { |
1030 | /* kick background reclaimer */ | ||
1031 | xfs_syncd_queue_reclaim(mp); | ||
1032 | |||
971 | if (!(gfp_mask & __GFP_FS)) | 1033 | if (!(gfp_mask & __GFP_FS)) |
972 | return -1; | 1034 | return -1; |
973 | 1035 | ||
974 | xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK, &nr_to_scan); | 1036 | xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, |
1037 | &nr_to_scan); | ||
975 | /* terminate if we don't exhaust the scan */ | 1038 | /* terminate if we don't exhaust the scan */ |
976 | if (nr_to_scan > 0) | 1039 | if (nr_to_scan > 0) |
977 | return -1; | 1040 | return -1; |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a0ad90e95299..19af0ab0d0c6 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -204,6 +204,7 @@ typedef struct xfs_mount { | |||
204 | #endif | 204 | #endif |
205 | struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ | 205 | struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ |
206 | struct delayed_work m_sync_work; /* background sync work */ | 206 | struct delayed_work m_sync_work; /* background sync work */ |
207 | struct delayed_work m_reclaim_work; /* background inode reclaim */ | ||
207 | struct work_struct m_flush_work; /* background inode flush */ | 208 | struct work_struct m_flush_work; /* background inode flush */ |
208 | __int64_t m_update_flags; /* sb flags we need to update | 209 | __int64_t m_update_flags; /* sb flags we need to update |
209 | on the next remount,rw */ | 210 | on the next remount,rw */ |