diff options
-rw-r--r-- | drivers/target/target_core_transport.c | 102 | ||||
-rw-r--r-- | include/target/target_core_base.h | 1 |
2 files changed, 69 insertions, 34 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index b1a3cdb29468..a0cd56ee5fe9 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -64,8 +64,9 @@ struct kmem_cache *t10_alua_lba_map_cache; | |||
64 | struct kmem_cache *t10_alua_lba_map_mem_cache; | 64 | struct kmem_cache *t10_alua_lba_map_mem_cache; |
65 | 65 | ||
66 | static void transport_complete_task_attr(struct se_cmd *cmd); | 66 | static void transport_complete_task_attr(struct se_cmd *cmd); |
67 | static int translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason); | ||
67 | static void transport_handle_queue_full(struct se_cmd *cmd, | 68 | static void transport_handle_queue_full(struct se_cmd *cmd, |
68 | struct se_device *dev); | 69 | struct se_device *dev, int err, bool write_pending); |
69 | static int transport_put_cmd(struct se_cmd *cmd); | 70 | static int transport_put_cmd(struct se_cmd *cmd); |
70 | static void target_complete_ok_work(struct work_struct *work); | 71 | static void target_complete_ok_work(struct work_struct *work); |
71 | 72 | ||
@@ -804,7 +805,8 @@ void target_qf_do_work(struct work_struct *work) | |||
804 | 805 | ||
805 | if (cmd->t_state == TRANSPORT_COMPLETE_QF_WP) | 806 | if (cmd->t_state == TRANSPORT_COMPLETE_QF_WP) |
806 | transport_write_pending_qf(cmd); | 807 | transport_write_pending_qf(cmd); |
807 | else if (cmd->t_state == TRANSPORT_COMPLETE_QF_OK) | 808 | else if (cmd->t_state == TRANSPORT_COMPLETE_QF_OK || |
809 | cmd->t_state == TRANSPORT_COMPLETE_QF_ERR) | ||
808 | transport_complete_qf(cmd); | 810 | transport_complete_qf(cmd); |
809 | } | 811 | } |
810 | } | 812 | } |
@@ -1719,7 +1721,7 @@ void transport_generic_request_failure(struct se_cmd *cmd, | |||
1719 | } | 1721 | } |
1720 | trace_target_cmd_complete(cmd); | 1722 | trace_target_cmd_complete(cmd); |
1721 | ret = cmd->se_tfo->queue_status(cmd); | 1723 | ret = cmd->se_tfo->queue_status(cmd); |
1722 | if (ret == -EAGAIN || ret == -ENOMEM) | 1724 | if (ret) |
1723 | goto queue_full; | 1725 | goto queue_full; |
1724 | goto check_stop; | 1726 | goto check_stop; |
1725 | default: | 1727 | default: |
@@ -1730,7 +1732,7 @@ void transport_generic_request_failure(struct se_cmd *cmd, | |||
1730 | } | 1732 | } |
1731 | 1733 | ||
1732 | ret = transport_send_check_condition_and_sense(cmd, sense_reason, 0); | 1734 | ret = transport_send_check_condition_and_sense(cmd, sense_reason, 0); |
1733 | if (ret == -EAGAIN || ret == -ENOMEM) | 1735 | if (ret) |
1734 | goto queue_full; | 1736 | goto queue_full; |
1735 | 1737 | ||
1736 | check_stop: | 1738 | check_stop: |
@@ -1739,8 +1741,7 @@ check_stop: | |||
1739 | return; | 1741 | return; |
1740 | 1742 | ||
1741 | queue_full: | 1743 | queue_full: |
1742 | cmd->t_state = TRANSPORT_COMPLETE_QF_OK; | 1744 | transport_handle_queue_full(cmd, cmd->se_dev, ret, false); |
1743 | transport_handle_queue_full(cmd, cmd->se_dev); | ||
1744 | } | 1745 | } |
1745 | EXPORT_SYMBOL(transport_generic_request_failure); | 1746 | EXPORT_SYMBOL(transport_generic_request_failure); |
1746 | 1747 | ||
@@ -1977,13 +1978,29 @@ static void transport_complete_qf(struct se_cmd *cmd) | |||
1977 | int ret = 0; | 1978 | int ret = 0; |
1978 | 1979 | ||
1979 | transport_complete_task_attr(cmd); | 1980 | transport_complete_task_attr(cmd); |
1981 | /* | ||
1982 | * If a fabric driver ->write_pending() or ->queue_data_in() callback | ||
1983 | * has returned neither -ENOMEM or -EAGAIN, assume it's fatal and | ||
1984 | * the same callbacks should not be retried. Return CHECK_CONDITION | ||
1985 | * if a scsi_status is not already set. | ||
1986 | * | ||
1987 | * If a fabric driver ->queue_status() has returned non zero, always | ||
1988 | * keep retrying no matter what.. | ||
1989 | */ | ||
1990 | if (cmd->t_state == TRANSPORT_COMPLETE_QF_ERR) { | ||
1991 | if (cmd->scsi_status) | ||
1992 | goto queue_status; | ||
1980 | 1993 | ||
1981 | if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { | 1994 | cmd->se_cmd_flags |= SCF_EMULATED_TASK_SENSE; |
1982 | trace_target_cmd_complete(cmd); | 1995 | cmd->scsi_status = SAM_STAT_CHECK_CONDITION; |
1983 | ret = cmd->se_tfo->queue_status(cmd); | 1996 | cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER; |
1984 | goto out; | 1997 | translate_sense_reason(cmd, TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE); |
1998 | goto queue_status; | ||
1985 | } | 1999 | } |
1986 | 2000 | ||
2001 | if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) | ||
2002 | goto queue_status; | ||
2003 | |||
1987 | switch (cmd->data_direction) { | 2004 | switch (cmd->data_direction) { |
1988 | case DMA_FROM_DEVICE: | 2005 | case DMA_FROM_DEVICE: |
1989 | if (cmd->scsi_status) | 2006 | if (cmd->scsi_status) |
@@ -2007,19 +2024,33 @@ queue_status: | |||
2007 | break; | 2024 | break; |
2008 | } | 2025 | } |
2009 | 2026 | ||
2010 | out: | ||
2011 | if (ret < 0) { | 2027 | if (ret < 0) { |
2012 | transport_handle_queue_full(cmd, cmd->se_dev); | 2028 | transport_handle_queue_full(cmd, cmd->se_dev, ret, false); |
2013 | return; | 2029 | return; |
2014 | } | 2030 | } |
2015 | transport_lun_remove_cmd(cmd); | 2031 | transport_lun_remove_cmd(cmd); |
2016 | transport_cmd_check_stop_to_fabric(cmd); | 2032 | transport_cmd_check_stop_to_fabric(cmd); |
2017 | } | 2033 | } |
2018 | 2034 | ||
2019 | static void transport_handle_queue_full( | 2035 | static void transport_handle_queue_full(struct se_cmd *cmd, struct se_device *dev, |
2020 | struct se_cmd *cmd, | 2036 | int err, bool write_pending) |
2021 | struct se_device *dev) | ||
2022 | { | 2037 | { |
2038 | /* | ||
2039 | * -EAGAIN or -ENOMEM signals retry of ->write_pending() and/or | ||
2040 | * ->queue_data_in() callbacks from new process context. | ||
2041 | * | ||
2042 | * Otherwise for other errors, transport_complete_qf() will send | ||
2043 | * CHECK_CONDITION via ->queue_status() instead of attempting to | ||
2044 | * retry associated fabric driver data-transfer callbacks. | ||
2045 | */ | ||
2046 | if (err == -EAGAIN || err == -ENOMEM) { | ||
2047 | cmd->t_state = (write_pending) ? TRANSPORT_COMPLETE_QF_WP : | ||
2048 | TRANSPORT_COMPLETE_QF_OK; | ||
2049 | } else { | ||
2050 | pr_warn_ratelimited("Got unknown fabric queue status: %d\n", err); | ||
2051 | cmd->t_state = TRANSPORT_COMPLETE_QF_ERR; | ||
2052 | } | ||
2053 | |||
2023 | spin_lock_irq(&dev->qf_cmd_lock); | 2054 | spin_lock_irq(&dev->qf_cmd_lock); |
2024 | list_add_tail(&cmd->se_qf_node, &cmd->se_dev->qf_cmd_list); | 2055 | list_add_tail(&cmd->se_qf_node, &cmd->se_dev->qf_cmd_list); |
2025 | atomic_inc_mb(&dev->dev_qf_count); | 2056 | atomic_inc_mb(&dev->dev_qf_count); |
@@ -2083,7 +2114,7 @@ static void target_complete_ok_work(struct work_struct *work) | |||
2083 | WARN_ON(!cmd->scsi_status); | 2114 | WARN_ON(!cmd->scsi_status); |
2084 | ret = transport_send_check_condition_and_sense( | 2115 | ret = transport_send_check_condition_and_sense( |
2085 | cmd, 0, 1); | 2116 | cmd, 0, 1); |
2086 | if (ret == -EAGAIN || ret == -ENOMEM) | 2117 | if (ret) |
2087 | goto queue_full; | 2118 | goto queue_full; |
2088 | 2119 | ||
2089 | transport_lun_remove_cmd(cmd); | 2120 | transport_lun_remove_cmd(cmd); |
@@ -2109,7 +2140,7 @@ static void target_complete_ok_work(struct work_struct *work) | |||
2109 | } else if (rc) { | 2140 | } else if (rc) { |
2110 | ret = transport_send_check_condition_and_sense(cmd, | 2141 | ret = transport_send_check_condition_and_sense(cmd, |
2111 | rc, 0); | 2142 | rc, 0); |
2112 | if (ret == -EAGAIN || ret == -ENOMEM) | 2143 | if (ret) |
2113 | goto queue_full; | 2144 | goto queue_full; |
2114 | 2145 | ||
2115 | transport_lun_remove_cmd(cmd); | 2146 | transport_lun_remove_cmd(cmd); |
@@ -2134,7 +2165,7 @@ queue_rsp: | |||
2134 | if (target_read_prot_action(cmd)) { | 2165 | if (target_read_prot_action(cmd)) { |
2135 | ret = transport_send_check_condition_and_sense(cmd, | 2166 | ret = transport_send_check_condition_and_sense(cmd, |
2136 | cmd->pi_err, 0); | 2167 | cmd->pi_err, 0); |
2137 | if (ret == -EAGAIN || ret == -ENOMEM) | 2168 | if (ret) |
2138 | goto queue_full; | 2169 | goto queue_full; |
2139 | 2170 | ||
2140 | transport_lun_remove_cmd(cmd); | 2171 | transport_lun_remove_cmd(cmd); |
@@ -2144,7 +2175,7 @@ queue_rsp: | |||
2144 | 2175 | ||
2145 | trace_target_cmd_complete(cmd); | 2176 | trace_target_cmd_complete(cmd); |
2146 | ret = cmd->se_tfo->queue_data_in(cmd); | 2177 | ret = cmd->se_tfo->queue_data_in(cmd); |
2147 | if (ret == -EAGAIN || ret == -ENOMEM) | 2178 | if (ret) |
2148 | goto queue_full; | 2179 | goto queue_full; |
2149 | break; | 2180 | break; |
2150 | case DMA_TO_DEVICE: | 2181 | case DMA_TO_DEVICE: |
@@ -2157,7 +2188,7 @@ queue_rsp: | |||
2157 | atomic_long_add(cmd->data_length, | 2188 | atomic_long_add(cmd->data_length, |
2158 | &cmd->se_lun->lun_stats.tx_data_octets); | 2189 | &cmd->se_lun->lun_stats.tx_data_octets); |
2159 | ret = cmd->se_tfo->queue_data_in(cmd); | 2190 | ret = cmd->se_tfo->queue_data_in(cmd); |
2160 | if (ret == -EAGAIN || ret == -ENOMEM) | 2191 | if (ret) |
2161 | goto queue_full; | 2192 | goto queue_full; |
2162 | break; | 2193 | break; |
2163 | } | 2194 | } |
@@ -2166,7 +2197,7 @@ queue_rsp: | |||
2166 | queue_status: | 2197 | queue_status: |
2167 | trace_target_cmd_complete(cmd); | 2198 | trace_target_cmd_complete(cmd); |
2168 | ret = cmd->se_tfo->queue_status(cmd); | 2199 | ret = cmd->se_tfo->queue_status(cmd); |
2169 | if (ret == -EAGAIN || ret == -ENOMEM) | 2200 | if (ret) |
2170 | goto queue_full; | 2201 | goto queue_full; |
2171 | break; | 2202 | break; |
2172 | default: | 2203 | default: |
@@ -2180,8 +2211,8 @@ queue_status: | |||
2180 | queue_full: | 2211 | queue_full: |
2181 | pr_debug("Handling complete_ok QUEUE_FULL: se_cmd: %p," | 2212 | pr_debug("Handling complete_ok QUEUE_FULL: se_cmd: %p," |
2182 | " data_direction: %d\n", cmd, cmd->data_direction); | 2213 | " data_direction: %d\n", cmd, cmd->data_direction); |
2183 | cmd->t_state = TRANSPORT_COMPLETE_QF_OK; | 2214 | |
2184 | transport_handle_queue_full(cmd, cmd->se_dev); | 2215 | transport_handle_queue_full(cmd, cmd->se_dev, ret, false); |
2185 | } | 2216 | } |
2186 | 2217 | ||
2187 | void target_free_sgl(struct scatterlist *sgl, int nents) | 2218 | void target_free_sgl(struct scatterlist *sgl, int nents) |
@@ -2449,18 +2480,14 @@ transport_generic_new_cmd(struct se_cmd *cmd) | |||
2449 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | 2480 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
2450 | 2481 | ||
2451 | ret = cmd->se_tfo->write_pending(cmd); | 2482 | ret = cmd->se_tfo->write_pending(cmd); |
2452 | if (ret == -EAGAIN || ret == -ENOMEM) | 2483 | if (ret) |
2453 | goto queue_full; | 2484 | goto queue_full; |
2454 | 2485 | ||
2455 | /* fabric drivers should only return -EAGAIN or -ENOMEM as error */ | 2486 | return 0; |
2456 | WARN_ON(ret); | ||
2457 | |||
2458 | return (!ret) ? 0 : TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
2459 | 2487 | ||
2460 | queue_full: | 2488 | queue_full: |
2461 | pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); | 2489 | pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); |
2462 | cmd->t_state = TRANSPORT_COMPLETE_QF_WP; | 2490 | transport_handle_queue_full(cmd, cmd->se_dev, ret, true); |
2463 | transport_handle_queue_full(cmd, cmd->se_dev); | ||
2464 | return 0; | 2491 | return 0; |
2465 | } | 2492 | } |
2466 | EXPORT_SYMBOL(transport_generic_new_cmd); | 2493 | EXPORT_SYMBOL(transport_generic_new_cmd); |
@@ -2470,10 +2497,10 @@ static void transport_write_pending_qf(struct se_cmd *cmd) | |||
2470 | int ret; | 2497 | int ret; |
2471 | 2498 | ||
2472 | ret = cmd->se_tfo->write_pending(cmd); | 2499 | ret = cmd->se_tfo->write_pending(cmd); |
2473 | if (ret == -EAGAIN || ret == -ENOMEM) { | 2500 | if (ret) { |
2474 | pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", | 2501 | pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", |
2475 | cmd); | 2502 | cmd); |
2476 | transport_handle_queue_full(cmd, cmd->se_dev); | 2503 | transport_handle_queue_full(cmd, cmd->se_dev, ret, true); |
2477 | } | 2504 | } |
2478 | } | 2505 | } |
2479 | 2506 | ||
@@ -3011,6 +3038,8 @@ static int __transport_check_aborted_status(struct se_cmd *cmd, int send_status) | |||
3011 | __releases(&cmd->t_state_lock) | 3038 | __releases(&cmd->t_state_lock) |
3012 | __acquires(&cmd->t_state_lock) | 3039 | __acquires(&cmd->t_state_lock) |
3013 | { | 3040 | { |
3041 | int ret; | ||
3042 | |||
3014 | assert_spin_locked(&cmd->t_state_lock); | 3043 | assert_spin_locked(&cmd->t_state_lock); |
3015 | WARN_ON_ONCE(!irqs_disabled()); | 3044 | WARN_ON_ONCE(!irqs_disabled()); |
3016 | 3045 | ||
@@ -3034,7 +3063,9 @@ static int __transport_check_aborted_status(struct se_cmd *cmd, int send_status) | |||
3034 | trace_target_cmd_complete(cmd); | 3063 | trace_target_cmd_complete(cmd); |
3035 | 3064 | ||
3036 | spin_unlock_irq(&cmd->t_state_lock); | 3065 | spin_unlock_irq(&cmd->t_state_lock); |
3037 | cmd->se_tfo->queue_status(cmd); | 3066 | ret = cmd->se_tfo->queue_status(cmd); |
3067 | if (ret) | ||
3068 | transport_handle_queue_full(cmd, cmd->se_dev, ret, false); | ||
3038 | spin_lock_irq(&cmd->t_state_lock); | 3069 | spin_lock_irq(&cmd->t_state_lock); |
3039 | 3070 | ||
3040 | return 1; | 3071 | return 1; |
@@ -3055,6 +3086,7 @@ EXPORT_SYMBOL(transport_check_aborted_status); | |||
3055 | void transport_send_task_abort(struct se_cmd *cmd) | 3086 | void transport_send_task_abort(struct se_cmd *cmd) |
3056 | { | 3087 | { |
3057 | unsigned long flags; | 3088 | unsigned long flags; |
3089 | int ret; | ||
3058 | 3090 | ||
3059 | spin_lock_irqsave(&cmd->t_state_lock, flags); | 3091 | spin_lock_irqsave(&cmd->t_state_lock, flags); |
3060 | if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION)) { | 3092 | if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION)) { |
@@ -3090,7 +3122,9 @@ send_abort: | |||
3090 | cmd->t_task_cdb[0], cmd->tag); | 3122 | cmd->t_task_cdb[0], cmd->tag); |
3091 | 3123 | ||
3092 | trace_target_cmd_complete(cmd); | 3124 | trace_target_cmd_complete(cmd); |
3093 | cmd->se_tfo->queue_status(cmd); | 3125 | ret = cmd->se_tfo->queue_status(cmd); |
3126 | if (ret) | ||
3127 | transport_handle_queue_full(cmd, cmd->se_dev, ret, false); | ||
3094 | } | 3128 | } |
3095 | 3129 | ||
3096 | static void target_tmr_work(struct work_struct *work) | 3130 | static void target_tmr_work(struct work_struct *work) |
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 2e282461cfa5..730ed3055336 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
@@ -117,6 +117,7 @@ enum transport_state_table { | |||
117 | TRANSPORT_ISTATE_PROCESSING = 11, | 117 | TRANSPORT_ISTATE_PROCESSING = 11, |
118 | TRANSPORT_COMPLETE_QF_WP = 18, | 118 | TRANSPORT_COMPLETE_QF_WP = 18, |
119 | TRANSPORT_COMPLETE_QF_OK = 19, | 119 | TRANSPORT_COMPLETE_QF_OK = 19, |
120 | TRANSPORT_COMPLETE_QF_ERR = 20, | ||
120 | }; | 121 | }; |
121 | 122 | ||
122 | /* Used for struct se_cmd->se_cmd_flags */ | 123 | /* Used for struct se_cmd->se_cmd_flags */ |