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

scsi: target: Make state_list per CPU

Do a state_list/execute_task_lock per CPU, so we can do submissions from
different CPUs without contention with each other.

Note: tcm_fc was passing TARGET_SCF_USE_CPUID, but never set cpuid. The
assumption is that it wanted to set the cpuid to the CPU it was submitting
from so it will get this behavior with this patch.

[mkp: s/printk/pr_err/ + resolve COMPARE AND WRITE patch conflict]

Link: https://lore.kernel.org/r/1604257174-4524-8-git-send-email-michael.christie@oracle.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Mike Christie and committed by
Martin K. Petersen
1526d9f1 6f55b06f

+112 -84
+14 -2
drivers/target/target_core_device.c
··· 721 721 { 722 722 struct se_device *dev; 723 723 struct se_lun *xcopy_lun; 724 + int i; 724 725 725 726 dev = hba->backend->ops->alloc_device(hba, name); 726 727 if (!dev) 727 728 return NULL; 729 + 730 + dev->queues = kcalloc(nr_cpu_ids, sizeof(*dev->queues), GFP_KERNEL); 731 + if (!dev->queues) { 732 + dev->transport->free_device(dev); 733 + return NULL; 734 + } 735 + 736 + dev->queue_cnt = nr_cpu_ids; 737 + for (i = 0; i < dev->queue_cnt; i++) { 738 + INIT_LIST_HEAD(&dev->queues[i].state_list); 739 + spin_lock_init(&dev->queues[i].lock); 740 + } 728 741 729 742 dev->se_hba = hba; 730 743 dev->transport = hba->backend->ops; ··· 748 735 INIT_LIST_HEAD(&dev->dev_sep_list); 749 736 INIT_LIST_HEAD(&dev->dev_tmr_list); 750 737 INIT_LIST_HEAD(&dev->delayed_cmd_list); 751 - INIT_LIST_HEAD(&dev->state_list); 752 738 INIT_LIST_HEAD(&dev->qf_cmd_list); 753 - spin_lock_init(&dev->execute_task_lock); 754 739 spin_lock_init(&dev->delayed_cmd_lock); 755 740 spin_lock_init(&dev->dev_reservation_lock); 756 741 spin_lock_init(&dev->se_port_lock); ··· 1021 1010 if (dev->transport->free_prot) 1022 1011 dev->transport->free_prot(dev); 1023 1012 1013 + kfree(dev->queues); 1024 1014 dev->transport->free_device(dev); 1025 1015 } 1026 1016
+73 -65
drivers/target/target_core_tmr.c
··· 121 121 unsigned long flags; 122 122 bool rc; 123 123 u64 ref_tag; 124 + int i; 124 125 125 - spin_lock_irqsave(&dev->execute_task_lock, flags); 126 - list_for_each_entry_safe(se_cmd, next, &dev->state_list, state_list) { 126 + for (i = 0; i < dev->queue_cnt; i++) { 127 + spin_lock_irqsave(&dev->queues[i].lock, flags); 128 + list_for_each_entry_safe(se_cmd, next, &dev->queues[i].state_list, 129 + state_list) { 130 + if (se_sess != se_cmd->se_sess) 131 + continue; 127 132 128 - if (se_sess != se_cmd->se_sess) 129 - continue; 133 + /* 134 + * skip task management functions, including 135 + * tmr->task_cmd 136 + */ 137 + if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) 138 + continue; 130 139 131 - /* skip task management functions, including tmr->task_cmd */ 132 - if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) 133 - continue; 140 + ref_tag = se_cmd->tag; 141 + if (tmr->ref_task_tag != ref_tag) 142 + continue; 134 143 135 - ref_tag = se_cmd->tag; 136 - if (tmr->ref_task_tag != ref_tag) 137 - continue; 144 + pr_err("ABORT_TASK: Found referenced %s task_tag: %llu\n", 145 + se_cmd->se_tfo->fabric_name, ref_tag); 138 146 139 - printk("ABORT_TASK: Found referenced %s task_tag: %llu\n", 140 - se_cmd->se_tfo->fabric_name, ref_tag); 147 + spin_lock(&se_sess->sess_cmd_lock); 148 + rc = __target_check_io_state(se_cmd, se_sess, 0); 149 + spin_unlock(&se_sess->sess_cmd_lock); 150 + if (!rc) 151 + continue; 141 152 142 - spin_lock(&se_sess->sess_cmd_lock); 143 - rc = __target_check_io_state(se_cmd, se_sess, 0); 144 - spin_unlock(&se_sess->sess_cmd_lock); 145 - if (!rc) 146 - continue; 153 + list_move_tail(&se_cmd->state_list, &aborted_list); 154 + se_cmd->state_active = false; 155 + spin_unlock_irqrestore(&dev->queues[i].lock, flags); 147 156 148 - list_move_tail(&se_cmd->state_list, &aborted_list); 149 - se_cmd->state_active = false; 157 + /* 158 + * Ensure that this ABORT request is visible to the LU 159 + * RESET code. 160 + */ 161 + if (!tmr->tmr_dev) 162 + WARN_ON_ONCE(transport_lookup_tmr_lun(tmr->task_cmd) < 0); 150 163 151 - spin_unlock_irqrestore(&dev->execute_task_lock, flags); 164 + if (dev->transport->tmr_notify) 165 + dev->transport->tmr_notify(dev, TMR_ABORT_TASK, 166 + &aborted_list); 152 167 153 - /* 154 - * Ensure that this ABORT request is visible to the LU RESET 155 - * code. 156 - */ 157 - if (!tmr->tmr_dev) 158 - WARN_ON_ONCE(transport_lookup_tmr_lun(tmr->task_cmd) < 159 - 0); 168 + list_del_init(&se_cmd->state_list); 169 + target_put_cmd_and_wait(se_cmd); 160 170 161 - if (dev->transport->tmr_notify) 162 - dev->transport->tmr_notify(dev, TMR_ABORT_TASK, 163 - &aborted_list); 164 - 165 - list_del_init(&se_cmd->state_list); 166 - target_put_cmd_and_wait(se_cmd); 167 - 168 - printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" 169 - " ref_tag: %llu\n", ref_tag); 170 - tmr->response = TMR_FUNCTION_COMPLETE; 171 - atomic_long_inc(&dev->aborts_complete); 172 - return; 171 + pr_err("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for ref_tag: %llu\n", 172 + ref_tag); 173 + tmr->response = TMR_FUNCTION_COMPLETE; 174 + atomic_long_inc(&dev->aborts_complete); 175 + return; 176 + } 177 + spin_unlock_irqrestore(&dev->queues[i].lock, flags); 173 178 } 174 - spin_unlock_irqrestore(&dev->execute_task_lock, flags); 175 179 176 180 if (dev->transport->tmr_notify) 177 181 dev->transport->tmr_notify(dev, TMR_ABORT_TASK, &aborted_list); ··· 277 273 struct se_session *sess; 278 274 struct se_cmd *cmd, *next; 279 275 unsigned long flags; 280 - int rc; 276 + int rc, i; 281 277 282 278 /* 283 279 * Complete outstanding commands with TASK_ABORTED SAM status. ··· 301 297 * Note that this seems to be independent of TAS (Task Aborted Status) 302 298 * in the Control Mode Page. 303 299 */ 304 - spin_lock_irqsave(&dev->execute_task_lock, flags); 305 - list_for_each_entry_safe(cmd, next, &dev->state_list, state_list) { 306 - /* 307 - * For PREEMPT_AND_ABORT usage, only process commands 308 - * with a matching reservation key. 309 - */ 310 - if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd)) 311 - continue; 300 + for (i = 0; i < dev->queue_cnt; i++) { 301 + spin_lock_irqsave(&dev->queues[i].lock, flags); 302 + list_for_each_entry_safe(cmd, next, &dev->queues[i].state_list, 303 + state_list) { 304 + /* 305 + * For PREEMPT_AND_ABORT usage, only process commands 306 + * with a matching reservation key. 307 + */ 308 + if (target_check_cdb_and_preempt(preempt_and_abort_list, 309 + cmd)) 310 + continue; 312 311 313 - /* 314 - * Not aborting PROUT PREEMPT_AND_ABORT CDB.. 315 - */ 316 - if (prout_cmd == cmd) 317 - continue; 312 + /* 313 + * Not aborting PROUT PREEMPT_AND_ABORT CDB.. 314 + */ 315 + if (prout_cmd == cmd) 316 + continue; 318 317 319 - sess = cmd->se_sess; 320 - if (WARN_ON_ONCE(!sess)) 321 - continue; 318 + sess = cmd->se_sess; 319 + if (WARN_ON_ONCE(!sess)) 320 + continue; 322 321 323 - spin_lock(&sess->sess_cmd_lock); 324 - rc = __target_check_io_state(cmd, tmr_sess, tas); 325 - spin_unlock(&sess->sess_cmd_lock); 326 - if (!rc) 327 - continue; 322 + spin_lock(&sess->sess_cmd_lock); 323 + rc = __target_check_io_state(cmd, tmr_sess, tas); 324 + spin_unlock(&sess->sess_cmd_lock); 325 + if (!rc) 326 + continue; 328 327 329 - list_move_tail(&cmd->state_list, &drain_task_list); 330 - cmd->state_active = false; 328 + list_move_tail(&cmd->state_list, &drain_task_list); 329 + cmd->state_active = false; 330 + } 331 + spin_unlock_irqrestore(&dev->queues[i].lock, flags); 331 332 } 332 - spin_unlock_irqrestore(&dev->execute_task_lock, flags); 333 333 334 334 if (dev->transport->tmr_notify) 335 335 dev->transport->tmr_notify(dev, preempt_and_abort_list ?
+13 -14
drivers/target/target_core_transport.c
··· 659 659 if (!dev) 660 660 return; 661 661 662 - spin_lock_irqsave(&dev->execute_task_lock, flags); 662 + spin_lock_irqsave(&dev->queues[cmd->cpuid].lock, flags); 663 663 if (cmd->state_active) { 664 664 list_del(&cmd->state_list); 665 665 cmd->state_active = false; 666 666 } 667 - spin_unlock_irqrestore(&dev->execute_task_lock, flags); 667 + spin_unlock_irqrestore(&dev->queues[cmd->cpuid].lock, flags); 668 668 } 669 669 670 670 /* ··· 875 875 876 876 INIT_WORK(&cmd->work, success ? target_complete_ok_work : 877 877 target_complete_failure_work); 878 - if (cmd->se_cmd_flags & SCF_USE_CPUID) 879 - queue_work_on(cmd->cpuid, target_completion_wq, &cmd->work); 880 - else 881 - queue_work(target_completion_wq, &cmd->work); 878 + queue_work_on(cmd->cpuid, target_completion_wq, &cmd->work); 882 879 } 883 880 EXPORT_SYMBOL(target_complete_cmd); 884 881 ··· 903 906 struct se_device *dev = cmd->se_dev; 904 907 unsigned long flags; 905 908 906 - spin_lock_irqsave(&dev->execute_task_lock, flags); 909 + spin_lock_irqsave(&dev->queues[cmd->cpuid].lock, flags); 907 910 if (!cmd->state_active) { 908 - list_add_tail(&cmd->state_list, &dev->state_list); 911 + list_add_tail(&cmd->state_list, 912 + &dev->queues[cmd->cpuid].state_list); 909 913 cmd->state_active = true; 910 914 } 911 - spin_unlock_irqrestore(&dev->execute_task_lock, flags); 915 + spin_unlock_irqrestore(&dev->queues[cmd->cpuid].lock, flags); 912 916 } 913 917 914 918 /* ··· 1397 1399 cmd->sense_buffer = sense_buffer; 1398 1400 cmd->orig_fe_lun = unpacked_lun; 1399 1401 1402 + if (!(cmd->se_cmd_flags & SCF_USE_CPUID)) 1403 + cmd->cpuid = smp_processor_id(); 1404 + 1400 1405 cmd->state_active = false; 1401 1406 } 1402 1407 EXPORT_SYMBOL(transport_init_se_cmd); ··· 1617 1616 BUG_ON(!se_tpg); 1618 1617 BUG_ON(se_cmd->se_tfo || se_cmd->se_sess); 1619 1618 BUG_ON(in_interrupt()); 1619 + 1620 + if (flags & TARGET_SCF_USE_CPUID) 1621 + se_cmd->se_cmd_flags |= SCF_USE_CPUID; 1620 1622 /* 1621 1623 * Initialize se_cmd for target operation. From this point 1622 1624 * exceptions are handled by sending exception status via ··· 1628 1624 transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 1629 1625 data_length, data_dir, task_attr, sense, 1630 1626 unpacked_lun); 1631 - 1632 - if (flags & TARGET_SCF_USE_CPUID) 1633 - se_cmd->se_cmd_flags |= SCF_USE_CPUID; 1634 - else 1635 - se_cmd->cpuid = WORK_CPU_UNBOUND; 1636 1627 1637 1628 if (flags & TARGET_SCF_UNKNOWN_SIZE) 1638 1629 se_cmd->unknown_data_length = 1;
+1 -1
drivers/target/tcm_fc/tfc_cmd.c
··· 550 550 if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb, 551 551 &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun), 552 552 ntohl(fcp->fc_dl), task_attr, data_dir, 553 - TARGET_SCF_ACK_KREF | TARGET_SCF_USE_CPUID)) 553 + TARGET_SCF_ACK_KREF)) 554 554 goto err; 555 555 556 556 pr_debug("r_ctl %x target_submit_cmd %p\n", fh->fh_r_ctl, cmd);
+11 -2
include/target/target_core_base.h
··· 540 540 unsigned int t_prot_nents; 541 541 sense_reason_t pi_err; 542 542 u64 sense_info; 543 + /* 544 + * CPU LIO will execute the cmd on. Defaults to the CPU the cmd is 545 + * initialized on. Drivers can override. 546 + */ 543 547 int cpuid; 544 548 }; 545 549 ··· 764 760 struct config_group scsi_lu_group; 765 761 }; 766 762 763 + struct se_device_queue { 764 + struct list_head state_list; 765 + spinlock_t lock; 766 + }; 767 + 767 768 struct se_device { 768 769 /* RELATIVE TARGET PORT IDENTIFER Counter */ 769 770 u16 dev_rpti_counter; ··· 801 792 atomic_t dev_qf_count; 802 793 u32 export_count; 803 794 spinlock_t delayed_cmd_lock; 804 - spinlock_t execute_task_lock; 805 795 spinlock_t dev_reservation_lock; 806 796 unsigned int dev_reservation_flags; 807 797 #define DRF_SPC2_RESERVATIONS 0x00000001 ··· 819 811 struct list_head dev_tmr_list; 820 812 struct work_struct qf_work_queue; 821 813 struct list_head delayed_cmd_list; 822 - struct list_head state_list; 823 814 struct list_head qf_cmd_list; 824 815 /* Pointer to associated SE HBA */ 825 816 struct se_hba *se_hba; ··· 845 838 /* For se_lun->lun_se_dev RCU read-side critical access */ 846 839 u32 hba_index; 847 840 struct rcu_head rcu_head; 841 + int queue_cnt; 842 + struct se_device_queue *queues; 848 843 }; 849 844 850 845 struct se_hba {