aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Wilson <[email protected]>2013-02-21 13:58:29 -0800
committerBrian Behlendorf <[email protected]>2013-10-18 14:34:01 -0700
commit7a6144076166944655d86f1449be8566d1a3c71a (patch)
treec038d9fa6ea3dd6c5b50936ce216618b7ff1d869
parenta6ce1eae54ca048ae7e7dfdcad05c5565a129226 (diff)
Illumos #3552
3552 condensing one space map burns 3 seconds of CPU in spa_sync() thread (fix race condition) References: https://www.illumos.org/issues/3552 illumos/illumos-gate@03f8c366886542ed249a15d755ae78ea4e775d9d Ported-by: Richard Yao <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Porting notes: This fixes an upstream regression that was introduced in commit zfsonlinux/zfs@e51be06697762215dc3b679f8668987034a5a048, which ported the Illumos 3552 changes. This fix was added to upstream rather quickly, but at the time of the port, no one spotted it and the race was rare enough that it passed our regression tests. I discovered this when comparing our metaslab.c to the illumos metaslab.c. Without this change it is possible for metaslab_group_alloc() to consume a large amount of cpu time. Since this occurs under a mutex in a rcu critical section the kernel will log this to the console as a self-detected cpu stall as follows: INFO: rcu_sched self-detected stall on CPU { 0} (t=60000 jiffies g=11431890 c=11431889 q=18271) Closes #1687 Closes #1720 Closes #1731 Closes #1747
-rw-r--r--module/zfs/metaslab.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/module/zfs/metaslab.c b/module/zfs/metaslab.c
index f9cb8cead..7837822e4 100644
--- a/module/zfs/metaslab.c
+++ b/module/zfs/metaslab.c
@@ -1388,6 +1388,13 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize,
mutex_exit(&mg->mg_lock);
return (-1ULL);
}
+
+ /*
+ * If the selected metaslab is condensing, skip it.
+ */
+ if (msp->ms_map->sm_condensing)
+ continue;
+
was_active = msp->ms_weight & METASLAB_ACTIVE_MASK;
if (activation_weight == METASLAB_WEIGHT_PRIMARY)
break;
@@ -1428,16 +1435,6 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize,
mutex_enter(&msp->ms_lock);
/*
- * If this metaslab is currently condensing then pick again as
- * we can't manipulate this metaslab until it's committed
- * to disk.
- */
- if (msp->ms_map->sm_condensing) {
- mutex_exit(&msp->ms_lock);
- continue;
- }
-
- /*
* Ensure that the metaslab we have selected is still
* capable of handling our request. It's possible that
* another thread may have changed the weight while we
@@ -1463,6 +1460,16 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize,
continue;
}
+ /*
+ * If this metaslab is currently condensing then pick again as
+ * we can't manipulate this metaslab until it's committed
+ * to disk.
+ */
+ if (msp->ms_map->sm_condensing) {
+ mutex_exit(&msp->ms_lock);
+ continue;
+ }
+
if ((offset = space_map_alloc(msp->ms_map, asize)) != -1ULL)
break;