[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAD=FV=XXpMnjXzPgDseoLGOYUHVQy9Z2cjmCC+OE+uDC43eNRw@mail.gmail.com>
Date: Tue, 21 Oct 2025 15:57:18 -0700
From: Doug Anderson <dianders@...omium.org>
To: Andrew Morton <akpm@...ux-foundation.org>
Cc: linux-kernel@...r.kernel.org, Andrew Chant <achant@...gle.com>,
Alexander Shishkin <alexander.shishkin@...ux.intel.com>, Brian Gerst <brgerst@...il.com>,
Christian Brauner <brauner@...nel.org>, Francesco Valla <francesco@...la.it>,
Geert Uytterhoeven <geert+renesas@...der.be>, Guo Weikang <guoweikang.kernel@...il.com>,
Huacai Chen <chenhuacai@...nel.org>, Jan Hendrik Farr <kernel@...rr.cc>, Jeff Xu <jeffxu@...omium.org>,
Kees Cook <kees@...nel.org>, Masahiro Yamada <masahiroy@...nel.org>,
Michal Koutný <mkoutny@...e.com>,
Miguel Ojeda <ojeda@...nel.org>, "Mike Rapoport (Microsoft)" <rppt@...nel.org>,
Nathan Chancellor <nathan@...nel.org>, Peter Zijlstra <peterz@...radead.org>,
Randy Dunlap <rdunlap@...radead.org>, Shakeel Butt <shakeel.butt@...ux.dev>,
Tejun Heo <tj@...nel.org>, Thomas Gleixner <tglx@...utronix.de>,
Thomas Weißschuh <thomas.weissschuh@...utronix.de>,
"Uladzislau Rezki (Sony)" <urezki@...il.com>
Subject: Re: [PATCH] init/main.c: Wrap long kernel cmdline when printing to logs
Hi,
On Tue, Oct 21, 2025 at 1:55 PM Andrew Morton <akpm@...ux-foundation.org> wrote:
>
> On Mon, 20 Oct 2025 13:00:22 -0700 Doug Anderson <dianders@...omium.org> wrote:
>
> > > And the code would presumably be much simpler if we simply chunked up
> > > the printing and spat out one really long line.
> >
> > I'm not quite sure what you're suggesting. Before my changes we _do_
> > try to spit out one really long line, but then printk() silently
> > truncates it for us at 1021 characters. Re-reading your suggestion,
> > I'm not sure if you're suggesting that we improve printk() to handle
> > lines longer than 1021 characters by chunking them up, or if you're
> > suggesting that this code could use "pr_cont()" to chunk things up.
> > ...or something totally different. ;-) Can you clarify?
>
> I was suggsting the latter - emit these really long lines via repeated
> calls to printk().
OK, I coded this up. I started with a pr_notice() and after 1021 bytes
I followed up with a pr_cont().
Unfortunately, this doesn't seem to work to make "one big line". The
subsequent strings w/ "pr_cont()" end up on separate lines. In other
words:
pr_notice(first_1021_byte_str);
pr_cont(second_1021_bytes_str);
pr_cont(last_10_byte_str);
Ends up with logs that look like:
[ 0.000000] first_1021_byte_str
[ 0.000000] second_1021_bytes_str
[ 0.000000] last_10_byte_str
...so we end up with a worse situation than with my patches since the
wrapping happens at exactly 1021 characters rather than wrapping based
on spaces.
I tried to dig into this a bit to make sure it wasn't just a bug in my
patch. I made it wrap at 504 bytes. Now I tested something like:
pr_notice(First_504_byte_str);
pr_cont(Second_504_bytes_str);
pr_cont(Third_504_bytes_str);
pr_cont(Fourth_504_bytes_str);
pr_cont(Last_10_byte_str);
Now I had:
[ 0.000000] First_504_byte_strSecond_504_bytes_str
[ 0.000000] Third_504_bytes_strFourth_504_bytes_str
[ 0.000000] Last_10_byte_str
In other words pr_cont() was working properly, but it seemed to
realize when the resultant string would be > 1021 characters and it
started a new line for me. This further cemented in my mind that it's
not a way around the 1021 character limit.
For giggles, I also tried backing out my patch and just doing:
-#define PRINTK_MESSAGE_MAX 2048
+#define PRINTK_MESSAGE_MAX 8192
-#define PRINTKRB_RECORD_MAX 1024
+#define PRINTKRB_RECORD_MAX 4096
When I looked at the serial console output I found success. My very
long cmdline was printed out in its entirety. ...but it made "dmesg"
real unhappy. :'( In fact, when I ran `dmesg` after doing this it
actually fully stopped printing anything when it got to the long line.
:-P Things looked OK when I looked at `/dev/kmsg` directly. ...so I
ran strace on `dmesg` on my system and I found:
read(3, "6,53,0,-;alternatives: applying "..., 2047) = 50
write(1, "\33[32m[ 0.000000] \33[0m\33[33malt"..., 74[ 0.000000]
alternatives: applying boot alternatives
) = 74
read(3, 0xaab6c875c2d8, 2047) = -1 EINVAL (Invalid argument)
close(3) = 0
In other words `dmesg` seemed to be trying to read 2047 bytes from
`/dev/kmsg` and this wasn't enough to hold the output line. You can
see in the kernel function devkmsg_read() that when this happens the
kernel returns -EINVAL.
We could _try_ to improve devkmsg_read() to be able to return partial
log lines, but that violates the docs. The file
`Documentation/ABI/testing/dev-kmsg` says:
Every read() from the opened device node receives one record
of the kernel's printk buffer.
...
Messages in the record ring buffer get overwritten as whole,
there are never partial messages received by read().
So tl;dr: as far as I can tell, we simply cannot put the whole cmdline
(which is 2048+ on many architectures) on one line without breaking
userspace. My userspace reads 2047 bytes and we'd need to return not
just the cmdline but the prefix "Kernel command line:" as well as the
data about time/log_level/etc.
Does any of the above change your mind about my wrapping scheme? ;-)
Obviously, I'd want to update my commit message with some of the
research...
-Doug
Powered by blists - more mailing lists