Illumos 5347 - idle pool may run itself out of space

5347 idle pool may run itself out of space
Reviewed by: Alex Reece <alex.reece@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Reviewed by: Richard Elling <richard.elling@richardelling.com>
Approved by: Dan McDonald <danmcd@omniti.com>

References:
  https://github.com/illumos/illumos-gate/commit/231aab8
  https://github.com/illumos/illumos-gate/commit/4a92375 3642
  https://www.illumos.org/issues/5347
  https://github.com/zfsonlinux/zfs/commit/89b1cd6 (partial commit & fix)
  https://github.com/zfsonlinux/zfs/commit/fbeddd6 Illumos 4390
  https://github.com/zfsonlinux/zfs/commit/2696dfa Illumos 3642, 3643

Porting notes:
This is completing the partial fix from FreeBSD

Ported-by: kernelOfTruth kerneloftruth@gmail.com
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3586
This commit is contained in:
Matthew Ahrens
2015-07-11 02:19:41 +02:00
committed by Brian Behlendorf
parent 93f6d7e2e5
commit 905edb405d
4 changed files with 51 additions and 25 deletions
+35 -16
View File
@@ -6393,21 +6393,6 @@ spa_sync(spa_t *spa, uint64_t txg)
}
}
/*
* If anything has changed in this txg, or if someone is waiting
* for this txg to sync (eg, spa_vdev_remove()), push the
* deferred frees from the previous txg. If not, leave them
* alone so that we don't generate work on an otherwise idle
* system.
*/
if (!txg_list_empty(&dp->dp_dirty_datasets, txg) ||
!txg_list_empty(&dp->dp_dirty_dirs, txg) ||
!txg_list_empty(&dp->dp_sync_tasks, txg) ||
((dsl_scan_active(dp->dp_scan) ||
txg_sync_waiting(dp)) && !spa_shutting_down(spa))) {
spa_sync_deferred_frees(spa, tx);
}
/*
* Iterate to convergence.
*/
@@ -6425,6 +6410,11 @@ spa_sync(spa_t *spa, uint64_t txg)
if (pass < zfs_sync_pass_deferred_free) {
spa_sync_frees(spa, free_bpl, tx);
} else {
/*
* We can not defer frees in pass 1, because
* we sync the deferred frees later in pass 1.
*/
ASSERT3U(pass, >, 1);
bplist_iterate(free_bpl, bpobj_enqueue_cb,
&spa->spa_deferred_bpobj, tx);
}
@@ -6435,8 +6425,37 @@ spa_sync(spa_t *spa, uint64_t txg)
while ((vd = txg_list_remove(&spa->spa_vdev_txg_list, txg)))
vdev_sync(vd, txg);
if (pass == 1)
if (pass == 1) {
spa_sync_upgrades(spa, tx);
ASSERT3U(txg, >=,
spa->spa_uberblock.ub_rootbp.blk_birth);
/*
* Note: We need to check if the MOS is dirty
* because we could have marked the MOS dirty
* without updating the uberblock (e.g. if we
* have sync tasks but no dirty user data). We
* need to check the uberblock's rootbp because
* it is updated if we have synced out dirty
* data (though in this case the MOS will most
* likely also be dirty due to second order
* effects, we don't want to rely on that here).
*/
if (spa->spa_uberblock.ub_rootbp.blk_birth < txg &&
!dmu_objset_is_dirty(mos, txg)) {
/*
* Nothing changed on the first pass,
* therefore this TXG is a no-op. Avoid
* syncing deferred frees, so that we
* can keep this TXG as a no-op.
*/
ASSERT(txg_list_empty(&dp->dp_dirty_datasets,
txg));
ASSERT(txg_list_empty(&dp->dp_dirty_dirs, txg));
ASSERT(txg_list_empty(&dp->dp_sync_tasks, txg));
break;
}
spa_sync_deferred_frees(spa, tx);
}
} while (dmu_objset_is_dirty(mos, txg));