[PATCH] makedumpfile: printk: add support for lockless ringbuffer

HAGIO KAZUHITO(萩尾 一仁) k-hagio-ab at nec.com
Wed Nov 25 19:14:16 EST 2020


-----Original Message-----
> On 2020-11-24, HAGIO KAZUHITO(萩尾 一仁)	<k-hagio-ab at nec.com> wrote:
> >> After looking more closely, I see that your patch is still using the
> >> old state flags. With the current version, there is now a value-based
> >> state field.
> >
> > Thank you for pointing it out!  Could you submit a follow-up patch?
> 
> I have attached a follow-up patch. It is pretty much the exact same
> patch as the one I sent for "crash".

Thank you for the patch again, John.  I appreciate it.  Will merge.

Apparently an email with attached file is held by the list system, so
unfolding it below to share and record, just in case.

Thanks,
Kazu


From 58396867cb3bfd1ca060cf5eb3a910d7f8c192c2 Mon Sep 17 00:00:00 2001
From: John Ogness <john.ogness at linutronix.de>
Date: Wed, 25 Nov 2020 10:10:31 +0106
Subject: [PATCH] printk: use committed/finalized state values

The ringbuffer entries use 2 state values (committed and finalized)
rather than a single flag to represent being available for reading.
Copy the definitions and state lookup function directly from the
kernel source and use the new states.

Signed-off-by: John Ogness <john.ogness at linutronix.de>
---
 printk.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 41 insertions(+), 7 deletions(-)

diff --git a/printk.c b/printk.c
index 8e00901..9cecbd1 100644
--- a/printk.c
+++ b/printk.c
@@ -1,12 +1,6 @@
 #include "makedumpfile.h"
 #include <ctype.h>
 
-#define DESC_SV_BITS		(sizeof(unsigned long) * 8)
-#define DESC_COMMITTED_MASK	(1UL << (DESC_SV_BITS - 1))
-#define DESC_REUSE_MASK		(1UL << (DESC_SV_BITS - 2))
-#define DESC_FLAGS_MASK		(DESC_COMMITTED_MASK | DESC_REUSE_MASK)
-#define DESC_ID_MASK		(~DESC_FLAGS_MASK)
-
 /* convenience struct for passing many values to helper functions */
 struct prb_map {
 	char		*prb;
@@ -21,12 +15,51 @@ struct prb_map {
 	char		*text_data;
 };
 
+/*
+ * desc_state and DESC_* definitions taken from kernel source:
+ *
+ * kernel/printk/printk_ringbuffer.h
+ */
+
+/* The possible responses of a descriptor state-query. */
+enum desc_state {
+	desc_miss	=  -1,	/* ID mismatch (pseudo state) */
+	desc_reserved	= 0x0,	/* reserved, in use by writer */
+	desc_committed	= 0x1,	/* committed by writer, could get reopened */
+	desc_finalized	= 0x2,	/* committed, no further modification allowed */
+	desc_reusable	= 0x3,	/* free, not yet used by any writer */
+};
+
+#define DESC_SV_BITS		(sizeof(unsigned long) * 8)
+#define DESC_FLAGS_SHIFT	(DESC_SV_BITS - 2)
+#define DESC_FLAGS_MASK		(3UL << DESC_FLAGS_SHIFT)
+#define DESC_STATE(sv)		(3UL & (sv >> DESC_FLAGS_SHIFT))
+#define DESC_ID_MASK		(~DESC_FLAGS_MASK)
+#define DESC_ID(sv)		((sv) & DESC_ID_MASK)
+
+/*
+ * get_desc_state() taken from kernel source:
+ *
+ * kernel/printk/printk_ringbuffer.c
+ */
+
+/* Query the state of a descriptor. */
+static enum desc_state get_desc_state(unsigned long id,
+				      unsigned long state_val)
+{
+	if (id != DESC_ID(state_val))
+		return desc_miss;
+
+	return DESC_STATE(state_val);
+}
+
 static void
 dump_record(struct prb_map *m, unsigned long id)
 {
 	unsigned long long ts_nsec;
 	unsigned long state_var;
 	unsigned short text_len;
+	enum desc_state state;
 	unsigned long begin;
 	unsigned long next;
 	char buf[BUFSIZE];
@@ -45,7 +78,8 @@ dump_record(struct prb_map *m, unsigned long id)
 
 	/* skip non-committed record */
 	state_var = ULONG(desc + OFFSET(prb_desc.state_var) + OFFSET(atomic_long_t.counter));
-	if ((state_var & DESC_FLAGS_MASK) != DESC_COMMITTED_MASK)
+	state = get_desc_state(id, state_var);
+	if (state != desc_committed && state != desc_finalized)
 		return;
 
 	begin = ULONG(desc + OFFSET(prb_desc.text_blk_lpos) + OFFSET(prb_data_blk_lpos.begin)) %
-- 
2.20.1



More information about the kexec mailing list