ve_printk() corrupts host's dmesg:
        # dmesg|wc -l
        599
        # vzctl create 101
        # vzctl set 101 --netif_add eth0 --save
        # vzctl start 101
        # vzctl exec 101 'tcpdump -w tcpdump.out -U -n -i eth0 esp'
        # dmesg|wc -l
        2

Add missing parts of prinkt virtualization to fix this.

https://jira.sw.ru/browse/PSBM-17899
https://jira.sw.ru/browse/PSBM-105442
Fixes: 7c0dae2429 ("ve/printk: printk virtualization")
Signed-off-by: Andrey Ryabinin <aryabi...@virtuozzo.com>
---
 Changes since v1:
 - rebase on new branch

 kernel/printk/printk.c | 86 +++++++++++++++++++++++++-----------------
 1 file changed, 52 insertions(+), 34 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 50e3921d5f1d..bcbae4948cff 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -544,23 +544,23 @@ static char *log_dict(const struct printk_log *msg)
 }
 
 /* get record by index; idx must point to valid msg */
-static struct printk_log *log_from_idx(u32 idx)
+static struct printk_log *log_from_idx(struct log_state *log, u32 idx)
 {
-       struct printk_log *msg = (struct printk_log *)(log_buf + idx);
+       struct printk_log *msg = (struct printk_log *)(log->buf + idx);
 
        /*
         * A length == 0 record is the end of buffer marker. Wrap around and
         * read the message at the start of the buffer.
         */
        if (!msg->len)
-               return (struct printk_log *)log_buf;
+               return (struct printk_log *)log->buf;
        return msg;
 }
 
 /* get next record; idx must point to valid msg */
-static u32 log_next(u32 idx)
+static u32 log_next(struct log_state *log, u32 idx)
 {
-       struct printk_log *msg = (struct printk_log *)(log_buf + idx);
+       struct printk_log *msg = (struct printk_log *)(log->buf + idx);
 
        /* length == 0 indicates the end of the buffer; wrap */
        /*
@@ -569,7 +569,7 @@ static u32 log_next(u32 idx)
         * return the one after that.
         */
        if (!msg->len) {
-               msg = (struct printk_log *)log_buf;
+               msg = (struct printk_log *)log->buf;
                return msg->len;
        }
        return idx + msg->len;
@@ -607,7 +607,7 @@ static int log_make_free_space(struct log_state *log,
        while (log->first_seq < log->next_seq &&
               !logbuf_has_space(log, msg_size, false)) {
                /* drop old messages until we have enough contiguous space */
-               log->first_idx = log_next(log->first_idx);
+               log->first_idx = log_next(log, log->first_idx);
                log->first_seq++;
        }
 
@@ -691,12 +691,12 @@ static int log_store(struct log_state *log,
                 * at the end of the buffer. Add an empty header with len == 0
                 * to signify a wrap around.
                 */
-               memset(log_buf + log->next_idx, 0, sizeof(struct printk_log));
+               memset(log->buf + log->next_idx, 0, sizeof(struct printk_log));
                log->next_idx = 0;
        }
 
        /* fill message */
-       msg = (struct printk_log *)(log_buf + log->next_idx);
+       msg = (struct printk_log *)(log->buf + log->next_idx);
        memcpy(log_text(msg), text, text_len);
        msg->text_len = text_len;
        if (trunc_msg_len) {
@@ -969,14 +969,14 @@ static ssize_t devkmsg_read(struct file *file, char 
__user *buf,
                goto out;
        }
 
-       msg = log_from_idx(user->idx);
+       msg = log_from_idx(log, user->idx);
        len = msg_print_ext_header(user->buf, sizeof(user->buf),
                                   msg, user->seq);
        len += msg_print_ext_body(user->buf + len, sizeof(user->buf) - len,
                                  log_dict(msg), msg->dict_len,
                                  log_text(msg), msg->text_len);
 
-       user->idx = log_next(user->idx);
+       user->idx = log_next(log, user->idx);
        user->seq++;
        logbuf_unlock_irq();
 
@@ -1457,12 +1457,12 @@ static int syslog_print(struct log_state *log,
                        log->syslog_time = printk_time;
 
                skip = log->syslog_partial;
-               msg = log_from_idx(log->syslog_idx);
+               msg = log_from_idx(log, log->syslog_idx);
                n = msg_print_text(msg, true, log->syslog_time, text,
                                   LOG_LINE_MAX + PREFIX_MAX);
                if (n - log->syslog_partial <= size) {
                        /* message fits into buffer, move forward */
-                       log->syslog_idx = log_next(log->syslog_idx);
+                       log->syslog_idx = log_next(log, log->syslog_idx);
                        log->syslog_seq++;
                        n -= log->syslog_partial;
                        log->syslog_partial = 0;
@@ -1515,10 +1515,10 @@ static int syslog_print_all(struct log_state *log,
        seq = log->clear_seq;
        idx = log->clear_idx;
        while (seq < log->next_seq) {
-               struct printk_log *msg = log_from_idx(idx);
+               struct printk_log *msg = log_from_idx(log, idx);
 
                len += msg_print_text(msg, true, time, NULL, 0);
-               idx = log_next(idx);
+               idx = log_next(log, idx);
                seq++;
        }
 
@@ -1526,10 +1526,10 @@ static int syslog_print_all(struct log_state *log,
        seq = log->clear_seq;
        idx = log->clear_idx;
        while (len > size && seq < log->next_seq) {
-               struct printk_log *msg = log_from_idx(idx);
+               struct printk_log *msg = log_from_idx(log, idx);
 
                len -= msg_print_text(msg, true, time, NULL, 0);
-               idx = log_next(idx);
+               idx = log_next(log, idx);
                seq++;
        }
 
@@ -1538,11 +1538,11 @@ static int syslog_print_all(struct log_state *log,
 
        len = 0;
        while (len >= 0 && seq < next_seq) {
-               struct printk_log *msg = log_from_idx(idx);
+               struct printk_log *msg = log_from_idx(log, idx);
                int textlen = msg_print_text(msg, true, time, text,
                                             LOG_LINE_MAX + PREFIX_MAX);
 
-               idx = log_next(idx);
+               idx = log_next(log, idx);
                seq++;
 
                logbuf_unlock_irq();
@@ -1670,12 +1670,12 @@ int do_syslog(int type, char __user *buf, int len, int 
source)
                                    log->syslog_time : printk_time;
 
                        while (seq < log->next_seq) {
-                               struct printk_log *msg = log_from_idx(idx);
+                               struct printk_log *msg = log_from_idx(log, idx);
 
                                error += msg_print_text(msg, true, time, NULL,
                                                        0);
                                time = printk_time;
-                               idx = log_next(idx);
+                               idx = log_next(log, idx);
                                seq++;
                        }
                        error -= log->syslog_partial;
@@ -1970,6 +1970,7 @@ static size_t log_output(struct log_state *log,
 int vprintk_store_log(struct log_state *log, int facility, int level,
                      const char *dict, size_t dictlen,
                      const char *fmt, va_list args)
+
 {
        static char textbuf[LOG_LINE_MAX];
        char *text = textbuf;
@@ -2034,6 +2035,7 @@ asmlinkage int vprintk_emit_log(struct log_state *log,
        bool in_sched = false, pending_output;
        unsigned long flags;
        u64 curr_log_seq;
+       bool need_wake = false;
 
        /* Suppress unimportant messages after panic happens */
        if (unlikely(suppress_printk))
@@ -2068,9 +2070,19 @@ asmlinkage int vprintk_emit_log(struct log_state *log,
                 * semaphore.  The release will print out buffers and wake up
                 * /dev/kmsg and syslog() users.
                 */
-               if (console_trylock_spinning())
+               if (log != &init_log_state) {
+                       logbuf_lock_irqsave(flags);
+                       if (log->seen_seq != log->next_seq && 
!oops_in_progress) {
+                               log->seen_seq = log->next_seq;
+                               need_wake = true;
+                       }
+                       logbuf_unlock_irqrestore(flags);
+               } else if (console_trylock_spinning())
                        console_unlock();
                preempt_enable();
+
+               if (need_wake)
+                       wake_up_interruptible(&log->wait);
        }
 
        if (pending_output)
@@ -2546,14 +2558,14 @@ void console_unlock(void)
                if (log->console_seq == log->next_seq)
                        break;
 
-               msg = log_from_idx(log->console_idx);
+               msg = log_from_idx(log, log->console_idx);
                if (suppress_message_printing(msg->level)) {
                        /*
                         * Skip record we have buffered and already printed
                         * directly to the console when we received it, and
                         * record that has level above the console loglevel.
                         */
-                       log->console_idx = log_next(log->console_idx);
+                       log->console_idx = log_next(log, log->console_idx);
                        log->console_seq++;
                        goto skip;
                }
@@ -2577,7 +2589,7 @@ void console_unlock(void)
                                                log_dict(msg), msg->dict_len,
                                                log_text(msg), msg->text_len);
                }
-               log->console_idx = log_next(log->console_idx);
+               log->console_idx = log_next(log, log->console_idx);
                log->console_seq++;
                raw_spin_unlock(&logbuf_lock);
 
@@ -3305,10 +3317,11 @@ bool kmsg_dump_get_line_nolock(struct kmsg_dumper 
*dumper, bool syslog,
        if (dumper->cur_seq >= log->next_seq)
                goto out;
 
-       msg = log_from_idx(dumper->cur_idx);
+
+       msg = log_from_idx(log, dumper->cur_idx);
        l = msg_print_text(msg, syslog, printk_time, line, size);
 
-       dumper->cur_idx = log_next(dumper->cur_idx);
+       dumper->cur_idx = log_next(log, dumper->cur_idx);
        dumper->cur_seq++;
        ret = true;
 out:
@@ -3400,10 +3413,10 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, 
bool syslog,
        seq = dumper->cur_seq;
        idx = dumper->cur_idx;
        while (seq < dumper->next_seq) {
-               struct printk_log *msg = log_from_idx(idx);
+               struct printk_log *msg = log_from_idx(log, idx);
 
                l += msg_print_text(msg, true, time, NULL, 0);
-               idx = log_next(idx);
+               idx = log_next(log, idx);
                seq++;
        }
 
@@ -3411,10 +3424,10 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, 
bool syslog,
        seq = dumper->cur_seq;
        idx = dumper->cur_idx;
        while (l > size && seq < dumper->next_seq) {
-               struct printk_log *msg = log_from_idx(idx);
+               struct printk_log *msg = log_from_idx(log, idx);
 
                l -= msg_print_text(msg, true, time, NULL, 0);
-               idx = log_next(idx);
+               idx = log_next(log, idx);
                seq++;
        }
 
@@ -3424,10 +3437,10 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, 
bool syslog,
 
        l = 0;
        while (seq < dumper->next_seq) {
-               struct printk_log *msg = log_from_idx(idx);
+               struct printk_log *msg = log_from_idx(log, idx);
 
                l += msg_print_text(msg, syslog, time, buf + l, size - l);
-               idx = log_next(idx);
+               idx = log_next(log, idx);
                seq++;
        }
 
@@ -3491,7 +3504,12 @@ int ve_log_init(struct ve_struct *ve)
 
        init_waitqueue_head(&log->wait);
        log->buf_len = VE_LOG_BUF_LEN;
-       /* buf will be initialized later by log_state_init() */
+
+       log->buf = kzalloc(log->buf_len, GFP_KERNEL);
+       if (!log->buf) {
+               kfree(log);
+               return -ENOMEM;
+       }
 
        ve->log_state = log;
        return 0;
-- 
2.26.2

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to