From de6192131ca934c59a032dba5a96838582637283 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sun, 16 Oct 2016 14:02:47 -0400 Subject: [PATCH] Add zfs_vdev_parallel_open_enabled module parameter Parallel vdev open causes the driver to deadlock when running ZFS on top of a zvol with something in between, including, but not limited to the loop device. Such configurations are unsupported because we do not have regression test coverage for them, but enough people have requested the capability over the years that we ought to give them a knob to make the configuration work in most instances. Signed-off-by: Richard Yao --- man/man5/zfs-module-parameters.5 | 20 ++++++++++++++++++++ module/zfs/vdev.c | 11 ++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/man/man5/zfs-module-parameters.5 b/man/man5/zfs-module-parameters.5 index 932342cfda21..794011899c6d 100644 --- a/man/man5/zfs-module-parameters.5 +++ b/man/man5/zfs-module-parameters.5 @@ -1049,6 +1049,26 @@ See the section "ZFS I/O SCHEDULER". Default value: \fB1\fR. .RE +.sp +.ne 2 +.na +\fBzfs_vdev_parallel_open_enabled\fR (bool) +.ad +.RS 12n +Accelerates vdev open from pool import or reopen from reload from cache by +allow child vdevs to be opened in parallel. +.sp +This almost always deadlocks in unsupported stacked ZFS configurations where a +zvol from one pool is the vdev for another pool via another type of block +device. Some logic exists in the kernel module to disable this in the direct +case when there is nothing in-between, but it is impossible to detect the +indirect case where another block device exists inbetween. Disabling this will +often make stacked ZFS configurations work, but they continue to be an +unsupported configuration because it is not subjected to regression testing. +.sp +Use \fB1\fR for yes (default) and \fB0\fR for no. +.RE + .sp .ne 2 .na diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index 5ff5cf3b1271..16bf7aae066e 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -51,6 +51,11 @@ */ int metaslabs_per_vdev = 200; +/* + * Allow system administrator to disable parallel open optimization so that + * unsupported ZFS on something else on zvol is semi-safe. + */ +int zfs_vdev_parallel_open_enabled = 1; /* * Virtual device management. */ @@ -1136,7 +1141,7 @@ vdev_uses_zvols(vdev_t *vd) int c; #ifdef _KERNEL - if (zvol_is_zvol(vd->vdev_path)) + if (zfs_vdev_parallel_open_enabled == 0 || zvol_is_zvol(vd->vdev_path)) return (B_TRUE); #endif @@ -3642,6 +3647,10 @@ EXPORT_SYMBOL(vdev_online); EXPORT_SYMBOL(vdev_offline); EXPORT_SYMBOL(vdev_clear); +module_param(zfs_vdev_parallel_open_enabled, int, 0644); +MODULE_PARM_DESC(zfs_vdev_parallel_open_enabled, + "Open vdev children in parallel during import."); + module_param(metaslabs_per_vdev, int, 0644); MODULE_PARM_DESC(metaslabs_per_vdev, "Divide added vdev into approximately (but no more than) this number "