From 88dd9e26d6d3e743f9c7e4562b94b2ad3c2994d3 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 2 Nov 2011 03:33:16 -0700 Subject: target: Make TFO->check_stop_free return free status This patch converts target_core_fabric_ops->check_stop_free() usage in transport_cmd_check_stop() and associated fabric module usage to return '1' when the passed se_cmd has been released directly within ->check_stop_free(), or return '0' when the passed se_cmd has not been released. This addresses an issue where transport_cmd_finish_abort() -> transport_cmd_check_stop_to_fabric() was leaking descriptors during LUN_RESET for modules using ->check_stop_free(), but not directly releasing se_cmd in all cases. Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- include/target/target_core_fabric_ops.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/target/target_core_fabric_ops.h b/include/target/target_core_fabric_ops.h index 126c675f4f14..04c591da0844 100644 --- a/include/target/target_core_fabric_ops.h +++ b/include/target/target_core_fabric_ops.h @@ -46,9 +46,12 @@ struct target_core_fabric_ops { int (*new_cmd_map)(struct se_cmd *); /* * Optional to release struct se_cmd and fabric dependent allocated - * I/O descriptor in transport_cmd_check_stop() + * I/O descriptor in transport_cmd_check_stop(). + * + * Returning 1 will signal a descriptor has been released. + * Returning 0 will signal a descriptor has not been released. */ - void (*check_stop_free)(struct se_cmd *); + int (*check_stop_free)(struct se_cmd *); void (*release_cmd)(struct se_cmd *); /* * Called with spin_lock_bh(struct se_portal_group->session_lock held. -- cgit v1.2.3 From 3151d069e9e77043b0e791719bc65896cf24d9f0 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 2 Nov 2011 08:28:20 -0700 Subject: target: Remove core TRANSPORT_FREE_CMD_INTR usage This patch drops TRANSPORT_FREE_CMD_INTR usage from target core, which includes the removal of transport_generic_free_cmd_intr() symbol, TRANSPORT_FREE_CMD_INTR usage in transport_processing_thread(), and special case LUN_RESET handling to skip TRANSPORT_FREE_CMD_INTR processing in core_tmr_drain_cmd_list(). We now expect that fabric modules will use an internal workqueue to provide process context when releasing se_cmd descriptor resources via transport_generic_free_cmd(). Reported-by: Christoph Hellwig Cc: Christoph Hellwig Cc: Roland Dreier Cc: Madhuranath Iyengar Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 10 ---------- drivers/target/target_core_transport.c | 10 ---------- include/target/target_core_base.h | 1 - include/target/target_core_transport.h | 1 - 4 files changed, 22 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index b1b9f2d6f935..1d2aaba3f372 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -329,16 +329,6 @@ static void core_tmr_drain_cmd_list( */ if (prout_cmd == cmd) continue; - /* - * Skip direct processing of TRANSPORT_FREE_CMD_INTR for - * HW target mode fabrics. - */ - spin_lock(&cmd->t_state_lock); - if (cmd->t_state == TRANSPORT_FREE_CMD_INTR) { - spin_unlock(&cmd->t_state_lock); - continue; - } - spin_unlock(&cmd->t_state_lock); atomic_set(&cmd->t_transport_queue_active, 0); atomic_dec(&qobj->queue_cnt); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index bf8867f44021..64ee3342e0c2 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1718,13 +1718,6 @@ int transport_generic_handle_tmr( } EXPORT_SYMBOL(transport_generic_handle_tmr); -void transport_generic_free_cmd_intr( - struct se_cmd *cmd) -{ - transport_add_cmd_to_queue(cmd, TRANSPORT_FREE_CMD_INTR, false); -} -EXPORT_SYMBOL(transport_generic_free_cmd_intr); - /* * If the task is active, request it to be stopped and sleep until it * has completed. @@ -4597,9 +4590,6 @@ get_cmd: case TRANSPORT_PROCESS_WRITE: transport_generic_process_write(cmd); break; - case TRANSPORT_FREE_CMD_INTR: - transport_generic_free_cmd(cmd, 0); - break; case TRANSPORT_PROCESS_TMR: transport_generic_do_tmr(cmd); break; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 35aa786f93da..d571bcfd16ad 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -89,7 +89,6 @@ enum transport_state_table { TRANSPORT_PROCESS_TMR = 9, TRANSPORT_ISTATE_PROCESSING = 11, TRANSPORT_NEW_CMD_MAP = 16, - TRANSPORT_FREE_CMD_INTR = 17, TRANSPORT_COMPLETE_QF_WP = 18, TRANSPORT_COMPLETE_QF_OK = 19, }; diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index a037a1a6fbba..d1b68c9ccb75 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h @@ -160,7 +160,6 @@ extern int transport_generic_handle_cdb_map(struct se_cmd *); extern int transport_generic_handle_data(struct se_cmd *); extern void transport_new_cmd_failure(struct se_cmd *); extern int transport_generic_handle_tmr(struct se_cmd *); -extern void transport_generic_free_cmd_intr(struct se_cmd *); extern bool target_stop_task(struct se_task *task, unsigned long *flags); extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32, struct scatterlist *, u32); -- cgit v1.2.3 From a17f091d1a7c570804cfc2c77701634da88f8ecf Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 2 Nov 2011 21:52:08 -0700 Subject: target: Add generic active I/O shutdown logic This patch adds the initial pieces of generic active I/O shutdown logic. This is intended to be a 'opt-in' feature for fabric modules that includes the following functions to provide a mechinism for fabric modules to track se_cmd via se_session->sess_cmd_list: *) target_get_sess_cmd() - Add se_cmd to sess->sess_cmd_list, called from fabric module incoming I/O path. *) target_put_sess_cmd() - Check for completion or drop se_cmd from ->sess_cmd_list *) target_splice_sess_cmd_list() - Splice active I/O list from ->sess_cmd_list to ->sess_wait_list, can called with HW fabric lock held. *) target_wait_for_sess_cmds() - Walk ->sess_wait_list waiting on individual ->cmd_wait_comp. Optional transport_wait_for_tasks() call. target_splice_sess_cmd_list() is allowed to be called under HW fabric lock, and performs the splice into se_sess->sess_wait_list and set se_cmd->cmd_wait_set. Then target_wait_for_sess_cmds() walks the list waiting for individual target_put_sess_cmd() fabric callbacks to complete. It also adds TFO->check_release_cmd() to split the completion and memory release calls, where a fabric module uses target_put_sess_cmd() to check for I/O completion during session shutdown. This is currently pushed out into fabric modules as current fabric code may sleep here waiting for TFO->check_stop_free() to complete in main response path, and because target_wait_for_sess_cmds() calling TFO->release_cmd() to free fabric descriptor memory directly. Cc: Christoph Hellwig Cc: Roland Dreier Signed-off-by: Nicholas A. Bellinger --- drivers/target/target_core_transport.c | 132 ++++++++++++++++++++++++++++++-- include/target/target_core_base.h | 9 +++ include/target/target_core_fabric_ops.h | 4 + include/target/target_core_transport.h | 6 +- 4 files changed, 145 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 81bc355be317..e84b26ffb17b 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -268,6 +268,9 @@ struct se_session *transport_init_session(void) } INIT_LIST_HEAD(&se_sess->sess_list); INIT_LIST_HEAD(&se_sess->sess_acl_list); + INIT_LIST_HEAD(&se_sess->sess_cmd_list); + INIT_LIST_HEAD(&se_sess->sess_wait_list); + spin_lock_init(&se_sess->sess_cmd_lock); return se_sess; } @@ -1505,11 +1508,12 @@ void transport_init_se_cmd( INIT_LIST_HEAD(&cmd->se_ordered_node); 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); + init_completion(&cmd->cmd_wait_comp); spin_lock_init(&cmd->t_state_lock); atomic_set(&cmd->transport_dev_active, 1); @@ -3950,6 +3954,14 @@ void transport_release_cmd(struct se_cmd *cmd) core_tmr_release_req(cmd->se_tmr_req); if (cmd->t_task_cdb != cmd->__t_task_cdb) kfree(cmd->t_task_cdb); + /* + * Check if target_wait_for_sess_cmds() is expecting to + * release se_cmd directly here.. + */ + if (cmd->check_release != 0 && cmd->se_tfo->check_release_cmd) + if (cmd->se_tfo->check_release_cmd(cmd) != 0) + return; + cmd->se_tfo->release_cmd(cmd); } EXPORT_SYMBOL(transport_release_cmd); @@ -3977,6 +3989,114 @@ void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) } EXPORT_SYMBOL(transport_generic_free_cmd); +/* target_get_sess_cmd - Add command to active ->sess_cmd_list + * @se_sess: session to reference + * @se_cmd: command descriptor to add + */ +void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); + list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); + se_cmd->check_release = 1; + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); +} +EXPORT_SYMBOL(target_get_sess_cmd); + +/* target_put_sess_cmd - Check for active I/O shutdown or list delete + * @se_sess: session to reference + * @se_cmd: command descriptor to drop + */ +int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); + if (list_empty(&se_cmd->se_cmd_list)) { + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + WARN_ON(1); + return 0; + } + + if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) { + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + complete(&se_cmd->cmd_wait_comp); + return 1; + } + list_del(&se_cmd->se_cmd_list); + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + + return 0; +} +EXPORT_SYMBOL(target_put_sess_cmd); + +/* target_splice_sess_cmd_list - Split active cmds into sess_wait_list + * @se_sess: session to split + */ +void target_splice_sess_cmd_list(struct se_session *se_sess) +{ + struct se_cmd *se_cmd; + unsigned long flags; + + WARN_ON(!list_empty(&se_sess->sess_wait_list)); + INIT_LIST_HEAD(&se_sess->sess_wait_list); + + spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); + se_sess->sess_tearing_down = 1; + + list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list); + + list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) + se_cmd->cmd_wait_set = 1; + + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); +} +EXPORT_SYMBOL(target_splice_sess_cmd_list); + +/* target_wait_for_sess_cmds - Wait for outstanding descriptors + * @se_sess: session to wait for active I/O + * @wait_for_tasks: Make extra transport_wait_for_tasks call + */ +void target_wait_for_sess_cmds( + struct se_session *se_sess, + int wait_for_tasks) +{ + struct se_cmd *se_cmd, *tmp_cmd; + bool rc = false; + + list_for_each_entry_safe(se_cmd, tmp_cmd, + &se_sess->sess_wait_list, se_cmd_list) { + list_del(&se_cmd->se_cmd_list); + + pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:" + " %d\n", se_cmd, se_cmd->t_state, + se_cmd->se_tfo->get_cmd_state(se_cmd)); + + if (wait_for_tasks) { + pr_debug("Calling transport_wait_for_tasks se_cmd: %p t_state: %d," + " fabric state: %d\n", se_cmd, se_cmd->t_state, + se_cmd->se_tfo->get_cmd_state(se_cmd)); + + rc = transport_wait_for_tasks(se_cmd); + + pr_debug("After transport_wait_for_tasks se_cmd: %p t_state: %d," + " fabric state: %d\n", se_cmd, se_cmd->t_state, + se_cmd->se_tfo->get_cmd_state(se_cmd)); + } + + if (!rc) { + wait_for_completion(&se_cmd->cmd_wait_comp); + pr_debug("After cmd_wait_comp: se_cmd: %p t_state: %d" + " fabric state: %d\n", se_cmd, se_cmd->t_state, + se_cmd->se_tfo->get_cmd_state(se_cmd)); + } + + se_cmd->se_tfo->release_cmd(se_cmd); + } +} +EXPORT_SYMBOL(target_wait_for_sess_cmds); + /* transport_lun_wait_for_tasks(): * * Called from ConfigFS context to stop the passed struct se_cmd to allow @@ -4153,14 +4273,14 @@ int transport_clear_lun_from_sessions(struct se_lun *lun) * Called from frontend fabric context to wait for storage engine * to pause and/or release frontend generated struct se_cmd. */ -void transport_wait_for_tasks(struct se_cmd *cmd) +bool transport_wait_for_tasks(struct se_cmd *cmd) { unsigned long flags; spin_lock_irqsave(&cmd->t_state_lock, flags); if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD) && !(cmd->se_tmr_req)) { spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return; + return false; } /* * Only perform a possible wait_for_tasks if SCF_SUPPORTED_SAM_OPCODE @@ -4168,7 +4288,7 @@ void transport_wait_for_tasks(struct se_cmd *cmd) */ if (!(cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) && !cmd->se_tmr_req) { spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return; + return false; } /* * If we are already stopped due to an external event (ie: LUN shutdown) @@ -4211,7 +4331,7 @@ void transport_wait_for_tasks(struct se_cmd *cmd) if (!atomic_read(&cmd->t_transport_active) || atomic_read(&cmd->t_transport_aborted)) { spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return; + return false; } atomic_set(&cmd->t_transport_stop, 1); @@ -4236,6 +4356,8 @@ void transport_wait_for_tasks(struct se_cmd *cmd) cmd->se_tfo->get_task_tag(cmd)); spin_unlock_irqrestore(&cmd->t_state_lock, flags); + + return true; } EXPORT_SYMBOL(transport_wait_for_tasks); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index d571bcfd16ad..dd245b68be5a 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -425,6 +425,9 @@ struct se_cmd { enum transport_state_table t_state; /* Transport specific error status */ int transport_error_status; + /* Used to signal cmd->se_tfo->check_release_cmd() usage per cmd */ + int check_release:1; + int cmd_wait_set:1; /* See se_cmd_flags_table */ u32 se_cmd_flags; u32 se_ordered_id; @@ -451,6 +454,8 @@ struct se_cmd { struct se_session *se_sess; struct se_tmr_req *se_tmr_req; struct list_head se_queue_node; + struct list_head se_cmd_list; + struct completion cmd_wait_comp; struct target_core_fabric_ops *se_tfo; int (*transport_emulate_cdb)(struct se_cmd *); void (*transport_complete_callback)(struct se_cmd *); @@ -558,12 +563,16 @@ struct se_node_acl { } ____cacheline_aligned; struct se_session { + int sess_tearing_down:1; u64 sess_bin_isid; struct se_node_acl *se_node_acl; struct se_portal_group *se_tpg; void *fabric_sess_ptr; struct list_head sess_list; struct list_head sess_acl_list; + struct list_head sess_cmd_list; + struct list_head sess_wait_list; + spinlock_t sess_cmd_lock; } ____cacheline_aligned; struct se_device; diff --git a/include/target/target_core_fabric_ops.h b/include/target/target_core_fabric_ops.h index 04c591da0844..0256825f923d 100644 --- a/include/target/target_core_fabric_ops.h +++ b/include/target/target_core_fabric_ops.h @@ -52,6 +52,10 @@ struct target_core_fabric_ops { * Returning 0 will signal a descriptor has not been released. */ int (*check_stop_free)(struct se_cmd *); + /* + * Optional check for active I/O shutdown + */ + int (*check_release_cmd)(struct se_cmd *); void (*release_cmd)(struct se_cmd *); /* * Called with spin_lock_bh(struct se_portal_group->session_lock held. diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index d1b68c9ccb75..c16e9431dd01 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h @@ -164,12 +164,16 @@ extern bool target_stop_task(struct se_task *task, unsigned long *flags); extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32, struct scatterlist *, u32); extern int transport_clear_lun_from_sessions(struct se_lun *); -extern void transport_wait_for_tasks(struct se_cmd *); +extern bool transport_wait_for_tasks(struct se_cmd *); extern int transport_check_aborted_status(struct se_cmd *, int); extern int transport_send_check_condition_and_sense(struct se_cmd *, u8, int); extern void transport_send_task_abort(struct se_cmd *); extern void transport_release_cmd(struct se_cmd *); extern void transport_generic_free_cmd(struct se_cmd *, int); +extern void target_get_sess_cmd(struct se_session *, struct se_cmd *); +extern int target_put_sess_cmd(struct se_session *, struct se_cmd *); +extern void target_splice_sess_cmd_list(struct se_session *); +extern void target_wait_for_sess_cmds(struct se_session *, int); extern void transport_generic_wait_for_cmds(struct se_cmd *, int); extern void transport_do_task_sg_chain(struct se_cmd *); extern void transport_generic_process_write(struct se_cmd *); -- cgit v1.2.3 From e76a35d6c809bd1638e3b1b535bb780ac731c380 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 3 Nov 2011 17:50:42 -0400 Subject: target: pass the se_task to the CDB emulation callback We want to be able to handle all CDBs through it and remove hacks like always using the first task in a CDB in target_report_luns. Also rename the callback to ->execute_task to better describe its use. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_alua.c | 6 ++-- drivers/target/target_core_alua.h | 4 +-- drivers/target/target_core_device.c | 12 ++------ drivers/target/target_core_pr.c | 13 ++++++--- drivers/target/target_core_pr.h | 8 +++--- drivers/target/target_core_transport.c | 50 +++++++++++++--------------------- include/target/target_core_base.h | 2 +- include/target/target_core_device.h | 2 +- 8 files changed, 42 insertions(+), 55 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 8f4447749c71..14668d05ea0d 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -58,8 +58,9 @@ struct t10_alua_lu_gp *default_lu_gp; * * See spc4r17 section 6.27 */ -int core_emulate_report_target_port_groups(struct se_cmd *cmd) +int target_emulate_report_target_port_groups(struct se_task *task) { + struct se_cmd *cmd = task->task_se_cmd; struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; struct se_port *port; struct t10_alua_tg_pt_gp *tg_pt_gp; @@ -172,8 +173,9 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd) * * See spc4r17 section 6.35 */ -int core_emulate_set_target_port_groups(struct se_cmd *cmd) +int target_emulate_set_target_port_groups(struct se_task *task) { + struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; struct se_subsystem_dev *su_dev = dev->se_sub_dev; struct se_port *port, *l_port = cmd->se_lun->lun_sep; diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index c86f97a081ed..c5b4ecd3e745 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h @@ -66,8 +66,8 @@ extern struct kmem_cache *t10_alua_lu_gp_mem_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; -extern int core_emulate_report_target_port_groups(struct se_cmd *); -extern int core_emulate_set_target_port_groups(struct se_cmd *); +extern int target_emulate_report_target_port_groups(struct se_task *); +extern int target_emulate_set_target_port_groups(struct se_task *); extern int core_alua_check_nonop_delay(struct se_cmd *); extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *, struct se_device *, struct se_port *, diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index f870c3bcfd82..ffbb1d6532e9 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -651,23 +651,15 @@ void core_dev_unexport( lun->lun_se_dev = NULL; } -int transport_core_report_lun_response(struct se_cmd *se_cmd) +int target_report_luns(struct se_task *se_task) { + struct se_cmd *se_cmd = se_task->task_se_cmd; struct se_dev_entry *deve; struct se_lun *se_lun; struct se_session *se_sess = se_cmd->se_sess; - struct se_task *se_task; unsigned char *buf; u32 cdb_offset = 0, lun_count = 0, offset = 8, i; - list_for_each_entry(se_task, &se_cmd->t_task_list, t_list) - break; - - if (!se_task) { - pr_err("Unable to locate struct se_task for struct se_cmd\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; - } - buf = transport_kmap_first_data_page(se_cmd); /* diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 34403e80b87c..09e1e3e896c6 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -198,8 +198,9 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd, int *ret) return false; } -int target_scsi2_reservation_release(struct se_cmd *cmd) +int target_scsi2_reservation_release(struct se_task *task) { + struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg = sess->se_tpg; @@ -235,8 +236,9 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) return 0; } -int target_scsi2_reservation_reserve(struct se_cmd *cmd) +int target_scsi2_reservation_reserve(struct se_task *task) { + struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg = sess->se_tpg; @@ -3734,8 +3736,9 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb) /* * See spc4r17 section 6.14 Table 170 */ -int target_scsi3_emulate_pr_out(struct se_cmd *cmd) +int target_scsi3_emulate_pr_out(struct se_task *task) { + struct se_cmd *cmd = task->task_se_cmd; unsigned char *cdb = &cmd->t_task_cdb[0]; unsigned char *buf; u64 res_key, sa_res_key; @@ -4203,8 +4206,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) return 0; } -int target_scsi3_emulate_pr_in(struct se_cmd *cmd) +int target_scsi3_emulate_pr_in(struct se_task *task) { + struct se_cmd *cmd = task->task_se_cmd; + /* * Following spc2r20 5.5.1 Reservations overview: * diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h index c9acb1108124..b97f6940dd05 100644 --- a/drivers/target/target_core_pr.h +++ b/drivers/target/target_core_pr.h @@ -47,8 +47,8 @@ extern struct kmem_cache *t10_pr_reg_cache; extern int core_pr_dump_initiator_port(struct t10_pr_registration *, char *, u32); -extern int target_scsi2_reservation_release(struct se_cmd *cmd); -extern int target_scsi2_reservation_reserve(struct se_cmd *cmd); +extern int target_scsi2_reservation_release(struct se_task *task); +extern int target_scsi2_reservation_reserve(struct se_task *task); extern int core_scsi3_alloc_aptpl_registration( struct t10_reservation *, u64, unsigned char *, unsigned char *, u32, @@ -63,8 +63,8 @@ extern unsigned char *core_scsi3_pr_dump_type(int); extern int core_scsi3_check_cdb_abort_and_preempt(struct list_head *, struct se_cmd *); -extern int target_scsi3_emulate_pr_in(struct se_cmd *cmd); -extern int target_scsi3_emulate_pr_out(struct se_cmd *cmd); +extern int target_scsi3_emulate_pr_in(struct se_task *task); +extern int target_scsi3_emulate_pr_out(struct se_task *task); extern int core_setup_reservations(struct se_device *, int); #endif /* TARGET_CORE_PR_H */ diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 717f84a9b42b..3ad8db2d3ad3 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2156,12 +2156,12 @@ check_depth: spin_unlock_irqrestore(&cmd->t_state_lock, flags); /* - * The struct se_cmd->transport_emulate_cdb() function pointer is used + * The struct se_cmd->execute_task() function pointer is used * to grab REPORT_LUNS and other CDBs we want to handle before they hit the * struct se_subsystem_api->do_task() caller below. */ - if (cmd->transport_emulate_cdb) { - error = cmd->transport_emulate_cdb(cmd); + if (cmd->execute_task) { + error = cmd->execute_task(task); if (error != 0) { cmd->transport_error_status = error; spin_lock_irqsave(&cmd->t_state_lock, flags); @@ -2174,7 +2174,7 @@ check_depth: goto check_depth; } /* - * Handle the successful completion for transport_emulate_cdb() + * Handle the successful completion for execute_task() * for synchronous operation, following SCF_EMULATE_CDB_ASYNC * Otherwise the caller is expected to complete the task with * proper status. @@ -2795,12 +2795,10 @@ static int transport_generic_cmd_sequencer( /* * Check for emulated MI_REPORT_TARGET_PGS. */ - if (cdb[1] == MI_REPORT_TARGET_PGS) { - cmd->transport_emulate_cdb = - (su_dev->t10_alua.alua_type == - SPC3_ALUA_EMULATED) ? - core_emulate_report_target_port_groups : - NULL; + if (cdb[1] == MI_REPORT_TARGET_PGS && + su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + cmd->execute_task = + target_emulate_report_target_port_groups; } size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; @@ -2843,13 +2841,13 @@ static int transport_generic_cmd_sequencer( break; case PERSISTENT_RESERVE_IN: if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) - cmd->transport_emulate_cdb = target_scsi3_emulate_pr_in; + cmd->execute_task = target_scsi3_emulate_pr_in; size = (cdb[7] << 8) + cdb[8]; cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; case PERSISTENT_RESERVE_OUT: if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) - cmd->transport_emulate_cdb = target_scsi3_emulate_pr_out; + cmd->execute_task = target_scsi3_emulate_pr_out; size = (cdb[7] << 8) + cdb[8]; cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; break; @@ -2868,12 +2866,10 @@ static int transport_generic_cmd_sequencer( * * Check for emulated MO_SET_TARGET_PGS. */ - if (cdb[1] == MO_SET_TARGET_PGS) { - cmd->transport_emulate_cdb = - (su_dev->t10_alua.alua_type == - SPC3_ALUA_EMULATED) ? - core_emulate_set_target_port_groups : - NULL; + if (cdb[1] == MO_SET_TARGET_PGS && + su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + cmd->execute_task = + target_emulate_set_target_port_groups; } size = (cdb[6] << 24) | (cdb[7] << 16) | @@ -2966,10 +2962,8 @@ static int transport_generic_cmd_sequencer( * is running in SPC_PASSTHROUGH, and wants reservations * emulation disabled. */ - if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) { - cmd->transport_emulate_cdb = - target_scsi2_reservation_reserve; - } + if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) + cmd->execute_task = target_scsi2_reservation_reserve; cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; break; case RELEASE: @@ -2983,10 +2977,8 @@ static int transport_generic_cmd_sequencer( else size = cmd->data_length; - if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) { - cmd->transport_emulate_cdb = - target_scsi2_reservation_release; - } + if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) + cmd->execute_task = target_scsi2_reservation_release; cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; break; case SYNCHRONIZE_CACHE: @@ -3007,9 +2999,6 @@ static int transport_generic_cmd_sequencer( size = transport_get_size(sectors, cdb, cmd); cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; - /* - * For TCM/pSCSI passthrough, skip cmd->transport_emulate_cdb() - */ if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) break; /* @@ -3086,8 +3075,7 @@ static int transport_generic_cmd_sequencer( cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; break; case REPORT_LUNS: - cmd->transport_emulate_cdb = - transport_core_report_lun_response; + cmd->execute_task = target_report_luns; size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; /* * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index dd245b68be5a..14c1a71a36eb 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -457,7 +457,7 @@ struct se_cmd { struct list_head se_cmd_list; struct completion cmd_wait_comp; struct target_core_fabric_ops *se_tfo; - int (*transport_emulate_cdb)(struct se_cmd *); + int (*execute_task)(struct se_task *); void (*transport_complete_callback)(struct se_cmd *); unsigned char *t_task_cdb; diff --git a/include/target/target_core_device.h b/include/target/target_core_device.h index 46571912086c..2be31ff8763b 100644 --- a/include/target/target_core_device.h +++ b/include/target/target_core_device.h @@ -17,7 +17,7 @@ extern int core_dev_export(struct se_device *, struct se_portal_group *, struct se_lun *); extern void core_dev_unexport(struct se_device *, struct se_portal_group *, struct se_lun *); -extern int transport_core_report_lun_response(struct se_cmd *); +extern int target_report_luns(struct se_task *); extern void se_release_device_for_hba(struct se_device *); extern void se_release_vpd_for_dev(struct se_device *); extern void se_clear_dev_ports(struct se_device *); -- cgit v1.2.3 From d29a5b6acc4b63d4e05ff554509df6fbeaf527cd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 3 Nov 2011 17:50:44 -0400 Subject: target: remove SCF_EMULATE_CDB_ASYNC All ->execute_task instances now need to complete the I/O explicitly, which can either happen synchronously or asynchronously. Note that a lot of the CDB emulations appear to return success even if some lowlevel operations failed. Given that this is an existing issue this patch doesn't change that fact. (nab: Adding missing switch breaks in PR-IN + PR_OUT) Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_alua.c | 5 +- drivers/target/target_core_cdb.c | 58 ++++++++++----- drivers/target/target_core_device.c | 2 + drivers/target/target_core_pr.c | 129 ++++++++++++++++++++++----------- drivers/target/target_core_transport.c | 47 +++--------- include/target/target_core_base.h | 1 - 6 files changed, 142 insertions(+), 100 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 14668d05ea0d..2739b93983a2 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -165,6 +165,8 @@ int target_emulate_report_target_port_groups(struct se_task *task) transport_kunmap_first_data_page(cmd); + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); return 0; } @@ -343,7 +345,8 @@ int target_emulate_set_target_port_groups(struct se_task *task) out: transport_kunmap_first_data_page(cmd); - + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); return 0; } diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index ff2dfa383735..5a03085304e5 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -688,8 +688,10 @@ target_emulate_inquiry(struct se_task *task) unsigned char *cdb = cmd->t_task_cdb; int p, ret; - if (!(cdb[1] & 0x1)) - return target_emulate_inquiry_std(cmd); + if (!(cdb[1] & 0x1)) { + ret = target_emulate_inquiry_std(cmd); + goto out; + } /* * Make sure we at least have 4 bytes of INQUIRY response @@ -708,17 +710,25 @@ target_emulate_inquiry(struct se_task *task) buf[0] = dev->transport->get_device_type(dev); - for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) + for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) { if (cdb[2] == evpd_handlers[p].page) { buf[1] = cdb[2]; ret = evpd_handlers[p].emulate(cmd, buf); - transport_kunmap_first_data_page(cmd); - return ret; + goto out_unmap; } + } - transport_kunmap_first_data_page(cmd); pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); - return -EINVAL; + ret = -EINVAL; + +out_unmap: + transport_kunmap_first_data_page(cmd); +out: + if (!ret) { + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); + } + return ret; } static int @@ -753,6 +763,8 @@ target_emulate_readcapacity(struct se_task *task) transport_kunmap_first_data_page(cmd); + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); return 0; } @@ -787,6 +799,8 @@ target_emulate_readcapacity_16(struct se_task *task) transport_kunmap_first_data_page(cmd); + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); return 0; } @@ -1000,6 +1014,8 @@ target_emulate_modesense(struct se_task *task) memcpy(rbuf, buf, offset); transport_kunmap_first_data_page(cmd); + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); return 0; } @@ -1065,7 +1081,8 @@ target_emulate_request_sense(struct se_task *task) end: transport_kunmap_first_data_page(cmd); - + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); return 0; } @@ -1122,7 +1139,10 @@ target_emulate_unmap(struct se_task *task) err: transport_kunmap_first_data_page(cmd); - + if (!ret) { + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); + } return ret; } @@ -1171,6 +1191,8 @@ target_emulate_write_same(struct se_task *task) return ret; } + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); return 0; } @@ -1189,6 +1211,14 @@ target_emulate_synchronize_cache(struct se_task *task) return 0; } +static int +target_emulate_noop(struct se_task *task) +{ + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); + return 0; +} + int transport_emulate_control_cdb(struct se_task *task) { @@ -1259,6 +1289,7 @@ transport_emulate_control_cdb(struct se_task *task) case TEST_UNIT_READY: case VERIFY: case WRITE_FILEMARKS: + ret = target_emulate_noop(task); break; default: pr_err("Unsupported SCSI Opcode: 0x%02x for %s\n", @@ -1268,15 +1299,6 @@ transport_emulate_control_cdb(struct se_task *task) if (ret < 0) return ret; - /* - * Handle the successful completion here unless a caller - * has explictly requested an asychronous completion. - */ - if (!(cmd->se_cmd_flags & SCF_EMULATE_CDB_ASYNC)) { - task->task_scsi_status = GOOD; - transport_complete_task(task, 1); - } - return PYX_TRANSPORT_SENT_TO_TRANSPORT; } diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index ffbb1d6532e9..28d2c808c56b 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -705,6 +705,8 @@ done: buf[2] = ((lun_count >> 8) & 0xff); buf[3] = (lun_count & 0xff); + se_task->task_scsi_status = GOOD; + transport_complete_task(se_task, 1); return PYX_TRANSPORT_SENT_TO_TRANSPORT; } diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 09e1e3e896c6..5a4ebfc3a54f 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -204,23 +204,21 @@ int target_scsi2_reservation_release(struct se_task *task) struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg = sess->se_tpg; - int ret; + int ret = 0; if (!sess || !tpg) - return 0; + goto out; if (target_check_scsi2_reservation_conflict(cmd, &ret)) - return ret; + goto out; + ret = 0; spin_lock(&dev->dev_reservation_lock); - if (!dev->dev_reserved_node_acl || !sess) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } + if (!dev->dev_reserved_node_acl || !sess) + goto out_unlock; + + if (dev->dev_reserved_node_acl != sess->se_node_acl) + goto out_unlock; - if (dev->dev_reserved_node_acl != sess->se_node_acl) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } dev->dev_reserved_node_acl = NULL; dev->dev_flags &= ~DF_SPC2_RESERVATIONS; if (dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID) { @@ -231,9 +229,15 @@ int target_scsi2_reservation_release(struct se_task *task) " MAPPED LUN: %u for %s\n", tpg->se_tpg_tfo->get_fabric_name(), cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun, sess->se_node_acl->initiatorname); - spin_unlock(&dev->dev_reservation_lock); - return 0; +out_unlock: + spin_unlock(&dev->dev_reservation_lock); +out: + if (!ret) { + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); + } + return ret; } int target_scsi2_reservation_reserve(struct se_task *task) @@ -242,23 +246,25 @@ int target_scsi2_reservation_reserve(struct se_task *task) struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg = sess->se_tpg; - int ret; + int ret = 0; if ((cmd->t_task_cdb[1] & 0x01) && (cmd->t_task_cdb[1] & 0x02)) { pr_err("LongIO and Obselete Bits set, returning" " ILLEGAL_REQUEST\n"); - return PYX_TRANSPORT_ILLEGAL_REQUEST; + ret = PYX_TRANSPORT_ILLEGAL_REQUEST; + goto out; } /* * This is currently the case for target_core_mod passthrough struct se_cmd * ops */ if (!sess || !tpg) - return 0; + goto out; if (target_check_scsi2_reservation_conflict(cmd, &ret)) - return ret; + goto out; + ret = 0; spin_lock(&dev->dev_reservation_lock); if (dev->dev_reserved_node_acl && (dev->dev_reserved_node_acl != sess->se_node_acl)) { @@ -271,8 +277,8 @@ int target_scsi2_reservation_reserve(struct se_task *task) " from %s \n", cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun, sess->se_node_acl->initiatorname); - spin_unlock(&dev->dev_reservation_lock); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + ret = PYX_TRANSPORT_RESERVATION_CONFLICT; + goto out_unlock; } dev->dev_reserved_node_acl = sess->se_node_acl; @@ -285,9 +291,15 @@ int target_scsi2_reservation_reserve(struct se_task *task) " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun, sess->se_node_acl->initiatorname); - spin_unlock(&dev->dev_reservation_lock); - return 0; +out_unlock: + spin_unlock(&dev->dev_reservation_lock); +out: + if (!ret) { + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); + } + return ret; } @@ -3744,6 +3756,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task) u64 res_key, sa_res_key; int sa, scope, type, aptpl; int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; + int ret; /* * Following spc2r20 5.5.1 Reservations overview: @@ -3758,7 +3771,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + ret = PYX_TRANSPORT_RESERVATION_CONFLICT; + goto out; } /* @@ -3771,7 +3785,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) if (cmd->data_length < 24) { pr_warn("SPC-PR: Received PR OUT parameter list" " length too small: %u\n", cmd->data_length); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + goto out; } /* * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB) @@ -3804,8 +3819,11 @@ int target_scsi3_emulate_pr_out(struct se_task *task) /* * SPEC_I_PT=1 is only valid for Service action: REGISTER */ - if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) { + ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + goto out; + } + /* * From spc4r17 section 6.14: * @@ -3819,7 +3837,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) (cmd->data_length != 24)) { pr_warn("SPC-PR: Received PR OUT illegal parameter" " list length: %u\n", cmd->data_length); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + goto out; } /* * (core_scsi3_emulate_pro_* function parameters @@ -3828,35 +3847,47 @@ int target_scsi3_emulate_pr_out(struct se_task *task) */ switch (sa) { case PRO_REGISTER: - return core_scsi3_emulate_pro_register(cmd, + ret = core_scsi3_emulate_pro_register(cmd, res_key, sa_res_key, aptpl, all_tg_pt, spec_i_pt, 0); + break; case PRO_RESERVE: - return core_scsi3_emulate_pro_reserve(cmd, - type, scope, res_key); + ret = core_scsi3_emulate_pro_reserve(cmd, type, scope, res_key); + break; case PRO_RELEASE: - return core_scsi3_emulate_pro_release(cmd, - type, scope, res_key); + ret = core_scsi3_emulate_pro_release(cmd, type, scope, res_key); + break; case PRO_CLEAR: - return core_scsi3_emulate_pro_clear(cmd, res_key); + ret = core_scsi3_emulate_pro_clear(cmd, res_key); + break; case PRO_PREEMPT: - return core_scsi3_emulate_pro_preempt(cmd, type, scope, + ret = core_scsi3_emulate_pro_preempt(cmd, type, scope, res_key, sa_res_key, 0); + break; case PRO_PREEMPT_AND_ABORT: - return core_scsi3_emulate_pro_preempt(cmd, type, scope, + ret = core_scsi3_emulate_pro_preempt(cmd, type, scope, res_key, sa_res_key, 1); + break; case PRO_REGISTER_AND_IGNORE_EXISTING_KEY: - return core_scsi3_emulate_pro_register(cmd, + ret = core_scsi3_emulate_pro_register(cmd, 0, sa_res_key, aptpl, all_tg_pt, spec_i_pt, 1); + break; case PRO_REGISTER_AND_MOVE: - return core_scsi3_emulate_pro_register_and_move(cmd, res_key, + ret = core_scsi3_emulate_pro_register_and_move(cmd, res_key, sa_res_key, aptpl, unreg); + break; default: pr_err("Unknown PERSISTENT_RESERVE_OUT service" " action: 0x%02x\n", cdb[1] & 0x1f); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + ret = PYX_TRANSPORT_INVALID_CDB_FIELD; + break; } - return PYX_TRANSPORT_INVALID_CDB_FIELD; +out: + if (!ret) { + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); + } + return ret; } /* @@ -4209,6 +4240,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) int target_scsi3_emulate_pr_in(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; + int ret; /* * Following spc2r20 5.5.1 Reservations overview: @@ -4228,18 +4260,29 @@ int target_scsi3_emulate_pr_in(struct se_task *task) switch (cmd->t_task_cdb[1] & 0x1f) { case PRI_READ_KEYS: - return core_scsi3_pri_read_keys(cmd); + ret = core_scsi3_pri_read_keys(cmd); + break; case PRI_READ_RESERVATION: - return core_scsi3_pri_read_reservation(cmd); + ret = core_scsi3_pri_read_reservation(cmd); + break; case PRI_REPORT_CAPABILITIES: - return core_scsi3_pri_report_capabilities(cmd); + ret = core_scsi3_pri_report_capabilities(cmd); + break; case PRI_READ_FULL_STATUS: - return core_scsi3_pri_read_full_status(cmd); + ret = core_scsi3_pri_read_full_status(cmd); + break; default: pr_err("Unknown PERSISTENT_RESERVE_IN service" " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + ret = PYX_TRANSPORT_INVALID_CDB_FIELD; + break; + } + + if (!ret) { + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); } + return ret; } static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 3ad8db2d3ad3..74015793c03a 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2162,28 +2162,6 @@ check_depth: */ if (cmd->execute_task) { error = cmd->execute_task(task); - if (error != 0) { - cmd->transport_error_status = error; - spin_lock_irqsave(&cmd->t_state_lock, flags); - task->task_flags &= ~TF_ACTIVE; - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - atomic_set(&cmd->t_transport_sent, 0); - transport_stop_tasks_for_cmd(cmd); - atomic_inc(&dev->depth_left); - transport_generic_request_failure(cmd, 0, 1); - goto check_depth; - } - /* - * Handle the successful completion for execute_task() - * for synchronous operation, following SCF_EMULATE_CDB_ASYNC - * Otherwise the caller is expected to complete the task with - * proper status. - */ - if (!(cmd->se_cmd_flags & SCF_EMULATE_CDB_ASYNC)) { - cmd->scsi_status = SAM_STAT_GOOD; - task->task_scsi_status = GOOD; - transport_complete_task(task, 1); - } } else { /* * Currently for all virtual TCM plugins including IBLOCK, FILEIO and @@ -2200,17 +2178,17 @@ check_depth: error = transport_emulate_control_cdb(task); else error = dev->transport->do_task(task); + } - if (error != 0) { - cmd->transport_error_status = error; - spin_lock_irqsave(&cmd->t_state_lock, flags); - task->task_flags &= ~TF_ACTIVE; - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - atomic_set(&cmd->t_transport_sent, 0); - transport_stop_tasks_for_cmd(cmd); - atomic_inc(&dev->depth_left); - transport_generic_request_failure(cmd, 0, 1); - } + if (error != 0) { + cmd->transport_error_status = error; + spin_lock_irqsave(&cmd->t_state_lock, flags); + task->task_flags &= ~TF_ACTIVE; + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + atomic_set(&cmd->t_transport_sent, 0); + transport_stop_tasks_for_cmd(cmd); + atomic_inc(&dev->depth_left); + transport_generic_request_failure(cmd, 0, 1); } goto check_depth; @@ -3001,11 +2979,6 @@ static int transport_generic_cmd_sequencer( if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) break; - /* - * Set SCF_EMULATE_CDB_ASYNC to ensure asynchronous operation - * for SYNCHRONIZE_CACHE* Immed=1 case in __transport_execute_tasks() - */ - cmd->se_cmd_flags |= SCF_EMULATE_CDB_ASYNC; /* * Check to ensure that LBA + Range does not exceed past end of * device for IBLOCK and FILEIO ->do_sync_cache() backend calls diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 14c1a71a36eb..7f5fed3c89e1 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -114,7 +114,6 @@ enum se_cmd_flags_table { SCF_DELAYED_CMD_FROM_SAM_ATTR = 0x00080000, SCF_UNUSED = 0x00100000, SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00400000, - SCF_EMULATE_CDB_ASYNC = 0x01000000, }; /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */ -- cgit v1.2.3