]> granicus.if.org Git - zfs/commitdiff
Use a dedicated taskq for vdev_file
authorChunwei Chen <tuxoko@gmail.com>
Wed, 21 Dec 2016 18:47:15 +0000 (10:47 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 21 Dec 2016 18:47:15 +0000 (10:47 -0800)
The introduction of parallel zvol prefetch causes deadlock when using
vdev_file.

spa_async->(spa_namespace_lock)->txg_wait_synced->(wait for txg_sync)
txg_sync->zio_wait->(wait for vdev_file_io_fsync on system_taskq)
zvol_prefetch_minors_impl (on system_taskq)->spa_open_common->(wait for spa_namespace_lock)

We fix this by using dedicated taskq for vdev_file.  This same change
was originally made in commit bc25c93 but reverted in commit aa9af22
when dynamic taskqs were added.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Chunwei Chen <tuxoko@gmail.com>
Closes #5506
Closes #5495

include/sys/vdev_file.h
module/zfs/spa_misc.c
module/zfs/vdev_file.c

index aebcf55cfd9a9fab9cbaf9dbd78923be7ec2f656..9a398c58391e24c101e1ae541725ada5dcbbb36d 100644 (file)
@@ -37,6 +37,9 @@ typedef struct vdev_file {
        vnode_t         *vf_vnode;
 } vdev_file_t;
 
+extern void vdev_file_init(void);
+extern void vdev_file_fini(void);
+
 #ifdef __cplusplus
 }
 #endif
index b022c236b4bc3ced0f1d5da3f3f782c1636985c2..73f40a583255d5156714f04e47530c84c1e36a8b 100644 (file)
@@ -1839,6 +1839,7 @@ spa_init(int mode)
        zil_init();
        vdev_cache_stat_init();
        vdev_raidz_math_init();
+       vdev_file_init();
        zfs_prop_init();
        zpool_prop_init();
        zpool_feature_init();
@@ -1853,6 +1854,7 @@ spa_fini(void)
 
        spa_evict_all();
 
+       vdev_file_fini();
        vdev_cache_stat_fini();
        vdev_raidz_math_fini();
        zil_fini();
index c78f2f4218be13dd361152cecb5d309d28eb84fa..54a50c318fe803142125fd2e82642d1a7eea91a6 100644 (file)
@@ -37,6 +37,8 @@
  * Virtual device vector for files.
  */
 
+static taskq_t *vdev_file_taskq;
+
 static void
 vdev_file_hold(vdev_t *vd)
 {
@@ -212,7 +214,7 @@ vdev_file_io_start(zio_t *zio)
                         * the sync must be dispatched to a different context.
                         */
                        if (spl_fstrans_check()) {
-                               VERIFY3U(taskq_dispatch(system_taskq,
+                               VERIFY3U(taskq_dispatch(vdev_file_taskq,
                                    vdev_file_io_fsync, zio, TQ_SLEEP), !=,
                                    TASKQID_INVALID);
                                return;
@@ -231,7 +233,7 @@ vdev_file_io_start(zio_t *zio)
 
        zio->io_target_timestamp = zio_handle_io_delay(zio);
 
-       VERIFY3U(taskq_dispatch(system_taskq, vdev_file_io_strategy, zio,
+       VERIFY3U(taskq_dispatch(vdev_file_taskq, vdev_file_io_strategy, zio,
            TQ_SLEEP), !=, TASKQID_INVALID);
 }
 
@@ -254,6 +256,21 @@ vdev_ops_t vdev_file_ops = {
        B_TRUE                  /* leaf vdev */
 };
 
+void
+vdev_file_init(void)
+{
+       vdev_file_taskq = taskq_create("z_vdev_file", MAX(boot_ncpus, 16),
+           minclsyspri, boot_ncpus, INT_MAX, TASKQ_DYNAMIC);
+
+       VERIFY(vdev_file_taskq);
+}
+
+void
+vdev_file_fini(void)
+{
+       taskq_destroy(vdev_file_taskq);
+}
+
 /*
  * From userland we access disks just like files.
  */