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