target: simplify command to task linkage

Now that we only have a single task per command we can use a direct pointer
to it instead of list.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Christoph Hellwig 2012-04-24 00:25:04 -04:00 committed by Nicholas Bellinger
parent 4101f0a89d
commit 785fdf70b2
3 changed files with 45 additions and 89 deletions

View File

@ -321,13 +321,11 @@ static void core_tmr_drain_task_list(
cmd->se_tfo->get_cmd_state(cmd), cmd->t_state, cmd->se_tfo->get_cmd_state(cmd), cmd->t_state,
cmd->t_task_cdb[0]); cmd->t_task_cdb[0]);
pr_debug("LUN_RESET: ITT[0x%08x] - pr_res_key: 0x%016Lx" pr_debug("LUN_RESET: ITT[0x%08x] - pr_res_key: 0x%016Lx"
" t_task_cdbs: %d t_task_cdbs_left: %d" " t_task_cdbs_left: %d"
" t_task_cdbs_sent: %d -- CMD_T_ACTIVE: %d" " -- CMD_T_ACTIVE: %d"
" CMD_T_STOP: %d CMD_T_SENT: %d\n", " CMD_T_STOP: %d CMD_T_SENT: %d\n",
cmd->se_tfo->get_task_tag(cmd), cmd->pr_res_key, cmd->se_tfo->get_task_tag(cmd), cmd->pr_res_key,
cmd->t_task_list_num,
atomic_read(&cmd->t_task_cdbs_left), atomic_read(&cmd->t_task_cdbs_left),
atomic_read(&cmd->t_task_cdbs_sent),
(cmd->transport_state & CMD_T_ACTIVE) != 0, (cmd->transport_state & CMD_T_ACTIVE) != 0,
(cmd->transport_state & CMD_T_STOP) != 0, (cmd->transport_state & CMD_T_STOP) != 0,
(cmd->transport_state & CMD_T_SENT) != 0); (cmd->transport_state & CMD_T_SENT) != 0);

View File

@ -453,9 +453,10 @@ static void transport_all_task_dev_remove_state(struct se_cmd *cmd)
if (!dev) if (!dev)
return; return;
list_for_each_entry(task, &cmd->t_task_list, t_list) { task = cmd->t_task;
if (task) {
if (task->task_flags & TF_ACTIVE) if (task->task_flags & TF_ACTIVE)
continue; return;
spin_lock_irqsave(&dev->execute_task_lock, flags); spin_lock_irqsave(&dev->execute_task_lock, flags);
if (task->t_state_active) { if (task->t_state_active) {
@ -675,8 +676,7 @@ static void transport_remove_cmd_from_queue(struct se_cmd *cmd)
*/ */
void transport_complete_sync_cache(struct se_cmd *cmd, int good) void transport_complete_sync_cache(struct se_cmd *cmd, int good)
{ {
struct se_task *task = list_entry(cmd->t_task_list.next, struct se_task *task = cmd->t_task;
struct se_task, t_list);
if (good) { if (good) {
cmd->scsi_status = SAM_STAT_GOOD; cmd->scsi_status = SAM_STAT_GOOD;
@ -774,8 +774,7 @@ EXPORT_SYMBOL(transport_complete_task);
void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
{ {
struct se_task *task = list_entry(cmd->t_task_list.next, struct se_task *task = cmd->t_task;
struct se_task, t_list);
task->task_scsi_status = scsi_status; task->task_scsi_status = scsi_status;
transport_complete_task(task, scsi_status == GOOD); transport_complete_task(task, scsi_status == GOOD);
@ -791,7 +790,6 @@ EXPORT_SYMBOL(target_complete_cmd);
*/ */
static inline int transport_add_task_check_sam_attr( static inline int transport_add_task_check_sam_attr(
struct se_task *task, struct se_task *task,
struct se_task *task_prev,
struct se_device *dev) struct se_device *dev)
{ {
/* /*
@ -805,14 +803,10 @@ static inline int transport_add_task_check_sam_attr(
/* /*
* HEAD_OF_QUEUE attribute for received CDB, which means * HEAD_OF_QUEUE attribute for received CDB, which means
* the first task that is associated with a struct se_cmd goes to * the first task that is associated with a struct se_cmd goes to
* head of the struct se_device->execute_task_list, and task_prev * head of the struct se_device->execute_task_list.
* after that for each subsequent task
*/ */
if (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG) { if (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG) {
list_add(&task->t_execute_list, list_add(&task->t_execute_list, &dev->execute_task_list);
(task_prev != NULL) ?
&task_prev->t_execute_list :
&dev->execute_task_list);
pr_debug("Set HEAD_OF_QUEUE for task CDB: 0x%02x" pr_debug("Set HEAD_OF_QUEUE for task CDB: 0x%02x"
" in execution queue\n", " in execution queue\n",
@ -834,12 +828,11 @@ static inline int transport_add_task_check_sam_attr(
*/ */
static void __transport_add_task_to_execute_queue( static void __transport_add_task_to_execute_queue(
struct se_task *task, struct se_task *task,
struct se_task *task_prev,
struct se_device *dev) struct se_device *dev)
{ {
int head_of_queue; int head_of_queue;
head_of_queue = transport_add_task_check_sam_attr(task, task_prev, dev); head_of_queue = transport_add_task_check_sam_attr(task, dev);
atomic_inc(&dev->execute_tasks); atomic_inc(&dev->execute_tasks);
if (task->t_state_active) if (task->t_state_active)
@ -850,9 +843,7 @@ static void __transport_add_task_to_execute_queue(
* will always return head_of_queue == 0 here * will always return head_of_queue == 0 here
*/ */
if (head_of_queue) if (head_of_queue)
list_add(&task->t_state_list, (task_prev) ? list_add(&task->t_state_list, &dev->state_task_list);
&task_prev->t_state_list :
&dev->state_task_list);
else else
list_add_tail(&task->t_state_list, &dev->state_task_list); list_add_tail(&task->t_state_list, &dev->state_task_list);
@ -870,7 +861,11 @@ static void transport_add_tasks_to_state_queue(struct se_cmd *cmd)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&cmd->t_state_lock, flags); spin_lock_irqsave(&cmd->t_state_lock, flags);
list_for_each_entry(task, &cmd->t_task_list, t_list) { task = cmd->t_task;
if (task) {
if (task->task_flags & TF_ACTIVE)
goto out;
spin_lock(&dev->execute_task_lock); spin_lock(&dev->execute_task_lock);
if (!task->t_state_active) { if (!task->t_state_active) {
list_add_tail(&task->t_state_list, list_add_tail(&task->t_state_list,
@ -883,24 +878,17 @@ static void transport_add_tasks_to_state_queue(struct se_cmd *cmd)
} }
spin_unlock(&dev->execute_task_lock); spin_unlock(&dev->execute_task_lock);
} }
out:
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
} }
static void __transport_add_tasks_from_cmd(struct se_cmd *cmd) static void __transport_add_tasks_from_cmd(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_task *task;
struct se_task *task, *task_prev = NULL;
list_for_each_entry(task, &cmd->t_task_list, t_list) { task = cmd->t_task;
if (!list_empty(&task->t_execute_list)) if (task && list_empty(&task->t_execute_list))
continue; __transport_add_task_to_execute_queue(task, cmd->se_dev);
/*
* __transport_add_task_to_execute_queue() handles the
* SAM Task Attribute emulation if enabled
*/
__transport_add_task_to_execute_queue(task, task_prev, dev);
task_prev = task;
}
} }
static void transport_add_tasks_from_cmd(struct se_cmd *cmd) static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
@ -1494,7 +1482,6 @@ void transport_init_se_cmd(
INIT_LIST_HEAD(&cmd->se_qf_node); INIT_LIST_HEAD(&cmd->se_qf_node);
INIT_LIST_HEAD(&cmd->se_queue_node); INIT_LIST_HEAD(&cmd->se_queue_node);
INIT_LIST_HEAD(&cmd->se_cmd_list); INIT_LIST_HEAD(&cmd->se_cmd_list);
INIT_LIST_HEAD(&cmd->t_task_list);
init_completion(&cmd->transport_lun_fe_stop_comp); init_completion(&cmd->transport_lun_fe_stop_comp);
init_completion(&cmd->transport_lun_stop_comp); init_completion(&cmd->transport_lun_stop_comp);
init_completion(&cmd->t_transport_stop_comp); init_completion(&cmd->t_transport_stop_comp);
@ -1895,7 +1882,7 @@ bool target_stop_task(struct se_task *task, unsigned long *flags)
static int transport_stop_tasks_for_cmd(struct se_cmd *cmd) static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
{ {
struct se_task *task, *task_tmp; struct se_task *task;
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
@ -1906,8 +1893,8 @@ static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
* No tasks remain in the execution queue * No tasks remain in the execution queue
*/ */
spin_lock_irqsave(&cmd->t_state_lock, flags); spin_lock_irqsave(&cmd->t_state_lock, flags);
list_for_each_entry_safe(task, task_tmp, task = cmd->t_task;
&cmd->t_task_list, t_list) { if (task) {
pr_debug("Processing task %p\n", task); pr_debug("Processing task %p\n", task);
/* /*
* If the struct se_task has not been sent and is not active, * If the struct se_task has not been sent and is not active,
@ -1921,7 +1908,7 @@ static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
pr_debug("Task %p removed from execute queue\n", task); pr_debug("Task %p removed from execute queue\n", task);
spin_lock_irqsave(&cmd->t_state_lock, flags); spin_lock_irqsave(&cmd->t_state_lock, flags);
continue; goto out;
} }
if (!target_stop_task(task, &flags)) { if (!target_stop_task(task, &flags)) {
@ -1929,8 +1916,8 @@ static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
ret++; ret++;
} }
} }
out:
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
return ret; return ret;
} }
@ -1947,12 +1934,10 @@ void transport_generic_request_failure(struct se_cmd *cmd)
pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n", pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n",
cmd->se_tfo->get_cmd_state(cmd), cmd->se_tfo->get_cmd_state(cmd),
cmd->t_state, cmd->scsi_sense_reason); cmd->t_state, cmd->scsi_sense_reason);
pr_debug("-----[ t_tasks: %d t_task_cdbs_left: %d" pr_debug("-----[ t_task_cdbs_left: %d"
" t_task_cdbs_sent: %d t_task_cdbs_ex_left: %d --" " t_task_cdbs_ex_left: %d --"
" CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n", " CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n",
cmd->t_task_list_num,
atomic_read(&cmd->t_task_cdbs_left), atomic_read(&cmd->t_task_cdbs_left),
atomic_read(&cmd->t_task_cdbs_sent),
atomic_read(&cmd->t_task_cdbs_ex_left), atomic_read(&cmd->t_task_cdbs_ex_left),
(cmd->transport_state & CMD_T_ACTIVE) != 0, (cmd->transport_state & CMD_T_ACTIVE) != 0,
(cmd->transport_state & CMD_T_STOP) != 0, (cmd->transport_state & CMD_T_STOP) != 0,
@ -2212,11 +2197,7 @@ check_depth:
cmd = task->task_se_cmd; cmd = task->task_se_cmd;
spin_lock_irqsave(&cmd->t_state_lock, flags); spin_lock_irqsave(&cmd->t_state_lock, flags);
task->task_flags |= (TF_ACTIVE | TF_SENT); task->task_flags |= (TF_ACTIVE | TF_SENT);
atomic_inc(&cmd->t_task_cdbs_sent); cmd->transport_state |= CMD_T_SENT;
if (atomic_read(&cmd->t_task_cdbs_sent) ==
cmd->t_task_list_num)
cmd->transport_state |= CMD_T_SENT;
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@ -2458,7 +2439,7 @@ static int transport_get_sense_data(struct se_cmd *cmd)
{ {
unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_task *task = NULL, *task_tmp; struct se_task *task = NULL;
unsigned long flags; unsigned long flags;
u32 offset = 0; u32 offset = 0;
@ -2473,15 +2454,15 @@ static int transport_get_sense_data(struct se_cmd *cmd)
return 0; return 0;
} }
list_for_each_entry_safe(task, task_tmp, task = cmd->t_task;
&cmd->t_task_list, t_list) { if (task) {
if (!(task->task_flags & TF_HAS_SENSE)) if (!(task->task_flags & TF_HAS_SENSE))
continue; goto out;
if (!dev->transport->get_sense_buffer) { if (!dev->transport->get_sense_buffer) {
pr_err("dev->transport->get_sense_buffer" pr_err("dev->transport->get_sense_buffer"
" is NULL\n"); " is NULL\n");
continue; goto out;
} }
sense_buffer = dev->transport->get_sense_buffer(task); sense_buffer = dev->transport->get_sense_buffer(task);
@ -2489,7 +2470,7 @@ static int transport_get_sense_data(struct se_cmd *cmd)
pr_err("ITT[0x%08x]_TASK[%p]: Unable to locate" pr_err("ITT[0x%08x]_TASK[%p]: Unable to locate"
" sense buffer for task with sense\n", " sense buffer for task with sense\n",
cmd->se_tfo->get_task_tag(cmd), task); cmd->se_tfo->get_task_tag(cmd), task);
continue; goto out;
} }
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@ -2509,8 +2490,8 @@ static int transport_get_sense_data(struct se_cmd *cmd)
cmd->scsi_status); cmd->scsi_status);
return 0; return 0;
} }
out:
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
return -1; return -1;
} }
@ -3429,24 +3410,11 @@ queue_full:
static void transport_free_dev_tasks(struct se_cmd *cmd) static void transport_free_dev_tasks(struct se_cmd *cmd)
{ {
struct se_task *task, *task_tmp; struct se_task *task;
unsigned long flags;
LIST_HEAD(dispose_list);
spin_lock_irqsave(&cmd->t_state_lock, flags); task = cmd->t_task;
list_for_each_entry_safe(task, task_tmp, if (task && !(task->task_flags & TF_ACTIVE))
&cmd->t_task_list, t_list) {
if (!(task->task_flags & TF_ACTIVE))
list_move_tail(&task->t_list, &dispose_list);
}
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
while (!list_empty(&dispose_list)) {
task = list_first_entry(&dispose_list, struct se_task, t_list);
list_del(&task->t_list);
cmd->se_dev->transport->free_task(task); cmd->se_dev->transport->free_task(task);
}
} }
static inline void transport_free_sgl(struct scatterlist *sgl, int nents) static inline void transport_free_sgl(struct scatterlist *sgl, int nents)
@ -3690,7 +3658,6 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_task *task; struct se_task *task;
unsigned long flags;
int ret = 0; int ret = 0;
/* /*
@ -3742,7 +3709,6 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
goto out_fail; goto out_fail;
} }
INIT_LIST_HEAD(&task->t_list);
INIT_LIST_HEAD(&task->t_execute_list); INIT_LIST_HEAD(&task->t_execute_list);
INIT_LIST_HEAD(&task->t_state_list); INIT_LIST_HEAD(&task->t_state_list);
init_completion(&task->task_stop_comp); init_completion(&task->task_stop_comp);
@ -3751,16 +3717,13 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
task->task_sg = cmd->t_data_sg; task->task_sg = cmd->t_data_sg;
task->task_sg_nents = cmd->t_data_nents; task->task_sg_nents = cmd->t_data_nents;
spin_lock_irqsave(&cmd->t_state_lock, flags); cmd->t_task = task;
list_add_tail(&task->t_list, &cmd->t_task_list);
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
atomic_inc(&cmd->t_fe_count); atomic_inc(&cmd->t_fe_count);
atomic_inc(&cmd->t_se_count); atomic_inc(&cmd->t_se_count);
cmd->t_task_list_num = 1; atomic_set(&cmd->t_task_cdbs_left, 1);
atomic_set(&cmd->t_task_cdbs_left, cmd->t_task_list_num); atomic_set(&cmd->t_task_cdbs_ex_left, 1);
atomic_set(&cmd->t_task_cdbs_ex_left, cmd->t_task_list_num);
/* /*
* For WRITEs, let the fabric know its buffer is ready.. * For WRITEs, let the fabric know its buffer is ready..
@ -4026,8 +3989,8 @@ static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun)
ret = transport_stop_tasks_for_cmd(cmd); ret = transport_stop_tasks_for_cmd(cmd);
pr_debug("ConfigFS: cmd: %p t_tasks: %d stop tasks ret:" pr_debug("ConfigFS: cmd: %p stop tasks ret:"
" %d\n", cmd, cmd->t_task_list_num, ret); " %d\n", cmd, ret);
if (!ret) { if (!ret) {
pr_debug("ConfigFS: ITT[0x%08x] - stopping cmd....\n", pr_debug("ConfigFS: ITT[0x%08x] - stopping cmd....\n",
cmd->se_tfo->get_task_tag(cmd)); cmd->se_tfo->get_task_tag(cmd));

View File

@ -492,7 +492,6 @@ struct se_task {
u16 task_flags; u16 task_flags;
u8 task_scsi_status; u8 task_scsi_status;
enum dma_data_direction task_data_direction; enum dma_data_direction task_data_direction;
struct list_head t_list;
struct list_head t_execute_list; struct list_head t_execute_list;
struct list_head t_state_list; struct list_head t_state_list;
bool t_state_active; bool t_state_active;
@ -573,7 +572,6 @@ struct se_cmd {
atomic_t t_se_count; atomic_t t_se_count;
atomic_t t_task_cdbs_left; atomic_t t_task_cdbs_left;
atomic_t t_task_cdbs_ex_left; atomic_t t_task_cdbs_ex_left;
atomic_t t_task_cdbs_sent;
unsigned int transport_state; unsigned int transport_state;
#define CMD_T_ABORTED (1 << 0) #define CMD_T_ABORTED (1 << 0)
#define CMD_T_ACTIVE (1 << 1) #define CMD_T_ACTIVE (1 << 1)
@ -598,10 +596,7 @@ struct se_cmd {
struct scatterlist *t_bidi_data_sg; struct scatterlist *t_bidi_data_sg;
unsigned int t_bidi_data_nents; unsigned int t_bidi_data_nents;
/* Used for BIDI READ */ struct se_task *t_task;
struct list_head t_task_list;
u32 t_task_list_num;
}; };
struct se_ua { struct se_ua {