summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-10-26 08:57:41 +0200
committerNicholas Bellinger <nab@linux-iscsi.org>2011-10-27 03:00:06 +0200
commitf147abb475ab47ce620cf3d18de5b3192c9fa7ed (patch)
tree2dddc11716663c387df52f102658c9812c62c54a
parenttcm_loop: Add explict read buffer memset for SCF_SCSI_CONTROL_SG_IO_CDB (diff)
downloadlinux-f147abb475ab47ce620cf3d18de5b3192c9fa7ed.tar.xz
linux-f147abb475ab47ce620cf3d18de5b3192c9fa7ed.zip
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: Bart 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: Nicholas A. Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_transport.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index d75255804481..5dee44639f8f 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -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)
@@ -1645,9 +1645,7 @@ int transport_handle_cdb_direct(
* and call transport_generic_request_failure() if necessary..
*/
ret = transport_generic_new_cmd(cmd);
- if (ret == -EAGAIN)
- return 0;
- else if (ret < 0) {
+ if (ret < 0) {
cmd->transport_error_status = ret;
transport_generic_request_failure(cmd, 0,
(cmd->data_direction != DMA_TO_DEVICE));
@@ -1886,7 +1884,7 @@ static void transport_generic_request_failure(
ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
ret = cmd->se_tfo->queue_status(cmd);
- if (ret == -EAGAIN)
+ if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
goto check_stop;
case PYX_TRANSPORT_USE_SENSE_REASON:
@@ -1913,7 +1911,7 @@ static void transport_generic_request_failure(
else {
ret = transport_send_check_condition_and_sense(cmd,
cmd->scsi_sense_reason, 0);
- if (ret == -EAGAIN)
+ if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
}
@@ -3308,7 +3306,7 @@ static void target_complete_ok_work(struct work_struct *work)
if (cmd->scsi_status) {
ret = transport_send_check_condition_and_sense(
cmd, reason, 1);
- if (ret == -EAGAIN)
+ if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
transport_lun_remove_cmd(cmd);
@@ -3333,7 +3331,7 @@ static void target_complete_ok_work(struct work_struct *work)
spin_unlock(&cmd->se_lun->lun_sep_lock);
ret = cmd->se_tfo->queue_data_in(cmd);
- if (ret == -EAGAIN)
+ if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
break;
case DMA_TO_DEVICE:
@@ -3354,14 +3352,14 @@ static void target_complete_ok_work(struct work_struct *work)
}
spin_unlock(&cmd->se_lun->lun_sep_lock);
ret = cmd->se_tfo->queue_data_in(cmd);
- if (ret == -EAGAIN)
+ if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
break;
}
/* Fall through for DMA_TO_DEVICE */
case DMA_NONE:
ret = cmd->se_tfo->queue_status(cmd);
- if (ret == -EAGAIN)
+ if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
break;
default:
@@ -3890,7 +3888,10 @@ EXPORT_SYMBOL(transport_generic_process_write);
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",
cmd);
transport_handle_queue_full(cmd, cmd->se_dev);
@@ -3920,7 +3921,7 @@ static int transport_generic_write_pending(struct se_cmd *cmd)
* frontend know that WRITE buffers are ready.
*/
ret = cmd->se_tfo->write_pending(cmd);
- if (ret == -EAGAIN)
+ if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
else if (ret < 0)
return ret;
@@ -3931,7 +3932,7 @@ queue_full:
pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
transport_handle_queue_full(cmd, cmd->se_dev);
- return ret;
+ return 0;
}
/**
@@ -4583,9 +4584,7 @@ get_cmd:
break;
}
ret = transport_generic_new_cmd(cmd);
- if (ret == -EAGAIN)
- break;
- else if (ret < 0) {
+ if (ret < 0) {
cmd->transport_error_status = ret;
transport_generic_request_failure(cmd,
0, (cmd->data_direction !=