mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: NeilBrown <neilb@suse.com>
To: Oleg Drokin <oleg.drokin@intel.com>,
	Andreas Dilger <andreas.dilger@intel.com>,
	James Simmons <jsimmons@infradead.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: lkml <linux-kernel@vger.kernel.org>,
	lustre <lustre-devel@lists.lustre.org>
Subject: [PATCH 16/16] staging: lustre: remove l_wait_event from ptlrpc_set_wait
Date: Mon, 18 Dec 2017 18:18:00 +1100	[thread overview]
Message-ID: <151358148037.5099.1272439971724416652.stgit@noble> (raw)
In-Reply-To: <151358127190.5099.12792810096274074963.stgit@noble>

This is the last remaining use of l_wait_event().
It is the only use of LWI_TIMEOUT_INTR_ALL() which
has a meaning that timeouts can be interrupted.
Only interrupts by "fatal" signals are allowed, so
introduce l_wait_event_abortable_timeout() to
support this.

Signed-off-by: NeilBrown <neilb@suse.com>
---
 drivers/staging/lustre/lustre/include/lustre_lib.h |   10 ++
 drivers/staging/lustre/lustre/ptlrpc/client.c      |   86 ++++++++------------
 .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h |    2 
 3 files changed, 47 insertions(+), 51 deletions(-)

diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h
index d157ed35a0bf..b23d3015b1c0 100644
--- a/drivers/staging/lustre/lustre/include/lustre_lib.h
+++ b/drivers/staging/lustre/lustre/include/lustre_lib.h
@@ -440,6 +440,16 @@ do {										\
 	__ret;								\
 })
 
+#define l_wait_event_abortable_timeout(wq, condition, timeout)		\
+({									\
+	sigset_t __blocked;						\
+	int __ret = 0;							\
+	__blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS);		\
+	__ret = wait_event_interruptible_timeout(wq, condition, timeout);\
+	cfs_restore_sigs(__blocked);					\
+	__ret;								\
+})
+
 #define l_wait_event_abortable_exclusive(wq, condition)			\
 ({									\
 	sigset_t __blocked;						\
diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c
index bb8c9ab68f5f..95131a34a98f 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/client.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/client.c
@@ -1774,7 +1774,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
 		}
 
 		/*
-		 * ptlrpc_set_wait->l_wait_event sets lwi_allow_intr
+		 * ptlrpc_set_wait allow signal to abort the timeout
 		 * so it sets rq_intr regardless of individual rpc
 		 * timeouts. The synchronous IO waiting path sets
 		 * rq_intr irrespective of whether ptlrpcd
@@ -2122,10 +2122,9 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink)
 
 /**
  * Time out all uncompleted requests in request set pointed by \a data
- * Callback used when waiting on sets with l_wait_event.
- * Always returns 1.
+ * Called when wait_event_timeout times out.
  */
-int ptlrpc_expired_set(struct ptlrpc_request_set *set)
+void ptlrpc_expired_set(struct ptlrpc_request_set *set)
 {
 	struct list_head *tmp;
 	time64_t now = ktime_get_real_seconds();
@@ -2155,18 +2154,6 @@ int ptlrpc_expired_set(struct ptlrpc_request_set *set)
 		 */
 		ptlrpc_expire_one_request(req, 1);
 	}
-
-	/*
-	 * When waiting for a whole set, we always break out of the
-	 * sleep so we can recalculate the timeout, or enable interrupts
-	 * if everyone's timed out.
-	 */
-	return 1;
-}
-static int ptlrpc_expired_set_void(void *data)
-{
-	struct ptlrpc_request_set *set = data;
-	return ptlrpc_expired_set(set);
 }
 
 /**
@@ -2182,11 +2169,10 @@ EXPORT_SYMBOL(ptlrpc_mark_interrupted);
 
 /**
  * Interrupts (sets interrupted flag) all uncompleted requests in
- * a set \a data. Callback for l_wait_event for interruptible waits.
+ * a set \a data. Called when wait_event_timeout receives signal.
  */
-static void ptlrpc_interrupted_set(void *data)
+static void ptlrpc_interrupted_set(struct ptlrpc_request_set *set)
 {
-	struct ptlrpc_request_set *set = data;
 	struct list_head *tmp;
 
 	CDEBUG(D_RPCTRACE, "INTERRUPTED SET %p\n", set);
@@ -2256,7 +2242,6 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
 {
 	struct list_head *tmp;
 	struct ptlrpc_request *req;
-	struct l_wait_info lwi;
 	int rc, timeout;
 
 	if (set->set_producer)
@@ -2282,46 +2267,47 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
 		CDEBUG(D_RPCTRACE, "set %p going to sleep for %d seconds\n",
 		       set, timeout);
 
-		if (timeout == 0 && !signal_pending(current))
+		if (timeout == 0 && !signal_pending(current)) {
 			/*
 			 * No requests are in-flight (ether timed out
 			 * or delayed), so we can allow interrupts.
 			 * We still want to block for a limited time,
 			 * so we allow interrupts during the timeout.
 			 */
-			lwi = LWI_TIMEOUT_INTR_ALL(HZ,
-						   ptlrpc_expired_set_void,
-						   ptlrpc_interrupted_set, set);
-		else
+			rc = l_wait_event_abortable_timeout(set->set_waitq,
+							    ptlrpc_check_set(NULL, set),
+							    HZ);
+			if (rc == 0) {
+				rc = -ETIMEDOUT;
+				ptlrpc_expired_set(set);
+			} else if (rc < 0) {
+				rc = -EINTR;
+				ptlrpc_interrupted_set(set);
+			} else
+				rc = 0;
+		} else {
 			/*
 			 * At least one request is in flight, so no
 			 * interrupts are allowed. Wait until all
 			 * complete, or an in-flight req times out.
 			 */
-			lwi = LWI_TIMEOUT((timeout ? timeout : 1) * HZ,
-					  ptlrpc_expired_set_void, set);
-
-		rc = l_wait_event(set->set_waitq, ptlrpc_check_set(NULL, set), &lwi);
-
-		/*
-		 * LU-769 - if we ignored the signal because it was already
-		 * pending when we started, we need to handle it now or we risk
-		 * it being ignored forever
-		 */
-		if (rc == -ETIMEDOUT && !lwi.lwi_allow_intr &&
-		    signal_pending(current)) {
-			sigset_t blocked_sigs =
-					   cfs_block_sigsinv(LUSTRE_FATAL_SIGS);
-
-			/*
-			 * In fact we only interrupt for the "fatal" signals
-			 * like SIGINT or SIGKILL. We still ignore less
-			 * important signals since ptlrpc set is not easily
-			 * reentrant from userspace again
-			 */
-			if (signal_pending(current))
-				ptlrpc_interrupted_set(set);
-			cfs_restore_sigs(blocked_sigs);
+			rc = wait_event_timeout(set->set_waitq,
+						ptlrpc_check_set(NULL, set),
+						(timeout ? timeout : 1) * HZ);
+			if (rc == 0) {
+				ptlrpc_expired_set(set);
+				rc = -ETIMEDOUT;
+				/*
+				 * LU-769 - if we ignored the signal
+				 * because it was already pending when
+				 * we started, we need to handle it
+				 * now or we risk it being ignored
+				 * forever
+				 */
+				if (l_fatal_signal_pending(current))
+					ptlrpc_interrupted_set(set);
+			} else
+				rc = 0;
 		}
 
 		LASSERT(rc == 0 || rc == -EINTR || rc == -ETIMEDOUT);
@@ -2528,7 +2514,7 @@ static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async)
 		return 0;
 
 	/*
-	 * We have to l_wait_event() whatever the result, to give liblustre
+	 * We have to wait_event_timeout() whatever the result, to give liblustre
 	 * a chance to run reply_in_callback(), and to make sure we've
 	 * unlinked before returning a req to the pool.
 	 */
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
index 6dd52d99d454..b7a8d7537a66 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h
@@ -68,7 +68,7 @@ void ptlrpc_request_cache_free(struct ptlrpc_request *req);
 void ptlrpc_init_xid(void);
 void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc,
 			    struct ptlrpc_request *req);
-int ptlrpc_expired_set(struct ptlrpc_request_set *set);
+void ptlrpc_expired_set(struct ptlrpc_request_set *set);
 int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set);
 void ptlrpc_resend_req(struct ptlrpc_request *request);
 void ptlrpc_set_bulk_mbits(struct ptlrpc_request *req);

  parent reply	other threads:[~2017-12-18  7:20 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-18  7:17 [PATCH SERIES 5: 00/16] staging: lustre: use standard wait_event macros NeilBrown
2017-12-18  7:17 ` [PATCH 03/16] staging: lustre: discard cfs_time_seconds() NeilBrown
2017-12-18  7:17 ` [PATCH 01/16] staging: lustre: discard SVC_SIGNAL and related functions NeilBrown
2017-12-18  7:17 ` [PATCH 02/16] staging: lustre: replace simple cases of l_wait_event() with wait_event() NeilBrown
2017-12-18 17:48   ` [lustre-devel] " Patrick Farrell
2017-12-18 21:37     ` NeilBrown
2017-12-18 18:03   ` Patrick Farrell
2017-12-19 10:37     ` Dilger, Andreas
2017-12-19 20:49       ` NeilBrown
2017-12-18  7:17 ` [PATCH 04/16] staging: lustre: use wait_event_timeout() where appropriate NeilBrown
2017-12-18 20:23   ` [lustre-devel] " Patrick Farrell
2017-12-18  7:18 ` [PATCH 14/16] staging: lustre: use explicit poll loop in ptlrpc_service_unlink_rqbd NeilBrown
2017-12-18  7:18 ` [PATCH 10/16] staging: lustre: remove back_to_sleep() and use loops NeilBrown
2017-12-18  7:18 ` [PATCH 12/16] staging: lustre: use wait_event_timeout in ptlrpcd() NeilBrown
2017-12-18  7:18 ` [PATCH 15/16] staging: lustre: use explicit poll loop in ptlrpc_unregister_reply NeilBrown
2017-12-18 21:09   ` [lustre-devel] " Patrick Farrell
2017-12-18  7:18 ` [PATCH 08/16] staging: lustre: open code polling loop instead of using l_wait_event() NeilBrown
2017-12-18 20:55   ` [lustre-devel] " Patrick Farrell
2017-12-18  7:18 ` [PATCH 09/16] staging: lustre: simplify waiting in ptlrpc_invalidate_import() NeilBrown
2017-12-18  7:18 ` [PATCH 07/16] staging: lustre: simplify waiting in ldlm_completion_ast() NeilBrown
2017-12-18  7:18 ` [PATCH 06/16] staging: lustre: simplify l_wait_event when intr handler but no timeout NeilBrown
2017-12-18  7:18 ` NeilBrown [this message]
2017-12-18  7:18 ` [PATCH 11/16] staging: lustre: make polling loop in ptlrpc_unregister_bulk more obvious NeilBrown
2017-12-18 21:03   ` [lustre-devel] " Patrick Farrell
2017-12-18  7:18 ` [PATCH 05/16] staging: lustre: introduce and use l_wait_event_abortable() NeilBrown
2017-12-18  7:18 ` [PATCH 13/16] staging: lustre: improve waiting in sptlrpc_req_refresh_ctx NeilBrown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=151358148037.5099.1272439971724416652.stgit@noble \
    --to=neilb@suse.com \
    --cc=andreas.dilger@intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jsimmons@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lustre-devel@lists.lustre.org \
    --cc=oleg.drokin@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®