]> granicus.if.org Git - zfs/commitdiff
Illumos #3836
authorMatthew Ahrens <mahrens@delphix.com>
Wed, 3 Jul 2013 16:13:38 +0000 (08:13 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 5 Nov 2013 20:14:56 +0000 (12:14 -0800)
3836 zio_free() can be processed immediately in the common case
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Adam Leventhal <ahl@delphix.com>
Approved by: Dan McDonald <danmcd@nexenta.com>

References:
  https://www.illumos.org/issues/3836
  illumos/illumos-gate@9cb154a3c9f170904dce9bad5bd5a7d256b922a4

Ported-by: Richard Yao <ryao@gentoo.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #1775

include/sys/zio_impl.h
module/zfs/zio.c

index 787079d2c90547cb7a682a53a8d5053b621c2fe0..08f820103e823681031100c8b2f65f8661e8293e 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 /*
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #ifndef _ZIO_IMPL_H
@@ -38,7 +38,7 @@ extern "C" {
 #endif
 
 /*
- * XXX -- Describe ZFS I/O pipleine here. Fill in as needed.
+ * XXX -- Describe ZFS I/O pipeline here. Fill in as needed.
  *
  * The ZFS I/O pipeline is comprised of various stages which are defined
  * in the zio_stage enum below. The individual stages are used to construct
@@ -213,7 +213,6 @@ enum zio_stage {
 #define        ZIO_FREE_PIPELINE                       \
        (ZIO_INTERLOCK_STAGES |                 \
        ZIO_STAGE_FREE_BP_INIT |                \
-       ZIO_STAGE_ISSUE_ASYNC |                 \
        ZIO_STAGE_DVA_FREE)
 
 #define        ZIO_DDT_FREE_PIPELINE                   \
index f0c9c0f08d09f147d9e99dd15cc57e470487151c..0ef9f28b40583f51a7c46f5d0210cd58ad4d1564 100644 (file)
@@ -783,7 +783,20 @@ void
 zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp)
 {
        metaslab_check_free(spa, bp);
-       bplist_append(&spa->spa_free_bplist[txg & TXG_MASK], bp);
+
+       /*
+        * Frees that are for the currently-syncing txg, are not going to be
+        * deferred, and which will not need to do a read (i.e. not GANG or
+        * DEDUP), can be processed immediately.  Otherwise, put them on the
+        * in-memory list for later processing.
+        */
+       if (BP_IS_GANG(bp) || BP_GET_DEDUP(bp) ||
+           txg != spa->spa_syncing_txg ||
+           spa_sync_pass(spa) >= zfs_sync_pass_deferred_free) {
+               bplist_append(&spa->spa_free_bplist[txg & TXG_MASK], bp);
+       } else {
+               VERIFY0(zio_wait(zio_free_sync(NULL, spa, txg, bp, 0)));
+       }
 }
 
 zio_t *
@@ -791,6 +804,7 @@ 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;
 
        dprintf_bp(bp, "freeing in txg %llu, pass %u",
            (longlong_t)txg, spa->spa_sync_pass);
@@ -802,9 +816,18 @@ zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
        metaslab_check_free(spa, bp);
        arc_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),
-           NULL, NULL, ZIO_TYPE_FREE, ZIO_PRIORITY_FREE, flags,
-           NULL, 0, NULL, ZIO_STAGE_OPEN, ZIO_FREE_PIPELINE);
+           NULL, NULL, ZIO_TYPE_FREE, ZIO_PRIORITY_NOW, flags,
+           NULL, 0, NULL, ZIO_STAGE_OPEN, stage);
+
 
        return (zio);
 }