diff options
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 30 | ||||
-rw-r--r-- | fs/xfs/xfs_super.c | 3 |
2 files changed, 23 insertions, 10 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index f05c6c99c4f3..508319039dce 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -5024,16 +5024,27 @@ xlog_recover_process_one_iunlink( | |||
5024 | } | 5024 | } |
5025 | 5025 | ||
5026 | /* | 5026 | /* |
5027 | * xlog_iunlink_recover | 5027 | * Recover AGI unlinked lists |
5028 | * | 5028 | * |
5029 | * This is called during recovery to process any inodes which | 5029 | * This is called during recovery to process any inodes which we unlinked but |
5030 | * we unlinked but not freed when the system crashed. These | 5030 | * not freed when the system crashed. These inodes will be on the lists in the |
5031 | * inodes will be on the lists in the AGI blocks. What we do | 5031 | * AGI blocks. What we do here is scan all the AGIs and fully truncate and free |
5032 | * here is scan all the AGIs and fully truncate and free any | 5032 | * any inodes found on the lists. Each inode is removed from the lists when it |
5033 | * inodes found on the lists. Each inode is removed from the | 5033 | * has been fully truncated and is freed. The freeing of the inode and its |
5034 | * lists when it has been fully truncated and is freed. The | 5034 | * removal from the list must be atomic. |
5035 | * freeing of the inode and its removal from the list must be | 5035 | * |
5036 | * atomic. | 5036 | * If everything we touch in the agi processing loop is already in memory, this |
5037 | * loop can hold the cpu for a long time. It runs without lock contention, | ||
5038 | * memory allocation contention, the need wait for IO, etc, and so will run | ||
5039 | * until we either run out of inodes to process, run low on memory or we run out | ||
5040 | * of log space. | ||
5041 | * | ||
5042 | * This behaviour is bad for latency on single CPU and non-preemptible kernels, | ||
5043 | * and can prevent other filesytem work (such as CIL pushes) from running. This | ||
5044 | * can lead to deadlocks if the recovery process runs out of log reservation | ||
5045 | * space. Hence we need to yield the CPU when there is other kernel work | ||
5046 | * scheduled on this CPU to ensure other scheduled work can run without undue | ||
5047 | * latency. | ||
5037 | */ | 5048 | */ |
5038 | STATIC void | 5049 | STATIC void |
5039 | xlog_recover_process_iunlinks( | 5050 | xlog_recover_process_iunlinks( |
@@ -5080,6 +5091,7 @@ xlog_recover_process_iunlinks( | |||
5080 | while (agino != NULLAGINO) { | 5091 | while (agino != NULLAGINO) { |
5081 | agino = xlog_recover_process_one_iunlink(mp, | 5092 | agino = xlog_recover_process_one_iunlink(mp, |
5082 | agno, agino, bucket); | 5093 | agno, agino, bucket); |
5094 | cond_resched(); | ||
5083 | } | 5095 | } |
5084 | } | 5096 | } |
5085 | xfs_buf_rele(agibp); | 5097 | xfs_buf_rele(agibp); |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index f9450235533c..391b4748cae3 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -818,7 +818,8 @@ xfs_init_mount_workqueues( | |||
818 | goto out_destroy_buf; | 818 | goto out_destroy_buf; |
819 | 819 | ||
820 | mp->m_cil_workqueue = alloc_workqueue("xfs-cil/%s", | 820 | mp->m_cil_workqueue = alloc_workqueue("xfs-cil/%s", |
821 | WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_fsname); | 821 | WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND, |
822 | 0, mp->m_fsname); | ||
822 | if (!mp->m_cil_workqueue) | 823 | if (!mp->m_cil_workqueue) |
823 | goto out_destroy_unwritten; | 824 | goto out_destroy_unwritten; |
824 | 825 | ||