Skip to contentSkip to conversation

Linux v4.14.172-rt78-rc1

PATCH New [email protected] 1 participant 9 messages Mar 9, 2020

Subsystems (8)
lore
Share & tools
lore
#0 lore raw

cover Linux v4.14.172-rt78-rc1

From: Tom Zanussi <[email protected]>

Dear RT Folks,

This is the RT stable review cycle of patch 4.14.172-rt78-rc1.

Please scream at me if I messed something up. Please test the patches too.

The -rc release will be uploaded to kernel.org and will be deleted when the final release is out. This is just a review release (or release candidate).

The pre-releases will not be pushed to the git repository, only the final release is.

If all goes well, this patch will be converted to the next main release on 2020-03-16.

To build 4.14.172-rt78-rc1 directly, the following patches should be applied:

https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.14.tar.xz

https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.14.172.xz

https://www.kernel.org/pub/linux/kernel/projects/rt/4.14/patch-4.14.172-rt78-rc1.patch.xz

You can also build from 4.14.172-rt77 by applying the incremental patch:

https://www.kernel.org/pub/linux/kernel/projects/rt/4.14/incr/patch-4.14.172-rt77-rt78-rc1.patch.xz

Enjoy,

-- Tom

Matt Fleming (1):
mm/memcontrol: Move misplaced local_unlock_irqrestore()

Scott Wood (2):
sched: migrate_enable: Use per-cpu cpu_stop_work
sched: migrate_enable: Remove __schedule() call

Sebastian Andrzej Siewior (4):
userfaultfd: Use a seqlock instead of seqcount
locallock: Include header for the `current' macro drm/vmwgfx: Drop preempt_disable() in vmw_fifo_ping_host()
tracing: make preempt_lazy and migrate_disable counter smaller

Tom Zanussi (1):
Linux 4.14.172-rt78-rc1

 drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c |  2 --
 fs/userfaultfd.c                     | 12 ++++++------
 include/linux/locallock.h            |  1 +
 include/linux/trace_events.h         |  3 +--
 kernel/sched/core.c                  | 23 ++++++++++++++---------
 kernel/trace/trace_events.c          |  4 ++--
 localversion-rt                      |  2 +-
 mm/memcontrol.c                      |  2 +-
 8 files changed, 26 insertions(+), 23 deletions(-)
Signature · 1 line
2.14.1
#2 lore raw

PATCH 2/8 sched: migrate_enable: Use per-cpu cpu_stop_work

From: Scott Wood <[email protected]>

v4.14.172-rt78-rc1 stable review patch.
If anyone has any objections, please let me know.

-----------

[ Upstream commit 2dcd94b443c5dcbc20281666321b7f025f9cc85c ]

Commit e6c287b1512d ("sched: migrate_enable: Use stop_one_cpu_nowait()") adds a busy wait to deal with an edge case where the migrated thread can resume running on another CPU before the stopper has consumed cpu_stop_work. However, this is done with preemption disabled and can potentially lead to deadlock.

While it is not guaranteed that the cpu_stop_work will be consumed before the migrating thread resumes and exits the stack frame, it is guaranteed that nothing other than the stopper can run on the old cpu between the migrating thread scheduling out and the cpu_stop_work being consumed. Thus, we can store cpu_stop_work in per-cpu data without it being reused too early.

Fixes e6c287b1512d ("sched: migrate_enable: Use stop_one_cpu_nowait()")

Conflicts:
kernel/sched/core.c

---
 kernel/sched/core.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)
kernel/sched/core.c +14 -8
index f30bb249123b5..960daa6bc7f04 100644
@@ -6964,6 +6964,9 @@ static void migrate_disabled_sched(struct task_struct *p)
 	p->migrate_disable_scheduled = 1;
 }
 
+static DEFINE_PER_CPU(struct cpu_stop_work, migrate_work);
+static DEFINE_PER_CPU(struct migration_arg, migrate_arg);
+
 void migrate_enable(void)
 {
 	struct task_struct *p = current;
@@ -7002,23 +7005,26 @@ void migrate_enable(void)
 
 	WARN_ON(smp_processor_id() != cpu);
 	if (!is_cpu_allowed(p, cpu)) {
-		struct migration_arg arg = { .task = p };
-		struct cpu_stop_work work;
+		struct migration_arg __percpu *arg;
+		struct cpu_stop_work __percpu *work;
 		struct rq_flags rf;
 
+		work = this_cpu_ptr(&migrate_work);
+		arg = this_cpu_ptr(&migrate_arg);
+		WARN_ON_ONCE(!arg->done && !work->disabled && work->arg);
+
+		arg->task = p;
+		arg->done = false;
+
 		rq = task_rq_lock(p, &rf);
 		update_rq_clock(rq);
-		arg.dest_cpu = select_fallback_rq(cpu, p);
+		arg->dest_cpu = select_fallback_rq(cpu, p);
 		task_rq_unlock(rq, p, &rf);
 
 		stop_one_cpu_nowait(task_cpu(p), migration_cpu_stop,
-				    &arg, &work);
+				    arg, work);
 		tlb_migrate_finish(p->mm);
 		__schedule(true);
-		if (!work.disabled) {
-			while (!arg.done)
-				cpu_relax();
-		}
 	}
 
 out:
Signature · 1 line
2.14.1
#4 lore raw

PATCH 4/8 mm/memcontrol: Move misplaced local_unlock_irqrestore()

In reply to [email protected]

From: Matt Fleming <[email protected]>

v4.14.172-rt78-rc1 stable review patch.
If anyone has any objections, please let me know.

-----------

[ Upstream commit 071a1d6a6e14d0dec240a8c67b425140d7f92f6a ]

The comment about local_lock_irqsave() mentions just the counters and css_put_many()'s callback just invokes a worker so it is safe to move the unlock function after memcg_check_events() so css_put_many() can be invoked without the lock acquired.

Cc Daniel Wagner <[email protected]>
[bigeasy: rewrote the patch description]
---
 mm/memcontrol.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/memcontrol.c +1 -1
index 0503b31e2a873..a359a24ebd9f0 100644
@@ -6102,10 +6102,10 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
 	mem_cgroup_charge_statistics(memcg, page, PageTransHuge(page),
 				     -nr_entries);
 	memcg_check_events(memcg, page);
+	local_unlock_irqrestore(event_lock, flags);
 
 	if (!mem_cgroup_is_root(memcg))
 		css_put_many(&memcg->css, nr_entries);
-	local_unlock_irqrestore(event_lock, flags);
 }
 
 /**
Signature · 1 line
2.14.1
#5 lore raw

PATCH 5/8 locallock: Include header for the `current' macro

In reply to [email protected]

From: Sebastian Andrzej Siewior <[email protected]>

v4.14.172-rt78-rc1 stable review patch.
If anyone has any objections, please let me know.

-----------

[ Upstream commit e693075a5fd852043fa8d2b0467e078d9e5cb782 ]

Include the header for `current' macro so that
CONFIG_KERNEL_HEADER_TEST=y passes.

---
 include/linux/locallock.h | 1 +
 1 file changed, 1 insertion(+)
include/linux/locallock.h +1 -0
index 921eab83cd34a..81c89d87723b5 100644
@@ -3,6 +3,7 @@
 
 #include <linux/percpu.h>
 #include <linux/spinlock.h>
+#include <asm/current.h>
 
 #ifdef CONFIG_PREEMPT_RT_BASE
 
Signature · 1 line
2.14.1
#6 lore raw

PATCH 6/8 drm/vmwgfx: Drop preempt_disable() in vmw_fifo_ping_host()

In reply to [email protected]

From: Sebastian Andrzej Siewior <[email protected]>

v4.14.172-rt78-rc1 stable review patch.
If anyone has any objections, please let me know.

-----------

[ Upstream commit b901491e7b9b7a676818d84e482b69be72fc142f ]

vmw_fifo_ping_host() disables preemption around a test and a register write via vmw_write(). The write function acquires a spinlock_t typed lock which is not allowed in a preempt_disable()ed section on PREEMPT_RT. This has been reported in the bugzilla.

It has been explained by Thomas Hellstrom that this preempt_disable()ed section is not required for correctness.

Remove the preempt_disable() section.

---
 drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 2 --
 1 file changed, 2 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +0 -2
index a1c68e6a689e3..713f202fca2cd 100644
@@ -167,10 +167,8 @@ void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
 {
 	u32 *fifo_mem = dev_priv->mmio_virt;
 
-	preempt_disable();
 	if (cmpxchg(fifo_mem + SVGA_FIFO_BUSY, 0, 1) == 0)
 		vmw_write(dev_priv, SVGA_REG_SYNC, reason);
-	preempt_enable();
 }
 
 void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
Signature · 1 line
2.14.1
#7 lore raw

PATCH 7/8 tracing: make preempt_lazy and migrate_disable counter smaller

In reply to [email protected]

From: Sebastian Andrzej Siewior <[email protected]>

v4.14.172-rt78-rc1 stable review patch.
If anyone has any objections, please let me know.

-----------

[ Upstream commit dd430bf5ecb40f9a89679c85868826475d71de54 ]

The migrate_disable counter should not exceed 255 so it is enough to store it in an 8bit field.
With this change we can move the preempt_lazy_count' member into the gap so the whole struct shrinks by 4 bytes to 12 bytes in total. Remove the padding' field, it is not needed.
Update the tracing fields in trace_define_common_fields() (it was missing the preempt_lazy_count field).

---
 include/linux/trace_events.h | 3 +--
 kernel/trace/trace_events.c  | 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)
include/linux/trace_events.h +1 -2
index edd1e42e8a2f7..01e9ab3107531 100644
@@ -62,8 +62,7 @@ struct trace_entry {
 	unsigned char		flags;
 	unsigned char		preempt_count;
 	int			pid;
-	unsigned short		migrate_disable;
-	unsigned short		padding;
+	unsigned char		migrate_disable;
 	unsigned char		preempt_lazy_count;
 };
 
kernel/trace/trace_events.c +2 -2
index 60e371451ec31..edd43841c94ad 100644
@@ -187,8 +187,8 @@ static int trace_define_common_fields(void)
 	__common_field(unsigned char, flags);
 	__common_field(unsigned char, preempt_count);
 	__common_field(int, pid);
-	__common_field(unsigned short, migrate_disable);
-	__common_field(unsigned short, padding);
+	__common_field(unsigned char, migrate_disable);
+	__common_field(unsigned char, preempt_lazy_count);
 
 	return ret;
 }
Signature · 1 line
2.14.1
#1 lore raw

PATCH 1/8 userfaultfd: Use a seqlock instead of seqcount

In reply to [email protected]

From: Sebastian Andrzej Siewior <[email protected]>

v4.14.172-rt78-rc1 stable review patch.
If anyone has any objections, please let me know.

-----------

[ Upstream commit dc952a564d02997330654be9628bbe97ba2a05d3 ]

On RT write_seqcount_begin() disables preemption which leads to warning in add_wait_queue() while the spinlock_t is acquired.
The waitqueue can't be converted to swait_queue because userfaultfd_wake_function() is used as a custom wake function.

Use seqlock instead seqcount to avoid the preempt_disable() section during add_wait_queue().

---
 fs/userfaultfd.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
fs/userfaultfd.c +6 -6
index e2b2196fd9428..71886a8e8f71b 100644
@@ -51,7 +51,7 @@ struct userfaultfd_ctx {
 	/* waitqueue head for events */
 	wait_queue_head_t event_wqh;
 	/* a refile sequence protected by fault_pending_wqh lock */
-	struct seqcount refile_seq;
+	seqlock_t refile_seq;
 	/* pseudo fd refcounting */
 	atomic_t refcount;
 	/* userfaultfd syscall flags */
@@ -1047,7 +1047,7 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
 			 * waitqueue could become empty if this is the
 			 * only userfault.
 			 */
-			write_seqcount_begin(&ctx->refile_seq);
+			write_seqlock(&ctx->refile_seq);
 
 			/*
 			 * The fault_pending_wqh.lock prevents the uwq
@@ -1073,7 +1073,7 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
 			list_del(&uwq->wq.entry);
 			__add_wait_queue(&ctx->fault_wqh, &uwq->wq);
 
-			write_seqcount_end(&ctx->refile_seq);
+			write_sequnlock(&ctx->refile_seq);
 
 			/* careful to always initialize msg if ret == 0 */
 			*msg = uwq->msg;
@@ -1246,11 +1246,11 @@ static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
 	 * sure we've userfaults to wake.
 	 */
 	do {
-		seq = read_seqcount_begin(&ctx->refile_seq);
+		seq = read_seqbegin(&ctx->refile_seq);
 		need_wakeup = waitqueue_active(&ctx->fault_pending_wqh) ||
 			waitqueue_active(&ctx->fault_wqh);
 		cond_resched();
-	} while (read_seqcount_retry(&ctx->refile_seq, seq));
+	} while (read_seqretry(&ctx->refile_seq, seq));
 	if (need_wakeup)
 		__wake_userfault(ctx, range);
 }
@@ -1915,7 +1915,7 @@ static void init_once_userfaultfd_ctx(void *mem)
 	init_waitqueue_head(&ctx->fault_wqh);
 	init_waitqueue_head(&ctx->event_wqh);
 	init_waitqueue_head(&ctx->fd_wqh);
-	seqcount_init(&ctx->refile_seq);
+	seqlock_init(&ctx->refile_seq);
 }
 
 /**
Signature · 1 line
2.14.1
#3 lore raw

PATCH 3/8 sched: migrate_enable: Remove __schedule() call

In reply to [email protected]

From: Scott Wood <[email protected]>

v4.14.172-rt78-rc1 stable review patch.
If anyone has any objections, please let me know.

-----------

[ Upstream commit b8162e61e9a33bd1de6452eb838fbf50a93ddd9a ]

We can rely on preempt_enable() to schedule. Besides simplifying the code, this potentially allows sequences such as the following to be permitted:

migrate_disable();
preempt_disable();
migrate_enable();
preempt_enable();

Conflicts:
kernel/sched/core.c

---
 kernel/sched/core.c | 1 -
 1 file changed, 1 deletion(-)
kernel/sched/core.c +0 -1
index 960daa6bc7f04..3ff48df25cff8 100644
@@ -7024,7 +7024,6 @@ void migrate_enable(void)
 		stop_one_cpu_nowait(task_cpu(p), migration_cpu_stop,
 				    arg, work);
 		tlb_migrate_finish(p->mm);
-		__schedule(true);
 	}
 
 out:
Signature · 1 line
2.14.1