aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_debug.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2014-08-31 19:09:59 -0400
committerChristoph Hellwig <hch@lst.de>2014-09-30 03:34:37 -0400
commitdb525fce95f0ee39102f06f8599ced3f3f3af128 (patch)
tree104a30ca4d06b3d62234a06007e192ff4ecc3fdb /drivers/scsi/scsi_debug.c
parenta41a9ad3bbf61fae0b6bfb232153da60d14fdbd9 (diff)
scsi_debug: deadlock between completions and surprise module removal
A deadlock has been reported when the completion of SCSI commands (simulated by a timer) was surprised by a module removal. This patch removes one half of the offending locks around timer deletions. This fix is applied both to stop_all_queued() which is were the deadlock was discovered and stop_queued_cmnd() which has very similar logic. This patch should be applied both to the lk 3.17 tree and Christoph's drivers-for-3.18 tree. Tested-and-reported-by: Milan Broz <gmazyland@gmail.com> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r--drivers/scsi/scsi_debug.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 1c475e9a46ab..2b6d447ad6d6 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -2743,6 +2743,13 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
2743 if (test_bit(k, queued_in_use_bm)) { 2743 if (test_bit(k, queued_in_use_bm)) {
2744 sqcp = &queued_arr[k]; 2744 sqcp = &queued_arr[k];
2745 if (cmnd == sqcp->a_cmnd) { 2745 if (cmnd == sqcp->a_cmnd) {
2746 devip = (struct sdebug_dev_info *)
2747 cmnd->device->hostdata;
2748 if (devip)
2749 atomic_dec(&devip->num_in_q);
2750 sqcp->a_cmnd = NULL;
2751 spin_unlock_irqrestore(&queued_arr_lock,
2752 iflags);
2746 if (scsi_debug_ndelay > 0) { 2753 if (scsi_debug_ndelay > 0) {
2747 if (sqcp->sd_hrtp) 2754 if (sqcp->sd_hrtp)
2748 hrtimer_cancel( 2755 hrtimer_cancel(
@@ -2755,18 +2762,13 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
2755 if (sqcp->tletp) 2762 if (sqcp->tletp)
2756 tasklet_kill(sqcp->tletp); 2763 tasklet_kill(sqcp->tletp);
2757 } 2764 }
2758 __clear_bit(k, queued_in_use_bm); 2765 clear_bit(k, queued_in_use_bm);
2759 devip = (struct sdebug_dev_info *) 2766 return 1;
2760 cmnd->device->hostdata;
2761 if (devip)
2762 atomic_dec(&devip->num_in_q);
2763 sqcp->a_cmnd = NULL;
2764 break;
2765 } 2767 }
2766 } 2768 }
2767 } 2769 }
2768 spin_unlock_irqrestore(&queued_arr_lock, iflags); 2770 spin_unlock_irqrestore(&queued_arr_lock, iflags);
2769 return (k < qmax) ? 1 : 0; 2771 return 0;
2770} 2772}
2771 2773
2772/* Deletes (stops) timers or tasklets of all queued commands */ 2774/* Deletes (stops) timers or tasklets of all queued commands */
@@ -2782,6 +2784,13 @@ static void stop_all_queued(void)
2782 if (test_bit(k, queued_in_use_bm)) { 2784 if (test_bit(k, queued_in_use_bm)) {
2783 sqcp = &queued_arr[k]; 2785 sqcp = &queued_arr[k];
2784 if (sqcp->a_cmnd) { 2786 if (sqcp->a_cmnd) {
2787 devip = (struct sdebug_dev_info *)
2788 sqcp->a_cmnd->device->hostdata;
2789 if (devip)
2790 atomic_dec(&devip->num_in_q);
2791 sqcp->a_cmnd = NULL;
2792 spin_unlock_irqrestore(&queued_arr_lock,
2793 iflags);
2785 if (scsi_debug_ndelay > 0) { 2794 if (scsi_debug_ndelay > 0) {
2786 if (sqcp->sd_hrtp) 2795 if (sqcp->sd_hrtp)
2787 hrtimer_cancel( 2796 hrtimer_cancel(
@@ -2794,12 +2803,8 @@ static void stop_all_queued(void)
2794 if (sqcp->tletp) 2803 if (sqcp->tletp)
2795 tasklet_kill(sqcp->tletp); 2804 tasklet_kill(sqcp->tletp);
2796 } 2805 }
2797 __clear_bit(k, queued_in_use_bm); 2806 clear_bit(k, queued_in_use_bm);
2798 devip = (struct sdebug_dev_info *) 2807 spin_lock_irqsave(&queued_arr_lock, iflags);
2799 sqcp->a_cmnd->device->hostdata;
2800 if (devip)
2801 atomic_dec(&devip->num_in_q);
2802 sqcp->a_cmnd = NULL;
2803 } 2808 }
2804 } 2809 }
2805 } 2810 }