Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi_dh_alua: Allow workqueue to run synchronously

Some arrays may only capable of handling one STPG at a time,
so this patch adds a singlethreaded workqueue for STPGs to be
submitted synchronously.

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Hannes Reinecke and committed by
Martin K. Petersen
00642a1b 03197b61

+18 -3
+18 -3
drivers/scsi/device_handler/scsi_dh_alua.c
··· 64 64 /* device handler flags */ 65 65 #define ALUA_OPTIMIZE_STPG 0x01 66 66 #define ALUA_RTPG_EXT_HDR_UNSUPP 0x02 67 + #define ALUA_SYNC_STPG 0x04 67 68 /* State machine flags */ 68 69 #define ALUA_PG_RUN_RTPG 0x10 69 70 #define ALUA_PG_RUN_STPG 0x20 ··· 77 76 static LIST_HEAD(port_group_list); 78 77 static DEFINE_SPINLOCK(port_group_lock); 79 78 static struct workqueue_struct *kaluad_wq; 79 + static struct workqueue_struct *kaluad_sync_wq; 80 80 81 81 struct alua_port_group { 82 82 struct kref kref; ··· 688 686 int err = SCSI_DH_OK; 689 687 struct alua_queue_data *qdata, *tmp; 690 688 unsigned long flags; 689 + struct workqueue_struct *alua_wq = kaluad_wq; 691 690 692 691 spin_lock_irqsave(&pg->lock, flags); 693 692 sdev = pg->rtpg_sdev; ··· 698 695 spin_unlock_irqrestore(&pg->lock, flags); 699 696 return; 700 697 } 698 + if (pg->flags & ALUA_SYNC_STPG) 699 + alua_wq = kaluad_sync_wq; 701 700 pg->flags |= ALUA_PG_RUNNING; 702 701 if (pg->flags & ALUA_PG_RUN_RTPG) { 703 702 pg->flags &= ~ALUA_PG_RUN_RTPG; ··· 710 705 pg->flags &= ~ALUA_PG_RUNNING; 711 706 pg->flags |= ALUA_PG_RUN_RTPG; 712 707 spin_unlock_irqrestore(&pg->lock, flags); 713 - queue_delayed_work(kaluad_wq, &pg->rtpg_work, 708 + queue_delayed_work(alua_wq, &pg->rtpg_work, 714 709 pg->interval * HZ); 715 710 return; 716 711 } ··· 727 722 pg->interval = 0; 728 723 pg->flags &= ~ALUA_PG_RUNNING; 729 724 spin_unlock_irqrestore(&pg->lock, flags); 730 - queue_delayed_work(kaluad_wq, &pg->rtpg_work, 725 + queue_delayed_work(alua_wq, &pg->rtpg_work, 731 726 pg->interval * HZ); 732 727 return; 733 728 } ··· 756 751 { 757 752 int start_queue = 0; 758 753 unsigned long flags; 754 + struct workqueue_struct *alua_wq = kaluad_wq; 759 755 760 756 if (!pg) 761 757 return; ··· 774 768 scsi_device_get(sdev); 775 769 start_queue = 1; 776 770 } 771 + if (pg->flags & ALUA_SYNC_STPG) 772 + alua_wq = kaluad_sync_wq; 777 773 spin_unlock_irqrestore(&pg->lock, flags); 778 774 779 775 if (start_queue && 780 - !queue_delayed_work(kaluad_wq, &pg->rtpg_work, 776 + !queue_delayed_work(alua_wq, &pg->rtpg_work, 781 777 msecs_to_jiffies(ALUA_RTPG_DELAY_MSECS))) { 782 778 scsi_device_put(sdev); 783 779 kref_put(&pg->kref, release_port_group); ··· 998 990 /* Temporary failure, bypass */ 999 991 return SCSI_DH_DEV_TEMP_BUSY; 1000 992 } 993 + kaluad_sync_wq = create_workqueue("kaluad_sync"); 994 + if (!kaluad_sync_wq) { 995 + destroy_workqueue(kaluad_wq); 996 + return SCSI_DH_DEV_TEMP_BUSY; 997 + } 1001 998 r = scsi_register_device_handler(&alua_dh); 1002 999 if (r != 0) { 1003 1000 printk(KERN_ERR "%s: Failed to register scsi device handler", 1004 1001 ALUA_DH_NAME); 1002 + destroy_workqueue(kaluad_sync_wq); 1005 1003 destroy_workqueue(kaluad_wq); 1006 1004 } 1007 1005 return r; ··· 1016 1002 static void __exit alua_exit(void) 1017 1003 { 1018 1004 scsi_unregister_device_handler(&alua_dh); 1005 + destroy_workqueue(kaluad_sync_wq); 1019 1006 destroy_workqueue(kaluad_wq); 1020 1007 } 1021 1008