On Mon, Aug 3, 2026 at 12:30 PM Breno Leitao <[email protected]> wrote: > > update_userdata() takes target_list_lock to swap nt->userdata and > nt->userdata_length, then frees the old buffer. Since commit > 7eab73b18630 ("netconsole: convert to NBCON console infrastructure") > that lock is also the console's device_lock, so writing a userdata value > from configfs serialises against the printk core emitting messages. > > The buffer is immutable once published, which is what RCU is for. Move > the string and its length into a single netconsole_userdata object and > publish it with rcu_replace_pointer(), freeing the old one with > kfree_rcu(). > > New userdata design: > > 0) Unify the userdata fields into a struct netcons_userdata > 1) update_userdata() no longer needs target_list_lock. > 2) writers stay serialised by dynamic_netconsole_mutex. > 3) reading userdata needs an RCU read lock. > > No functional change intended. > > Signed-off-by: Breno Leitao <[email protected]> > --- > drivers/net/netconsole.c | 88 > +++++++++++++++++++++++++++++------------------- > 1 file changed, 54 insertions(+), 34 deletions(-) > > diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c > index 862001d09aa84..c88c82f2136cb 100644 > --- a/drivers/net/netconsole.c > +++ b/drivers/net/netconsole.c > @@ -135,13 +135,27 @@ enum target_state { > STATE_DEACTIVATED, > }; > > +/** > + * struct netcons_userdata - Formatted userdata payload of a target. > + * @rcu: Used to free the payload after a grace period. > + * @length: Length of @data, excluding the NUL terminator. > + * @data: Formatted " key=value\n" entries, NUL terminated. > + * > + * Immutable once published, so the transmit path never observes @data and > + * @length disagreeing. > + */ > +struct netcons_userdata { > + struct rcu_head rcu; > + size_t length; > + char data[]; > +}; > + > /** > * struct netconsole_target - Represents a configured netconsole target. > * @list: Links this target into the target_list. > * @group: Links us into the configfs subsystem hierarchy. > * @userdata_group: Links to the userdata configfs hierarchy > - * @userdata: Cached, formatted string of append > - * @userdata_length: String length of userdata. > + * @userdata: Cached, formatted userdata payload. RCU protected. > * @sysdata: Cached, formatted string of append > * @sysdata_fields: Sysdata features enabled. > * @msgcounter: Message sent counter. > @@ -176,8 +190,7 @@ struct netconsole_target { > #ifdef CONFIG_NETCONSOLE_DYNAMIC > struct config_group group; > struct config_group userdata_group; > - char *userdata; > - size_t userdata_length; > + struct netcons_userdata __rcu *userdata;
With userdata now annotated with __rcu, it should be freed with kfree(rcu_access_pointer(nt->userdata)) to avoid a sparse warning: $ make C=1 drivers/net/netconsole.o DESCEND objtool DESCEND bpf/resolve_btfids INSTALL libsubcmd_headers CC drivers/net/netconsole.o CHECK drivers/net/netconsole.c drivers/net/netconsole.c:1702:17: expected void const *objp drivers/net/netconsole.c:1702:17: got struct netcons_userdata [noderef] __rcu *userdata drivers/net/netconsole.c:2689:17: expected void const *objp drivers/net/netconsole.c:2689:17: got struct netcons_userdata [noderef] __rcu *userdata

