Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52023a31 authored by Clark Williams's avatar Clark Williams Committed by Alistair Delva
Browse files

UPSTREAM: mm/kasan/quarantine.c: make quarantine_lock a raw_spinlock_t

(Upstream commit 026d1eaf5ef1a5d6258b46e4e411cd9f5ab8c41d).

The static lock quarantine_lock is used in quarantine.c to protect the
quarantine queue datastructures.  It is taken inside quarantine queue
manipulation routines (quarantine_put(), quarantine_reduce() and
quarantine_remove_cache()), with IRQs disabled.  This is not a problem on
a stock kernel but is problematic on an RT kernel where spin locks are
sleeping spinlocks, which can sleep and can not be acquired with disabled
interrupts.

Convert the quarantine_lock to a raw spinlock_t.  The usage of
quarantine_lock is confined to quarantine.c and the work performed while
the lock is held is used for debug purpose.

[bigeasy@linutronix.de: slightly altered the commit message]
Link: http://lkml.kernel.org/r/20181010214945.5owshc3mlrh74z4b@linutronix.de


Signed-off-by: default avatarClark Williams <williams@redhat.com>
Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: default avatarDmitry Vyukov <dvyukov@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Bug: 128674696
Change-Id: I12f35246b81b23cad5ce8b90407c00b86bf90cc0
parent c904d75b
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ static int quarantine_head;
static int quarantine_tail;
/* Total size of all objects in global_quarantine across all batches. */
static unsigned long quarantine_size;
static DEFINE_SPINLOCK(quarantine_lock);
static DEFINE_RAW_SPINLOCK(quarantine_lock);
DEFINE_STATIC_SRCU(remove_cache_srcu);

/* Maximum size of the global queue. */
@@ -190,7 +190,7 @@ void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache)
	if (unlikely(q->bytes > QUARANTINE_PERCPU_SIZE)) {
		qlist_move_all(q, &temp);

		spin_lock(&quarantine_lock);
		raw_spin_lock(&quarantine_lock);
		WRITE_ONCE(quarantine_size, quarantine_size + temp.bytes);
		qlist_move_all(&temp, &global_quarantine[quarantine_tail]);
		if (global_quarantine[quarantine_tail].bytes >=
@@ -203,7 +203,7 @@ void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache)
			if (new_tail != quarantine_head)
				quarantine_tail = new_tail;
		}
		spin_unlock(&quarantine_lock);
		raw_spin_unlock(&quarantine_lock);
	}

	local_irq_restore(flags);
@@ -230,7 +230,7 @@ void quarantine_reduce(void)
	 * expected case).
	 */
	srcu_idx = srcu_read_lock(&remove_cache_srcu);
	spin_lock_irqsave(&quarantine_lock, flags);
	raw_spin_lock_irqsave(&quarantine_lock, flags);

	/*
	 * Update quarantine size in case of hotplug. Allocate a fraction of
@@ -254,7 +254,7 @@ void quarantine_reduce(void)
			quarantine_head = 0;
	}

	spin_unlock_irqrestore(&quarantine_lock, flags);
	raw_spin_unlock_irqrestore(&quarantine_lock, flags);

	qlist_free_all(&to_free, NULL);
	srcu_read_unlock(&remove_cache_srcu, srcu_idx);
@@ -310,17 +310,17 @@ void quarantine_remove_cache(struct kmem_cache *cache)
	 */
	on_each_cpu(per_cpu_remove_cache, cache, 1);

	spin_lock_irqsave(&quarantine_lock, flags);
	raw_spin_lock_irqsave(&quarantine_lock, flags);
	for (i = 0; i < QUARANTINE_BATCHES; i++) {
		if (qlist_empty(&global_quarantine[i]))
			continue;
		qlist_move_cache(&global_quarantine[i], &to_free, cache);
		/* Scanning whole quarantine can take a while. */
		spin_unlock_irqrestore(&quarantine_lock, flags);
		raw_spin_unlock_irqrestore(&quarantine_lock, flags);
		cond_resched();
		spin_lock_irqsave(&quarantine_lock, flags);
		raw_spin_lock_irqsave(&quarantine_lock, flags);
	}
	spin_unlock_irqrestore(&quarantine_lock, flags);
	raw_spin_unlock_irqrestore(&quarantine_lock, flags);

	qlist_free_all(&to_free, cache);