aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]module/zfs/dsl_pool.c14
-rw-r--r--module/zfs/vdev_queue.c15
2 files changed, 23 insertions, 6 deletions
diff --git a/module/zfs/dsl_pool.c b/module/zfs/dsl_pool.c
index ada0eac63..cf5259acd 100644..100755
--- a/module/zfs/dsl_pool.c
+++ b/module/zfs/dsl_pool.c
@@ -182,12 +182,20 @@ dsl_pool_init(spa_t *spa, uint64_t txg, dsl_pool_t **dpp)
int err;
dsl_pool_t *dp = dsl_pool_open_impl(spa, txg);
+ /*
+ * Initialize the caller's dsl_pool_t structure before we actually open
+ * the meta objset. This is done because a self-healing write zio may
+ * be issued as part of dmu_objset_open_impl() and the spa needs its
+ * dsl_pool_t initialized in order to handle the write.
+ */
+ *dpp = dp;
+
err = dmu_objset_open_impl(spa, NULL, &dp->dp_meta_rootbp,
&dp->dp_meta_objset);
- if (err != 0)
+ if (err != 0) {
dsl_pool_close(dp);
- else
- *dpp = dp;
+ *dpp = NULL;
+ }
return (err);
}
diff --git a/module/zfs/vdev_queue.c b/module/zfs/vdev_queue.c
index d67912d96..8522c2627 100644
--- a/module/zfs/vdev_queue.c
+++ b/module/zfs/vdev_queue.c
@@ -249,20 +249,29 @@ static int
vdev_queue_max_async_writes(spa_t *spa)
{
int writes;
- uint64_t dirty = spa->spa_dsl_pool->dp_dirty_total;
+ uint64_t dirty = 0;
+ dsl_pool_t *dp = spa_get_dsl(spa);
uint64_t min_bytes = zfs_dirty_data_max *
zfs_vdev_async_write_active_min_dirty_percent / 100;
uint64_t max_bytes = zfs_dirty_data_max *
zfs_vdev_async_write_active_max_dirty_percent / 100;
/*
+ * Async writes may occur before the assignment of the spa's
+ * dsl_pool_t if a self-healing zio is issued prior to the
+ * completion of dmu_objset_open_impl().
+ */
+ if (dp == NULL)
+ return (zfs_vdev_async_write_max_active);
+
+ /*
* Sync tasks correspond to interactive user actions. To reduce the
* execution time of those actions we push data out as fast as possible.
*/
- if (spa_has_pending_synctask(spa)) {
+ if (spa_has_pending_synctask(spa))
return (zfs_vdev_async_write_max_active);
- }
+ dirty = dp->dp_dirty_total;
if (dirty < min_bytes)
return (zfs_vdev_async_write_min_active);
if (dirty > max_bytes)