[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250120-rational-bullfrog-of-tornado-2cd6f4@leitao>
Date: Mon, 20 Jan 2025 09:30:48 -0800
From: Breno Leitao <leitao@...ian.org>
To: Jakub Kicinski <kuba@...nel.org>
Cc: Andrew Lunn <andrew+netdev@...n.ch>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>, Paolo Abeni <pabeni@...hat.com>,
Simon Horman <horms@...nel.org>, Jonathan Corbet <corbet@....net>,
Shuah Khan <shuah@...nel.org>, netdev@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-doc@...r.kernel.org,
linux-kselftest@...r.kernel.org, kernel-team@...a.com,
max@...sevol.com, thepacketgeek@...il.com
Subject: Re: [PATCH net-next v2 3/5] netconsole: add support for sysdata and
CPU population
On Fri, Jan 17, 2025 at 06:35:20PM -0800, Jakub Kicinski wrote:
> On Fri, 17 Jan 2025 03:02:40 -0800 Breno Leitao wrote:
> > > Looks like previously all the data was on the stack, now we have a mix.
> >
> > Not sure I followed. The data ({userdata,extradata}_complete) was always
> > inside nt field, which belongs to target_list.
>
> I mean the buffer we use for formatting. Today it's this:
>
> static char buf[MAX_PRINT_CHUNK]; /* protected by target_list_lock */
> int header_len, msgbody_len;
> const char *msgbody;
>
> right? I missed that "static" actually so it's not on the stack,
> it's in the .bss section.
Since you raised this topic, I don't think buf needs to be static
for a functional perspective, since `buf` is completely overwritten
every time send_msg functions are called.
> > > Maybe we can pack all the bits of state into a struct for easier
> > > passing around, but still put it on the stack?
> >
> > It depends on what state you need here. We can certainly pass runtime
> > (aka sysdata in this patchset) data in the stack, but doing the same for
> > userdata would require extra computation in runtime. In other words, the
> > userdata_complete and length are calculated at configfs update time
> > today, and only read during runtime, and there is no connection between
> > configfs and runtime (write_ext_msg()) except through the stack.
> >
> >
> > On the other side, if we want to have extradata_complete in the stack, I
> > still think that userdata will need to be in the stack, and create a
> > buffer in runtime's frame and copy userdata + sysdata at run time, doing
> > an extra copy.
> >
> > Trying to put this in code, this is what I thought:
> >
> > /* Copy to the stack (buf) the userdata string + sysdata */
> > static void append_runtime_sysdata(struct netconsole_target *nt, char *buf) {
> > if (!(nt->sysdata_fields & CPU_NR))
> > return;
> >
> > return scnprintf(buf, MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS,
> > "%s cpu=%u\n", nt->userdata_complete, raw_smp_processor_id());
> > }
> >
> > /* Move complete string in the stack and send from there */
> > static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
> > int msg_len) {
> > ...
> > #ifdef CONFIG_NETCONSOLE_DYNAMIC
> > struct char buf[MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS];
> > extradata_len = append_runtime_sysdata(nt, buf);
> > #endif
> >
> > send_msg_{no}_fragmentation(nt, msg, buf, extradata_len, release_len)
> > ...
> > }
>
> My thinking was to handle it like the release.
> Print it at the send_msg_no_fragmentation() stage directly
> into the static buffer. Does that get hairy coding-wise?
I suppose the advantage of doing this approach is to reduce a
memcpy/strcpy, right?
If this is what your motivation, I think we cannot remove it from the
fragmented case. Let me share my thought process:
1) sysdata needs to be appended to both send_msg_fragmented() and
send_msg_no_fragmentation(). The fragmented case is the problem.
2) It is trivially done in send_msg_fragmented() case.
3) For the send_msg_no_fragmentation() case, there is no trivial way to
get it done without using a secondary buffer and then memcpy to `buf`.
Let's suppose sysdata has "cpu=42", and original `buf` has only 5 available
chars, thus it needs to have 2 msgs to accommodate the full message.
Then the it needs to track that `cpu=4` will be sent in a msg and create
another message with the missing `2`.
The only way to do it properly is having a extra buffer where we
have `cpu=42` and copy 5 bytes from there, and then copy the last one in
the next iteration. I am not sure we can do it in one shot.
On top of that, I am planning to increase other features in sysdata
(such as current task name, modules and even consolidate the release as
sysdata), which has two implications:
1) Average messages size will become bigger. Thus, memcpy will be needed
one way or another.
2) Unless we can come up with a smart solution, this solution will be
harder to reason about.
If you want to invest more time in this direction, I am more than happy
to create a PoC, so we can discuss more concretely.
Thanks,
--breno
Powered by blists - more mailing lists