Skip to content

Commit de6fcbd

Browse files
sergey-senozhatskypmladek
authored andcommitted
printk: convert the rest to printk-safe
This patch converts the rest of logbuf users (which are out of printk recursion case, but can deadlock in printk). To make printk-safe usage easier the patch introduces 4 helper macros: - logbuf_lock_irq()/logbuf_unlock_irq() lock/unlock the logbuf lock and disable/enable local IRQ - logbuf_lock_irqsave(flags)/logbuf_unlock_irqrestore(flags) lock/unlock the logbuf lock and saves/restores local IRQ state Link: http://lkml.kernel.org/r/20161227141611.940-9-sergey.senozhatsky@gmail.com Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Jan Kara <jack@suse.cz> Cc: Tejun Heo <tj@kernel.org> Cc: Calvin Owens <calvinowens@fb.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Peter Hurley <peter@hurleysoftware.com> Cc: linux-kernel@vger.kernel.org Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Signed-off-by: Petr Mladek <pmladek@suse.com>
1 parent 8b1742c commit de6fcbd

File tree

1 file changed

+65
-38
lines changed

1 file changed

+65
-38
lines changed

kernel/printk/printk.c

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,34 @@ __packed __aligned(4)
370370
*/
371371
DEFINE_RAW_SPINLOCK(logbuf_lock);
372372

373+
/*
374+
* Helper macros to lock/unlock logbuf_lock and switch between
375+
* printk-safe/unsafe modes.
376+
*/
377+
#define logbuf_lock_irq() \
378+
do { \
379+
printk_safe_enter_irq(); \
380+
raw_spin_lock(&logbuf_lock); \
381+
} while (0)
382+
383+
#define logbuf_unlock_irq() \
384+
do { \
385+
raw_spin_unlock(&logbuf_lock); \
386+
printk_safe_exit_irq(); \
387+
} while (0)
388+
389+
#define logbuf_lock_irqsave(flags) \
390+
do { \
391+
printk_safe_enter_irqsave(flags); \
392+
raw_spin_lock(&logbuf_lock); \
393+
} while (0)
394+
395+
#define logbuf_unlock_irqrestore(flags) \
396+
do { \
397+
raw_spin_unlock(&logbuf_lock); \
398+
printk_safe_exit_irqrestore(flags); \
399+
} while (0)
400+
373401
#ifdef CONFIG_PRINTK
374402
DECLARE_WAIT_QUEUE_HEAD(log_wait);
375403
/* the next printk record to read by syslog(READ) or /proc/kmsg */
@@ -801,28 +829,29 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
801829
ret = mutex_lock_interruptible(&user->lock);
802830
if (ret)
803831
return ret;
804-
raw_spin_lock_irq(&logbuf_lock);
832+
833+
logbuf_lock_irq();
805834
while (user->seq == log_next_seq) {
806835
if (file->f_flags & O_NONBLOCK) {
807836
ret = -EAGAIN;
808-
raw_spin_unlock_irq(&logbuf_lock);
837+
logbuf_unlock_irq();
809838
goto out;
810839
}
811840

812-
raw_spin_unlock_irq(&logbuf_lock);
841+
logbuf_unlock_irq();
813842
ret = wait_event_interruptible(log_wait,
814843
user->seq != log_next_seq);
815844
if (ret)
816845
goto out;
817-
raw_spin_lock_irq(&logbuf_lock);
846+
logbuf_lock_irq();
818847
}
819848

820849
if (user->seq < log_first_seq) {
821850
/* our last seen message is gone, return error and reset */
822851
user->idx = log_first_idx;
823852
user->seq = log_first_seq;
824853
ret = -EPIPE;
825-
raw_spin_unlock_irq(&logbuf_lock);
854+
logbuf_unlock_irq();
826855
goto out;
827856
}
828857

@@ -835,7 +864,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
835864

836865
user->idx = log_next(user->idx);
837866
user->seq++;
838-
raw_spin_unlock_irq(&logbuf_lock);
867+
logbuf_unlock_irq();
839868

840869
if (len > count) {
841870
ret = -EINVAL;
@@ -862,7 +891,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
862891
if (offset)
863892
return -ESPIPE;
864893

865-
raw_spin_lock_irq(&logbuf_lock);
894+
logbuf_lock_irq();
866895
switch (whence) {
867896
case SEEK_SET:
868897
/* the first record */
@@ -886,7 +915,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
886915
default:
887916
ret = -EINVAL;
888917
}
889-
raw_spin_unlock_irq(&logbuf_lock);
918+
logbuf_unlock_irq();
890919
return ret;
891920
}
892921

@@ -900,15 +929,15 @@ static unsigned int devkmsg_poll(struct file *file, poll_table *wait)
900929

901930
poll_wait(file, &log_wait, wait);
902931

903-
raw_spin_lock_irq(&logbuf_lock);
932+
logbuf_lock_irq();
904933
if (user->seq < log_next_seq) {
905934
/* return error when data has vanished underneath us */
906935
if (user->seq < log_first_seq)
907936
ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI;
908937
else
909938
ret = POLLIN|POLLRDNORM;
910939
}
911-
raw_spin_unlock_irq(&logbuf_lock);
940+
logbuf_unlock_irq();
912941

913942
return ret;
914943
}
@@ -938,10 +967,10 @@ static int devkmsg_open(struct inode *inode, struct file *file)
938967

939968
mutex_init(&user->lock);
940969

941-
raw_spin_lock_irq(&logbuf_lock);
970+
logbuf_lock_irq();
942971
user->idx = log_first_idx;
943972
user->seq = log_first_seq;
944-
raw_spin_unlock_irq(&logbuf_lock);
973+
logbuf_unlock_irq();
945974

946975
file->private_data = user;
947976
return 0;
@@ -1083,13 +1112,13 @@ void __init setup_log_buf(int early)
10831112
return;
10841113
}
10851114

1086-
raw_spin_lock_irqsave(&logbuf_lock, flags);
1115+
logbuf_lock_irqsave(flags);
10871116
log_buf_len = new_log_buf_len;
10881117
log_buf = new_log_buf;
10891118
new_log_buf_len = 0;
10901119
free = __LOG_BUF_LEN - log_next_idx;
10911120
memcpy(log_buf, __log_buf, __LOG_BUF_LEN);
1092-
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
1121+
logbuf_unlock_irqrestore(flags);
10931122

10941123
pr_info("log_buf_len: %d bytes\n", log_buf_len);
10951124
pr_info("early log buf free: %d(%d%%)\n",
@@ -1267,15 +1296,15 @@ static int syslog_print(char __user *buf, int size)
12671296
size_t n;
12681297
size_t skip;
12691298

1270-
raw_spin_lock_irq(&logbuf_lock);
1299+
logbuf_lock_irq();
12711300
if (syslog_seq < log_first_seq) {
12721301
/* messages are gone, move to first one */
12731302
syslog_seq = log_first_seq;
12741303
syslog_idx = log_first_idx;
12751304
syslog_partial = 0;
12761305
}
12771306
if (syslog_seq == log_next_seq) {
1278-
raw_spin_unlock_irq(&logbuf_lock);
1307+
logbuf_unlock_irq();
12791308
break;
12801309
}
12811310

@@ -1294,7 +1323,7 @@ static int syslog_print(char __user *buf, int size)
12941323
syslog_partial += n;
12951324
} else
12961325
n = 0;
1297-
raw_spin_unlock_irq(&logbuf_lock);
1326+
logbuf_unlock_irq();
12981327

12991328
if (!n)
13001329
break;
@@ -1323,7 +1352,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
13231352
if (!text)
13241353
return -ENOMEM;
13251354

1326-
raw_spin_lock_irq(&logbuf_lock);
1355+
logbuf_lock_irq();
13271356
if (buf) {
13281357
u64 next_seq;
13291358
u64 seq;
@@ -1371,12 +1400,12 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
13711400
idx = log_next(idx);
13721401
seq++;
13731402

1374-
raw_spin_unlock_irq(&logbuf_lock);
1403+
logbuf_unlock_irq();
13751404
if (copy_to_user(buf + len, text, textlen))
13761405
len = -EFAULT;
13771406
else
13781407
len += textlen;
1379-
raw_spin_lock_irq(&logbuf_lock);
1408+
logbuf_lock_irq();
13801409

13811410
if (seq < log_first_seq) {
13821411
/* messages are gone, move to next one */
@@ -1390,7 +1419,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
13901419
clear_seq = log_next_seq;
13911420
clear_idx = log_next_idx;
13921421
}
1393-
raw_spin_unlock_irq(&logbuf_lock);
1422+
logbuf_unlock_irq();
13941423

13951424
kfree(text);
13961425
return len;
@@ -1477,7 +1506,7 @@ int do_syslog(int type, char __user *buf, int len, int source)
14771506
break;
14781507
/* Number of chars in the log buffer */
14791508
case SYSLOG_ACTION_SIZE_UNREAD:
1480-
raw_spin_lock_irq(&logbuf_lock);
1509+
logbuf_lock_irq();
14811510
if (syslog_seq < log_first_seq) {
14821511
/* messages are gone, move to first one */
14831512
syslog_seq = log_first_seq;
@@ -1505,7 +1534,7 @@ int do_syslog(int type, char __user *buf, int len, int source)
15051534
}
15061535
error -= syslog_partial;
15071536
}
1508-
raw_spin_unlock_irq(&logbuf_lock);
1537+
logbuf_unlock_irq();
15091538
break;
15101539
/* Size of the log buffer */
15111540
case SYSLOG_ACTION_SIZE_BUFFER:
@@ -1682,9 +1711,8 @@ asmlinkage int vprintk_emit(int facility, int level,
16821711
boot_delay_msec(level);
16831712
printk_delay();
16841713

1685-
printk_safe_enter_irqsave(flags);
16861714
/* This stops the holder of console_sem just where we want him */
1687-
raw_spin_lock(&logbuf_lock);
1715+
logbuf_lock_irqsave(flags);
16881716
/*
16891717
* The printf needs to come first; we need the syslog
16901718
* prefix which might be passed-in as a parameter.
@@ -1727,8 +1755,7 @@ asmlinkage int vprintk_emit(int facility, int level,
17271755

17281756
printed_len += log_output(facility, level, lflags, dict, dictlen, text, text_len);
17291757

1730-
raw_spin_unlock(&logbuf_lock);
1731-
printk_safe_exit_irqrestore(flags);
1758+
logbuf_unlock_irqrestore(flags);
17321759

17331760
/* If called from the scheduler, we can not call up(). */
17341761
if (!in_sched) {
@@ -2501,10 +2528,10 @@ void register_console(struct console *newcon)
25012528
* console_unlock(); will print out the buffered messages
25022529
* for us.
25032530
*/
2504-
raw_spin_lock_irqsave(&logbuf_lock, flags);
2531+
logbuf_lock_irqsave(flags);
25052532
console_seq = syslog_seq;
25062533
console_idx = syslog_idx;
2507-
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2534+
logbuf_unlock_irqrestore(flags);
25082535
/*
25092536
* We're about to replay the log buffer. Only do this to the
25102537
* just-registered console to avoid excessive message spam to
@@ -2803,12 +2830,12 @@ void kmsg_dump(enum kmsg_dump_reason reason)
28032830
/* initialize iterator with data about the stored records */
28042831
dumper->active = true;
28052832

2806-
raw_spin_lock_irqsave(&logbuf_lock, flags);
2833+
logbuf_lock_irqsave(flags);
28072834
dumper->cur_seq = clear_seq;
28082835
dumper->cur_idx = clear_idx;
28092836
dumper->next_seq = log_next_seq;
28102837
dumper->next_idx = log_next_idx;
2811-
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2838+
logbuf_unlock_irqrestore(flags);
28122839

28132840
/* invoke dumper which will iterate over records */
28142841
dumper->dump(dumper, reason);
@@ -2893,9 +2920,9 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
28932920
unsigned long flags;
28942921
bool ret;
28952922

2896-
raw_spin_lock_irqsave(&logbuf_lock, flags);
2923+
logbuf_lock_irqsave(flags);
28972924
ret = kmsg_dump_get_line_nolock(dumper, syslog, line, size, len);
2898-
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2925+
logbuf_unlock_irqrestore(flags);
28992926

29002927
return ret;
29012928
}
@@ -2934,7 +2961,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
29342961
if (!dumper->active)
29352962
goto out;
29362963

2937-
raw_spin_lock_irqsave(&logbuf_lock, flags);
2964+
logbuf_lock_irqsave(flags);
29382965
if (dumper->cur_seq < log_first_seq) {
29392966
/* messages are gone, move to first available one */
29402967
dumper->cur_seq = log_first_seq;
@@ -2943,7 +2970,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
29432970

29442971
/* last entry */
29452972
if (dumper->cur_seq >= dumper->next_seq) {
2946-
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
2973+
logbuf_unlock_irqrestore(flags);
29472974
goto out;
29482975
}
29492976

@@ -2985,7 +3012,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
29853012
dumper->next_seq = next_seq;
29863013
dumper->next_idx = next_idx;
29873014
ret = true;
2988-
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
3015+
logbuf_unlock_irqrestore(flags);
29893016
out:
29903017
if (len)
29913018
*len = l;
@@ -3023,9 +3050,9 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper)
30233050
{
30243051
unsigned long flags;
30253052

3026-
raw_spin_lock_irqsave(&logbuf_lock, flags);
3053+
logbuf_lock_irqsave(flags);
30273054
kmsg_dump_rewind_nolock(dumper);
3028-
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
3055+
logbuf_unlock_irqrestore(flags);
30293056
}
30303057
EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
30313058

0 commit comments

Comments
 (0)