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

scsi: target/core: Make ABORT and LUN RESET handling synchronous

Instead of invoking target driver callback functions from the context that
handles an abort or LUN RESET task management function, only set the abort
flag from that context and perform the actual abort handling from the
context of the regular command processing flow. This approach has the
advantage that the task management code becomes much easier to read and to
verify since the number of potential race conditions against the command
processing flow is strongly reduced.

This patch has been tested by running the following two shell commands
concurrently for about ten minutes for both the iSCSI and the SRP target
drivers ($dev is an initiator device node connected with storage provided
by the target driver under test):

* fio with data verification enabled on a filesystem mounted on top of
$dev.

* while true; do sg_reset -d $dev; echo -n .; sleep .1; done

Cc: Nicholas Bellinger <nab@linux-iscsi.org>
Cc: Mike Christie <mchristi@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: David Disseldorp <ddiss@suse.de>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Bart Van Assche and committed by
Martin K. Petersen
2c9fa49e aaa00cc9

+149 -135
-2
drivers/target/target_core_internal.h
··· 138 138 void release_se_kmem_caches(void); 139 139 u32 scsi_get_new_index(scsi_index_t); 140 140 void transport_subsystem_check_init(void); 141 - int transport_cmd_finish_abort(struct se_cmd *); 142 141 unsigned char *transport_dump_cmd_direction(struct se_cmd *); 143 142 void transport_dump_dev_state(struct se_device *, char *, int *); 144 143 void transport_dump_dev_info(struct se_device *, struct se_lun *, ··· 147 148 int transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int); 148 149 int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); 149 150 void transport_clear_lun_ref(struct se_lun *); 150 - void transport_send_task_abort(struct se_cmd *); 151 151 sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); 152 152 void target_qf_do_work(struct work_struct *work); 153 153 bool target_check_wce(struct se_device *dev);
+28 -21
drivers/target/target_core_tmr.c
··· 171 171 172 172 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); 173 173 174 - cancel_work_sync(&se_cmd->work); 175 - transport_wait_for_tasks(se_cmd); 174 + /* 175 + * Ensure that this ABORT request is visible to the LU RESET 176 + * code. 177 + */ 178 + if (!tmr->tmr_dev) 179 + WARN_ON_ONCE(transport_lookup_tmr_lun(tmr->task_cmd, 180 + se_cmd->orig_fe_lun) < 0); 176 181 177 - if (!transport_cmd_finish_abort(se_cmd)) 178 - target_put_sess_cmd(se_cmd); 182 + target_put_cmd_and_wait(se_cmd); 179 183 180 184 printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" 181 185 " ref_tag: %llu\n", ref_tag); ··· 273 269 (preempt_and_abort_list) ? "Preempt" : "", tmr_p, 274 270 tmr_p->function, tmr_p->response, cmd->t_state); 275 271 276 - cancel_work_sync(&cmd->work); 277 - transport_wait_for_tasks(cmd); 278 - 279 - if (!transport_cmd_finish_abort(cmd)) 280 - target_put_sess_cmd(cmd); 272 + target_put_cmd_and_wait(cmd); 281 273 } 282 274 } 283 275 276 + /** 277 + * core_tmr_drain_state_list() - abort SCSI commands associated with a device 278 + * 279 + * @dev: Device for which to abort outstanding SCSI commands. 280 + * @prout_cmd: Pointer to the SCSI PREEMPT AND ABORT if this function is called 281 + * to realize the PREEMPT AND ABORT functionality. 282 + * @tmr_sess: Session through which the LUN RESET has been received. 283 + * @tas: Task Aborted Status (TAS) bit from the SCSI control mode page. 284 + * A quote from SPC-4, paragraph "7.5.10 Control mode page": 285 + * "A task aborted status (TAS) bit set to zero specifies that 286 + * aborted commands shall be terminated by the device server 287 + * without any response to the application client. A TAS bit set 288 + * to one specifies that commands aborted by the actions of an I_T 289 + * nexus other than the I_T nexus on which the command was 290 + * received shall be completed with TASK ABORTED status." 291 + * @preempt_and_abort_list: For the PREEMPT AND ABORT functionality, a list 292 + * with registrations that will be preempted. 293 + */ 284 294 static void core_tmr_drain_state_list( 285 295 struct se_device *dev, 286 296 struct se_cmd *prout_cmd, ··· 369 351 cmd->tag, (preempt_and_abort_list) ? "preempt" : "", 370 352 cmd->pr_res_key); 371 353 372 - /* 373 - * If the command may be queued onto a workqueue cancel it now. 374 - * 375 - * This is equivalent to removal from the execute queue in the 376 - * loop above, but we do it down here given that 377 - * cancel_work_sync may block. 378 - */ 379 - cancel_work_sync(&cmd->work); 380 - transport_wait_for_tasks(cmd); 381 - 382 - if (!transport_cmd_finish_abort(cmd)) 383 - target_put_sess_cmd(cmd); 354 + target_put_cmd_and_wait(cmd); 384 355 } 385 356 } 386 357
+120 -112
drivers/target/target_core_transport.c
··· 707 707 percpu_ref_put(&lun->lun_ref); 708 708 } 709 709 710 - int transport_cmd_finish_abort(struct se_cmd *cmd) 711 - { 712 - bool send_tas = cmd->transport_state & CMD_T_TAS; 713 - bool ack_kref = (cmd->se_cmd_flags & SCF_ACK_KREF); 714 - int ret = 0; 715 - 716 - if (send_tas) 717 - transport_send_task_abort(cmd); 718 - 719 - if (cmd->se_cmd_flags & SCF_SE_LUN_CMD) 720 - transport_lun_remove_cmd(cmd); 721 - /* 722 - * Allow the fabric driver to unmap any resources before 723 - * releasing the descriptor via TFO->release_cmd() 724 - */ 725 - if (!send_tas) 726 - cmd->se_tfo->aborted_task(cmd); 727 - 728 - if (transport_cmd_check_stop_to_fabric(cmd)) 729 - return 1; 730 - if (!send_tas && ack_kref) 731 - ret = target_put_sess_cmd(cmd); 732 - 733 - return ret; 734 - } 735 - 736 710 static void target_complete_failure_work(struct work_struct *work) 737 711 { 738 712 struct se_cmd *cmd = container_of(work, struct se_cmd, work); ··· 756 782 } 757 783 EXPORT_SYMBOL(transport_copy_sense_to_cmd); 758 784 785 + static void target_handle_abort(struct se_cmd *cmd) 786 + { 787 + bool tas = cmd->transport_state & CMD_T_TAS; 788 + bool ack_kref = cmd->se_cmd_flags & SCF_ACK_KREF; 789 + int ret; 790 + 791 + pr_debug("tag %#llx: send_abort_response = %d\n", cmd->tag, tas); 792 + 793 + if (tas) { 794 + if (!(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) { 795 + cmd->scsi_status = SAM_STAT_TASK_ABORTED; 796 + pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x, ITT: 0x%08llx\n", 797 + cmd->t_task_cdb[0], cmd->tag); 798 + trace_target_cmd_complete(cmd); 799 + ret = cmd->se_tfo->queue_status(cmd); 800 + if (ret) { 801 + transport_handle_queue_full(cmd, cmd->se_dev, 802 + ret, false); 803 + return; 804 + } 805 + } else { 806 + cmd->se_tmr_req->response = TMR_FUNCTION_REJECTED; 807 + cmd->se_tfo->queue_tm_rsp(cmd); 808 + } 809 + } else { 810 + /* 811 + * Allow the fabric driver to unmap any resources before 812 + * releasing the descriptor via TFO->release_cmd(). 813 + */ 814 + cmd->se_tfo->aborted_task(cmd); 815 + if (ack_kref) 816 + WARN_ON_ONCE(target_put_sess_cmd(cmd) != 0); 817 + /* 818 + * To do: establish a unit attention condition on the I_T 819 + * nexus associated with cmd. See also the paragraph "Aborting 820 + * commands" in SAM. 821 + */ 822 + } 823 + 824 + WARN_ON_ONCE(kref_read(&cmd->cmd_kref) == 0); 825 + 826 + transport_lun_remove_cmd(cmd); 827 + 828 + transport_cmd_check_stop_to_fabric(cmd); 829 + } 830 + 831 + static void target_abort_work(struct work_struct *work) 832 + { 833 + struct se_cmd *cmd = container_of(work, struct se_cmd, work); 834 + 835 + target_handle_abort(cmd); 836 + } 837 + 838 + static bool target_cmd_interrupted(struct se_cmd *cmd) 839 + { 840 + int post_ret; 841 + 842 + if (cmd->transport_state & CMD_T_ABORTED) { 843 + if (cmd->transport_complete_callback) 844 + cmd->transport_complete_callback(cmd, false, &post_ret); 845 + INIT_WORK(&cmd->work, target_abort_work); 846 + queue_work(target_completion_wq, &cmd->work); 847 + return true; 848 + } else if (cmd->transport_state & CMD_T_STOP) { 849 + if (cmd->transport_complete_callback) 850 + cmd->transport_complete_callback(cmd, false, &post_ret); 851 + complete_all(&cmd->t_transport_stop_comp); 852 + return true; 853 + } 854 + 855 + return false; 856 + } 857 + 858 + /* May be called from interrupt context so must not sleep. */ 759 859 void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) 760 860 { 761 - struct se_device *dev = cmd->se_dev; 762 861 int success; 763 862 unsigned long flags; 863 + 864 + if (target_cmd_interrupted(cmd)) 865 + return; 764 866 765 867 cmd->scsi_status = scsi_status; 766 868 ··· 853 803 break; 854 804 } 855 805 856 - /* 857 - * Check for case where an explicit ABORT_TASK has been received 858 - * and transport_wait_for_tasks() will be waiting for completion.. 859 - */ 860 - if (cmd->transport_state & CMD_T_ABORTED || 861 - cmd->transport_state & CMD_T_STOP) { 862 - spin_unlock_irqrestore(&cmd->t_state_lock, flags); 863 - /* 864 - * If COMPARE_AND_WRITE was stopped by __transport_wait_for_tasks(), 865 - * release se_device->caw_sem obtained by sbc_compare_and_write() 866 - * since target_complete_ok_work() or target_complete_failure_work() 867 - * won't be called to invoke the normal CAW completion callbacks. 868 - */ 869 - if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) { 870 - up(&dev->caw_sem); 871 - } 872 - complete_all(&cmd->t_transport_stop_comp); 873 - return; 874 - } else if (!success) { 806 + if (!success) { 875 807 INIT_WORK(&cmd->work, target_complete_failure_work); 876 808 } else { 877 809 INIT_WORK(&cmd->work, target_complete_ok_work); ··· 1837 1805 if (cmd->transport_complete_callback) 1838 1806 cmd->transport_complete_callback(cmd, false, NULL); 1839 1807 1840 - if (cmd->transport_state & CMD_T_ABORTED) 1808 + if (cmd->transport_state & CMD_T_ABORTED) { 1809 + INIT_WORK(&cmd->work, target_abort_work); 1810 + queue_work(target_completion_wq, &cmd->work); 1841 1811 return; 1812 + } 1842 1813 1843 1814 switch (sense_reason) { 1844 1815 case TCM_NON_EXISTENT_LUN: ··· 2055 2020 * 2056 2021 * If the received CDB has already been aborted stop processing it here. 2057 2022 */ 2023 + if (target_cmd_interrupted(cmd)) 2024 + return; 2025 + 2058 2026 spin_lock_irq(&cmd->t_state_lock); 2059 - if (cmd->transport_state & CMD_T_ABORTED) { 2060 - spin_unlock_irq(&cmd->t_state_lock); 2061 - return; 2062 - } 2063 - if (cmd->transport_state & CMD_T_STOP) { 2064 - pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08llx\n", 2065 - __func__, __LINE__, cmd->tag); 2066 - 2067 - spin_unlock_irq(&cmd->t_state_lock); 2068 - complete_all(&cmd->t_transport_stop_comp); 2069 - return; 2070 - } 2071 - 2072 2027 cmd->t_state = TRANSPORT_PROCESSING; 2073 2028 cmd->transport_state &= ~CMD_T_PRE_EXECUTE; 2074 2029 cmd->transport_state |= CMD_T_ACTIVE | CMD_T_SENT; ··· 2672 2647 } 2673 2648 2674 2649 /* 2650 + * Call target_put_sess_cmd() and wait until target_release_cmd_kref(@cmd) has 2651 + * finished. 2652 + */ 2653 + void target_put_cmd_and_wait(struct se_cmd *cmd) 2654 + { 2655 + DECLARE_COMPLETION_ONSTACK(compl); 2656 + 2657 + WARN_ON_ONCE(cmd->abrt_compl); 2658 + cmd->abrt_compl = &compl; 2659 + target_put_sess_cmd(cmd); 2660 + wait_for_completion(&compl); 2661 + } 2662 + 2663 + /* 2675 2664 * This function is called by frontend drivers after processing of a command 2676 2665 * has finished. 2677 2666 * 2678 - * The protocol for ensuring that either the regular flow or the TMF 2679 - * code drops one reference is as follows: 2667 + * The protocol for ensuring that either the regular frontend command 2668 + * processing flow or target_handle_abort() code drops one reference is as 2669 + * follows: 2680 2670 * - Calling .queue_data_in(), .queue_status() or queue_tm_rsp() will cause 2681 - * the frontend driver to drop one reference, synchronously or asynchronously. 2671 + * the frontend driver to call this function synchronously or asynchronously. 2672 + * That will cause one reference to be dropped. 2682 2673 * - During regular command processing the target core sets CMD_T_COMPLETE 2683 2674 * before invoking one of the .queue_*() functions. 2684 2675 * - The code that aborts commands skips commands and TMFs for which ··· 2706 2665 * - For aborted commands for which CMD_T_TAS has been set .queue_status() will 2707 2666 * be called and will drop a reference. 2708 2667 * - For aborted commands for which CMD_T_TAS has not been set .aborted_task() 2709 - * will be called. transport_cmd_finish_abort() will drop the final reference. 2668 + * will be called. target_handle_abort() will drop the final reference. 2710 2669 */ 2711 2670 int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) 2712 2671 { ··· 2731 2690 } 2732 2691 if (aborted) 2733 2692 cmd->free_compl = &compl; 2734 - if (!aborted || tas) 2735 - ret = target_put_sess_cmd(cmd); 2693 + ret = target_put_sess_cmd(cmd); 2736 2694 if (aborted) { 2737 2695 pr_debug("Detected CMD_T_ABORTED for ITT: %llu\n", cmd->tag); 2738 2696 wait_for_completion(&compl); ··· 3259 3219 { 3260 3220 unsigned long flags; 3261 3221 3222 + WARN_ON_ONCE(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB); 3223 + 3262 3224 spin_lock_irqsave(&cmd->t_state_lock, flags); 3263 3225 if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { 3264 3226 spin_unlock_irqrestore(&cmd->t_state_lock, flags); ··· 3277 3235 } 3278 3236 EXPORT_SYMBOL(transport_send_check_condition_and_sense); 3279 3237 3280 - void transport_send_task_abort(struct se_cmd *cmd) 3281 - { 3282 - unsigned long flags; 3283 - int ret; 3284 - 3285 - spin_lock_irqsave(&cmd->t_state_lock, flags); 3286 - if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION)) { 3287 - spin_unlock_irqrestore(&cmd->t_state_lock, flags); 3288 - return; 3289 - } 3290 - spin_unlock_irqrestore(&cmd->t_state_lock, flags); 3291 - 3292 - cmd->scsi_status = SAM_STAT_TASK_ABORTED; 3293 - 3294 - transport_lun_remove_cmd(cmd); 3295 - 3296 - pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x, ITT: 0x%08llx\n", 3297 - cmd->t_task_cdb[0], cmd->tag); 3298 - 3299 - trace_target_cmd_complete(cmd); 3300 - ret = cmd->se_tfo->queue_status(cmd); 3301 - if (ret) 3302 - transport_handle_queue_full(cmd, cmd->se_dev, ret, false); 3303 - } 3304 - 3305 3238 static void target_tmr_work(struct work_struct *work) 3306 3239 { 3307 3240 struct se_cmd *cmd = container_of(work, struct se_cmd, work); 3308 3241 struct se_device *dev = cmd->se_dev; 3309 3242 struct se_tmr_req *tmr = cmd->se_tmr_req; 3310 - unsigned long flags; 3311 3243 int ret; 3312 3244 3313 - spin_lock_irqsave(&cmd->t_state_lock, flags); 3314 - if (cmd->transport_state & CMD_T_ABORTED) { 3315 - tmr->response = TMR_FUNCTION_REJECTED; 3316 - spin_unlock_irqrestore(&cmd->t_state_lock, flags); 3317 - goto check_stop; 3318 - } 3319 - spin_unlock_irqrestore(&cmd->t_state_lock, flags); 3245 + if (cmd->transport_state & CMD_T_ABORTED) 3246 + goto aborted; 3320 3247 3321 3248 switch (tmr->function) { 3322 3249 case TMR_ABORT_TASK: ··· 3319 3308 break; 3320 3309 } 3321 3310 3322 - spin_lock_irqsave(&cmd->t_state_lock, flags); 3323 - if (cmd->transport_state & CMD_T_ABORTED) { 3324 - spin_unlock_irqrestore(&cmd->t_state_lock, flags); 3325 - goto check_stop; 3326 - } 3327 - spin_unlock_irqrestore(&cmd->t_state_lock, flags); 3311 + if (cmd->transport_state & CMD_T_ABORTED) 3312 + goto aborted; 3328 3313 3329 3314 cmd->se_tfo->queue_tm_rsp(cmd); 3330 3315 3331 - check_stop: 3332 - transport_lun_remove_cmd(cmd); 3333 3316 transport_cmd_check_stop_to_fabric(cmd); 3317 + return; 3318 + 3319 + aborted: 3320 + target_handle_abort(cmd); 3334 3321 } 3335 3322 3336 3323 int transport_generic_handle_tmr( ··· 3347 3338 spin_unlock_irqrestore(&cmd->t_state_lock, flags); 3348 3339 3349 3340 if (aborted) { 3350 - pr_warn_ratelimited("handle_tmr caught CMD_T_ABORTED TMR %d" 3351 - "ref_tag: %llu tag: %llu\n", cmd->se_tmr_req->function, 3352 - cmd->se_tmr_req->ref_task_tag, cmd->tag); 3353 - transport_lun_remove_cmd(cmd); 3354 - transport_cmd_check_stop_to_fabric(cmd); 3341 + pr_warn_ratelimited("handle_tmr caught CMD_T_ABORTED TMR %d ref_tag: %llu tag: %llu\n", 3342 + cmd->se_tmr_req->function, 3343 + cmd->se_tmr_req->ref_task_tag, cmd->tag); 3344 + target_handle_abort(cmd); 3355 3345 return 0; 3356 3346 } 3357 3347
+1
include/target/target_core_fabric.h
··· 166 166 int transport_handle_cdb_direct(struct se_cmd *); 167 167 sense_reason_t transport_generic_new_cmd(struct se_cmd *); 168 168 169 + void target_put_cmd_and_wait(struct se_cmd *cmd); 169 170 void target_execute_cmd(struct se_cmd *cmd); 170 171 171 172 int transport_generic_free_cmd(struct se_cmd *, int);