Commit eb7e1f3a authored by NeilBrown's avatar NeilBrown Committed by Greg Kroah-Hartman
Browse files

staging: lustre: introduce and use l_wait_event_abortable()



lustre sometimes wants to wait for an event, but abort if
one of a specific list of signals arrives.  This is a little
bit like wait_event_killable(), except that the signals are
identified a different way.

So introduce l_wait_event_abortable() which provides this
functionality.
Having separate functions for separate needs is more in line
with the pattern set by include/linux/wait.h, than having a
single function which tries to include all possible needs.

Also introduce l_wait_event_abortable_exclusive().

Note that l_wait_event() return -EINTR on a signal, while
Linux wait_event functions return -ERESTARTSYS.
l_wait_event_{abortable_,}exclusive follow the Linux pattern.

Reviewed-by: default avatarJames Simmons <jsimmons@infradead.org>
Signed-off-by: default avatarNeilBrown <neilb@suse.com>
Reviewed-by: default avatarPatrick Farrell <paf@cray.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 98b09280
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -336,4 +336,28 @@ do { \
/** @} lib */



/* l_wait_event_abortable() is a bit like wait_event_killable()
 * except there is a fixed set of signals which will abort:
 * LUSTRE_FATAL_SIGS
 */
#define l_wait_event_abortable(wq, condition)				\
({									\
	sigset_t __blocked;						\
	int __ret = 0;							\
	__blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS);		\
	__ret = wait_event_interruptible(wq, condition);		\
	cfs_restore_sigs(__blocked);					\
	__ret;								\
})

#define l_wait_event_abortable_exclusive(wq, condition)			\
({									\
	sigset_t __blocked;						\
	int __ret = 0;							\
	__blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS);		\
	__ret = wait_event_interruptible_exclusive(wq, condition);	\
	cfs_restore_sigs(__blocked);					\
	__ret;								\
})
#endif /* _LUSTRE_LIB_H */
+6 −6
Original line number Diff line number Diff line
@@ -879,7 +879,6 @@ static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force)
	ldlm_namespace_cleanup(ns, force ? LDLM_FL_LOCAL_ONLY : 0);

	if (atomic_read(&ns->ns_bref) > 0) {
		struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
		int rc;

		CDEBUG(D_DLMTRACE,
@@ -887,11 +886,12 @@ static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force)
		       ldlm_ns_name(ns), atomic_read(&ns->ns_bref));
force_wait:
		if (force)
			lwi = LWI_TIMEOUT(msecs_to_jiffies(obd_timeout *
					  MSEC_PER_SEC) / 4, NULL, NULL);

		rc = l_wait_event(ns->ns_waitq,
				  atomic_read(&ns->ns_bref) == 0, &lwi);
			rc = wait_event_idle_timeout(ns->ns_waitq,
						     atomic_read(&ns->ns_bref) == 0,
						     obd_timeout * HZ / 4) ? 0 : -ETIMEDOUT;
		else
			rc = l_wait_event_abortable(ns->ns_waitq,
						    atomic_read(&ns->ns_bref) == 0);

		/* Forced cleanups should be able to reclaim all references,
		 * so it's safe to wait forever... we can't leak locks...
+4 −8
Original line number Diff line number Diff line
@@ -986,16 +986,12 @@ void ll_put_super(struct super_block *sb)
	}

	/* Wait for unstable pages to be committed to stable storage */
	if (!force) {
		struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);

		rc = l_wait_event(sbi->ll_cache->ccc_unstable_waitq,
				  !atomic_long_read(&sbi->ll_cache->ccc_unstable_nr),
				  &lwi);
	}
	if (!force)
		rc = l_wait_event_abortable(sbi->ll_cache->ccc_unstable_waitq,
					    !atomic_long_read(&sbi->ll_cache->ccc_unstable_nr));

	ccc_count = atomic_long_read(&sbi->ll_cache->ccc_unstable_nr);
	if (!force && rc != -EINTR)
	if (!force && rc != -ERESTARTSYS)
		LASSERTF(!ccc_count, "count: %li\n", ccc_count);

	/* We need to set force before the lov_disconnect in
+3 −6
Original line number Diff line number Diff line
@@ -1332,7 +1332,6 @@ static bool obd_request_slot_avail(struct client_obd *cli,
int obd_get_request_slot(struct client_obd *cli)
{
	struct obd_request_slot_waiter orsw;
	struct l_wait_info lwi;
	int rc;

	spin_lock(&cli->cl_loi_list_lock);
@@ -1347,11 +1346,9 @@ int obd_get_request_slot(struct client_obd *cli)
	orsw.orsw_signaled = false;
	spin_unlock(&cli->cl_loi_list_lock);

	lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
	rc = l_wait_event(orsw.orsw_waitq,
	rc = l_wait_event_abortable(orsw.orsw_waitq,
				    obd_request_slot_avail(cli, &orsw) ||
			  orsw.orsw_signaled,
			  &lwi);
				    orsw.orsw_signaled);

	/*
	 * Here, we must take the lock to avoid the on-stack 'orsw' to be
+2 −3
Original line number Diff line number Diff line
@@ -104,7 +104,6 @@ EXPORT_SYMBOL(__llog_ctxt_put);

int llog_cleanup(const struct lu_env *env, struct llog_ctxt *ctxt)
{
	struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
	struct obd_llog_group *olg;
	int rc, idx;

@@ -129,8 +128,8 @@ int llog_cleanup(const struct lu_env *env, struct llog_ctxt *ctxt)
		CERROR("Error %d while cleaning up ctxt %p\n",
		       rc, ctxt);

	l_wait_event(olg->olg_waitq,
		     llog_group_ctxt_null(olg, idx), &lwi);
	l_wait_event_abortable(olg->olg_waitq,
			     llog_group_ctxt_null(olg, idx));

	return rc;
}
Loading