anolis: sw64: improve sw64_rrk

ANBZ: #4688

Implement an improved sw64_rrk which stores the timestamp and loglevel.

Signed-off-by: Mao Minkai <maominkai@wxiat.com>
Reviewed-by: He Sheng <hesheng@wxiat.com>
Signed-off-by: Gu Zitao <guzitao@wxiat.com>
Reviewed-by: Min Li <gumi@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/5372
This commit is contained in:
Mao Minkai 2025-04-15 16:46:36 +08:00 committed by 小龙
parent d4872090ae
commit cc583d3b7a
2 changed files with 85 additions and 19 deletions

View File

@ -12,33 +12,88 @@
static DEFINE_SPINLOCK(printk_lock);
unsigned long sw64_printk_offset;
static unsigned long sw64_printk_offset;
#define PRINTK_SIZE 0x100000UL
void sw64_printk(const char *fmt, va_list args)
static bool rrk_last_newline_end;
static unsigned long rrk_last_id;
static const char * const level_str[] = {
"(0)EMERG",
"(1)ALERT",
"(2)CRIT",
"(3)ERR",
"(4)WARNING",
"(5)NOTICE",
"(6)INFO",
"(7)DEBUG"
};
#define LEVEL_STR_MAX_LEN 10 // length of "(4)WARNING"
void sw64_rrk_store(const char *text, u16 text_len, u64 ts_nsec, int level,
unsigned long id, bool newline_end)
{
char *sw64_printk_buf;
unsigned long flags;
char textbuf[1024];
const char *text;
size_t text_len;
size_t __maybe_unused rrk_len;
char header_buf[128];
/* same time fmt as print_time() in printk.c */
char header_fmt[] = "[%5llu.%06llu %-"__stringify(LEVEL_STR_MAX_LEN)"s] ";
size_t header_len;
char *newline;
/* if writing a new entry while the last one did not end with '\n', print '\n' first */
bool newline_first = rrk_last_id && (rrk_last_id != id) && (!rrk_last_newline_end);
bool wrap = false;
unsigned long max_offset_allowed;
spin_lock_irqsave(&printk_lock, flags);
sw64_printk_buf = (char *)(KERNEL_PRINTK_BUFF_BASE + sw64_printk_offset);
header_len = scnprintf(header_buf, sizeof(header_buf), header_fmt,
ts_nsec / NSEC_PER_SEC, (ts_nsec % NSEC_PER_SEC) / NSEC_PER_USEC,
level >= 0 ? level_str[level] : "CONT");
text_len = vscnprintf(textbuf, sizeof(textbuf), fmt, args);
text = printk_skip_headers(textbuf);
text_len -= text - textbuf;
if (sw64_printk_offset >= (PRINTK_SIZE - 1024)) {
max_offset_allowed = PRINTK_SIZE - text_len - header_len - (newline_first ? 1 : 0);
if (unlikely(sw64_printk_offset >= max_offset_allowed)) {
sw64_printk_offset = 0;
sw64_printk_buf = (char *)(KERNEL_PRINTK_BUFF_BASE + sw64_printk_offset);
memset(sw64_printk_buf, 0, PRINTK_SIZE);
wrap = true;
}
sw64_printk_buf = (char *)(KERNEL_PRINTK_BUFF_BASE + sw64_printk_offset);
if (unlikely(newline_first)) {
sw64_printk_buf[0] = '\n';
sw64_printk_buf++;
sw64_printk_offset++;
}
if (likely(level != -1) || unlikely(wrap)) {
memcpy(sw64_printk_buf, header_buf, header_len);
sw64_printk_offset += header_len;
sw64_printk_buf += header_len;
}
while (unlikely((newline = strnchr(text, text_len, '\n')))) {
size_t len;
/* copy the first line */
newline++;
len = newline - text;
memcpy(sw64_printk_buf, text, len);
/* add padding for next line */
memset(&sw64_printk_buf[len], ' ', header_len);
text += len;
text_len -= len;
sw64_printk_buf += len + header_len;
sw64_printk_offset += len + header_len;
}
memcpy(sw64_printk_buf, text, text_len);
sw64_printk_offset += text_len;
if (likely(sw64_printk_buf[text_len - 1] != '\n' && newline_end)) {
sw64_printk_buf[text_len] = '\n';
sw64_printk_offset++;
}
if (is_in_emul()) {
void __iomem *addr = __va(QEMU_PRINTF_BUFF_BASE);
@ -47,6 +102,9 @@ void sw64_printk(const char *fmt, va_list args)
*(u64 *)addr = data;
}
rrk_last_id = id;
rrk_last_newline_end = newline_end;
spin_unlock_irqrestore(&printk_lock, flags);
}
#endif
@ -55,8 +113,8 @@ void sw64_printk(const char *fmt, va_list args)
#include <linux/uaccess.h>
static DEFINE_SPINLOCK(printf_lock);
#define USER_PRINT_BUFF_BASE (0x600000UL + __START_KERNEL_map)
#define USER_PRINT_BUFF_LEN 0x100000UL
#define USER_PRINT_BUFF_BASE (0x600000UL + __START_KERNEL_map)
#define USER_PRINT_BUFF_LEN 0x100000UL
#define USER_MESSAGE_MAX_LEN 0x100000UL
unsigned long sw64_printf_offset;
int sw64_user_printf(const char __user *buf, int len)

View File

@ -504,6 +504,10 @@ static void truncate_msg(u16 *text_len, u16 *trunc_msg_len)
*trunc_msg_len = 0;
}
#ifdef CONFIG_SW64_RRK
extern void sw64_rrk_store(const char *text, u16 text_len, u64 ts_nsec, int level,
unsigned long id, bool final);
#endif
/* insert record into the buffer, discard old ones, update heads */
static int log_store(u32 caller_id, int facility, int level,
enum log_flags flags, u64 ts_nsec,
@ -547,6 +551,11 @@ static int log_store(u32 caller_id, int facility, int level,
else
prb_final_commit(&e);
#ifdef CONFIG_SW64_RRK
sw64_rrk_store(&r.text_buf[0], r.info->text_len, r.info->ts_nsec, r.info->level,
e.id, !!(flags & LOG_NEWLINE));
#endif
return (text_len + trunc_msg_len);
}
@ -1974,6 +1983,10 @@ static size_t log_output(int facility, int level, enum log_flags lflags,
} else {
prb_commit(&e);
}
#ifdef CONFIG_SW64_RRK
sw64_rrk_store(text, text_len, r.info->ts_nsec, -1,
e.id, !!(lflags & LOG_NEWLINE));
#endif
return text_len;
}
}
@ -1993,11 +2006,6 @@ int vprintk_store(int facility, int level,
size_t text_len;
enum log_flags lflags = 0;
#ifdef CONFIG_SW64_RRK
extern void sw64_printk(const char *fmt, va_list args);
sw64_printk(fmt, args);
#endif
/*
* The printf needs to come first; we need the syslog
* prefix which might be passed-in as a parameter.