From 819cb8299997a33db50368df889a65bba0e779fb Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 12 Oct 2012 14:03:26 +0200 Subject: [PATCH] ib_srp: Avoid that module removal can trigger a deadlock Avoid that scsi_remove_host() is invoked from the context of a work queue thread on which work has been queued that scsi_remove_host() might be waiting for. That avoids that module removal of ib_srp triggers a deadlock on a pre-2.6.36 kernel. This patch has been tested on RHEL 6.1, RHEL 6.2, RHEL 6.3 and SLES 11 SP2. Reported-by: Rupert Dance Signed-off-by: Bart Van Assche --- ...025-ib_srp-Backport-to-older-kernels.patch | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/patches/0025-ib_srp-Backport-to-older-kernels.patch b/patches/0025-ib_srp-Backport-to-older-kernels.patch index 20edccf..d070430 100644 --- a/patches/0025-ib_srp-Backport-to-older-kernels.patch +++ b/patches/0025-ib_srp-Backport-to-older-kernels.patch @@ -12,7 +12,7 @@ Signed-off-by: Bart Van Assche 1 file changed, 108 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c -index bcbf22e..fab74e0 100644 +index bcbf22e..d42e9c4 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -30,8 +30,13 @@ @@ -29,7 +29,7 @@ index bcbf22e..fab74e0 100644 #include #include #include -@@ -41,21 +46,27 @@ +@@ -41,21 +46,32 @@ #include #include @@ -56,23 +56,16 @@ index bcbf22e..fab74e0 100644 +#ifndef pr_warn +#define pr_warn pr_warning +#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++static struct workqueue_struct *srp_wq; ++#define ib_wq srp_wq ++#endif + MODULE_AUTHOR("Roland Dreier"); MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator " "v" DRV_VERSION " (" DRV_RELDATE ")"); -@@ -675,7 +686,11 @@ err: - if (target->state == SRP_TARGET_CONNECTING) { - target->state = SRP_TARGET_DEAD; - INIT_WORK(&target->work, srp_remove_work); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) - queue_work(ib_wq, &target->work); -+#else -+ schedule_work(&target->work); -+#endif - } - spin_unlock_irq(&target->lock); - -@@ -1254,7 +1269,50 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr) +@@ -1254,7 +1270,50 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr) } } @@ -124,7 +117,7 @@ index bcbf22e..fab74e0 100644 { struct srp_target_port *target = host_to_target(shost); struct srp_request *req; -@@ -1822,6 +1880,9 @@ static struct scsi_host_template srp_template = { +@@ -1822,6 +1881,9 @@ static struct scsi_host_template srp_template = { .name = "InfiniBand SRP initiator", .proc_name = DRV_NAME, .info = srp_target_info, @@ -134,18 +127,32 @@ index bcbf22e..fab74e0 100644 .queuecommand = srp_queuecommand, .eh_abort_handler = srp_abort, .eh_device_reset_handler = srp_reset_device, -@@ -2412,7 +2473,11 @@ static void srp_remove_one(struct ib_device *device) - * started before we marked our target ports as - * removed, and any target port removal tasks. - */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) - flush_workqueue(ib_wq); -+#else -+ flush_scheduled_work(); +@@ -2491,11 +2553,25 @@ static int __init srp_init_module(void) + return ret; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++ srp_wq = create_workqueue("srp"); ++ if (IS_ERR(srp_wq)) { ++ ib_unregister_client(&srp_client); ++ ib_sa_unregister_client(&srp_sa_client); ++ class_unregister(&srp_class); ++ srp_release_transport(ib_srp_transport_template); ++ return PTR_ERR(srp_wq); ++ } +#endif ++ + return 0; + } - list_for_each_entry_safe(target, tmp_target, - &host->target_list, list) { + static void __exit srp_cleanup_module(void) + { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++ destroy_workqueue(srp_wq); ++#endif + ib_unregister_client(&srp_client); + ib_sa_unregister_client(&srp_sa_client); + class_unregister(&srp_class); -- 1.7.9.5 -- 2.41.0