aboutsummaryrefslogtreecommitdiffstats
path: root/include/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-11-03 00:52:08 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-11-04 03:50:26 -0400
commita17f091d1a7c570804cfc2c77701634da88f8ecf (patch)
tree50884063148c31cb5ee7b9a3f13bcc41f585cb92 /include/target
parent2235007c4d3245c0eca5e49497aafe5a111c00fb (diff)
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 <hch@lst.de> Cc: Roland Dreier <roland@purestorage.com> Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'include/target')
-rw-r--r--include/target/target_core_base.h9
-rw-r--r--include/target/target_core_fabric_ops.h4
-rw-r--r--include/target/target_core_transport.h6
3 files changed, 18 insertions, 1 deletions
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 {
425 enum transport_state_table t_state; 425 enum transport_state_table t_state;
426 /* Transport specific error status */ 426 /* Transport specific error status */
427 int transport_error_status; 427 int transport_error_status;
428 /* Used to signal cmd->se_tfo->check_release_cmd() usage per cmd */
429 int check_release:1;
430 int cmd_wait_set:1;
428 /* See se_cmd_flags_table */ 431 /* See se_cmd_flags_table */
429 u32 se_cmd_flags; 432 u32 se_cmd_flags;
430 u32 se_ordered_id; 433 u32 se_ordered_id;
@@ -451,6 +454,8 @@ struct se_cmd {
451 struct se_session *se_sess; 454 struct se_session *se_sess;
452 struct se_tmr_req *se_tmr_req; 455 struct se_tmr_req *se_tmr_req;
453 struct list_head se_queue_node; 456 struct list_head se_queue_node;
457 struct list_head se_cmd_list;
458 struct completion cmd_wait_comp;
454 struct target_core_fabric_ops *se_tfo; 459 struct target_core_fabric_ops *se_tfo;
455 int (*transport_emulate_cdb)(struct se_cmd *); 460 int (*transport_emulate_cdb)(struct se_cmd *);
456 void (*transport_complete_callback)(struct se_cmd *); 461 void (*transport_complete_callback)(struct se_cmd *);
@@ -558,12 +563,16 @@ struct se_node_acl {
558} ____cacheline_aligned; 563} ____cacheline_aligned;
559 564
560struct se_session { 565struct se_session {
566 int sess_tearing_down:1;
561 u64 sess_bin_isid; 567 u64 sess_bin_isid;
562 struct se_node_acl *se_node_acl; 568 struct se_node_acl *se_node_acl;
563 struct se_portal_group *se_tpg; 569 struct se_portal_group *se_tpg;
564 void *fabric_sess_ptr; 570 void *fabric_sess_ptr;
565 struct list_head sess_list; 571 struct list_head sess_list;
566 struct list_head sess_acl_list; 572 struct list_head sess_acl_list;
573 struct list_head sess_cmd_list;
574 struct list_head sess_wait_list;
575 spinlock_t sess_cmd_lock;
567} ____cacheline_aligned; 576} ____cacheline_aligned;
568 577
569struct se_device; 578struct 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 {
52 * Returning 0 will signal a descriptor has not been released. 52 * Returning 0 will signal a descriptor has not been released.
53 */ 53 */
54 int (*check_stop_free)(struct se_cmd *); 54 int (*check_stop_free)(struct se_cmd *);
55 /*
56 * Optional check for active I/O shutdown
57 */
58 int (*check_release_cmd)(struct se_cmd *);
55 void (*release_cmd)(struct se_cmd *); 59 void (*release_cmd)(struct se_cmd *);
56 /* 60 /*
57 * Called with spin_lock_bh(struct se_portal_group->session_lock held. 61 * 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);
164extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32, 164extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32,
165 struct scatterlist *, u32); 165 struct scatterlist *, u32);
166extern int transport_clear_lun_from_sessions(struct se_lun *); 166extern int transport_clear_lun_from_sessions(struct se_lun *);
167extern void transport_wait_for_tasks(struct se_cmd *); 167extern bool transport_wait_for_tasks(struct se_cmd *);
168extern int transport_check_aborted_status(struct se_cmd *, int); 168extern int transport_check_aborted_status(struct se_cmd *, int);
169extern int transport_send_check_condition_and_sense(struct se_cmd *, u8, int); 169extern int transport_send_check_condition_and_sense(struct se_cmd *, u8, int);
170extern void transport_send_task_abort(struct se_cmd *); 170extern void transport_send_task_abort(struct se_cmd *);
171extern void transport_release_cmd(struct se_cmd *); 171extern void transport_release_cmd(struct se_cmd *);
172extern void transport_generic_free_cmd(struct se_cmd *, int); 172extern void transport_generic_free_cmd(struct se_cmd *, int);
173extern void target_get_sess_cmd(struct se_session *, struct se_cmd *);
174extern int target_put_sess_cmd(struct se_session *, struct se_cmd *);
175extern void target_splice_sess_cmd_list(struct se_session *);
176extern void target_wait_for_sess_cmds(struct se_session *, int);
173extern void transport_generic_wait_for_cmds(struct se_cmd *, int); 177extern void transport_generic_wait_for_cmds(struct se_cmd *, int);
174extern void transport_do_task_sg_chain(struct se_cmd *); 178extern void transport_do_task_sg_chain(struct se_cmd *);
175extern void transport_generic_process_write(struct se_cmd *); 179extern void transport_generic_process_write(struct se_cmd *);