diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 14:25:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 14:25:33 -0400 |
commit | fa93669a1917f93b09142d4b2298329b82d7d36d (patch) | |
tree | 7f8d6dc9d1fbb086c59a799a3a7137c46fb9959e /kernel | |
parent | b13bc8dda81c54a66a1c84e66f60b8feba659f28 (diff) | |
parent | 6791457a090d9a234a40b501c2536f0aefaeae4b (diff) |
Merge tag 'driver-core-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core changes from Greg Kroah-Hartman:
"Here's the big driver core pull request for 3.6-rc1.
Unlike 3.5, this kernel should be a lot tamer, with the printk changes
now settled down. All we have here is some extcon driver updates, w1
driver updates, a few printk cleanups that weren't needed for 3.5, but
are good to have now, and some other minor fixes/changes in the driver
core.
All of these have been in the linux-next releases for a while now.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
* tag 'driver-core-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (38 commits)
printk: Export struct log size and member offsets through vmcoreinfo
Drivers: hv: Change the hex constant to a decimal constant
driver core: don't trigger uevent after failure
extcon: MAX77693: Add extcon-max77693 driver to support Maxim MAX77693 MUIC device
sysfs: fail dentry revalidation after namespace change fix
sysfs: fail dentry revalidation after namespace change
extcon: spelling of detach in function doc
extcon: arizona: Stop microphone detection if we give up on it
extcon: arizona: Update cable reporting calls and split headset
PM / Runtime: Do not increment device usage counts before probing
kmsg - do not flush partial lines when the console is busy
kmsg - export "continuation record" flag to /dev/kmsg
kmsg - avoid warning for CONFIG_PRINTK=n compilations
kmsg - properly print over-long continuation lines
driver-core: Use kobj_to_dev instead of re-implementing it
driver-core: Move kobj_to_dev from genhd.h to device.h
driver core: Move deferred devices to the end of dpm_list before probing
driver core: move uevent call to driver_register
driver core: fix shutdown races with probe/remove(v3)
Extcon: Arizona: Add driver for Wolfson Arizona class devices
...
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/printk.c | 159 |
1 files changed, 121 insertions, 38 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index ac4bc9e79465..50c96b5651b6 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -216,6 +216,7 @@ struct log { | |||
216 | */ | 216 | */ |
217 | static DEFINE_RAW_SPINLOCK(logbuf_lock); | 217 | static DEFINE_RAW_SPINLOCK(logbuf_lock); |
218 | 218 | ||
219 | #ifdef CONFIG_PRINTK | ||
219 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ | 220 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ |
220 | static u64 syslog_seq; | 221 | static u64 syslog_seq; |
221 | static u32 syslog_idx; | 222 | static u32 syslog_idx; |
@@ -228,14 +229,19 @@ static u32 log_first_idx; | |||
228 | 229 | ||
229 | /* index and sequence number of the next record to store in the buffer */ | 230 | /* index and sequence number of the next record to store in the buffer */ |
230 | static u64 log_next_seq; | 231 | static u64 log_next_seq; |
231 | #ifdef CONFIG_PRINTK | ||
232 | static u32 log_next_idx; | 232 | static u32 log_next_idx; |
233 | 233 | ||
234 | /* the next printk record to write to the console */ | ||
235 | static u64 console_seq; | ||
236 | static u32 console_idx; | ||
237 | static enum log_flags console_prev; | ||
238 | |||
234 | /* the next printk record to read after the last 'clear' command */ | 239 | /* the next printk record to read after the last 'clear' command */ |
235 | static u64 clear_seq; | 240 | static u64 clear_seq; |
236 | static u32 clear_idx; | 241 | static u32 clear_idx; |
237 | 242 | ||
238 | #define LOG_LINE_MAX 1024 | 243 | #define PREFIX_MAX 32 |
244 | #define LOG_LINE_MAX 1024 - PREFIX_MAX | ||
239 | 245 | ||
240 | /* record buffer */ | 246 | /* record buffer */ |
241 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 247 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
@@ -360,6 +366,7 @@ static void log_store(int facility, int level, | |||
360 | struct devkmsg_user { | 366 | struct devkmsg_user { |
361 | u64 seq; | 367 | u64 seq; |
362 | u32 idx; | 368 | u32 idx; |
369 | enum log_flags prev; | ||
363 | struct mutex lock; | 370 | struct mutex lock; |
364 | char buf[8192]; | 371 | char buf[8192]; |
365 | }; | 372 | }; |
@@ -425,6 +432,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
425 | struct log *msg; | 432 | struct log *msg; |
426 | u64 ts_usec; | 433 | u64 ts_usec; |
427 | size_t i; | 434 | size_t i; |
435 | char cont = '-'; | ||
428 | size_t len; | 436 | size_t len; |
429 | ssize_t ret; | 437 | ssize_t ret; |
430 | 438 | ||
@@ -462,8 +470,25 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
462 | msg = log_from_idx(user->idx); | 470 | msg = log_from_idx(user->idx); |
463 | ts_usec = msg->ts_nsec; | 471 | ts_usec = msg->ts_nsec; |
464 | do_div(ts_usec, 1000); | 472 | do_div(ts_usec, 1000); |
465 | len = sprintf(user->buf, "%u,%llu,%llu;", | 473 | |
466 | (msg->facility << 3) | msg->level, user->seq, ts_usec); | 474 | /* |
475 | * If we couldn't merge continuation line fragments during the print, | ||
476 | * export the stored flags to allow an optional external merge of the | ||
477 | * records. Merging the records isn't always neccessarily correct, like | ||
478 | * when we hit a race during printing. In most cases though, it produces | ||
479 | * better readable output. 'c' in the record flags mark the first | ||
480 | * fragment of a line, '+' the following. | ||
481 | */ | ||
482 | if (msg->flags & LOG_CONT && !(user->prev & LOG_CONT)) | ||
483 | cont = 'c'; | ||
484 | else if ((msg->flags & LOG_CONT) || | ||
485 | ((user->prev & LOG_CONT) && !(msg->flags & LOG_PREFIX))) | ||
486 | cont = '+'; | ||
487 | |||
488 | len = sprintf(user->buf, "%u,%llu,%llu,%c;", | ||
489 | (msg->facility << 3) | msg->level, | ||
490 | user->seq, ts_usec, cont); | ||
491 | user->prev = msg->flags; | ||
467 | 492 | ||
468 | /* escape non-printable characters */ | 493 | /* escape non-printable characters */ |
469 | for (i = 0; i < msg->text_len; i++) { | 494 | for (i = 0; i < msg->text_len; i++) { |
@@ -646,6 +671,15 @@ void log_buf_kexec_setup(void) | |||
646 | VMCOREINFO_SYMBOL(log_buf_len); | 671 | VMCOREINFO_SYMBOL(log_buf_len); |
647 | VMCOREINFO_SYMBOL(log_first_idx); | 672 | VMCOREINFO_SYMBOL(log_first_idx); |
648 | VMCOREINFO_SYMBOL(log_next_idx); | 673 | VMCOREINFO_SYMBOL(log_next_idx); |
674 | /* | ||
675 | * Export struct log size and field offsets. User space tools can | ||
676 | * parse it and detect any changes to structure down the line. | ||
677 | */ | ||
678 | VMCOREINFO_STRUCT_SIZE(log); | ||
679 | VMCOREINFO_OFFSET(log, ts_nsec); | ||
680 | VMCOREINFO_OFFSET(log, len); | ||
681 | VMCOREINFO_OFFSET(log, text_len); | ||
682 | VMCOREINFO_OFFSET(log, dict_len); | ||
649 | } | 683 | } |
650 | #endif | 684 | #endif |
651 | 685 | ||
@@ -876,7 +910,7 @@ static size_t msg_print_text(const struct log *msg, enum log_flags prev, | |||
876 | 910 | ||
877 | if (buf) { | 911 | if (buf) { |
878 | if (print_prefix(msg, syslog, NULL) + | 912 | if (print_prefix(msg, syslog, NULL) + |
879 | text_len + 1>= size - len) | 913 | text_len + 1 >= size - len) |
880 | break; | 914 | break; |
881 | 915 | ||
882 | if (prefix) | 916 | if (prefix) |
@@ -907,7 +941,7 @@ static int syslog_print(char __user *buf, int size) | |||
907 | struct log *msg; | 941 | struct log *msg; |
908 | int len = 0; | 942 | int len = 0; |
909 | 943 | ||
910 | text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); | 944 | text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
911 | if (!text) | 945 | if (!text) |
912 | return -ENOMEM; | 946 | return -ENOMEM; |
913 | 947 | ||
@@ -930,7 +964,8 @@ static int syslog_print(char __user *buf, int size) | |||
930 | 964 | ||
931 | skip = syslog_partial; | 965 | skip = syslog_partial; |
932 | msg = log_from_idx(syslog_idx); | 966 | msg = log_from_idx(syslog_idx); |
933 | n = msg_print_text(msg, syslog_prev, true, text, LOG_LINE_MAX); | 967 | n = msg_print_text(msg, syslog_prev, true, text, |
968 | LOG_LINE_MAX + PREFIX_MAX); | ||
934 | if (n - syslog_partial <= size) { | 969 | if (n - syslog_partial <= size) { |
935 | /* message fits into buffer, move forward */ | 970 | /* message fits into buffer, move forward */ |
936 | syslog_idx = log_next(syslog_idx); | 971 | syslog_idx = log_next(syslog_idx); |
@@ -969,7 +1004,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
969 | char *text; | 1004 | char *text; |
970 | int len = 0; | 1005 | int len = 0; |
971 | 1006 | ||
972 | text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); | 1007 | text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
973 | if (!text) | 1008 | if (!text) |
974 | return -ENOMEM; | 1009 | return -ENOMEM; |
975 | 1010 | ||
@@ -1022,7 +1057,8 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
1022 | struct log *msg = log_from_idx(idx); | 1057 | struct log *msg = log_from_idx(idx); |
1023 | int textlen; | 1058 | int textlen; |
1024 | 1059 | ||
1025 | textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX); | 1060 | textlen = msg_print_text(msg, prev, true, text, |
1061 | LOG_LINE_MAX + PREFIX_MAX); | ||
1026 | if (textlen < 0) { | 1062 | if (textlen < 0) { |
1027 | len = textlen; | 1063 | len = textlen; |
1028 | break; | 1064 | break; |
@@ -1349,20 +1385,36 @@ static struct cont { | |||
1349 | u64 ts_nsec; /* time of first print */ | 1385 | u64 ts_nsec; /* time of first print */ |
1350 | u8 level; /* log level of first message */ | 1386 | u8 level; /* log level of first message */ |
1351 | u8 facility; /* log level of first message */ | 1387 | u8 facility; /* log level of first message */ |
1388 | enum log_flags flags; /* prefix, newline flags */ | ||
1352 | bool flushed:1; /* buffer sealed and committed */ | 1389 | bool flushed:1; /* buffer sealed and committed */ |
1353 | } cont; | 1390 | } cont; |
1354 | 1391 | ||
1355 | static void cont_flush(void) | 1392 | static void cont_flush(enum log_flags flags) |
1356 | { | 1393 | { |
1357 | if (cont.flushed) | 1394 | if (cont.flushed) |
1358 | return; | 1395 | return; |
1359 | if (cont.len == 0) | 1396 | if (cont.len == 0) |
1360 | return; | 1397 | return; |
1361 | 1398 | ||
1362 | log_store(cont.facility, cont.level, LOG_NOCONS, cont.ts_nsec, | 1399 | if (cont.cons) { |
1363 | NULL, 0, cont.buf, cont.len); | 1400 | /* |
1364 | 1401 | * If a fragment of this line was directly flushed to the | |
1365 | cont.flushed = true; | 1402 | * console; wait for the console to pick up the rest of the |
1403 | * line. LOG_NOCONS suppresses a duplicated output. | ||
1404 | */ | ||
1405 | log_store(cont.facility, cont.level, flags | LOG_NOCONS, | ||
1406 | cont.ts_nsec, NULL, 0, cont.buf, cont.len); | ||
1407 | cont.flags = flags; | ||
1408 | cont.flushed = true; | ||
1409 | } else { | ||
1410 | /* | ||
1411 | * If no fragment of this line ever reached the console, | ||
1412 | * just submit it to the store and free the buffer. | ||
1413 | */ | ||
1414 | log_store(cont.facility, cont.level, flags, 0, | ||
1415 | NULL, 0, cont.buf, cont.len); | ||
1416 | cont.len = 0; | ||
1417 | } | ||
1366 | } | 1418 | } |
1367 | 1419 | ||
1368 | static bool cont_add(int facility, int level, const char *text, size_t len) | 1420 | static bool cont_add(int facility, int level, const char *text, size_t len) |
@@ -1371,7 +1423,8 @@ static bool cont_add(int facility, int level, const char *text, size_t len) | |||
1371 | return false; | 1423 | return false; |
1372 | 1424 | ||
1373 | if (cont.len + len > sizeof(cont.buf)) { | 1425 | if (cont.len + len > sizeof(cont.buf)) { |
1374 | cont_flush(); | 1426 | /* the line gets too long, split it up in separate records */ |
1427 | cont_flush(LOG_CONT); | ||
1375 | return false; | 1428 | return false; |
1376 | } | 1429 | } |
1377 | 1430 | ||
@@ -1380,12 +1433,17 @@ static bool cont_add(int facility, int level, const char *text, size_t len) | |||
1380 | cont.level = level; | 1433 | cont.level = level; |
1381 | cont.owner = current; | 1434 | cont.owner = current; |
1382 | cont.ts_nsec = local_clock(); | 1435 | cont.ts_nsec = local_clock(); |
1436 | cont.flags = 0; | ||
1383 | cont.cons = 0; | 1437 | cont.cons = 0; |
1384 | cont.flushed = false; | 1438 | cont.flushed = false; |
1385 | } | 1439 | } |
1386 | 1440 | ||
1387 | memcpy(cont.buf + cont.len, text, len); | 1441 | memcpy(cont.buf + cont.len, text, len); |
1388 | cont.len += len; | 1442 | cont.len += len; |
1443 | |||
1444 | if (cont.len > (sizeof(cont.buf) * 80) / 100) | ||
1445 | cont_flush(LOG_CONT); | ||
1446 | |||
1389 | return true; | 1447 | return true; |
1390 | } | 1448 | } |
1391 | 1449 | ||
@@ -1394,7 +1452,7 @@ static size_t cont_print_text(char *text, size_t size) | |||
1394 | size_t textlen = 0; | 1452 | size_t textlen = 0; |
1395 | size_t len; | 1453 | size_t len; |
1396 | 1454 | ||
1397 | if (cont.cons == 0) { | 1455 | if (cont.cons == 0 && (console_prev & LOG_NEWLINE)) { |
1398 | textlen += print_time(cont.ts_nsec, text); | 1456 | textlen += print_time(cont.ts_nsec, text); |
1399 | size -= textlen; | 1457 | size -= textlen; |
1400 | } | 1458 | } |
@@ -1409,7 +1467,8 @@ static size_t cont_print_text(char *text, size_t size) | |||
1409 | } | 1467 | } |
1410 | 1468 | ||
1411 | if (cont.flushed) { | 1469 | if (cont.flushed) { |
1412 | text[textlen++] = '\n'; | 1470 | if (cont.flags & LOG_NEWLINE) |
1471 | text[textlen++] = '\n'; | ||
1413 | /* got everything, release buffer */ | 1472 | /* got everything, release buffer */ |
1414 | cont.len = 0; | 1473 | cont.len = 0; |
1415 | } | 1474 | } |
@@ -1507,7 +1566,7 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1507 | * or another task also prints continuation lines. | 1566 | * or another task also prints continuation lines. |
1508 | */ | 1567 | */ |
1509 | if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) | 1568 | if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) |
1510 | cont_flush(); | 1569 | cont_flush(LOG_NEWLINE); |
1511 | 1570 | ||
1512 | /* buffer line if possible, otherwise store it right away */ | 1571 | /* buffer line if possible, otherwise store it right away */ |
1513 | if (!cont_add(facility, level, text, text_len)) | 1572 | if (!cont_add(facility, level, text, text_len)) |
@@ -1525,7 +1584,7 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1525 | if (cont.len && cont.owner == current) { | 1584 | if (cont.len && cont.owner == current) { |
1526 | if (!(lflags & LOG_PREFIX)) | 1585 | if (!(lflags & LOG_PREFIX)) |
1527 | stored = cont_add(facility, level, text, text_len); | 1586 | stored = cont_add(facility, level, text, text_len); |
1528 | cont_flush(); | 1587 | cont_flush(LOG_NEWLINE); |
1529 | } | 1588 | } |
1530 | 1589 | ||
1531 | if (!stored) | 1590 | if (!stored) |
@@ -1616,9 +1675,20 @@ asmlinkage int printk(const char *fmt, ...) | |||
1616 | } | 1675 | } |
1617 | EXPORT_SYMBOL(printk); | 1676 | EXPORT_SYMBOL(printk); |
1618 | 1677 | ||
1619 | #else | 1678 | #else /* CONFIG_PRINTK */ |
1620 | 1679 | ||
1680 | #define LOG_LINE_MAX 0 | ||
1681 | #define PREFIX_MAX 0 | ||
1621 | #define LOG_LINE_MAX 0 | 1682 | #define LOG_LINE_MAX 0 |
1683 | static u64 syslog_seq; | ||
1684 | static u32 syslog_idx; | ||
1685 | static u64 console_seq; | ||
1686 | static u32 console_idx; | ||
1687 | static enum log_flags syslog_prev; | ||
1688 | static u64 log_first_seq; | ||
1689 | static u32 log_first_idx; | ||
1690 | static u64 log_next_seq; | ||
1691 | static enum log_flags console_prev; | ||
1622 | static struct cont { | 1692 | static struct cont { |
1623 | size_t len; | 1693 | size_t len; |
1624 | size_t cons; | 1694 | size_t cons; |
@@ -1902,10 +1972,34 @@ void wake_up_klogd(void) | |||
1902 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | 1972 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); |
1903 | } | 1973 | } |
1904 | 1974 | ||
1905 | /* the next printk record to write to the console */ | 1975 | static void console_cont_flush(char *text, size_t size) |
1906 | static u64 console_seq; | 1976 | { |
1907 | static u32 console_idx; | 1977 | unsigned long flags; |
1908 | static enum log_flags console_prev; | 1978 | size_t len; |
1979 | |||
1980 | raw_spin_lock_irqsave(&logbuf_lock, flags); | ||
1981 | |||
1982 | if (!cont.len) | ||
1983 | goto out; | ||
1984 | |||
1985 | /* | ||
1986 | * We still queue earlier records, likely because the console was | ||
1987 | * busy. The earlier ones need to be printed before this one, we | ||
1988 | * did not flush any fragment so far, so just let it queue up. | ||
1989 | */ | ||
1990 | if (console_seq < log_next_seq && !cont.cons) | ||
1991 | goto out; | ||
1992 | |||
1993 | len = cont_print_text(text, size); | ||
1994 | raw_spin_unlock(&logbuf_lock); | ||
1995 | stop_critical_timings(); | ||
1996 | call_console_drivers(cont.level, text, len); | ||
1997 | start_critical_timings(); | ||
1998 | local_irq_restore(flags); | ||
1999 | return; | ||
2000 | out: | ||
2001 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | ||
2002 | } | ||
1909 | 2003 | ||
1910 | /** | 2004 | /** |
1911 | * console_unlock - unlock the console system | 2005 | * console_unlock - unlock the console system |
@@ -1923,7 +2017,7 @@ static enum log_flags console_prev; | |||
1923 | */ | 2017 | */ |
1924 | void console_unlock(void) | 2018 | void console_unlock(void) |
1925 | { | 2019 | { |
1926 | static char text[LOG_LINE_MAX]; | 2020 | static char text[LOG_LINE_MAX + PREFIX_MAX]; |
1927 | static u64 seen_seq; | 2021 | static u64 seen_seq; |
1928 | unsigned long flags; | 2022 | unsigned long flags; |
1929 | bool wake_klogd = false; | 2023 | bool wake_klogd = false; |
@@ -1937,19 +2031,7 @@ void console_unlock(void) | |||
1937 | console_may_schedule = 0; | 2031 | console_may_schedule = 0; |
1938 | 2032 | ||
1939 | /* flush buffered message fragment immediately to console */ | 2033 | /* flush buffered message fragment immediately to console */ |
1940 | raw_spin_lock_irqsave(&logbuf_lock, flags); | 2034 | console_cont_flush(text, sizeof(text)); |
1941 | if (cont.len && (cont.cons < cont.len || cont.flushed)) { | ||
1942 | size_t len; | ||
1943 | |||
1944 | len = cont_print_text(text, sizeof(text)); | ||
1945 | raw_spin_unlock(&logbuf_lock); | ||
1946 | stop_critical_timings(); | ||
1947 | call_console_drivers(cont.level, text, len); | ||
1948 | start_critical_timings(); | ||
1949 | local_irq_restore(flags); | ||
1950 | } else | ||
1951 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | ||
1952 | |||
1953 | again: | 2035 | again: |
1954 | for (;;) { | 2036 | for (;;) { |
1955 | struct log *msg; | 2037 | struct log *msg; |
@@ -1986,6 +2068,7 @@ skip: | |||
1986 | * will properly dump everything later. | 2068 | * will properly dump everything later. |
1987 | */ | 2069 | */ |
1988 | msg->flags &= ~LOG_NOCONS; | 2070 | msg->flags &= ~LOG_NOCONS; |
2071 | console_prev = msg->flags; | ||
1989 | goto skip; | 2072 | goto skip; |
1990 | } | 2073 | } |
1991 | 2074 | ||