diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-10-26 02:57:41 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-10-26 21:00:06 -0400 |
commit | f147abb475ab47ce620cf3d18de5b3192c9fa7ed (patch) | |
tree | 2dddc11716663c387df52f102658c9812c62c54a /drivers/target | |
parent | 8cd79f24350826b81e16990d9e12bc878e67d385 (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.c | 31 |
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 | ||
914 | static void target_qf_do_work(struct work_struct *work) | 914 | static 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 | ||
3891 | static void transport_write_pending_qf(struct se_cmd *cmd) | 3889 | static 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 != |