[PATCH RFC 07/11] dyndbg: use READ_ONCE()/WRITE_ONCE() to access descriptor flags

From: Thomas Weißschuh

Date: Sun Oct 11 2026 - 08:58:01 EST


The descriptor flags are accessed concurrently. Use
READ_ONCE()/WRITE_ONCE() to keep their contents consistent.

Signed-off-by: Thomas Weißschuh <linux@xxxxxxxxxxxxxx>

---
I am not entirely sure about this. We are only using single bits, so
torn reads/writes should not matter. But LKMM has no guidance on this as
far as I can see. Also for Rust this seems to be necessary.
---
include/linux/dynamic_debug.h | 6 +++---
lib/dynamic_debug.c | 24 +++++++++++++-----------
2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index b1ff7c0e9a5f..6986142928ef 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -164,7 +164,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,

#define __dynamic_dump_stack(desc) \
{ \
- if (desc.flags & _DPRINTK_FLAGS_INCL_STACK) \
+ if (READ_ONCE(desc.flags) & _DPRINTK_FLAGS_INCL_STACK) \
dump_stack(); \
}

@@ -207,10 +207,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,

#ifdef DEBUG
#define DYNAMIC_DEBUG_BRANCH(descriptor) \
- likely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
+ likely(READ_ONCE(descriptor.flags) & _DPRINTK_FLAGS_PRINT)
#else
#define DYNAMIC_DEBUG_BRANCH(descriptor) \
- unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
+ unlikely(READ_ONCE(descriptor.flags) & _DPRINTK_FLAGS_PRINT)
#endif

#endif /* CONFIG_JUMP_LABEL */
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 18a71a9108d3..6dfd125fa6be 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -244,7 +244,7 @@ static int ddebug_change(const struct ddebug_query *query,

nfound++;

- newflags = (dp->flags & modifiers->mask) | modifiers->flags;
+ newflags = (READ_ONCE(dp->flags) & modifiers->mask) | modifiers->flags;
if (newflags == dp->flags)
continue;
#ifdef CONFIG_JUMP_LABEL
@@ -260,7 +260,7 @@ static int ddebug_change(const struct ddebug_query *query,
dt->mod_name, dp->function,
ddebug_describe_flags(dp->flags, &fbuf),
ddebug_describe_flags(newflags, &nbuf));
- dp->flags = newflags;
+ WRITE_ONCE(dp->flags, newflags);
}
}
mutex_unlock(&ddebug_lock);
@@ -822,12 +822,12 @@ static int remaining(int wrote)
return 0;
}

-static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
+static char *__dynamic_emit_prefix(const struct _ddebug *desc, u8 flags, char *buf)
{
int pos_after_tid;
int pos = 0;

- if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
+ if (flags & _DPRINTK_FLAGS_INCL_TID) {
if (in_interrupt())
pos += snprintf(buf + pos, remaining(pos), "<intr> ");
else
@@ -835,16 +835,16 @@ static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
task_pid_vnr(current));
}
pos_after_tid = pos;
- if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
+ if (flags & _DPRINTK_FLAGS_INCL_MODNAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
desc->modname);
- if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
+ if (flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
desc->function);
- if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
+ if (flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
trim_prefix(desc->filename));
- if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
+ if (flags & _DPRINTK_FLAGS_INCL_LINENO)
pos += snprintf(buf + pos, remaining(pos), "%d:",
desc->lineno);
if (pos - pos_after_tid)
@@ -857,8 +857,10 @@ static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)

static inline char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
{
- if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_ANY))
- return __dynamic_emit_prefix(desc, buf);
+ u8 flags = READ_ONCE(desc->flags);
+
+ if (unlikely(flags & _DPRINTK_FLAGS_INCL_ANY))
+ return __dynamic_emit_prefix(desc, flags, buf);
return buf;
}

@@ -1146,7 +1148,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
seq_printf(m, "%s:%u [%s]%s =%s \"",
trim_prefix(dp->filename), dp->lineno,
iter->table->mod_name, dp->function,
- ddebug_describe_flags(dp->flags, &flags));
+ ddebug_describe_flags(READ_ONCE(dp->flags), &flags));
seq_escape_str(m, dp->format, ESCAPE_SPACE, "\t\r\n\"");
seq_putc(m, '"');


--
2.56.0