Commit 07bde79a authored by Nicholas Bellinger's avatar Nicholas Bellinger

target: Add SCF_EMULATE_QUEUE_FULL -> transport_handle_queue_full

This patch adds SCF_EMULATE_QUEUE_FULL support using -EAGAIN failures
via transport_handle_queue_full() to signal queue full in completion
path TFO->queue_data_in() and TFO->queue_status() callbacks.

This is done using a new se_cmd->transport_qf_callback() to handle
the following queue full exception cases within target core:

*) TRANSPORT_COMPLETE_OK (for completion path queue full)

*) TRANSPORT_COMPLETE_QF_WP (for TRANSPORT_WRITE_PENDING queue full)

*) transport_send_check_condition_and_sense() failure paths in
   transport_generic_request_failure() and transport_generic_complete_ok()

All logic is driven using se_device->qf_work_queue -> target_qf_do_work()
to to requeue outstanding se_cmd at the head of se_dev->queue_obj->qobj_list
for transport_processing_thread() execution.

Tested using tcm_qla2xxx with MAX_OUTSTANDING_COMMANDS=128 for FCP READ
to trigger the TRANSPORT_COMPLETE_OK queue full cases, and a simulated
TFO->write_pending() -EAGAIN failure to trigger TRANSPORT_COMPLETE_QF_WP.
Reported-by: default avatarRoland Dreier <roland@purestorage.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 695434e1
This diff is collapsed.
...@@ -99,6 +99,7 @@ enum transport_state_table { ...@@ -99,6 +99,7 @@ enum transport_state_table {
TRANSPORT_FREE = 15, TRANSPORT_FREE = 15,
TRANSPORT_NEW_CMD_MAP = 16, TRANSPORT_NEW_CMD_MAP = 16,
TRANSPORT_FREE_CMD_INTR = 17, TRANSPORT_FREE_CMD_INTR = 17,
TRANSPORT_COMPLETE_QF_WP = 18,
}; };
/* Used for struct se_cmd->se_cmd_flags */ /* Used for struct se_cmd->se_cmd_flags */
...@@ -125,6 +126,7 @@ enum se_cmd_flags_table { ...@@ -125,6 +126,7 @@ enum se_cmd_flags_table {
SCF_PASSTHROUGH_CONTIG_TO_SG = 0x00200000, SCF_PASSTHROUGH_CONTIG_TO_SG = 0x00200000,
SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00400000, SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00400000,
SCF_EMULATE_CDB_ASYNC = 0x01000000, SCF_EMULATE_CDB_ASYNC = 0x01000000,
SCF_EMULATE_QUEUE_FULL = 0x02000000,
}; };
/* struct se_dev_entry->lun_flags and struct se_lun->lun_access */ /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
...@@ -466,6 +468,7 @@ struct se_cmd { ...@@ -466,6 +468,7 @@ struct se_cmd {
struct list_head se_delayed_node; struct list_head se_delayed_node;
struct list_head se_ordered_node; struct list_head se_ordered_node;
struct list_head se_lun_node; struct list_head se_lun_node;
struct list_head se_qf_node;
struct se_device *se_dev; struct se_device *se_dev;
struct se_dev_entry *se_deve; struct se_dev_entry *se_deve;
struct se_device *se_obj_ptr; struct se_device *se_obj_ptr;
...@@ -480,6 +483,8 @@ struct se_cmd { ...@@ -480,6 +483,8 @@ struct se_cmd {
void (*transport_split_cdb)(unsigned long long, u32 *, unsigned char *); void (*transport_split_cdb)(unsigned long long, u32 *, unsigned char *);
void (*transport_wait_for_tasks)(struct se_cmd *, int, int); void (*transport_wait_for_tasks)(struct se_cmd *, int, int);
void (*transport_complete_callback)(struct se_cmd *); void (*transport_complete_callback)(struct se_cmd *);
int (*transport_qf_callback)(struct se_cmd *);
unsigned char *t_task_cdb; unsigned char *t_task_cdb;
unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE];
unsigned long long t_task_lba; unsigned long long t_task_lba;
...@@ -743,6 +748,7 @@ struct se_device { ...@@ -743,6 +748,7 @@ struct se_device {
atomic_t dev_status_thr_count; atomic_t dev_status_thr_count;
atomic_t dev_hoq_count; atomic_t dev_hoq_count;
atomic_t dev_ordered_sync; atomic_t dev_ordered_sync;
atomic_t dev_qf_count;
struct se_obj dev_obj; struct se_obj dev_obj;
struct se_obj dev_access_obj; struct se_obj dev_access_obj;
struct se_obj dev_export_obj; struct se_obj dev_export_obj;
...@@ -758,6 +764,7 @@ struct se_device { ...@@ -758,6 +764,7 @@ struct se_device {
spinlock_t dev_status_thr_lock; spinlock_t dev_status_thr_lock;
spinlock_t se_port_lock; spinlock_t se_port_lock;
spinlock_t se_tmr_lock; spinlock_t se_tmr_lock;
spinlock_t qf_cmd_lock;
/* Used for legacy SPC-2 reservationsa */ /* Used for legacy SPC-2 reservationsa */
struct se_node_acl *dev_reserved_node_acl; struct se_node_acl *dev_reserved_node_acl;
/* Used for ALUA Logical Unit Group membership */ /* Used for ALUA Logical Unit Group membership */
...@@ -771,10 +778,12 @@ struct se_device { ...@@ -771,10 +778,12 @@ struct se_device {
struct task_struct *process_thread; struct task_struct *process_thread;
pid_t process_thread_pid; pid_t process_thread_pid;
struct task_struct *dev_mgmt_thread; struct task_struct *dev_mgmt_thread;
struct work_struct qf_work_queue;
struct list_head delayed_cmd_list; struct list_head delayed_cmd_list;
struct list_head ordered_cmd_list; struct list_head ordered_cmd_list;
struct list_head execute_task_list; struct list_head execute_task_list;
struct list_head state_task_list; struct list_head state_task_list;
struct list_head qf_cmd_list;
/* Pointer to associated SE HBA */ /* Pointer to associated SE HBA */
struct se_hba *se_hba; struct se_hba *se_hba;
struct se_subsystem_dev *se_sub_dev; struct se_subsystem_dev *se_sub_dev;
......
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