Skip to content

Commit 636babd

Browse files
jognesspmladek
authored andcommitted
printk: add syslog_lock
The global variables @syslog_seq, @syslog_partial, @syslog_time and write access to @clear_seq are protected by @logbuf_lock. Once @logbuf_lock is removed, these variables will need their own synchronization method. Introduce @syslog_lock for this purpose. @syslog_lock is a raw_spin_lock for now. This simplifies the transition to removing @logbuf_lock. Once @logbuf_lock and the safe buffers are removed, @syslog_lock can change to spin_lock. Signed-off-by: John Ogness <[email protected]> Reviewed-by: Petr Mladek <[email protected]> Signed-off-by: Petr Mladek <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 35b2b16 commit 636babd

File tree

1 file changed

+37
-4
lines changed

1 file changed

+37
-4
lines changed

kernel/printk/printk.c

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,12 @@ DEFINE_RAW_SPINLOCK(logbuf_lock);
390390
printk_safe_exit_irqrestore(flags); \
391391
} while (0)
392392

393+
/* syslog_lock protects syslog_* variables and write access to clear_seq. */
394+
static DEFINE_RAW_SPINLOCK(syslog_lock);
395+
393396
#ifdef CONFIG_PRINTK
394397
DECLARE_WAIT_QUEUE_HEAD(log_wait);
398+
/* All 3 protected by @syslog_lock. */
395399
/* the next printk record to read by syslog(READ) or /proc/kmsg */
396400
static u64 syslog_seq;
397401
static size_t syslog_partial;
@@ -410,7 +414,7 @@ struct latched_seq {
410414
/*
411415
* The next printk record to read after the last 'clear' command. There are
412416
* two copies (updated with seqcount_latch) so that reads can locklessly
413-
* access a valid value. Writers are synchronized by @logbuf_lock.
417+
* access a valid value. Writers are synchronized by @syslog_lock.
414418
*/
415419
static struct latched_seq clear_seq = {
416420
.latch = SEQCNT_LATCH_ZERO(clear_seq.latch),
@@ -470,7 +474,7 @@ bool printk_percpu_data_ready(void)
470474
return __printk_percpu_data_ready;
471475
}
472476

473-
/* Must be called under logbuf_lock. */
477+
/* Must be called under syslog_lock. */
474478
static void latched_seq_write(struct latched_seq *ls, u64 val)
475479
{
476480
raw_write_seqcount_latch(&ls->latch);
@@ -1529,7 +1533,9 @@ static int syslog_print(char __user *buf, int size)
15291533
size_t skip;
15301534

15311535
logbuf_lock_irq();
1536+
raw_spin_lock(&syslog_lock);
15321537
if (!prb_read_valid(prb, syslog_seq, &r)) {
1538+
raw_spin_unlock(&syslog_lock);
15331539
logbuf_unlock_irq();
15341540
break;
15351541
}
@@ -1559,6 +1565,7 @@ static int syslog_print(char __user *buf, int size)
15591565
syslog_partial += n;
15601566
} else
15611567
n = 0;
1568+
raw_spin_unlock(&syslog_lock);
15621569
logbuf_unlock_irq();
15631570

15641571
if (!n)
@@ -1625,8 +1632,11 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
16251632
break;
16261633
}
16271634

1628-
if (clear)
1635+
if (clear) {
1636+
raw_spin_lock(&syslog_lock);
16291637
latched_seq_write(&clear_seq, seq);
1638+
raw_spin_unlock(&syslog_lock);
1639+
}
16301640
logbuf_unlock_irq();
16311641

16321642
kfree(text);
@@ -1636,10 +1646,24 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
16361646
static void syslog_clear(void)
16371647
{
16381648
logbuf_lock_irq();
1649+
raw_spin_lock(&syslog_lock);
16391650
latched_seq_write(&clear_seq, prb_next_seq(prb));
1651+
raw_spin_unlock(&syslog_lock);
16401652
logbuf_unlock_irq();
16411653
}
16421654

1655+
/* Return a consistent copy of @syslog_seq. */
1656+
static u64 read_syslog_seq_irq(void)
1657+
{
1658+
u64 seq;
1659+
1660+
raw_spin_lock_irq(&syslog_lock);
1661+
seq = syslog_seq;
1662+
raw_spin_unlock_irq(&syslog_lock);
1663+
1664+
return seq;
1665+
}
1666+
16431667
int do_syslog(int type, char __user *buf, int len, int source)
16441668
{
16451669
struct printk_info info;
@@ -1663,8 +1687,9 @@ int do_syslog(int type, char __user *buf, int len, int source)
16631687
return 0;
16641688
if (!access_ok(buf, len))
16651689
return -EFAULT;
1690+
16661691
error = wait_event_interruptible(log_wait,
1667-
prb_read_valid(prb, syslog_seq, NULL));
1692+
prb_read_valid(prb, read_syslog_seq_irq(), NULL));
16681693
if (error)
16691694
return error;
16701695
error = syslog_print(buf, len);
@@ -1713,8 +1738,10 @@ int do_syslog(int type, char __user *buf, int len, int source)
17131738
/* Number of chars in the log buffer */
17141739
case SYSLOG_ACTION_SIZE_UNREAD:
17151740
logbuf_lock_irq();
1741+
raw_spin_lock(&syslog_lock);
17161742
if (!prb_read_valid_info(prb, syslog_seq, &info, NULL)) {
17171743
/* No unread messages. */
1744+
raw_spin_unlock(&syslog_lock);
17181745
logbuf_unlock_irq();
17191746
return 0;
17201747
}
@@ -1743,6 +1770,7 @@ int do_syslog(int type, char __user *buf, int len, int source)
17431770
}
17441771
error -= syslog_partial;
17451772
}
1773+
raw_spin_unlock(&syslog_lock);
17461774
logbuf_unlock_irq();
17471775
break;
17481776
/* Size of the log buffer */
@@ -2992,7 +3020,12 @@ void register_console(struct console *newcon)
29923020
*/
29933021
exclusive_console = newcon;
29943022
exclusive_console_stop_seq = console_seq;
3023+
3024+
/* Get a consistent copy of @syslog_seq. */
3025+
raw_spin_lock(&syslog_lock);
29953026
console_seq = syslog_seq;
3027+
raw_spin_unlock(&syslog_lock);
3028+
29963029
logbuf_unlock_irqrestore(flags);
29973030
}
29983031
console_unlock();

0 commit comments

Comments
 (0)