[PATCH 04/21] target: Use a new completion object for transport_wait_for_tasks()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Make transport_wait_for_tasks() use a completion that has been
allocated on the stack instead of the t_transport_stop_comp member
of struct se_cmd. Introduce a callback mechanism in struct se_cmd.

This is a first step towards removing the t_transport_stop_comp
member. That member variable cannot yet be removed via this patch
because the tcm_qla2xxx driver uses it directly.

Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxxxxxx>
---
 drivers/target/target_core_transport.c | 34 ++++++++++++++++++++++++++++++----
 include/target/target_core_base.h      | 12 ++++++++++++
 include/target/target_core_fabric.h    |  3 +++
 3 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 19c9241..3538a36 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -598,7 +598,6 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
 
 		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-		complete_all(&cmd->t_transport_stop_comp);
 		return 1;
 	}
 
@@ -723,7 +722,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
 	if (cmd->transport_state & CMD_T_ABORTED &&
 	    cmd->transport_state & CMD_T_STOP) {
 		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-		complete_all(&cmd->t_transport_stop_comp);
 		return;
 	} else if (!success) {
 		INIT_WORK(&cmd->work, target_complete_failure_work);
@@ -1177,10 +1175,25 @@ void transport_init_se_cmd(
 	cmd->sam_task_attr = task_attr;
 	cmd->sense_buffer = sense_buffer;
 
+	cmd->cb_count = 0;
 	cmd->state_active = false;
 }
 EXPORT_SYMBOL(transport_init_se_cmd);
 
+void __target_add_cmd_cb(struct se_cmd *cmd, void (*done)(void *),
+			 void *done_arg)
+{
+	int i;
+
+	lockdep_assert_held(&cmd->t_state_lock);
+
+	i = cmd->cb_count++;
+	BUG_ON(i >= ARRAY_SIZE(cmd->done_cb));
+	cmd->done_cb[i].cb = done;
+	cmd->done_cb[i].arg = done_arg;
+}
+EXPORT_SYMBOL(__target_add_cmd_cb);
+
 static sense_reason_t
 transport_check_alloc_task_attr(struct se_cmd *cmd)
 {
@@ -1853,7 +1866,6 @@ void target_execute_cmd(struct se_cmd *cmd)
 			__func__, __LINE__, cmd->tag);
 
 		spin_unlock_irq(&cmd->t_state_lock);
-		complete_all(&cmd->t_transport_stop_comp);
 		return;
 	}
 
@@ -2510,6 +2522,8 @@ static void target_release_cmd_kref(struct kref *kref)
 {
 	struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
 	struct se_session *se_sess = se_cmd->se_sess;
+	struct se_cmd_done_cb *cbe;
+	int i;
 
 	if (list_empty(&se_cmd->se_cmd_list)) {
 		se_cmd->se_tfo->release_cmd(se_cmd);
@@ -2524,6 +2538,11 @@ static void target_release_cmd_kref(struct kref *kref)
 	list_del(&se_cmd->se_cmd_list);
 	spin_unlock(&se_sess->sess_cmd_lock);
 
+	for (i = 0; i < se_cmd->cb_count; i++) {
+		cbe = &se_cmd->done_cb[i];
+		cbe->cb(cbe->arg);
+	}
+
 	se_cmd->se_tfo->release_cmd(se_cmd);
 }
 
@@ -2609,6 +2628,11 @@ void transport_clear_lun_ref(struct se_lun *lun)
 	wait_for_completion(&lun->lun_ref_comp);
 }
 
+static void target_cmd_done(void *arg)
+{
+	complete(arg);
+}
+
 /**
  * transport_wait_for_tasks - wait for completion to occur
  * @cmd:	command to wait
@@ -2618,6 +2642,7 @@ void transport_clear_lun_ref(struct se_lun *lun)
  */
 bool transport_wait_for_tasks(struct se_cmd *cmd)
 {
+	DECLARE_COMPLETION_ONSTACK(cmd_done);
 	unsigned long flags;
 
 	spin_lock_irqsave(&cmd->t_state_lock, flags);
@@ -2643,9 +2668,10 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
 	pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08llx i_state: %d, t_state: %d, CMD_T_STOP\n",
 		cmd, cmd->tag, cmd->se_tfo->get_cmd_state(cmd), cmd->t_state);
 
+	__target_add_cmd_cb(cmd, target_cmd_done, &cmd_done);
 	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-	wait_for_completion(&cmd->t_transport_stop_comp);
+	wait_for_completion(&cmd_done);
 
 	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 2b57314..65f7258 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -466,6 +466,16 @@ struct se_dif_v1_tuple {
 #define TCM_ORDERED_TAG	0x22
 #define TCM_ACA_TAG	0x24
 
+/**
+ * struct se_cmd_done_cb - callback function invoked after a se_cmd finished
+ * @cb:		Callback function.
+ * @cb_arg:	Argument that will be passed to the callback function.
+ */
+struct se_cmd_done_cb {
+	void	(*cb)(void *);
+	void	*arg;
+};
+
 struct se_cmd {
 	/* SAM response code being sent to initiator */
 	u8			scsi_status;
@@ -527,6 +537,8 @@ struct se_cmd {
 #define CMD_T_BUSY		(1 << 9)
 	spinlock_t		t_state_lock;
 	struct completion	t_transport_stop_comp;
+	unsigned int		cb_count;   /* protected by t_state_lock */
+	struct se_cmd_done_cb	done_cb[1]; /* protected by t_state_lock */
 
 	struct work_struct	work;
 
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index ecaa792..33e98b9 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -131,6 +131,9 @@ int	target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
 int	transport_handle_cdb_direct(struct se_cmd *);
 sense_reason_t	transport_generic_new_cmd(struct se_cmd *);
 
+void	__target_add_cmd_cb(struct se_cmd *cmd, void (*done)(void *),
+			    void *done_arg);
+
 void	target_execute_cmd(struct se_cmd *cmd);
 
 int	transport_generic_free_cmd(struct se_cmd *, int);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux