@user->seq is indirectly protected by @logbuf_lock. Once @logbuf_lock
is removed, @user->seq will be no longer safe from an atomicity point
of view.

In preparation for the removal of @logbuf_lock, change it to
atomic64_t to provide this safety.

Signed-off-by: John Ogness <john.ogn...@linutronix.de>
Reviewed-by: Petr Mladek <pmla...@suse.com>
---
 kernel/printk/printk.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index b78b85947312..82d89eec4aac 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -662,7 +662,7 @@ static ssize_t msg_print_ext_body(char *buf, size_t size,
 
 /* /dev/kmsg - userspace message inject/listen interface */
 struct devkmsg_user {
-       u64 seq;
+       atomic64_t seq;
        struct ratelimit_state rs;
        struct mutex lock;
        char buf[CONSOLE_EXT_LOG_MAX];
@@ -763,7 +763,7 @@ static ssize_t devkmsg_read(struct file *file, char __user 
*buf,
                return ret;
 
        logbuf_lock_irq();
-       if (!prb_read_valid(prb, user->seq, r)) {
+       if (!prb_read_valid(prb, atomic64_read(&user->seq), r)) {
                if (file->f_flags & O_NONBLOCK) {
                        ret = -EAGAIN;
                        logbuf_unlock_irq();
@@ -772,15 +772,15 @@ static ssize_t devkmsg_read(struct file *file, char 
__user *buf,
 
                logbuf_unlock_irq();
                ret = wait_event_interruptible(log_wait,
-                                       prb_read_valid(prb, user->seq, r));
+                               prb_read_valid(prb, atomic64_read(&user->seq), 
r));
                if (ret)
                        goto out;
                logbuf_lock_irq();
        }
 
-       if (r->info->seq != user->seq) {
+       if (r->info->seq != atomic64_read(&user->seq)) {
                /* our last seen message is gone, return error and reset */
-               user->seq = r->info->seq;
+               atomic64_set(&user->seq, r->info->seq);
                ret = -EPIPE;
                logbuf_unlock_irq();
                goto out;
@@ -791,7 +791,7 @@ static ssize_t devkmsg_read(struct file *file, char __user 
*buf,
                                  &r->text_buf[0], r->info->text_len,
                                  &r->info->dev_info);
 
-       user->seq = r->info->seq + 1;
+       atomic64_set(&user->seq, r->info->seq + 1);
        logbuf_unlock_irq();
 
        if (len > count) {
@@ -831,7 +831,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t 
offset, int whence)
        switch (whence) {
        case SEEK_SET:
                /* the first record */
-               user->seq = prb_first_valid_seq(prb);
+               atomic64_set(&user->seq, prb_first_valid_seq(prb));
                break;
        case SEEK_DATA:
                /*
@@ -839,11 +839,11 @@ static loff_t devkmsg_llseek(struct file *file, loff_t 
offset, int whence)
                 * like issued by 'dmesg -c'. Reading /dev/kmsg itself
                 * changes no global state, and does not clear anything.
                 */
-               user->seq = latched_seq_read_nolock(&clear_seq);
+               atomic64_set(&user->seq, latched_seq_read_nolock(&clear_seq));
                break;
        case SEEK_END:
                /* after the last record */
-               user->seq = prb_next_seq(prb);
+               atomic64_set(&user->seq, prb_next_seq(prb));
                break;
        default:
                ret = -EINVAL;
@@ -864,9 +864,9 @@ static __poll_t devkmsg_poll(struct file *file, poll_table 
*wait)
        poll_wait(file, &log_wait, wait);
 
        logbuf_lock_irq();
-       if (prb_read_valid_info(prb, user->seq, &info, NULL)) {
+       if (prb_read_valid_info(prb, atomic64_read(&user->seq), &info, NULL)) {
                /* return error when data has vanished underneath us */
-               if (info.seq != user->seq)
+               if (info.seq != atomic64_read(&user->seq))
                        ret = EPOLLIN|EPOLLRDNORM|EPOLLERR|EPOLLPRI;
                else
                        ret = EPOLLIN|EPOLLRDNORM;
@@ -905,7 +905,7 @@ static int devkmsg_open(struct inode *inode, struct file 
*file)
                        &user->text_buf[0], sizeof(user->text_buf));
 
        logbuf_lock_irq();
-       user->seq = prb_first_valid_seq(prb);
+       atomic64_set(&user->seq, prb_first_valid_seq(prb));
        logbuf_unlock_irq();
 
        file->private_data = user;
-- 
2.20.1

Reply via email to