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 --- include/target/target_core_base.h | 9 +++++++++ include/target/target_core_fabric_ops.h | 4 ++++ include/target/target_core_transport.h | 6 +++++- 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'include/target') 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-59-g8ed1b