Messages in this thread Patch in this message | | | From | Petr Mladek <> | Subject | [PATCH 07/10] printk: Split text formatting and analyze from vprintk_emit() | Date | Mon, 25 May 2015 14:46:30 +0200 |
| |
vprintk_emit() is too long. Let's move the text formatting and the text analyze into a separate function.
I am not super happy with the result. The primary aim is to reduce future mistakes when backporting fixes in this code to older stable kernel releases. Therefore I want to keep the changes in the code at minimum. Especially, I want to avoid conversion of @text into "char **" because it is harder to read.
Well, there is one exception. @level is accessed via a pointer. It looks safe because compiler warns about type mismatch when the access is not updated. Also it used only in a very simple code.
Better ideas are welcome!
This patch just shuffles the code. There is no change in the functionality.
Signed-off-by: Petr Mladek <pmladek@suse.cz> --- kernel/printk/printk.c | 122 +++++++++++++++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 44 deletions(-)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 91b8043044ac..7d009144f97f 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1740,13 +1740,85 @@ static int vprintk_delayed_warnings(void) return printed_len; } +/** + * vprintk_format_and_analyze - format and analyze the text message + * @fmt: text format + * @args: argumetns used to generate the formated text + * @dict: pointer to the message dictionary + * @facility: syslog facility + * @level: syslog level; might be replaced by the one found in the fomatted text + * @ftext: pointer to the formatted text after the syslog prefix + * @ftext_len: length of the formatted text without the syslog prefix + * + * This function modifies the global textbuf and therefore it must be called + * under lockbuf_lock! + */ +static enum log_flags vprinkt_format_and_analyze(const char *fmt, va_list args, + const char *dict, int facility, + int *level, + char **ftext, + size_t *ftext_len) +{ + char *text = textbuf; + size_t text_len; + enum log_flags lflags = 0; + + /* + * The printf needs to come first; we need the syslog + * prefix which might be passed-in as a parameter. + */ + text_len = vscnprintf(text, sizeof(textbuf), fmt, args); + + /* mark and strip a trailing newline */ + if (text_len && text[text_len-1] == '\n') { + text_len--; + lflags |= LOG_NEWLINE; + } + + /* strip kernel syslog prefix and extract log level or control flags */ + if (facility == 0) { + int kern_level = printk_get_level(text); + + if (kern_level) { + const char *end_of_header = printk_skip_level(text); + + switch (kern_level) { + case '0' ... '7': + if (*level == LOGLEVEL_DEFAULT) + *level = kern_level - '0'; + /* fallthrough */ + case 'd': /* KERN_DEFAULT */ + lflags |= LOG_PREFIX; + } + /* + * No need to check length here because vscnprintf + * put '\0' at the end of the string. Only valid and + * newly printed level is detected. + */ + text_len -= end_of_header - text; + text = (char *)end_of_header; + } + } + + if (*level == LOGLEVEL_DEFAULT) + *level = default_message_loglevel; + + if (dict) + lflags |= LOG_PREFIX|LOG_NEWLINE; + + *ftext = text; + *ftext_len = text_len; + + return lflags; +} + asmlinkage int vprintk_emit(int facility, int level, const char *dict, size_t dictlen, const char *fmt, va_list args) { - char *text = textbuf; - size_t text_len = 0; - enum log_flags lflags = 0; + char *text; + size_t text_len; + enum log_flags lflags; unsigned long flags; int this_cpu; int printed_len = 0; @@ -1808,47 +1880,9 @@ asmlinkage int vprintk_emit(int facility, int level, printed_len += vprintk_delayed_warnings(); - /* - * The printf needs to come first; we need the syslog - * prefix which might be passed-in as a parameter. - */ - text_len = vscnprintf(text, sizeof(textbuf), fmt, args); - - /* mark and strip a trailing newline */ - if (text_len && text[text_len-1] == '\n') { - text_len--; - lflags |= LOG_NEWLINE; - } - - /* strip kernel syslog prefix and extract log level or control flags */ - if (facility == 0) { - int kern_level = printk_get_level(text); - - if (kern_level) { - const char *end_of_header = printk_skip_level(text); - switch (kern_level) { - case '0' ... '7': - if (level == LOGLEVEL_DEFAULT) - level = kern_level - '0'; - /* fallthrough */ - case 'd': /* KERN_DEFAULT */ - lflags |= LOG_PREFIX; - } - /* - * No need to check length here because vscnprintf - * put '\0' at the end of the string. Only valid and - * newly printed level is detected. - */ - text_len -= end_of_header - text; - text = (char *)end_of_header; - } - } - - if (level == LOGLEVEL_DEFAULT) - level = default_message_loglevel; - - if (dict) - lflags |= LOG_PREFIX|LOG_NEWLINE; + lflags = vprinkt_format_and_analyze(fmt, args, dict, facility, + &level, + &text, &text_len); if (!(lflags & LOG_NEWLINE)) { /* -- 1.8.5.6
| |