aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-10-26 02:57:41 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-10-26 21:00:06 -0400
commitf147abb475ab47ce620cf3d18de5b3192c9fa7ed (patch)
tree2dddc11716663c387df52f102658c9812c62c54a /drivers/target
parent8cd79f24350826b81e16990d9e12bc878e67d385 (diff)
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>
Diffstat (limited to 'drivers/target')
-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(
908} 908}
909 909
910/* 910/*
911 * Handle QUEUE_FULL / -EAGAIN status 911 * Handle QUEUE_FULL / -EAGAIN and -ENOMEM status
912 */ 912 */
913 913
914static void target_qf_do_work(struct work_struct *work) 914static void target_qf_do_work(struct work_struct *work)
@@ -1645,9 +1645,7 @@ int transport_handle_cdb_direct(
1645 * and call transport_generic_request_failure() if necessary.. 1645 * and call transport_generic_request_failure() if necessary..
1646 */ 1646 */
1647 ret = transport_generic_new_cmd(cmd); 1647 ret = transport_generic_new_cmd(cmd);
1648 if (ret == -EAGAIN) 1648 if (ret < 0) {
1649 return 0;
1650 else if (ret < 0) {
1651 cmd->transport_error_status = ret; 1649 cmd->transport_error_status = ret;
1652 transport_generic_request_failure(cmd, 0, 1650 transport_generic_request_failure(cmd, 0,
1653 (cmd->data_direction != DMA_TO_DEVICE)); 1651 (cmd->data_direction != DMA_TO_DEVICE));
@@ -1886,7 +1884,7 @@ static void transport_generic_request_failure(
1886 ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); 1884 ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
1887 1885
1888 ret = cmd->se_tfo->queue_status(cmd); 1886 ret = cmd->se_tfo->queue_status(cmd);
1889 if (ret == -EAGAIN) 1887 if (ret == -EAGAIN || ret == -ENOMEM)
1890 goto queue_full; 1888 goto queue_full;
1891 goto check_stop; 1889 goto check_stop;
1892 case PYX_TRANSPORT_USE_SENSE_REASON: 1890 case PYX_TRANSPORT_USE_SENSE_REASON:
@@ -1913,7 +1911,7 @@ static void transport_generic_request_failure(
1913 else { 1911 else {
1914 ret = transport_send_check_condition_and_sense(cmd, 1912 ret = transport_send_check_condition_and_sense(cmd,
1915 cmd->scsi_sense_reason, 0); 1913 cmd->scsi_sense_reason, 0);
1916 if (ret == -EAGAIN) 1914 if (ret == -EAGAIN || ret == -ENOMEM)
1917 goto queue_full; 1915 goto queue_full;
1918 } 1916 }
1919 1917
@@ -3308,7 +3306,7 @@ static void target_complete_ok_work(struct work_struct *work)
3308 if (cmd->scsi_status) { 3306 if (cmd->scsi_status) {
3309 ret = transport_send_check_condition_and_sense( 3307 ret = transport_send_check_condition_and_sense(
3310 cmd, reason, 1); 3308 cmd, reason, 1);
3311 if (ret == -EAGAIN) 3309 if (ret == -EAGAIN || ret == -ENOMEM)
3312 goto queue_full; 3310 goto queue_full;
3313 3311
3314 transport_lun_remove_cmd(cmd); 3312 transport_lun_remove_cmd(cmd);
@@ -3333,7 +3331,7 @@ static void target_complete_ok_work(struct work_struct *work)
3333 spin_unlock(&cmd->se_lun->lun_sep_lock); 3331 spin_unlock(&cmd->se_lun->lun_sep_lock);
3334 3332
3335 ret = cmd->se_tfo->queue_data_in(cmd); 3333 ret = cmd->se_tfo->queue_data_in(cmd);
3336 if (ret == -EAGAIN) 3334 if (ret == -EAGAIN || ret == -ENOMEM)
3337 goto queue_full; 3335 goto queue_full;
3338 break; 3336 break;
3339 case DMA_TO_DEVICE: 3337 case DMA_TO_DEVICE:
@@ -3354,14 +3352,14 @@ static void target_complete_ok_work(struct work_struct *work)
3354 } 3352 }
3355 spin_unlock(&cmd->se_lun->lun_sep_lock); 3353 spin_unlock(&cmd->se_lun->lun_sep_lock);
3356 ret = cmd->se_tfo->queue_data_in(cmd); 3354 ret = cmd->se_tfo->queue_data_in(cmd);
3357 if (ret == -EAGAIN) 3355 if (ret == -EAGAIN || ret == -ENOMEM)
3358 goto queue_full; 3356 goto queue_full;
3359 break; 3357 break;
3360 } 3358 }
3361 /* Fall through for DMA_TO_DEVICE */ 3359 /* Fall through for DMA_TO_DEVICE */
3362 case DMA_NONE: 3360 case DMA_NONE:
3363 ret = cmd->se_tfo->queue_status(cmd); 3361 ret = cmd->se_tfo->queue_status(cmd);
3364 if (ret == -EAGAIN) 3362 if (ret == -EAGAIN || ret == -ENOMEM)
3365 goto queue_full; 3363 goto queue_full;
3366 break; 3364 break;
3367 default: 3365 default:
@@ -3890,7 +3888,10 @@ EXPORT_SYMBOL(transport_generic_process_write);
3890 3888
3891static void transport_write_pending_qf(struct se_cmd *cmd) 3889static void transport_write_pending_qf(struct se_cmd *cmd)
3892{ 3890{
3893 if (cmd->se_tfo->write_pending(cmd) == -EAGAIN) { 3891 int ret;
3892
3893 ret = cmd->se_tfo->write_pending(cmd);
3894 if (ret == -EAGAIN || ret == -ENOMEM) {
3894 pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", 3895 pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n",
3895 cmd); 3896 cmd);
3896 transport_handle_queue_full(cmd, cmd->se_dev); 3897 transport_handle_queue_full(cmd, cmd->se_dev);
@@ -3920,7 +3921,7 @@ static int transport_generic_write_pending(struct se_cmd *cmd)
3920 * frontend know that WRITE buffers are ready. 3921 * frontend know that WRITE buffers are ready.
3921 */ 3922 */
3922 ret = cmd->se_tfo->write_pending(cmd); 3923 ret = cmd->se_tfo->write_pending(cmd);
3923 if (ret == -EAGAIN) 3924 if (ret == -EAGAIN || ret == -ENOMEM)
3924 goto queue_full; 3925 goto queue_full;
3925 else if (ret < 0) 3926 else if (ret < 0)
3926 return ret; 3927 return ret;
@@ -3931,7 +3932,7 @@ queue_full:
3931 pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); 3932 pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
3932 cmd->t_state = TRANSPORT_COMPLETE_QF_WP; 3933 cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
3933 transport_handle_queue_full(cmd, cmd->se_dev); 3934 transport_handle_queue_full(cmd, cmd->se_dev);
3934 return ret; 3935 return 0;
3935} 3936}
3936 3937
3937/** 3938/**
@@ -4583,9 +4584,7 @@ get_cmd:
4583 break; 4584 break;
4584 } 4585 }
4585 ret = transport_generic_new_cmd(cmd); 4586 ret = transport_generic_new_cmd(cmd);
4586 if (ret == -EAGAIN) 4587 if (ret < 0) {
4587 break;
4588 else if (ret < 0) {
4589 cmd->transport_error_status = ret; 4588 cmd->transport_error_status = ret;
4590 transport_generic_request_failure(cmd, 4589 transport_generic_request_failure(cmd,
4591 0, (cmd->data_direction != 4590 0, (cmd->data_direction !=