Commit f147abb4 authored by Nicholas Bellinger's avatar Nicholas Bellinger

target: Check -ENOMEM to signal QUEUE_FULL from fabric callbacks

This patch changes target core to also check for -ENOMEM from fabric callbacks
to signal QUEUE_FULL status, instead of just -EAGAIN in order to catch a
larger set of fabric failure cases that want to trigger QUEUE_FULL logic.
This includes the callbacks for ->write_pending(), ->queue_data_in() and
->queue_status().

It also makes transport_generic_write_pending() return zero upon QUEUE_FULL,
and removes two unnecessary -EAGAIN checks to catch write pending QUEUE_FULL
cases from transport_generic_new_cmd() failures in transport_handle_cdb_direct()
and transport_processing_thread():TRANSPORT_NEW_CMD_MAP state.
Reported-by: default avatarBart Van Assche <bvanassche@acm.org>
Cc: Bart Van Assche <bvanassche@acm.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Roland Dreier <roland@purestorage.com>
Signed-off-by: default avatarNicholas A. Bellinger <nab@linux-iscsi.org>
parent 8cd79f24
...@@ -908,7 +908,7 @@ void transport_remove_task_from_execute_queue( ...@@ -908,7 +908,7 @@ void transport_remove_task_from_execute_queue(
} }
/* /*
* Handle QUEUE_FULL / -EAGAIN status * Handle QUEUE_FULL / -EAGAIN and -ENOMEM status
*/ */
static void target_qf_do_work(struct work_struct *work) static void target_qf_do_work(struct work_struct *work)
...@@ -1645,9 +1645,7 @@ int transport_handle_cdb_direct( ...@@ -1645,9 +1645,7 @@ int transport_handle_cdb_direct(
* and call transport_generic_request_failure() if necessary.. * and call transport_generic_request_failure() if necessary..
*/ */
ret = transport_generic_new_cmd(cmd); ret = transport_generic_new_cmd(cmd);
if (ret == -EAGAIN) if (ret < 0) {
return 0;
else if (ret < 0) {
cmd->transport_error_status = ret; cmd->transport_error_status = ret;
transport_generic_request_failure(cmd, 0, transport_generic_request_failure(cmd, 0,
(cmd->data_direction != DMA_TO_DEVICE)); (cmd->data_direction != DMA_TO_DEVICE));
...@@ -1886,7 +1884,7 @@ static void transport_generic_request_failure( ...@@ -1886,7 +1884,7 @@ static void transport_generic_request_failure(
ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
ret = cmd->se_tfo->queue_status(cmd); ret = cmd->se_tfo->queue_status(cmd);
if (ret == -EAGAIN) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
goto check_stop; goto check_stop;
case PYX_TRANSPORT_USE_SENSE_REASON: case PYX_TRANSPORT_USE_SENSE_REASON:
...@@ -1913,7 +1911,7 @@ static void transport_generic_request_failure( ...@@ -1913,7 +1911,7 @@ static void transport_generic_request_failure(
else { else {
ret = transport_send_check_condition_and_sense(cmd, ret = transport_send_check_condition_and_sense(cmd,
cmd->scsi_sense_reason, 0); cmd->scsi_sense_reason, 0);
if (ret == -EAGAIN) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
} }
...@@ -3308,7 +3306,7 @@ static void target_complete_ok_work(struct work_struct *work) ...@@ -3308,7 +3306,7 @@ static void target_complete_ok_work(struct work_struct *work)
if (cmd->scsi_status) { if (cmd->scsi_status) {
ret = transport_send_check_condition_and_sense( ret = transport_send_check_condition_and_sense(
cmd, reason, 1); cmd, reason, 1);
if (ret == -EAGAIN) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
transport_lun_remove_cmd(cmd); transport_lun_remove_cmd(cmd);
...@@ -3333,7 +3331,7 @@ static void target_complete_ok_work(struct work_struct *work) ...@@ -3333,7 +3331,7 @@ static void target_complete_ok_work(struct work_struct *work)
spin_unlock(&cmd->se_lun->lun_sep_lock); spin_unlock(&cmd->se_lun->lun_sep_lock);
ret = cmd->se_tfo->queue_data_in(cmd); ret = cmd->se_tfo->queue_data_in(cmd);
if (ret == -EAGAIN) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
break; break;
case DMA_TO_DEVICE: case DMA_TO_DEVICE:
...@@ -3354,14 +3352,14 @@ static void target_complete_ok_work(struct work_struct *work) ...@@ -3354,14 +3352,14 @@ static void target_complete_ok_work(struct work_struct *work)
} }
spin_unlock(&cmd->se_lun->lun_sep_lock); spin_unlock(&cmd->se_lun->lun_sep_lock);
ret = cmd->se_tfo->queue_data_in(cmd); ret = cmd->se_tfo->queue_data_in(cmd);
if (ret == -EAGAIN) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
break; break;
} }
/* Fall through for DMA_TO_DEVICE */ /* Fall through for DMA_TO_DEVICE */
case DMA_NONE: case DMA_NONE:
ret = cmd->se_tfo->queue_status(cmd); ret = cmd->se_tfo->queue_status(cmd);
if (ret == -EAGAIN) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
break; break;
default: default:
...@@ -3890,7 +3888,10 @@ EXPORT_SYMBOL(transport_generic_process_write); ...@@ -3890,7 +3888,10 @@ EXPORT_SYMBOL(transport_generic_process_write);
static void transport_write_pending_qf(struct se_cmd *cmd) static void transport_write_pending_qf(struct se_cmd *cmd)
{ {
if (cmd->se_tfo->write_pending(cmd) == -EAGAIN) { int ret;
ret = cmd->se_tfo->write_pending(cmd);
if (ret == -EAGAIN || ret == -ENOMEM) {
pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n",
cmd); cmd);
transport_handle_queue_full(cmd, cmd->se_dev); transport_handle_queue_full(cmd, cmd->se_dev);
...@@ -3920,7 +3921,7 @@ static int transport_generic_write_pending(struct se_cmd *cmd) ...@@ -3920,7 +3921,7 @@ static int transport_generic_write_pending(struct se_cmd *cmd)
* frontend know that WRITE buffers are ready. * frontend know that WRITE buffers are ready.
*/ */
ret = cmd->se_tfo->write_pending(cmd); ret = cmd->se_tfo->write_pending(cmd);
if (ret == -EAGAIN) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
else if (ret < 0) else if (ret < 0)
return ret; return ret;
...@@ -3931,7 +3932,7 @@ static int transport_generic_write_pending(struct se_cmd *cmd) ...@@ -3931,7 +3932,7 @@ static int transport_generic_write_pending(struct se_cmd *cmd)
pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
cmd->t_state = TRANSPORT_COMPLETE_QF_WP; cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
transport_handle_queue_full(cmd, cmd->se_dev); transport_handle_queue_full(cmd, cmd->se_dev);
return ret; return 0;
} }
/** /**
...@@ -4583,9 +4584,7 @@ static int transport_processing_thread(void *param) ...@@ -4583,9 +4584,7 @@ static int transport_processing_thread(void *param)
break; break;
} }
ret = transport_generic_new_cmd(cmd); ret = transport_generic_new_cmd(cmd);
if (ret == -EAGAIN) if (ret < 0) {
break;
else if (ret < 0) {
cmd->transport_error_status = ret; cmd->transport_error_status = ret;
transport_generic_request_failure(cmd, transport_generic_request_failure(cmd,
0, (cmd->data_direction != 0, (cmd->data_direction !=
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment