[ANNOUNCE] v6.4-rt6

From: Sebastian Andrzej Siewior
Date: Mon Jun 26 2023 - 10:19:15 EST


Dear RT folks!

I'm pleased to announce the v6.4-rt6 patch set.

Changes since v6.4-rt5:

- Closing a bpf socket caused a RCU warning.

- While updating the zonelist due to memory-hotplug, a lock was
acquired in the wrong context followed by a "sleeping while atomic"
warning. Addressing this issue required additionally a change to
printk and lockdep's annotation for seqcount.

Known issues
None

The delta patch against v6.4-rt5 is appended below and can be found here:

https://cdn.kernel.org/pub/linux/kernel/projects/rt/6.4/incr/patch-6.4-rt5-rt6.patch.xz

You can get this release via the git tree at:

git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git v6.4-rt6

The RT patch against v6.4 can be found here:

https://cdn.kernel.org/pub/linux/kernel/projects/rt/6.4/older/patch-6.4-rt6.patch.xz

The split quilt queue is available at:

https://cdn.kernel.org/pub/linux/kernel/projects/rt/6.4/older/patches-6.4-rt6.tar.xz

Sebastian

diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 3926e90279477..d778af83c8f36 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -512,8 +512,8 @@ do { \

static inline void do_write_seqcount_begin_nested(seqcount_t *s, int subclass)
{
- do_raw_write_seqcount_begin(s);
seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_);
+ do_raw_write_seqcount_begin(s);
}

/**
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index f1c8733f76b83..370a2cda6d854 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2781,28 +2781,31 @@ static void bpf_link_put_deferred(struct work_struct *work)
bpf_link_free(link);
}

-/* bpf_link_put can be called from atomic context, but ensures that resources
- * are freed from process context
+/* bpf_link_put might be called from atomic context. It needs to be called
+ * from sleepable context in order to acquire sleeping locks during the process.
*/
void bpf_link_put(struct bpf_link *link)
{
if (!atomic64_dec_and_test(&link->refcnt))
return;

- if (in_atomic()) {
- INIT_WORK(&link->work, bpf_link_put_deferred);
- schedule_work(&link->work);
- } else {
- bpf_link_free(link);
- }
+ INIT_WORK(&link->work, bpf_link_put_deferred);
+ schedule_work(&link->work);
}
EXPORT_SYMBOL(bpf_link_put);

+static void bpf_link_put_direct(struct bpf_link *link)
+{
+ if (!atomic64_dec_and_test(&link->refcnt))
+ return;
+ bpf_link_free(link);
+}
+
static int bpf_link_release(struct inode *inode, struct file *filp)
{
struct bpf_link *link = filp->private_data;

- bpf_link_put(link);
+ bpf_link_put_direct(link);
return 0;
}

@@ -4778,7 +4781,7 @@ static int link_update(union bpf_attr *attr)
if (ret)
bpf_prog_put(new_prog);
out_put_link:
- bpf_link_put(link);
+ bpf_link_put_direct(link);
return ret;
}

@@ -4801,7 +4804,7 @@ static int link_detach(union bpf_attr *attr)
else
ret = -EOPNOTSUPP;

- bpf_link_put(link);
+ bpf_link_put_direct(link);
return ret;
}

@@ -4871,7 +4874,7 @@ static int bpf_link_get_fd_by_id(const union bpf_attr *attr)

fd = bpf_link_new_fd(link);
if (fd < 0)
- bpf_link_put(link);
+ bpf_link_put_direct(link);

return fd;
}
@@ -4948,7 +4951,7 @@ static int bpf_iter_create(union bpf_attr *attr)
return PTR_ERR(link);

err = bpf_iter_new_fd(link);
- bpf_link_put(link);
+ bpf_link_put_direct(link);

return err;
}
diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c
index 5c1470bd60bcb..a324eaeb25333 100644
--- a/kernel/printk/printk_safe.c
+++ b/kernel/printk/printk_safe.c
@@ -39,13 +39,13 @@ void __printk_safe_exit(unsigned long *flags)

void __printk_deferred_enter(void)
{
- WARN_ON_ONCE(!in_atomic());
+ cant_migrate();
this_cpu_inc(printk_context.recursion);
}

void __printk_deferred_exit(void)
{
- WARN_ON_ONCE(!in_atomic());
+ cant_migrate();
this_cpu_dec(printk_context.recursion);
}

diff --git a/localversion-rt b/localversion-rt
index 0efe7ba1930e1..8fc605d806670 100644
--- a/localversion-rt
+++ b/localversion-rt
@@ -1 +1 @@
--rt5
+-rt6
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 47421bedc12b7..440e9af67b48d 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -5808,19 +5808,17 @@ static void __build_all_zonelists(void *data)
unsigned long flags;

/*
- * Explicitly disable this CPU's interrupts before taking seqlock
- * to prevent any IRQ handler from calling into the page allocator
- * (e.g. GFP_ATOMIC) that could hit zonelist_iter_begin and livelock.
+ * The zonelist_update_seq must be acquired with irqsave because the
+ * reader can be invoked from IRQ with GFP_ATOMIC.
*/
- local_irq_save(flags);
+ write_seqlock_irqsave(&zonelist_update_seq, flags);
/*
- * Explicitly disable this CPU's synchronous printk() before taking
- * seqlock to prevent any printk() from trying to hold port->lock, for
+ * Also disable synchronous printk() to prevent any printk() from
+ * trying to hold port->lock, for
* tty_insert_flip_string_and_push_buffer() on other CPU might be
* calling kmalloc(GFP_ATOMIC | __GFP_NOWARN) with port->lock held.
*/
printk_deferred_enter();
- write_seqlock(&zonelist_update_seq);

#ifdef CONFIG_NUMA
memset(node_load, 0, sizeof(node_load));
@@ -5857,9 +5855,8 @@ static void __build_all_zonelists(void *data)
#endif
}

- write_sequnlock(&zonelist_update_seq);
printk_deferred_exit();
- local_irq_restore(flags);
+ write_sequnlock_irqrestore(&zonelist_update_seq, flags);
}

static noinline void __init