Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751727AbbEYMsJ (ORCPT ); Mon, 25 May 2015 08:48:09 -0400 Received: from cantor2.suse.de ([195.135.220.15]:53624 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751203AbbEYMrG (ORCPT ); Mon, 25 May 2015 08:47:06 -0400 From: Petr Mladek To: Andrew Morton Cc: Frederic Weisbecker , Steven Rostedt , Dave Anderson , "Paul E. McKenney" , Kay Sievers , Jiri Kosina , Michal Hocko , Jan Kara , linux-kernel@vger.kernel.org, Wang Long , peifeiyue@huawei.com, dzickus@redhat.com, morgan.wang@huawei.com, sasha.levin@oracle.com, Petr Mladek Subject: [PATCH 07/10] printk: Split text formatting and analyze from vprintk_emit() Date: Mon, 25 May 2015 14:46:30 +0200 Message-Id: <1432557993-20458-8-git-send-email-pmladek@suse.cz> X-Mailer: git-send-email 1.8.5.6 In-Reply-To: <1432557993-20458-1-git-send-email-pmladek@suse.cz> References: <1432557993-20458-1-git-send-email-pmladek@suse.cz> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5141 Lines: 176 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 --- 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 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/