diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-06-05 19:27:53 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-06-06 17:20:23 -0400 |
commit | b3e5fe1688b998ba5287a68667ef7cc568739e44 (patch) | |
tree | 5d7a9999d5cfc92ff4cd4ccc50d1ebea95f41334 /drivers/target/tcm_fc/tfc_io.c | |
parent | 1d2b60a5545942b1376cb48c1d55843d71e3a08f (diff) |
tcm_fc: Generate TASK_SET_FULL status for DataIN failures
This patch changes ft_queue_data_in() to set SAM_STAT_TASK_SET_FULL
status upon a lport->tt.seq_send() failure, where it will now stop
sending subsequent DataIN, and immediately attempt to send the
response with exception status.
Sending a response with SAM_STAT_TASK_SET_FULL status is useful in
order to signal the initiator that it should try to reduce it's
current queue_depth, to lower the number of outstanding I/Os on
the wire.
Also, add a check to skip sending DataIN if TASK_SET_FULL status
has already been set due to a response lport->tt.seq_send()
failure, that has asked target-core to requeue a response.
Reported-by: Vasu Dev <vasu.dev@linux.intel.com>
Reviewed-by: Vasu Dev <vasu.dev@linux.intel.com>
Cc: Jun Wu <jwu@stormojo.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/tcm_fc/tfc_io.c')
-rw-r--r-- | drivers/target/tcm_fc/tfc_io.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c index e415af32115a..97b486c3dda1 100644 --- a/drivers/target/tcm_fc/tfc_io.c +++ b/drivers/target/tcm_fc/tfc_io.c | |||
@@ -82,6 +82,10 @@ int ft_queue_data_in(struct se_cmd *se_cmd) | |||
82 | 82 | ||
83 | if (cmd->aborted) | 83 | if (cmd->aborted) |
84 | return 0; | 84 | return 0; |
85 | |||
86 | if (se_cmd->scsi_status == SAM_STAT_TASK_SET_FULL) | ||
87 | goto queue_status; | ||
88 | |||
85 | ep = fc_seq_exch(cmd->seq); | 89 | ep = fc_seq_exch(cmd->seq); |
86 | lport = ep->lp; | 90 | lport = ep->lp; |
87 | cmd->seq = lport->tt.seq_start_next(cmd->seq); | 91 | cmd->seq = lport->tt.seq_start_next(cmd->seq); |
@@ -178,14 +182,23 @@ int ft_queue_data_in(struct se_cmd *se_cmd) | |||
178 | FC_TYPE_FCP, f_ctl, fh_off); | 182 | FC_TYPE_FCP, f_ctl, fh_off); |
179 | error = lport->tt.seq_send(lport, seq, fp); | 183 | error = lport->tt.seq_send(lport, seq, fp); |
180 | if (error) { | 184 | if (error) { |
181 | /* XXX For now, initiator will retry */ | 185 | pr_info_ratelimited("%s: Failed to send frame %p, " |
182 | pr_err_ratelimited("%s: Failed to send frame %p, " | ||
183 | "xid <0x%x>, remaining %zu, " | 186 | "xid <0x%x>, remaining %zu, " |
184 | "lso_max <0x%x>\n", | 187 | "lso_max <0x%x>\n", |
185 | __func__, fp, ep->xid, | 188 | __func__, fp, ep->xid, |
186 | remaining, lport->lso_max); | 189 | remaining, lport->lso_max); |
190 | /* | ||
191 | * Go ahead and set TASK_SET_FULL status ignoring the | ||
192 | * rest of the DataIN, and immediately attempt to | ||
193 | * send the response via ft_queue_status() in order | ||
194 | * to notify the initiator that it should reduce it's | ||
195 | * per LUN queue_depth. | ||
196 | */ | ||
197 | se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL; | ||
198 | break; | ||
187 | } | 199 | } |
188 | } | 200 | } |
201 | queue_status: | ||
189 | return ft_queue_status(se_cmd); | 202 | return ft_queue_status(se_cmd); |
190 | } | 203 | } |
191 | 204 | ||