From 785fdf70b2b46588c973ad8b65ed62871994452f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 24 Apr 2012 00:25:04 -0400 Subject: [PATCH] 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 Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 6 +- drivers/target/target_core_transport.c | 121 +++++++++---------------- include/target/target_core_base.h | 7 +- 3 files changed, 45 insertions(+), 89 deletions(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index f015839aef89..98204d06cdf6 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -321,13 +321,11 @@ static void core_tmr_drain_task_list( cmd->se_tfo->get_cmd_state(cmd), cmd->t_state, cmd->t_task_cdb[0]); pr_debug("LUN_RESET: ITT[0x%08x] - pr_res_key: 0x%016Lx" - " t_task_cdbs: %d t_task_cdbs_left: %d" - " t_task_cdbs_sent: %d -- CMD_T_ACTIVE: %d" + " t_task_cdbs_left: %d" + " -- CMD_T_ACTIVE: %d" " CMD_T_STOP: %d CMD_T_SENT: %d\n", 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_sent), (cmd->transport_state & CMD_T_ACTIVE) != 0, (cmd->transport_state & CMD_T_STOP) != 0, (cmd->transport_state & CMD_T_SENT) != 0); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 5267198688fe..a2246359e6f4 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -453,9 +453,10 @@ static void transport_all_task_dev_remove_state(struct se_cmd *cmd) if (!dev) return; - list_for_each_entry(task, &cmd->t_task_list, t_list) { + task = cmd->t_task; + if (task) { if (task->task_flags & TF_ACTIVE) - continue; + return; spin_lock_irqsave(&dev->execute_task_lock, flags); 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) { - struct se_task *task = list_entry(cmd->t_task_list.next, - struct se_task, t_list); + struct se_task *task = cmd->t_task; if (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) { - struct se_task *task = list_entry(cmd->t_task_list.next, - struct se_task, t_list); + struct se_task *task = cmd->t_task; task->task_scsi_status = scsi_status; 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( struct se_task *task, - struct se_task *task_prev, 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 * 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 - * after that for each subsequent task + * head of the struct se_device->execute_task_list. */ if (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG) { - list_add(&task->t_execute_list, - (task_prev != NULL) ? - &task_prev->t_execute_list : - &dev->execute_task_list); + list_add(&task->t_execute_list, &dev->execute_task_list); pr_debug("Set HEAD_OF_QUEUE for task CDB: 0x%02x" " 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( struct se_task *task, - struct se_task *task_prev, struct se_device *dev) { 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); 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 */ if (head_of_queue) - list_add(&task->t_state_list, (task_prev) ? - &task_prev->t_state_list : - &dev->state_task_list); + list_add(&task->t_state_list, &dev->state_task_list); else 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; 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); if (!task->t_state_active) { 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); } +out: spin_unlock_irqrestore(&cmd->t_state_lock, flags); } static void __transport_add_tasks_from_cmd(struct se_cmd *cmd) { - struct se_device *dev = cmd->se_dev; - struct se_task *task, *task_prev = NULL; + struct se_task *task; - list_for_each_entry(task, &cmd->t_task_list, t_list) { - if (!list_empty(&task->t_execute_list)) - continue; - /* - * __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; - } + task = cmd->t_task; + if (task && list_empty(&task->t_execute_list)) + __transport_add_task_to_execute_queue(task, cmd->se_dev); } 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_queue_node); 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_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) { - struct se_task *task, *task_tmp; + struct se_task *task; unsigned long flags; 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 */ spin_lock_irqsave(&cmd->t_state_lock, flags); - list_for_each_entry_safe(task, task_tmp, - &cmd->t_task_list, t_list) { + task = cmd->t_task; + if (task) { pr_debug("Processing task %p\n", task); /* * 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); spin_lock_irqsave(&cmd->t_state_lock, flags); - continue; + goto out; } if (!target_stop_task(task, &flags)) { @@ -1929,8 +1916,8 @@ static int transport_stop_tasks_for_cmd(struct se_cmd *cmd) ret++; } } +out: spin_unlock_irqrestore(&cmd->t_state_lock, flags); - 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", cmd->se_tfo->get_cmd_state(cmd), cmd->t_state, cmd->scsi_sense_reason); - pr_debug("-----[ t_tasks: %d t_task_cdbs_left: %d" - " t_task_cdbs_sent: %d t_task_cdbs_ex_left: %d --" + pr_debug("-----[ t_task_cdbs_left: %d" + " t_task_cdbs_ex_left: %d --" " 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_sent), atomic_read(&cmd->t_task_cdbs_ex_left), (cmd->transport_state & CMD_T_ACTIVE) != 0, (cmd->transport_state & CMD_T_STOP) != 0, @@ -2212,11 +2197,7 @@ check_depth: cmd = task->task_se_cmd; spin_lock_irqsave(&cmd->t_state_lock, flags); task->task_flags |= (TF_ACTIVE | TF_SENT); - atomic_inc(&cmd->t_task_cdbs_sent); - - if (atomic_read(&cmd->t_task_cdbs_sent) == - cmd->t_task_list_num) - cmd->transport_state |= CMD_T_SENT; + cmd->transport_state |= CMD_T_SENT; 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; struct se_device *dev = cmd->se_dev; - struct se_task *task = NULL, *task_tmp; + struct se_task *task = NULL; unsigned long flags; u32 offset = 0; @@ -2473,15 +2454,15 @@ static int transport_get_sense_data(struct se_cmd *cmd) return 0; } - list_for_each_entry_safe(task, task_tmp, - &cmd->t_task_list, t_list) { + task = cmd->t_task; + if (task) { if (!(task->task_flags & TF_HAS_SENSE)) - continue; + goto out; if (!dev->transport->get_sense_buffer) { pr_err("dev->transport->get_sense_buffer" " is NULL\n"); - continue; + goto out; } 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" " sense buffer for task with sense\n", cmd->se_tfo->get_task_tag(cmd), task); - continue; + goto out; } 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); return 0; } +out: spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return -1; } @@ -3429,24 +3410,11 @@ queue_full: static void transport_free_dev_tasks(struct se_cmd *cmd) { - struct se_task *task, *task_tmp; - unsigned long flags; - LIST_HEAD(dispose_list); - - spin_lock_irqsave(&cmd->t_state_lock, flags); - list_for_each_entry_safe(task, task_tmp, - &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); + struct se_task *task; - list_del(&task->t_list); + task = cmd->t_task; + if (task && !(task->task_flags & TF_ACTIVE)) cmd->se_dev->transport->free_task(task); - } } 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_task *task; - unsigned long flags; int ret = 0; /* @@ -3742,7 +3709,6 @@ int transport_generic_new_cmd(struct se_cmd *cmd) goto out_fail; } - INIT_LIST_HEAD(&task->t_list); INIT_LIST_HEAD(&task->t_execute_list); INIT_LIST_HEAD(&task->t_state_list); 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_nents = cmd->t_data_nents; - spin_lock_irqsave(&cmd->t_state_lock, flags); - list_add_tail(&task->t_list, &cmd->t_task_list); - spin_unlock_irqrestore(&cmd->t_state_lock, flags); + cmd->t_task = task; atomic_inc(&cmd->t_fe_count); atomic_inc(&cmd->t_se_count); - cmd->t_task_list_num = 1; - atomic_set(&cmd->t_task_cdbs_left, cmd->t_task_list_num); - atomic_set(&cmd->t_task_cdbs_ex_left, cmd->t_task_list_num); + atomic_set(&cmd->t_task_cdbs_left, 1); + atomic_set(&cmd->t_task_cdbs_ex_left, 1); /* * 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); - pr_debug("ConfigFS: cmd: %p t_tasks: %d stop tasks ret:" - " %d\n", cmd, cmd->t_task_list_num, ret); + pr_debug("ConfigFS: cmd: %p stop tasks ret:" + " %d\n", cmd, ret); if (!ret) { pr_debug("ConfigFS: ITT[0x%08x] - stopping cmd....\n", cmd->se_tfo->get_task_tag(cmd)); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 19b8b2381d75..382542af3120 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -492,7 +492,6 @@ struct se_task { u16 task_flags; u8 task_scsi_status; enum dma_data_direction task_data_direction; - struct list_head t_list; struct list_head t_execute_list; struct list_head t_state_list; bool t_state_active; @@ -573,7 +572,6 @@ struct se_cmd { atomic_t t_se_count; atomic_t t_task_cdbs_left; atomic_t t_task_cdbs_ex_left; - atomic_t t_task_cdbs_sent; unsigned int transport_state; #define CMD_T_ABORTED (1 << 0) #define CMD_T_ACTIVE (1 << 1) @@ -598,10 +596,7 @@ struct se_cmd { struct scatterlist *t_bidi_data_sg; unsigned int t_bidi_data_nents; - /* Used for BIDI READ */ - struct list_head t_task_list; - u32 t_task_list_num; - + struct se_task *t_task; }; struct se_ua { -- 2.20.1