The commit is pushed to "branch-rh9-5.14.vz9.1.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after ark-5.14 ------> commit d04759114253d359ae2eda81a0664b912e95ec7c Author: Konstantin Khorenko <khore...@virtuozzo.com> Date: Thu Sep 30 21:40:37 2021 +0300
ve/printk: Virtualize log_wait queue https://jira.sw.ru/browse/PSBM-17899 Signed-off-by: Vladimir Davydov <vdavy...@parallels.com> Signed-off-by: Stanislav Kinsburskiy <skinsbur...@virtuozzo.com> +++ ve/printk: Fix printk virtualization 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 Signed-off-by: Andrey Ryabinin <aryabi...@virtuozzo.com> Rebasing to vz9: part of vz8 commit: d63aeb311a64 ("ve/printk: printk virtualization") https://jira.sw.ru/browse/PSBM-133985 Note: we don't wake up wait_queue if vprintk_emit_log() has been called in sched context. Rare case, we've lived that way forever. Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com> --- fs/proc/kmsg.c | 4 ++-- kernel/printk/printk.c | 60 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index b38ad552887f..386ec85dea0f 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c @@ -18,7 +18,7 @@ #include <linux/uaccess.h> #include <asm/io.h> -extern wait_queue_head_t log_wait; +extern void log_poll_wait(struct file *file, poll_table *wait); static int kmsg_open(struct inode * inode, struct file * file) { @@ -42,7 +42,7 @@ static ssize_t kmsg_read(struct file *file, char __user *buf, static __poll_t kmsg_poll(struct file *file, poll_table *wait) { - poll_wait(file, &log_wait, wait); + log_poll_wait(file, wait); if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_PROC)) return EPOLLIN | EPOLLRDNORM; return 0; diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 04244a3edeab..7f1bec17866d 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -360,7 +360,6 @@ enum log_flags { static DEFINE_RAW_SPINLOCK(syslog_lock); #ifdef CONFIG_PRINTK -DECLARE_WAIT_QUEUE_HEAD(log_wait); struct latched_seq { seqcount_latch_t latch; @@ -419,6 +418,8 @@ static struct log_state { u64 exclusive_console_stop_seq; unsigned long console_dropped; + wait_queue_head_t wait; + /* * The next printk record to read after the last 'clear' command. There are * two copies (updated with seqcount_latch) so that reads can locklessly @@ -429,6 +430,7 @@ static struct log_state { } init_log_state = { .buf = __log_buf, .buf_len = __LOG_BUF_LEN, + .wait = __WAIT_QUEUE_HEAD_INITIALIZER(init_log_state.wait), .clear_seq = { .latch = SEQCNT_LATCH_ZERO(init_log_state.clear_seq.latch), .val[0] = 0, @@ -460,6 +462,11 @@ static inline struct log_state *ve_log_state(void) return log; } +void log_poll_wait(struct file *filp, poll_table *p) +{ + poll_wait(filp, &ve_log_state()->wait, p); +} + /* * We cannot access per-CPU data (e.g. per-CPU flush irq_work) before * per_cpu_areas are initialised. This variable is set to true when @@ -782,7 +789,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, } printk_safe_exit_irq(); - ret = wait_event_interruptible(log_wait, + ret = wait_event_interruptible(log->wait, prb_read_valid(log->prb, atomic64_read(&user->seq), r)); if (ret) goto out; @@ -874,7 +881,7 @@ static __poll_t devkmsg_poll(struct file *file, poll_table *wait) if (!user) return EPOLLERR|EPOLLNVAL; - poll_wait(file, &log_wait, wait); + poll_wait(file, &log->wait, wait); printk_safe_enter_irq(); if (prb_read_valid_info(log->prb, atomic64_read(&user->seq), &info, NULL)) { @@ -1705,7 +1712,7 @@ int do_syslog(int type, char __user *buf, int len, int source) if (!access_ok(buf, len)) return -EFAULT; - error = wait_event_interruptible(log_wait, + error = wait_event_interruptible(log->wait, prb_read_valid(log->prb, read_syslog_seq_irq(), NULL)); if (error) return error; @@ -2220,20 +2227,29 @@ asmlinkage int vprintk_emit_log(struct log_state *log, /* If called from the scheduler, we can not call up(). */ if (!in_sched) { - /* - * Disable preemption to avoid being preempted while holding - * console_sem which would prevent anyone from printing to - * console - */ - preempt_disable(); - /* - * Try to acquire and then immediately release the console - * semaphore. The release will print out buffers and wake up - * /dev/kmsg and syslog() users. - */ - if (console_trylock_spinning()) - console_unlock(); - preempt_enable(); + if (log == &init_log_state) { + /* + * Disable preemption to avoid being preempted while holding + * console_sem which would prevent anyone from printing to + * console + */ + preempt_disable(); + /* + * Try to acquire and then immediately release the console + * semaphore. The release will print out buffers and wake up + * /dev/kmsg and syslog() users. + */ + if (console_trylock_spinning()) + console_unlock(); + preempt_enable(); + } else { + /* + * For (in_sched) case we need to wake up via + * irq_work_queue(), so ... let's just wake up only in + * (!in_sched) case for now. + */ + wake_up_interruptible(&log->wait); + } } wake_up_klogd(); @@ -3230,6 +3246,7 @@ static DEFINE_PER_CPU(int, printk_pending); static void wake_up_klogd_work_func(struct irq_work *irq_work) { + struct log_state *log = &init_log_state; int pending = __this_cpu_xchg(printk_pending, 0); if (pending & PRINTK_PENDING_OUTPUT) { @@ -3239,7 +3256,7 @@ static void wake_up_klogd_work_func(struct irq_work *irq_work) } if (pending & PRINTK_PENDING_WAKEUP) - wake_up_interruptible(&log_wait); + wake_up_interruptible(&log->wait); } static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = @@ -3247,11 +3264,13 @@ static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = void wake_up_klogd(void) { + struct log_state *log = &init_log_state; + if (!printk_percpu_data_ready()) return; preempt_disable(); - if (waitqueue_active(&log_wait)) { + if (waitqueue_active(&log->wait)) { this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); irq_work_queue(this_cpu_ptr(&wake_up_klogd_work)); } @@ -3696,6 +3715,7 @@ int ve_log_init(struct ve_struct *ve) return ret; } + init_waitqueue_head(&log->wait); seqcount_latch_init(&log->clear_seq.latch); ve->log_state = log; _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel