From: Jitendra Bhivare Date: Thu, 14 Apr 2016 03:50:05 +0000 (+0530) Subject: be2iscsi: Replace _bh with _irqsave/irqrestore X-Git-Tag: v4.1.12-92~119^2~36 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=9c3b94c883c3ffe63ceebbe37a05640020e32b0f;p=users%2Fjedix%2Flinux-maple.git be2iscsi: Replace _bh with _irqsave/irqrestore Kernel panic - not syncing: Watchdog detected hard LOCKUP on cpu 21 Pid: 13242, comm: flush-8:80 Tainted: G W -- ------------ 2.6.32-573.el6.x86_64 #1 Call Trace: [] ? panic+0xa7/0x16f [] ? sched_clock+0x9/0x10 [] ? watchdog_overflow_callback+0xcd/0xd0 [] ? __perf_event_overflow+0xa7/0x240 [] ? x86_perf_event_set_period+0xf4/0x180 [] ? perf_event_overflow+0x14/0x20 [] ? intel_pmu_handle_irq+0x202/0x3f0 [] ? perf_event_nmi_handler+0x39/0xb0 [] ? notifier_call_chain+0x55/0x80 [] ? scsi_done+0x0/0x60 [] ? atomic_notifier_call_chain+0x1a/0x20 [] ? notify_die+0x2e/0x30 [] ? do_nmi+0x1c3/0x350 [] ? nmi+0x20/0x30 [] ? scsi_done+0x0/0x60 [] ? scsi_done+0x0/0x60 [] ? _spin_lock+0x1e/0x30 <> [] ? iscsi_queuecommand+0x7f/0x4e0 [libiscsi] [] ? scsi_dispatch_cmd+0xe5/0x310 [] ? scsi_request_fn+0x5be/0x750 [] ? del_timer+0x7d/0xe0 [] ? __generic_unplug_device+0x32/0x40 [] ? elv_insert+0xd3/0x190 [] ? __elv_add_request+0x40/0x90 In beiscsi_alloc_pdu, _bh versions of spin_lock are being used for protecting SGLs and WRBs. _bh versions are needed as the function gets invoked in process context and BLOCK_IOPOLL softirq. In spin_unlock_bh, after releasing the lock and enabling BH, do_softirq is called which executes till last SOFTIRQ. beiscsi_alloc_pdu is called under session lock. Through block layer, iSCSI stack in some cases send IOs with interrupts disabled. In such paths, CPU will get stuck for a while for session lock with interrupts disabled because in other CPU do_softirq is executing under session lock thus causing hard lock up. Use spin_lock_irqsave/spin_lock_irqrestore as the driver can't be sure in all paths interrupts are enabled. Signed-off-by: Jitendra Bhivare Orabug: 23712824 Signed-off-by: Manjunath Govindashetty --- diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 9614edbeea013..75553e209c52f 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1123,8 +1123,9 @@ beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) { struct sgl_handle *psgl_handle; + unsigned long flags; - spin_lock_bh(&phba->io_sgl_lock); + spin_lock_irqsave(&phba->io_sgl_lock, flags); if (phba->io_sgl_hndl_avbl) { beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, "BM_%d : In alloc_io_sgl_handle," @@ -1142,14 +1143,16 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) phba->io_sgl_alloc_index++; } else psgl_handle = NULL; - spin_unlock_bh(&phba->io_sgl_lock); + spin_unlock_irqrestore(&phba->io_sgl_lock, flags); return psgl_handle; } static void free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) { - spin_lock_bh(&phba->io_sgl_lock); + unsigned long flags; + + spin_lock_irqsave(&phba->io_sgl_lock, flags); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, "BM_%d : In free_,io_sgl_free_index=%d\n", phba->io_sgl_free_index); @@ -1164,7 +1167,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) "value there=%p\n", phba->io_sgl_free_index, phba->io_sgl_hndl_base [phba->io_sgl_free_index]); - spin_unlock_bh(&phba->io_sgl_lock); + spin_unlock_irqrestore(&phba->io_sgl_lock, flags); return; } phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle; @@ -1173,7 +1176,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->io_sgl_free_index = 0; else phba->io_sgl_free_index++; - spin_unlock_bh(&phba->io_sgl_lock); + spin_unlock_irqrestore(&phba->io_sgl_lock, flags); } static inline struct wrb_handle * @@ -1181,15 +1184,16 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, unsigned int wrbs_per_cxn) { struct wrb_handle *pwrb_handle; + unsigned long flags; - spin_lock_bh(&pwrb_context->wrb_lock); + spin_lock_irqsave(&pwrb_context->wrb_lock, flags); pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index]; pwrb_context->wrb_handles_available--; if (pwrb_context->alloc_index == (wrbs_per_cxn - 1)) pwrb_context->alloc_index = 0; else pwrb_context->alloc_index++; - spin_unlock_bh(&pwrb_context->wrb_lock); + spin_unlock_irqrestore(&pwrb_context->wrb_lock, flags); return pwrb_handle; } @@ -1221,14 +1225,16 @@ beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context, struct wrb_handle *pwrb_handle, unsigned int wrbs_per_cxn) { - spin_lock_bh(&pwrb_context->wrb_lock); + unsigned long flags; + + spin_lock_irqsave(&pwrb_context->wrb_lock, flags); pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; pwrb_context->wrb_handles_available++; if (pwrb_context->free_index == (wrbs_per_cxn - 1)) pwrb_context->free_index = 0; else pwrb_context->free_index++; - spin_unlock_bh(&pwrb_context->wrb_lock); + spin_unlock_irqrestore(&pwrb_context->wrb_lock, flags); } /** @@ -1257,8 +1263,9 @@ free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) { struct sgl_handle *psgl_handle; + unsigned long flags; - spin_lock_bh(&phba->mgmt_sgl_lock); + spin_lock_irqsave(&phba->mgmt_sgl_lock, flags); if (phba->eh_sgl_hndl_avbl) { psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index]; phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL; @@ -1276,14 +1283,16 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) phba->eh_sgl_alloc_index++; } else psgl_handle = NULL; - spin_unlock_bh(&phba->mgmt_sgl_lock); + spin_unlock_irqrestore(&phba->mgmt_sgl_lock, flags); return psgl_handle; } void free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) { - spin_lock_bh(&phba->mgmt_sgl_lock); + unsigned long flags; + + spin_lock_irqsave(&phba->mgmt_sgl_lock, flags); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, "BM_%d : In free_mgmt_sgl_handle," "eh_sgl_free_index=%d\n", @@ -1298,7 +1307,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) "BM_%d : Double Free in eh SGL ," "eh_sgl_free_index=%d\n", phba->eh_sgl_free_index); - spin_unlock_bh(&phba->mgmt_sgl_lock); + spin_unlock_irqrestore(&phba->mgmt_sgl_lock, flags); return; } phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle; @@ -1308,7 +1317,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->eh_sgl_free_index = 0; else phba->eh_sgl_free_index++; - spin_unlock_bh(&phba->mgmt_sgl_lock); + spin_unlock_irqrestore(&phba->mgmt_sgl_lock, flags); } static void