All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 10/17] target/core: Make it possible to wait from more than one context for command completio
@ 2018-09-17 21:35 Bart Van Assche
  2018-10-07  3:44 ` [PATCH 10/17] target/core: Make it possible to wait from more than one context for command compl Nicholas A. Bellinger
  2018-10-08 18:02 ` Bart Van Assche
  0 siblings, 2 replies; 3+ messages in thread
From: Bart Van Assche @ 2018-09-17 21:35 UTC (permalink / raw)
  To: target-devel

This patch does not change any functionality but makes the next patch
easier to read.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Nicholas Bellinger <nab@linux-iscsi.org>
Cc: Mike Christie <mchristi@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
---
 drivers/target/target_core_transport.c | 69 ++++++++++++++++++++++----
 include/target/target_core_base.h      |  2 +-
 2 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 79fa79afcdc2..1fecd2bb53af 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1331,7 +1331,7 @@ void transport_init_se_cmd(
 	INIT_LIST_HEAD(&cmd->se_cmd_list);
 	INIT_LIST_HEAD(&cmd->state_list);
 	init_completion(&cmd->t_transport_stop_comp);
-	cmd->compl = NULL;
+	init_waitqueue_head(&cmd->release_wq);
 	spin_lock_init(&cmd->t_state_lock);
 	INIT_WORK(&cmd->work, NULL);
 	kref_init(&cmd->cmd_kref);
@@ -2649,6 +2649,47 @@ static void target_wait_free_cmd(struct se_cmd *cmd, bool *aborted, bool *tas)
 	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 }
 
+static void __target_put_cmd_and_wait(struct se_cmd *cmd, bool put)
+{
+	DEFINE_WAIT(wait);
+	long ret;
+
+	prepare_to_wait(&cmd->release_wq, &wait, TASK_UNINTERRUPTIBLE);
+	if (put)
+		target_put_sess_cmd(cmd);
+	for (;;) {
+		if (list_empty_careful(&wait.entry))
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (list_empty_careful(&wait.entry)) {
+			set_current_state(TASK_RUNNING);
+			break;
+		}
+		ret = schedule_timeout(180 * HZ);
+		if (ret = 0)
+			target_show_cmd("still waiting for ", cmd);
+	}
+}
+
+/*
+ * Call target_put_sess_cmd() and wait until target_release_cmd_kref(@cmd) has
+ * finished.
+ */
+static void target_put_cmd_and_wait(struct se_cmd *cmd)
+{
+	__target_put_cmd_and_wait(cmd, true);
+}
+
+/*
+ * Wait until target_release_cmd_kref(@cmd) has finished. Calling this function
+ * is only safe if the release function does not free the memory allocated for
+ * @cmd. This is e.g. the case for the iSCSI target driver.
+ */
+static void target_wait_for_cmd(struct se_cmd *cmd)
+{
+	__target_put_cmd_and_wait(cmd, false);
+}
+
 /*
  * This function is called by frontend drivers after processing of a command
  * has finished.
@@ -2672,7 +2713,6 @@ static void target_wait_free_cmd(struct se_cmd *cmd, bool *aborted, bool *tas)
  */
 int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
 {
-	DECLARE_COMPLETION_ONSTACK(compl);
 	int ret = 0;
 	bool aborted = false, tas = false;
 
@@ -2691,14 +2731,17 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
 		if (cmd->se_lun)
 			transport_lun_remove_cmd(cmd);
 	}
-	if (aborted)
-		cmd->compl = &compl;
-	if (!aborted || tas)
-		ret = target_put_sess_cmd(cmd);
 	if (aborted) {
 		pr_debug("Detected CMD_T_ABORTED for ITT: %llu\n", cmd->tag);
-		wait_for_completion(&compl);
+		if (tas) {
+			target_put_cmd_and_wait(cmd);
+		} else {
+			WARN_ON_ONCE(!wait_for_tasks);
+			target_wait_for_cmd(cmd);
+		}
 		ret = 1;
+	} else {
+		ret = target_put_sess_cmd(cmd);
 	}
 	return ret;
 }
@@ -2759,9 +2802,16 @@ 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 completion *compl = se_cmd->compl;
+	struct wait_queue_head release_wq;
 	unsigned long flags;
 
+	init_waitqueue_head(&release_wq);
+	/*
+	 * No locking is required since we are in the release function and
+	 * adding to release_wq is only allowed while holding a reference.
+	 */
+	list_splice_init(&se_cmd->release_wq.head, &release_wq.head);
+
 	if (se_sess) {
 		spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
 		list_del_init(&se_cmd->se_cmd_list);
@@ -2770,8 +2820,7 @@ static void target_release_cmd_kref(struct kref *kref)
 
 	target_free_cmd_mem(se_cmd);
 	se_cmd->se_tfo->release_cmd(se_cmd);
-	if (compl)
-		complete(compl);
+	wake_up_all(&release_wq);
 
 	percpu_ref_put(&se_sess->cmd_count);
 }
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index d084479fbe18..d93ec20710c2 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -475,7 +475,7 @@ struct se_cmd {
 	struct se_session	*se_sess;
 	struct se_tmr_req	*se_tmr_req;
 	struct list_head	se_cmd_list;
-	struct completion	*compl;
+	struct wait_queue_head	release_wq;
 	const struct target_core_fabric_ops *se_tfo;
 	sense_reason_t		(*execute_cmd)(struct se_cmd *);
 	sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool, int *);
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 10/17] target/core: Make it possible to wait from more than one context for command compl
  2018-09-17 21:35 [PATCH 10/17] target/core: Make it possible to wait from more than one context for command completio Bart Van Assche
@ 2018-10-07  3:44 ` Nicholas A. Bellinger
  2018-10-08 18:02 ` Bart Van Assche
  1 sibling, 0 replies; 3+ messages in thread
From: Nicholas A. Bellinger @ 2018-10-07  3:44 UTC (permalink / raw)
  To: target-devel

On Mon, 2018-09-17 at 14:35 -0700, Bart Van Assche wrote:
> This patch does not change any functionality but makes the next patch
> easier to read.
> 
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
> Cc: Nicholas Bellinger <nab@linux-iscsi.org>
> Cc: Mike Christie <mchristi@redhat.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Hannes Reinecke <hare@suse.de>
> ---
>  drivers/target/target_core_transport.c | 69 ++++++++++++++++++++++----
>  include/target/target_core_base.h      |  2 +-
>  2 files changed, 60 insertions(+), 11 deletions(-)
> 

<SNIP>

> @@ -2759,9 +2802,16 @@ 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 completion *compl = se_cmd->compl;
> +	struct wait_queue_head release_wq;
>  	unsigned long flags;
>  
> +	init_waitqueue_head(&release_wq);
> +	/*
> +	 * No locking is required since we are in the release function and
> +	 * adding to release_wq is only allowed while holding a reference.
> +	 */
> +	list_splice_init(&se_cmd->release_wq.head, &release_wq.head);
> +
>  	if (se_sess) {
>  		spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
>  		list_del_init(&se_cmd->se_cmd_list);
> @@ -2770,8 +2820,7 @@ static void target_release_cmd_kref(struct kref *kref)
>  
>  	target_free_cmd_mem(se_cmd);
>  	se_cmd->se_tfo->release_cmd(se_cmd);
> -	if (compl)
> -		complete(compl);
> +	wake_up_all(&release_wq);
>  
>  	percpu_ref_put(&se_sess->cmd_count);
>  }

Your earlier commit 7b2cc7dc0 in mainline to use a local stack compl in
transport_generic_free_cmd() was a reasonable change, because fast-path
code in target_release_cmd_kref() was only doing a complete() when the
se_cmd was actually being quiesced..

However, the addition of wake_up_all() above for every se_cmd means a
__wake_up_common_lock() happens no matter what every time in fast-path
code.

Please, don't do this.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 10/17] target/core: Make it possible to wait from more than one context for command compl
  2018-09-17 21:35 [PATCH 10/17] target/core: Make it possible to wait from more than one context for command completio Bart Van Assche
  2018-10-07  3:44 ` [PATCH 10/17] target/core: Make it possible to wait from more than one context for command compl Nicholas A. Bellinger
@ 2018-10-08 18:02 ` Bart Van Assche
  1 sibling, 0 replies; 3+ messages in thread
From: Bart Van Assche @ 2018-10-08 18:02 UTC (permalink / raw)
  To: target-devel

On Sat, 2018-10-06 at 20:44 -0700, Nicholas A. Bellinger wrote:
+AD4 On Mon, 2018-09-17 at 14:35 -0700, Bart Van Assche wrote:
+AD4 +AD4 +AEAAQA -2759,9 +-2802,16 +AEAAQA static void target+AF8-release+AF8-cmd+AF8-kref(struct kref +ACo-kref)
+AD4 +AD4  +AHs
+AD4 +AD4  	struct se+AF8-cmd +ACo-se+AF8-cmd +AD0 container+AF8-of(kref, struct se+AF8-cmd, cmd+AF8-kref)+ADs
+AD4 +AD4  	struct se+AF8-session +ACo-se+AF8-sess +AD0 se+AF8-cmd-+AD4-se+AF8-sess+ADs
+AD4 +AD4 -	struct completion +ACo-compl +AD0 se+AF8-cmd-+AD4-compl+ADs
+AD4 +AD4 +-	struct wait+AF8-queue+AF8-head release+AF8-wq+ADs
+AD4 +AD4  	unsigned long flags+ADs
+AD4 +AD4  
+AD4 +AD4 +-	init+AF8-waitqueue+AF8-head(+ACY-release+AF8-wq)+ADs
+AD4 +AD4 +-	/+ACo
+AD4 +AD4 +-	 +ACo No locking is required since we are in the release function and
+AD4 +AD4 +-	 +ACo adding to release+AF8-wq is only allowed while holding a reference.
+AD4 +AD4 +-	 +ACo-/
+AD4 +AD4 +-	list+AF8-splice+AF8-init(+ACY-se+AF8-cmd-+AD4-release+AF8-wq.head, +ACY-release+AF8-wq.head)+ADs
+AD4 +AD4 +-
+AD4 +AD4  	if (se+AF8-sess) +AHs
+AD4 +AD4  		spin+AF8-lock+AF8-irqsave(+ACY-se+AF8-sess-+AD4-sess+AF8-cmd+AF8-lock, flags)+ADs
+AD4 +AD4  		list+AF8-del+AF8-init(+ACY-se+AF8-cmd-+AD4-se+AF8-cmd+AF8-list)+ADs
+AD4 +AD4 +AEAAQA -2770,8 +-2820,7 +AEAAQA static void target+AF8-release+AF8-cmd+AF8-kref(struct kref +ACo-kref)
+AD4 +AD4  
+AD4 +AD4  	target+AF8-free+AF8-cmd+AF8-mem(se+AF8-cmd)+ADs
+AD4 +AD4  	se+AF8-cmd-+AD4-se+AF8-tfo-+AD4-release+AF8-cmd(se+AF8-cmd)+ADs
+AD4 +AD4 -	if (compl)
+AD4 +AD4 -		complete(compl)+ADs
+AD4 +AD4 +-	wake+AF8-up+AF8-all(+ACY-release+AF8-wq)+ADs
+AD4 +AD4  
+AD4 +AD4  	percpu+AF8-ref+AF8-put(+ACY-se+AF8-sess-+AD4-cmd+AF8-count)+ADs
+AD4 +AD4  +AH0
+AD4 
+AD4 Your earlier commit 7b2cc7dc0 in mainline to use a local stack compl in
+AD4 transport+AF8-generic+AF8-free+AF8-cmd() was a reasonable change, because fast-path
+AD4 code in target+AF8-release+AF8-cmd+AF8-kref() was only doing a complete() when the
+AD4 se+AF8-cmd was actually being quiesced..
+AD4 
+AD4 However, the addition of wake+AF8-up+AF8-all() above for every se+AF8-cmd means a
+AD4 +AF8AXw-wake+AF8-up+AF8-common+AF8-lock() happens no matter what every time in fast-path
+AD4 code.

That's easy to fix. How about replacing this patch with the following patch?


+AFs-PATCH+AF0 target/core: Make it possible to wait from more than one context for command completion

This patch does not change any functionality but makes the next patch
easier to read.

Signed-off-by: Bart Van Assche +ADw-bvanassche+AEA-acm.org+AD4
Cc: Nicholas Bellinger +ADw-nab+AEA-linux-iscsi.org+AD4
Cc: Mike Christie +ADw-mchristi+AEA-redhat.com+AD4
Cc: Christoph Hellwig +ADw-hch+AEA-lst.de+AD4
Cc: Hannes Reinecke +ADw-hare+AEA-suse.de+AD4
---
 drivers/target/target+AF8-core+AF8-transport.c +AHw 15 +-+-+-+-+-+-+-+-+-+------
 include/target/target+AF8-core+AF8-base.h      +AHw  2 +--
 2 files changed, 11 insertions(+-), 6 deletions(-)

diff --git a/drivers/target/target+AF8-core+AF8-transport.c b/drivers/target/target+AF8-core+AF8-transport.c
index 79fa79afcdc2..de54494cf98f 100644
--- a/drivers/target/target+AF8-core+AF8-transport.c
+-+-+- b/drivers/target/target+AF8-core+AF8-transport.c
+AEAAQA -1331,7 +-1331,7 +AEAAQA void transport+AF8-init+AF8-se+AF8-cmd(
 	INIT+AF8-LIST+AF8-HEAD(+ACY-cmd-+AD4-se+AF8-cmd+AF8-list)+ADs
 	INIT+AF8-LIST+AF8-HEAD(+ACY-cmd-+AD4-state+AF8-list)+ADs
 	init+AF8-completion(+ACY-cmd-+AD4-t+AF8-transport+AF8-stop+AF8-comp)+ADs
-	cmd-+AD4-compl +AD0 NULL+ADs
+-	memset(cmd-+AD4-compl, 0, sizeof(cmd-+AD4-compl))+ADs
 	spin+AF8-lock+AF8-init(+ACY-cmd-+AD4-t+AF8-state+AF8-lock)+ADs
 	INIT+AF8-WORK(+ACY-cmd-+AD4-work, NULL)+ADs
 	kref+AF8-init(+ACY-cmd-+AD4-cmd+AF8-kref)+ADs
+AEAAQA -2692,7 +-2692,7 +AEAAQA int transport+AF8-generic+AF8-free+AF8-cmd(struct se+AF8-cmd +ACo-cmd, int wait+AF8-for+AF8-tasks)
 			transport+AF8-lun+AF8-remove+AF8-cmd(cmd)+ADs
 	+AH0
 	if (aborted)
-		cmd-+AD4-compl +AD0 +ACY-compl+ADs
+-		cmd-+AD4-compl+AFs-0+AF0 +AD0 +ACY-compl+ADs
 	if (+ACE-aborted +AHwAfA tas)
 		ret +AD0 target+AF8-put+AF8-sess+AF8-cmd(cmd)+ADs
 	if (aborted) +AHs
+AEAAQA -2759,9 +-2759,12 +AEAAQA static void target+AF8-release+AF8-cmd+AF8-kref(struct kref +ACo-kref)
 +AHs
 	struct se+AF8-cmd +ACo-se+AF8-cmd +AD0 container+AF8-of(kref, struct se+AF8-cmd, cmd+AF8-kref)+ADs
 	struct se+AF8-session +ACo-se+AF8-sess +AD0 se+AF8-cmd-+AD4-se+AF8-sess+ADs
-	struct completion +ACo-compl +AD0 se+AF8-cmd-+AD4-compl+ADs
+-	struct completion +ACo-compl+AFs-2+AF0AOw
 	unsigned long flags+ADs
 
+-	BUILD+AF8-BUG+AF8-ON(sizeof(compl) +ACEAPQ sizeof(se+AF8-cmd-+AD4-compl))+ADs
+-	memcpy(compl, se+AF8-cmd-+AD4-compl, sizeof(compl))+ADs
+-
 	if (se+AF8-sess) +AHs
 		spin+AF8-lock+AF8-irqsave(+ACY-se+AF8-sess-+AD4-sess+AF8-cmd+AF8-lock, flags)+ADs
 		list+AF8-del+AF8-init(+ACY-se+AF8-cmd-+AD4-se+AF8-cmd+AF8-list)+ADs
+AEAAQA -2770,8 +-2773,10 +AEAAQA static void target+AF8-release+AF8-cmd+AF8-kref(struct kref +ACo-kref)
 
 	target+AF8-free+AF8-cmd+AF8-mem(se+AF8-cmd)+ADs
 	se+AF8-cmd-+AD4-se+AF8-tfo-+AD4-release+AF8-cmd(se+AF8-cmd)+ADs
-	if (compl)
-		complete(compl)+ADs
+-	if (compl+AFs-0+AF0)
+-		complete(compl+AFs-0+AF0)+ADs
+-	if (compl+AFs-1+AF0)
+-		complete(compl+AFs-1+AF0)+ADs
 
 	percpu+AF8-ref+AF8-put(+ACY-se+AF8-sess-+AD4-cmd+AF8-count)+ADs
 +AH0
diff --git a/include/target/target+AF8-core+AF8-base.h b/include/target/target+AF8-core+AF8-base.h
index d084479fbe18..34c9a8ffa4af 100644
--- a/include/target/target+AF8-core+AF8-base.h
+-+-+- b/include/target/target+AF8-core+AF8-base.h
+AEAAQA -475,7 +-475,7 +AEAAQA struct se+AF8-cmd +AHs
 	struct se+AF8-session	+ACo-se+AF8-sess+ADs
 	struct se+AF8-tmr+AF8-req	+ACo-se+AF8-tmr+AF8-req+ADs
 	struct list+AF8-head	se+AF8-cmd+AF8-list+ADs
-	struct completion	+ACo-compl+ADs
+-	struct completion	+ACo-compl+AFs-2+AF0AOw
 	const struct target+AF8-core+AF8-fabric+AF8-ops +ACo-se+AF8-tfo+ADs
 	sense+AF8-reason+AF8-t		(+ACo-execute+AF8-cmd)(struct se+AF8-cmd +ACo)+ADs
 	sense+AF8-reason+AF8-t (+ACo-transport+AF8-complete+AF8-callback)(struct se+AF8-cmd +ACo, bool, int +ACo)+ADs

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-10-08 18:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-17 21:35 [PATCH 10/17] target/core: Make it possible to wait from more than one context for command completio Bart Van Assche
2018-10-07  3:44 ` [PATCH 10/17] target/core: Make it possible to wait from more than one context for command compl Nicholas A. Bellinger
2018-10-08 18:02 ` Bart Van Assche

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.