net: netconsole: append userdata to fragmented netconsole messages
authorMatthew Wood <thepacketgeek@gmail.com>
Sun, 4 Feb 2024 23:27:39 +0000 (15:27 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 9 Feb 2024 10:23:46 +0000 (10:23 +0000)
Regardless of whether the original message body or formatted userdata
exceeds the MAX_PRINT_CHUNK, append userdata to the netconsole message
starting with the first chunk that has available space after writing the
body.

Co-developed-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Matthew Wood <thepacketgeek@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/netconsole.c

index d53bb11723365a4d586b509e8c62d9ef2bd61cbe..0de108a1c0c8b6041f54b4bd004b3e92da8c6e9d 100644 (file)
@@ -1085,24 +1085,48 @@ static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
        memcpy(buf + release_len, header, header_len);
        header_len += release_len;
 
-       while (offset < body_len) {
+       while (offset < body_len + userdata_len) {
                int this_header = header_len;
-               int this_chunk;
+               int this_offset = 0;
+               int this_chunk = 0;
 
                this_header += scnprintf(buf + this_header,
                                         sizeof(buf) - this_header,
-                                        ",ncfrag=%d/%d;", offset, body_len);
-
-               this_chunk = min(body_len - offset,
-                                MAX_PRINT_CHUNK - this_header);
-               if (WARN_ON_ONCE(this_chunk <= 0))
-                       return;
-
-               memcpy(buf + this_header, body + offset, this_chunk);
-
-               netpoll_send_udp(&nt->np, buf, this_header + this_chunk);
+                                        ",ncfrag=%d/%d;", offset,
+                                        body_len + userdata_len);
+
+               /* Not all body data has been written yet */
+               if (offset < body_len) {
+                       this_chunk = min(body_len - offset,
+                                        MAX_PRINT_CHUNK - this_header);
+                       if (WARN_ON_ONCE(this_chunk <= 0))
+                               return;
+                       memcpy(buf + this_header, body + offset, this_chunk);
+                       this_offset += this_chunk;
+               }
+               /* Body is fully written and there is pending userdata to write,
+                * append userdata in this chunk
+                */
+               if (offset + this_offset >= body_len &&
+                   offset + this_offset < userdata_len + body_len) {
+                       int sent_userdata = (offset + this_offset) - body_len;
+                       int preceding_bytes = this_chunk + this_header;
+
+                       if (WARN_ON_ONCE(sent_userdata < 0))
+                               return;
+
+                       this_chunk = min(userdata_len - sent_userdata,
+                                        MAX_PRINT_CHUNK - preceding_bytes);
+                       if (WARN_ON_ONCE(this_chunk <= 0))
+                               return;
+                       memcpy(buf + this_header + this_offset,
+                              userdata + sent_userdata,
+                              this_chunk);
+                       this_offset += this_chunk;
+               }
 
-               offset += this_chunk;
+               netpoll_send_udp(&nt->np, buf, this_header + this_offset);
+               offset += this_offset;
        }
 }