Commit 57f60202 authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

rcutorture: Properly synchronize with OOM notifier



The current rcutorture forward-progress code assumes that it is the
only cause of out-of-memory (OOM) events.  For script-based rcutorture
testing, this assumption is in fact correct.  However, testing based
on modprobe/rmmod might well encounter external OOM events, which could
happen at any time.

This commit therefore properly synchronizes the interaction between
rcutorture's forward-progress testing and its OOM notifier by adding a
global mutex.

Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent c8fa6371
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -1796,6 +1796,7 @@ struct rcu_fwd {
	unsigned long rcu_launder_gp_seq_start;
};

static DEFINE_MUTEX(rcu_fwd_mutex);
static struct rcu_fwd *rcu_fwds;
static bool rcu_fwd_emergency_stop;

@@ -2062,8 +2063,14 @@ static void rcu_torture_fwd_prog_cr(struct rcu_fwd *rfp)
static int rcutorture_oom_notify(struct notifier_block *self,
				 unsigned long notused, void *nfreed)
{
	struct rcu_fwd *rfp = rcu_fwds;
	struct rcu_fwd *rfp;

	mutex_lock(&rcu_fwd_mutex);
	rfp = rcu_fwds;
	if (!rfp) {
		mutex_unlock(&rcu_fwd_mutex);
		return NOTIFY_OK;
	}
	WARN(1, "%s invoked upon OOM during forward-progress testing.\n",
	     __func__);
	rcu_torture_fwd_cb_hist(rfp);
@@ -2081,6 +2088,7 @@ static int rcutorture_oom_notify(struct notifier_block *self,
	smp_mb(); /* Frees before return to avoid redoing OOM. */
	(*(unsigned long *)nfreed)++; /* Forward progress CBs freed! */
	pr_info("%s returning after OOM processing.\n", __func__);
	mutex_unlock(&rcu_fwd_mutex);
	return NOTIFY_OK;
}

@@ -2148,7 +2156,9 @@ static int __init rcu_torture_fwd_prog_init(void)
		return -ENOMEM;
	spin_lock_init(&rfp->rcu_fwd_lock);
	rfp->rcu_fwd_cb_tail = &rfp->rcu_fwd_cb_head;
	mutex_lock(&rcu_fwd_mutex);
	rcu_fwds = rfp;
	mutex_unlock(&rcu_fwd_mutex);
	return torture_create_kthread(rcu_torture_fwd_prog, rfp, fwd_prog_task);
}

@@ -2158,7 +2168,9 @@ static void rcu_torture_fwd_prog_cleanup(void)

	torture_stop_kthread(rcu_torture_fwd_prog, fwd_prog_task);
	rfp = rcu_fwds;
	mutex_lock(&rcu_fwd_mutex);
	rcu_fwds = NULL;
	mutex_unlock(&rcu_fwd_mutex);
	kfree(rfp);
}