lkml.org 
[lkml]   [2015]   [May]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 07/10] printk: Split text formatting and analyze from vprintk_emit()
    Date
    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


    \
     
     \ /
      Last update: 2015-05-25 15:01    [W:4.189 / U:0.080 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site