aboutsummaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
Diffstat (limited to 'module')
-rw-r--r--module/zfs/arc.c2
-rw-r--r--module/zfs/dmu_objset.c3
-rw-r--r--module/zfs/mmp.c3
-rw-r--r--module/zfs/spa.c6
-rw-r--r--module/zfs/zio.c67
5 files changed, 52 insertions, 29 deletions
diff --git a/module/zfs/arc.c b/module/zfs/arc.c
index 8fa8c91ac..3df53d2db 100644
--- a/module/zfs/arc.c
+++ b/module/zfs/arc.c
@@ -8396,7 +8396,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
mutex_exit(hash_lock);
- (void) zio_nowait(wzio);
+ zio_nowait(wzio);
}
multilist_sublist_unlock(mls);
diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c
index 9f9eb1e01..a91ecb640 100644
--- a/module/zfs/dmu_objset.c
+++ b/module/zfs/dmu_objset.c
@@ -1714,8 +1714,7 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
while ((dr = list_head(list)) != NULL) {
ASSERT0(dr->dr_dbuf->db_level);
list_remove(list, dr);
- if (dr->dr_zio)
- zio_nowait(dr->dr_zio);
+ zio_nowait(dr->dr_zio);
}
/* Enable dnode backfill if enough objects have been freed. */
diff --git a/module/zfs/mmp.c b/module/zfs/mmp.c
index f1a30f877..e1e468557 100644
--- a/module/zfs/mmp.c
+++ b/module/zfs/mmp.c
@@ -678,8 +678,7 @@ mmp_thread(void *arg)
}
/* Outstanding writes are allowed to complete. */
- if (mmp->mmp_zio_root)
- zio_wait(mmp->mmp_zio_root);
+ zio_wait(mmp->mmp_zio_root);
mmp->mmp_zio_root = NULL;
mmp_thread_exit(mmp, &mmp->mmp_thread, &cpr);
diff --git a/module/zfs/spa.c b/module/zfs/spa.c
index c12b20270..a6f97eb37 100644
--- a/module/zfs/spa.c
+++ b/module/zfs/spa.c
@@ -8125,10 +8125,10 @@ bpobj_enqueue_free_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
static int
spa_free_sync_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
{
- zio_t *zio = arg;
+ zio_t *pio = arg;
- zio_nowait(zio_free_sync(zio, zio->io_spa, dmu_tx_get_txg(tx), bp,
- zio->io_flags));
+ zio_nowait(zio_free_sync(pio, pio->io_spa, dmu_tx_get_txg(tx), bp,
+ pio->io_flags));
return (0);
}
diff --git a/module/zfs/zio.c b/module/zfs/zio.c
index 9dc3c830a..cbe6fc751 100644
--- a/module/zfs/zio.c
+++ b/module/zfs/zio.c
@@ -1194,40 +1194,46 @@ zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp)
!spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP))) {
bplist_append(&spa->spa_free_bplist[txg & TXG_MASK], bp);
} else {
- VERIFY0(zio_wait(zio_free_sync(NULL, spa, txg, bp, 0)));
+ VERIFY3P(zio_free_sync(NULL, spa, txg, bp, 0), ==, NULL);
}
}
+/*
+ * To improve performance, this function may return NULL if we were able
+ * to do the free immediately. This avoids the cost of creating a zio
+ * (and linking it to the parent, etc).
+ */
zio_t *
zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
enum zio_flag flags)
{
- zio_t *zio;
- enum zio_stage stage = ZIO_FREE_PIPELINE;
-
ASSERT(!BP_IS_HOLE(bp));
ASSERT(spa_syncing_txg(spa) == txg);
if (BP_IS_EMBEDDED(bp))
- return (zio_null(pio, spa, NULL, NULL, NULL, 0));
+ return (NULL);
metaslab_check_free(spa, bp);
arc_freed(spa, bp);
dsl_scan_freed(spa, bp);
- /*
- * GANG and DEDUP blocks can induce a read (for the gang block header,
- * or the DDT), so issue them asynchronously so that this thread is
- * not tied up.
- */
- if (BP_IS_GANG(bp) || BP_GET_DEDUP(bp))
- stage |= ZIO_STAGE_ISSUE_ASYNC;
-
- zio = zio_create(pio, spa, txg, bp, NULL, BP_GET_PSIZE(bp),
- BP_GET_PSIZE(bp), NULL, NULL, ZIO_TYPE_FREE, ZIO_PRIORITY_NOW,
- flags, NULL, 0, NULL, ZIO_STAGE_OPEN, stage);
+ if (BP_IS_GANG(bp) || BP_GET_DEDUP(bp)) {
+ /*
+ * GANG and DEDUP blocks can induce a read (for the gang block
+ * header, or the DDT), so issue them asynchronously so that
+ * this thread is not tied up.
+ */
+ enum zio_stage stage =
+ ZIO_FREE_PIPELINE | ZIO_STAGE_ISSUE_ASYNC;
- return (zio);
+ return (zio_create(pio, spa, txg, bp, NULL, BP_GET_PSIZE(bp),
+ BP_GET_PSIZE(bp), NULL, NULL,
+ ZIO_TYPE_FREE, ZIO_PRIORITY_NOW,
+ flags, NULL, 0, NULL, ZIO_STAGE_OPEN, stage));
+ } else {
+ metaslab_free(spa, bp, txg, B_FALSE);
+ return (NULL);
+ }
}
zio_t *
@@ -2165,6 +2171,15 @@ __zio_execute(zio_t *zio)
int
zio_wait(zio_t *zio)
{
+ /*
+ * Some routines, like zio_free_sync(), may return a NULL zio
+ * to avoid the performance overhead of creating and then destroying
+ * an unneeded zio. For the callers' simplicity, we accept a NULL
+ * zio and ignore it.
+ */
+ if (zio == NULL)
+ return (0);
+
long timeout = MSEC_TO_TICK(zfs_deadman_ziotime_ms);
int error;
@@ -2202,6 +2217,12 @@ zio_wait(zio_t *zio)
void
zio_nowait(zio_t *zio)
{
+ /*
+ * See comment in zio_wait().
+ */
+ if (zio == NULL)
+ return;
+
ASSERT3P(zio->io_executor, ==, NULL);
if (zio->io_child_type == ZIO_CHILD_LOGICAL &&
@@ -2489,8 +2510,13 @@ static zio_t *
zio_free_gang(zio_t *pio, blkptr_t *bp, zio_gang_node_t *gn, abd_t *data,
uint64_t offset)
{
- return (zio_free_sync(pio, pio->io_spa, pio->io_txg, bp,
- ZIO_GANG_CHILD_FLAGS(pio)));
+ zio_t *zio = zio_free_sync(pio, pio->io_spa, pio->io_txg, bp,
+ ZIO_GANG_CHILD_FLAGS(pio));
+ if (zio == NULL) {
+ zio = zio_null(pio, pio->io_spa,
+ NULL, NULL, NULL, ZIO_GANG_CHILD_FLAGS(pio));
+ }
+ return (zio);
}
/* ARGSUSED */
@@ -3273,8 +3299,7 @@ zio_ddt_write(zio_t *zio)
ddt_exit(ddt);
- if (cio)
- zio_nowait(cio);
+ zio_nowait(cio);
return (zio);
}