Disable direct reclaim for z_wr_* threads
authorBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 6 May 2011 22:12:15 +0000 (15:12 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 6 May 2011 22:26:26 +0000 (15:26 -0700)
The direct reclaim path in the z_wr_* threads must be disabled
to ensure forward progress is always maintained for txg processing.
This ensures that a txg will never get stuck waiting on itself
because it entered the following memory reclaim callpath.

  ->prune_icache()->dispose_list()->zpl_clear_inode()->zfs_inactive()
  ->dmu_tx_assign()->dmu_tx_wait()->tgx_wait_open()

It would be preferable to target this exact code path but the
kernel offers no way to do this without custom patches.  To avoid
this we are forced to disable all reclaim for these threads.  It
should not be necessary to do this for other other z_* threads
because they will not hold a txg open.

Closes #232

include/sys/zfs_context.h
module/zfs/spa.c

index 2ac41e0..1027e72 100644 (file)
@@ -368,6 +368,7 @@ typedef void (task_func_t)(void *);
 #define        TASKQ_DYNAMIC           0x0004  /* Use dynamic thread scheduling */
 #define        TASKQ_THREADS_CPU_PCT   0x0008  /* Scale # threads by # cpus */
 #define        TASKQ_DC_BATCH          0x0010  /* Mark threads as batch */
+#define        TASKQ_NORECLAIM         0x0020  /* Disable direct memory reclaim */
 
 #define        TQ_SLEEP        KM_SLEEP        /* Can block for memory */
 #define        TQ_NOSLEEP      KM_NOSLEEP      /* cannot block for memory; may fail */
index 3599e61..57d25c3 100644 (file)
@@ -614,9 +614,8 @@ spa_get_errlists(spa_t *spa, avl_tree_t *last, avl_tree_t *scrub)
 
 static taskq_t *
 spa_taskq_create(spa_t *spa, const char *name, enum zti_modes mode,
-    uint_t value)
+    uint_t value, uint_t flags)
 {
-       uint_t flags = TASKQ_PREPOPULATE;
        boolean_t batch = B_FALSE;
 
        switch (mode) {
@@ -666,13 +665,17 @@ spa_create_zio_taskqs(spa_t *spa)
                        const zio_taskq_info_t *ztip = &zio_taskqs[t][q];
                        enum zti_modes mode = ztip->zti_mode;
                        uint_t value = ztip->zti_value;
+                       uint_t flags = TASKQ_PREPOPULATE;
                        char name[32];
 
+                       if (t == ZIO_TYPE_WRITE)
+                               flags |= TASKQ_NORECLAIM;
+
                        (void) snprintf(name, sizeof (name),
                            "%s_%s", zio_type_name[t], zio_taskq_types[q]);
 
                        spa->spa_zio_taskq[t][q] =
-                           spa_taskq_create(spa, name, mode, value);
+                           spa_taskq_create(spa, name, mode, value, flags);
                }
        }
 }