History

printk: convert @syslog_lock to mutex

@syslog_lock was a raw_spin_lock to simplify the transition of removing @logbuf_lock and the safe buffers. With that transition complete, and since all uses of @syslog_lock are within sleepable contexts, @syslog_lock can become a mutex. Note that until now register_console() would disable interrupts using irqsave, which implies that it may be called with interrupts disabled. And indeed, there is one possible call chain on parisc where this happens: handle_interruption(code=1) /* High-priority machine check (HPMC) */ pdc_console_restart() pdc_console_init_force() register_console() However, register_console() calls console_lock(), which might sleep. So it has never been allowed to call register_console() from an atomic context and the above call chain is a bug. Note that the removal of read_syslog_seq_irq() is slightly changing the behavior of SYSLOG_ACTION_READ by testing against a possibly outdated @seq value. However, the value of @seq could have changed after the test, so it is not a new window. A follow-up commit closes this window.

John Ogness committed 5 years ago

Commit b371cbb1 parent 85e3e7f1 file · +20 −29Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/printk/printk.c+20−29
@@ -356,7 +356,7 @@ enum log_flags { · 355 unmodified lines
356356 };
357357
358358 /* syslog_lock protects syslog_* variables and write access to clear_seq. */
359−static DEFINE_RAW_SPINLOCK(syslog_lock);
359+static DEFINE_MUTEX(syslog_lock);
360360
361361 #ifdef CONFIG_PRINTK
362362 DECLARE_WAIT_QUEUE_HEAD(log_wait);
@@ -1497,9 +1497,9 @@ static int syslog_print(char __user *buf, int size) · 1134 unmodified lines
14971497 size_t n;
14981498 size_t skip;
14991499
1500− raw_spin_lock_irq(&syslog_lock);
1500+ mutex_lock(&syslog_lock);
15011501 if (!prb_read_valid(prb, syslog_seq, &r)) {
1502− raw_spin_unlock_irq(&syslog_lock);
1502+ mutex_unlock(&syslog_lock);
15031503 break;
15041504 }
15051505 if (r.info->seq != syslog_seq) {
@@ -1528,7 +1528,7 @@ static int syslog_print(char __user *buf, int size) · 22 unmodified lines
15281528 syslog_partial += n;
15291529 } else
15301530 n = 0;
1531− raw_spin_unlock_irq(&syslog_lock);
1531+ mutex_unlock(&syslog_lock);
15321532
15331533 if (!n)
15341534 break;
@@ -1592,9 +1592,9 @@ static int syslog_print_all(char __user *buf, int size, bool clear) · 57 unmodified lines
15921592 }
15931593
15941594 if (clear) {
1595− raw_spin_lock_irq(&syslog_lock);
1595+ mutex_lock(&syslog_lock);
15961596 latched_seq_write(&clear_seq, seq);
1597− raw_spin_unlock_irq(&syslog_lock);
1597+ mutex_unlock(&syslog_lock);
15981598 }
15991599
16001600 kfree(text);
@@ -1603,21 +1603,9 @@ static int syslog_print_all(char __user *buf, int size, bool clear) · 2 unmodified lines
16031603
16041604 static void syslog_clear(void)
16051605 {
1606− raw_spin_lock_irq(&syslog_lock);
1606+ mutex_lock(&syslog_lock);
16071607 latched_seq_write(&clear_seq, prb_next_seq(prb));
1608− raw_spin_unlock_irq(&syslog_lock);
1609−}
1610−
1611−/* Return a consistent copy of @syslog_seq. */
1612−static u64 read_syslog_seq_irq(void)
1613−{
1614− u64 seq;
1615−
1616− raw_spin_lock_irq(&syslog_lock);
1617− seq = syslog_seq;
1618− raw_spin_unlock_irq(&syslog_lock);
1619−
1620− return seq;
1608+ mutex_unlock(&syslog_lock);
16211609 }
16221610
16231611 int do_syslog(int type, char __user *buf, int len, int source)
@@ -1626,6 +1614,7 @@ int do_syslog(int type, char __user *buf, int len, int source) · 2 unmodified lines
16261614 bool clear = false;
16271615 static int saved_console_loglevel = LOGLEVEL_DEFAULT;
16281616 int error;
1617+ u64 seq;
16291618
16301619 error = check_syslog_permissions(type, source);
16311620 if (error)
@@ -1644,8 +1633,12 @@ int do_syslog(int type, char __user *buf, int len, int source) · 12 unmodified lines
16441633 if (!access_ok(buf, len))
16451634 return -EFAULT;
16461635
1647− error = wait_event_interruptible(log_wait,
1648− prb_read_valid(prb, read_syslog_seq_irq(), NULL));
1636+ /* Get a consistent copy of @syslog_seq. */
1637+ mutex_lock(&syslog_lock);
1638+ seq = syslog_seq;
1639+ mutex_unlock(&syslog_lock);
1640+
1641+ error = wait_event_interruptible(log_wait, prb_read_valid(prb, seq, NULL));
16491642 if (error)
16501643 return error;
16511644 error = syslog_print(buf, len);
@@ -1693,10 +1686,10 @@ int do_syslog(int type, char __user *buf, int len, int source) · 41 unmodified lines
16931686 break;
16941687 /* Number of chars in the log buffer */
16951688 case SYSLOG_ACTION_SIZE_UNREAD:
1696− raw_spin_lock_irq(&syslog_lock);
1689+ mutex_lock(&syslog_lock);
16971690 if (!prb_read_valid_info(prb, syslog_seq, &info, NULL)) {
16981691 /* No unread messages. */
1699− raw_spin_unlock_irq(&syslog_lock);
1692+ mutex_unlock(&syslog_lock);
17001693 return 0;
17011694 }
17021695 if (info.seq != syslog_seq) {
@@ -1714,7 +1707,6 @@ int do_syslog(int type, char __user *buf, int len, int source) · 11 unmodified lines
17141707 } else {
17151708 bool time = syslog_partial ? syslog_time : printk_time;
17161709 unsigned int line_count;
1717− u64 seq;
17181710
17191711 prb_for_each_info(syslog_seq, prb, seq, &info,
17201712 &line_count) {
@@ -1724,7 +1716,7 @@ int do_syslog(int type, char __user *buf, int len, int source) · 3 unmodified lines
17241716 }
17251717 error -= syslog_partial;
17261718 }
1727− raw_spin_unlock_irq(&syslog_lock);
1719+ mutex_unlock(&syslog_lock);
17281720 break;
17291721 /* Size of the log buffer */
17301722 case SYSLOG_ACTION_SIZE_BUFFER:
@@ -2929,7 +2921,6 @@ static int try_enable_new_console(struct console *newcon, bool user_specified) · 1198 unmodified lines
29292921 */
29302922 void register_console(struct console *newcon)
29312923 {
2932− unsigned long flags;
29332924 struct console *bcon = NULL;
29342925 int err;
29352926
@@ -3034,9 +3025,9 @@ void register_console(struct console *newcon) · 98 unmodified lines
30343025 exclusive_console_stop_seq = console_seq;
30353026
30363027 /* Get a consistent copy of @syslog_seq. */
3037− raw_spin_lock_irqsave(&syslog_lock, flags);
3028+ mutex_lock(&syslog_lock);
30383029 console_seq = syslog_seq;
3039− raw_spin_unlock_irqrestore(&syslog_lock, flags);
3030+ mutex_unlock(&syslog_lock);
30403031 }
30413032 console_unlock();
30423033 console_sysfs_notify();

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t