Merge tag 'printk-for-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek...
[muen/linux.git] / kernel / printk / printk.c
index d3d1703..8eee85b 100644 (file)
@@ -344,7 +344,6 @@ static int console_msg_format = MSG_FORMAT_DEFAULT;
 
 enum log_flags {
        LOG_NEWLINE     = 2,    /* text ended with a newline */
-       LOG_PREFIX      = 4,    /* text started with a prefix */
        LOG_CONT        = 8,    /* text is a fragment of a continuation line */
 };
 
@@ -356,6 +355,9 @@ struct printk_log {
        u8 facility;            /* syslog facility */
        u8 flags:5;             /* internal record flags */
        u8 level:3;             /* syslog level */
+#ifdef CONFIG_PRINTK_CALLER
+       u32 caller_id;            /* thread id or processor id */
+#endif
 }
 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 __packed __aligned(4)
@@ -422,7 +424,11 @@ static u64 exclusive_console_stop_seq;
 static u64 clear_seq;
 static u32 clear_idx;
 
+#ifdef CONFIG_PRINTK_CALLER
+#define PREFIX_MAX             48
+#else
 #define PREFIX_MAX             32
+#endif
 #define LOG_LINE_MAX           (1024 - PREFIX_MAX)
 
 #define LOG_LEVEL(v)           ((v) & 0x07)
@@ -577,7 +583,7 @@ static u32 truncate_msg(u16 *text_len, u16 *trunc_msg_len,
 }
 
 /* insert record into the buffer, discard old ones, update heads */
-static int log_store(int facility, int level,
+static int log_store(u32 caller_id, int facility, int level,
                     enum log_flags flags, u64 ts_nsec,
                     const char *dict, u16 dict_len,
                     const char *text, u16 text_len)
@@ -625,6 +631,9 @@ static int log_store(int facility, int level,
                msg->ts_nsec = ts_nsec;
        else
                msg->ts_nsec = local_clock();
+#ifdef CONFIG_PRINTK_CALLER
+       msg->caller_id = caller_id;
+#endif
        memset(log_dict(msg) + dict_len, 0, pad_len);
        msg->len = size;
 
@@ -688,12 +697,21 @@ static ssize_t msg_print_ext_header(char *buf, size_t size,
                                    struct printk_log *msg, u64 seq)
 {
        u64 ts_usec = msg->ts_nsec;
+       char caller[20];
+#ifdef CONFIG_PRINTK_CALLER
+       u32 id = msg->caller_id;
+
+       snprintf(caller, sizeof(caller), ",caller=%c%u",
+                id & 0x80000000 ? 'C' : 'T', id & ~0x80000000);
+#else
+       caller[0] = '\0';
+#endif
 
        do_div(ts_usec, 1000);
 
-       return scnprintf(buf, size, "%u,%llu,%llu,%c;",
-                      (msg->facility << 3) | msg->level, seq, ts_usec,
-                      msg->flags & LOG_CONT ? 'c' : '-');
+       return scnprintf(buf, size, "%u,%llu,%llu,%c%s;",
+                        (msg->facility << 3) | msg->level, seq, ts_usec,
+                        msg->flags & LOG_CONT ? 'c' : '-', caller);
 }
 
 static ssize_t msg_print_ext_body(char *buf, size_t size,
@@ -1038,6 +1056,9 @@ void log_buf_vmcoreinfo_setup(void)
        VMCOREINFO_OFFSET(printk_log, len);
        VMCOREINFO_OFFSET(printk_log, text_len);
        VMCOREINFO_OFFSET(printk_log, dict_len);
+#ifdef CONFIG_PRINTK_CALLER
+       VMCOREINFO_OFFSET(printk_log, caller_id);
+#endif
 }
 #endif
 
@@ -1236,10 +1257,23 @@ static size_t print_time(u64 ts, char *buf)
 {
        unsigned long rem_nsec = do_div(ts, 1000000000);
 
-       return sprintf(buf, "[%5lu.%06lu] ",
+       return sprintf(buf, "[%5lu.%06lu]",
                       (unsigned long)ts, rem_nsec / 1000);
 }
 
+#ifdef CONFIG_PRINTK_CALLER
+static size_t print_caller(u32 id, char *buf)
+{
+       char caller[12];
+
+       snprintf(caller, sizeof(caller), "%c%u",
+                id & 0x80000000 ? 'C' : 'T', id & ~0x80000000);
+       return sprintf(buf, "[%6s]", caller);
+}
+#else
+#define print_caller(id, buf) 0
+#endif
+
 static size_t print_prefix(const struct printk_log *msg, bool syslog,
                           bool time, char *buf)
 {
@@ -1247,8 +1281,17 @@ static size_t print_prefix(const struct printk_log *msg, bool syslog,
 
        if (syslog)
                len = print_syslog((msg->facility << 3) | msg->level, buf);
+
        if (time)
                len += print_time(msg->ts_nsec, buf + len);
+
+       len += print_caller(msg->caller_id, buf + len);
+
+       if (IS_ENABLED(CONFIG_PRINTK_CALLER) || time) {
+               buf[len++] = ' ';
+               buf[len] = '\0';
+       }
+
        return len;
 }
 
@@ -1752,6 +1795,12 @@ static inline void printk_delay(void)
        }
 }
 
+static inline u32 printk_caller_id(void)
+{
+       return in_task() ? task_pid_nr(current) :
+               0x80000000 + raw_smp_processor_id();
+}
+
 /*
  * Continuation lines are buffered, and not committed to the record buffer
  * until the line is complete, or a race forces it. The line fragments
@@ -1761,7 +1810,7 @@ static inline void printk_delay(void)
 static struct cont {
        char buf[LOG_LINE_MAX];
        size_t len;                     /* length == 0 means unused buffer */
-       struct task_struct *owner;      /* task of first print*/
+       u32 caller_id;                  /* printk_caller_id() of first print */
        u64 ts_nsec;                    /* time of first print */
        u8 level;                       /* log level of first message */
        u8 facility;                    /* log facility of first message */
@@ -1773,12 +1822,13 @@ static void cont_flush(void)
        if (cont.len == 0)
                return;
 
-       log_store(cont.facility, cont.level, cont.flags, cont.ts_nsec,
-                 NULL, 0, cont.buf, cont.len);
+       log_store(cont.caller_id, cont.facility, cont.level, cont.flags,
+                 cont.ts_nsec, NULL, 0, cont.buf, cont.len);
        cont.len = 0;
 }
 
-static bool cont_add(int facility, int level, enum log_flags flags, const char *text, size_t len)
+static bool cont_add(u32 caller_id, int facility, int level,
+                    enum log_flags flags, const char *text, size_t len)
 {
        /* If the line gets too long, split it up in separate records. */
        if (cont.len + len > sizeof(cont.buf)) {
@@ -1789,7 +1839,7 @@ static bool cont_add(int facility, int level, enum log_flags flags, const char *
        if (!cont.len) {
                cont.facility = facility;
                cont.level = level;
-               cont.owner = current;
+               cont.caller_id = caller_id;
                cont.ts_nsec = local_clock();
                cont.flags = flags;
        }
@@ -1809,13 +1859,15 @@ static bool cont_add(int facility, int level, enum log_flags flags, const char *
 
 static size_t log_output(int facility, int level, enum log_flags lflags, const char *dict, size_t dictlen, char *text, size_t text_len)
 {
+       const u32 caller_id = printk_caller_id();
+
        /*
         * If an earlier line was buffered, and we're a continuation
-        * write from the same process, try to add it to the buffer.
+        * write from the same context, try to add it to the buffer.
         */
        if (cont.len) {
-               if (cont.owner == current && (lflags & LOG_CONT)) {
-                       if (cont_add(facility, level, lflags, text, text_len))
+               if (cont.caller_id == caller_id && (lflags & LOG_CONT)) {
+                       if (cont_add(caller_id, facility, level, lflags, text, text_len))
                                return text_len;
                }
                /* Otherwise, make sure it's flushed */
@@ -1828,12 +1880,13 @@ static size_t log_output(int facility, int level, enum log_flags lflags, const c
 
        /* If it doesn't end in a newline, try to buffer the current line */
        if (!(lflags & LOG_NEWLINE)) {
-               if (cont_add(facility, level, lflags, text, text_len))
+               if (cont_add(caller_id, facility, level, lflags, text, text_len))
                        return text_len;
        }
 
        /* Store it in the record log */
-       return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len);
+       return log_store(caller_id, facility, level, lflags, 0,
+                        dict, dictlen, text, text_len);
 }
 
 /* Must be called under logbuf_lock. */
@@ -1867,9 +1920,6 @@ int vprintk_store(int facility, int level,
                        case '0' ... '7':
                                if (level == LOGLEVEL_DEFAULT)
                                        level = kern_level - '0';
-                               /* fallthrough */
-                       case 'd':       /* KERN_DEFAULT */
-                               lflags |= LOG_PREFIX;
                                break;
                        case 'c':       /* KERN_CONT */
                                lflags |= LOG_CONT;
@@ -1884,7 +1934,7 @@ int vprintk_store(int facility, int level,
                level = default_message_loglevel;
 
        if (dict)
-               lflags |= LOG_PREFIX|LOG_NEWLINE;
+               lflags |= LOG_NEWLINE;
 
        return log_output(facility, level, lflags,
                          dict, dictlen, text, text_len);