Skip to content

Commit d594d8f

Browse files
committed
Merge tag 'printk-for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux
Pull printk updates from Petr Mladek: "The big new thing is the fully lockless ringbuffer implementation, including the support for continuous lines. It will allow to store and read messages in any situation wihtout the risk of deadlocks and without the need of temporary per-CPU buffers. The access is still serialized by logbuf_lock. It synchronizes few more operations, for example, temporary buffer for formatting the message, syslog and kmsg_dump operations. The lock removal is being discussed and should be ready for the next release. The continuous lines are handled exactly the same way as before to avoid regressions in user space. It means that they are appended to the last message when the caller is the same. Only the last message can be extended. The data ring includes plain text of the messages. Except for an integer at the beginning of each message that points back to the descriptor ring with other metadata. The dictionary has to stay. journalctl uses it to filter the log. It allows to show messages related to a given device. The dictionary values are stored in the descriptor ring with the other metadata. This is the first part of the printk rework as discussed at Plumbers 2019, see https://lore.kernel.org/r/[email protected]. The next big step will be handling consoles by kthreads during the normal system operation. It will require special handling of situations when the kthreads could not get scheduled, for example, early boot, suspend, panic. Other changes: - Add John Ogness as a reviewer for printk subsystem. He is author of the rework and is familiar with the code and history. - Fix locking in serial8250_do_startup() to prevent lockdep report. - Few code cleanups" * tag 'printk-for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux: (27 commits) printk: Use fallthrough pseudo-keyword printk: reduce setup_text_buf size to LOG_LINE_MAX printk: avoid and/or handle record truncation printk: remove dict ring printk: move dictionary keys to dev_printk_info printk: move printk_info into separate array printk: reimplement log_cont using record extension printk: ringbuffer: add finalization/extension support printk: ringbuffer: change representation of states printk: ringbuffer: clear initial reserved fields printk: ringbuffer: add BLK_DATALESS() macro printk: ringbuffer: relocate get_data() printk: ringbuffer: avoid memcpy() on state_var printk: ringbuffer: fix setting state in desc_read() kernel.h: Move oops_in_progress to printk.h scripts/gdb: update for lockless printk ringbuffer scripts/gdb: add utils.read_ulong() docs: vmcoreinfo: add lockless printk ringbuffer vmcoreinfo printk: reduce LOG_BUF_SHIFT range for H8300 printk: ringbuffer: support dataless records ...
2 parents 029f56d + 70333f4 commit d594d8f

File tree

18 files changed

+3410
-731
lines changed

18 files changed

+3410
-731
lines changed

Documentation/admin-guide/kdump/gdbmacros.txt

Lines changed: 109 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -170,91 +170,150 @@ document trapinfo
170170
address the kernel panicked.
171171
end
172172

173-
define dump_log_idx
174-
set $idx = $arg0
175-
if ($argc > 1)
176-
set $prev_flags = $arg1
173+
define dump_record
174+
set var $desc = $arg0
175+
set var $info = $arg1
176+
if ($argc > 2)
177+
set var $prev_flags = $arg2
177178
else
178-
set $prev_flags = 0
179+
set var $prev_flags = 0
179180
end
180-
set $msg = ((struct printk_log *) (log_buf + $idx))
181-
set $prefix = 1
182-
set $newline = 1
183-
set $log = log_buf + $idx + sizeof(*$msg)
184-
185-
# prev & LOG_CONT && !(msg->flags & LOG_PREIX)
186-
if (($prev_flags & 8) && !($msg->flags & 4))
187-
set $prefix = 0
181+
182+
set var $prefix = 1
183+
set var $newline = 1
184+
185+
set var $begin = $desc->text_blk_lpos.begin % (1U << prb->text_data_ring.size_bits)
186+
set var $next = $desc->text_blk_lpos.next % (1U << prb->text_data_ring.size_bits)
187+
188+
# handle data-less record
189+
if ($begin & 1)
190+
set var $text_len = 0
191+
set var $log = ""
192+
else
193+
# handle wrapping data block
194+
if ($begin > $next)
195+
set var $begin = 0
196+
end
197+
198+
# skip over descriptor id
199+
set var $begin = $begin + sizeof(long)
200+
201+
# handle truncated message
202+
if ($next - $begin < $info->text_len)
203+
set var $text_len = $next - $begin
204+
else
205+
set var $text_len = $info->text_len
206+
end
207+
208+
set var $log = &prb->text_data_ring.data[$begin]
209+
end
210+
211+
# prev & LOG_CONT && !(info->flags & LOG_PREIX)
212+
if (($prev_flags & 8) && !($info->flags & 4))
213+
set var $prefix = 0
188214
end
189215

190-
# msg->flags & LOG_CONT
191-
if ($msg->flags & 8)
216+
# info->flags & LOG_CONT
217+
if ($info->flags & 8)
192218
# (prev & LOG_CONT && !(prev & LOG_NEWLINE))
193219
if (($prev_flags & 8) && !($prev_flags & 2))
194-
set $prefix = 0
220+
set var $prefix = 0
195221
end
196-
# (!(msg->flags & LOG_NEWLINE))
197-
if (!($msg->flags & 2))
198-
set $newline = 0
222+
# (!(info->flags & LOG_NEWLINE))
223+
if (!($info->flags & 2))
224+
set var $newline = 0
199225
end
200226
end
201227

202228
if ($prefix)
203-
printf "[%5lu.%06lu] ", $msg->ts_nsec / 1000000000, $msg->ts_nsec % 1000000000
229+
printf "[%5lu.%06lu] ", $info->ts_nsec / 1000000000, $info->ts_nsec % 1000000000
204230
end
205-
if ($msg->text_len != 0)
206-
eval "printf \"%%%d.%ds\", $log", $msg->text_len, $msg->text_len
231+
if ($text_len)
232+
eval "printf \"%%%d.%ds\", $log", $text_len, $text_len
207233
end
208234
if ($newline)
209235
printf "\n"
210236
end
211-
if ($msg->dict_len > 0)
212-
set $dict = $log + $msg->text_len
213-
set $idx = 0
214-
set $line = 1
215-
while ($idx < $msg->dict_len)
216-
if ($line)
217-
printf " "
218-
set $line = 0
237+
238+
# handle dictionary data
239+
240+
set var $dict = &$info->dev_info.subsystem[0]
241+
set var $dict_len = sizeof($info->dev_info.subsystem)
242+
if ($dict[0] != '\0')
243+
printf " SUBSYSTEM="
244+
set var $idx = 0
245+
while ($idx < $dict_len)
246+
set var $c = $dict[$idx]
247+
if ($c == '\0')
248+
loop_break
249+
else
250+
if ($c < ' ' || $c >= 127 || $c == '\\')
251+
printf "\\x%02x", $c
252+
else
253+
printf "%c", $c
254+
end
219255
end
220-
set $c = $dict[$idx]
256+
set var $idx = $idx + 1
257+
end
258+
printf "\n"
259+
end
260+
261+
set var $dict = &$info->dev_info.device[0]
262+
set var $dict_len = sizeof($info->dev_info.device)
263+
if ($dict[0] != '\0')
264+
printf " DEVICE="
265+
set var $idx = 0
266+
while ($idx < $dict_len)
267+
set var $c = $dict[$idx]
221268
if ($c == '\0')
222-
printf "\n"
223-
set $line = 1
269+
loop_break
224270
else
225271
if ($c < ' ' || $c >= 127 || $c == '\\')
226272
printf "\\x%02x", $c
227273
else
228274
printf "%c", $c
229275
end
230276
end
231-
set $idx = $idx + 1
277+
set var $idx = $idx + 1
232278
end
233279
printf "\n"
234280
end
235281
end
236-
document dump_log_idx
237-
Dump a single log given its index in the log buffer. The first
238-
parameter is the index into log_buf, the second is optional and
239-
specified the previous log buffer's flags, used for properly
240-
formatting continued lines.
282+
document dump_record
283+
Dump a single record. The first parameter is the descriptor,
284+
the second parameter is the info, the third parameter is
285+
optional and specifies the previous record's flags, used for
286+
properly formatting continued lines.
241287
end
242288

243289
define dmesg
244-
set $i = log_first_idx
245-
set $end_idx = log_first_idx
246-
set $prev_flags = 0
290+
# definitions from kernel/printk/printk_ringbuffer.h
291+
set var $desc_committed = 1
292+
set var $desc_finalized = 2
293+
set var $desc_sv_bits = sizeof(long) * 8
294+
set var $desc_flags_shift = $desc_sv_bits - 2
295+
set var $desc_flags_mask = 3 << $desc_flags_shift
296+
set var $id_mask = ~$desc_flags_mask
297+
298+
set var $desc_count = 1U << prb->desc_ring.count_bits
299+
set var $prev_flags = 0
300+
301+
set var $id = prb->desc_ring.tail_id.counter
302+
set var $end_id = prb->desc_ring.head_id.counter
247303

248304
while (1)
249-
set $msg = ((struct printk_log *) (log_buf + $i))
250-
if ($msg->len == 0)
251-
set $i = 0
252-
else
253-
dump_log_idx $i $prev_flags
254-
set $i = $i + $msg->len
255-
set $prev_flags = $msg->flags
305+
set var $desc = &prb->desc_ring.descs[$id % $desc_count]
306+
set var $info = &prb->desc_ring.infos[$id % $desc_count]
307+
308+
# skip non-committed record
309+
set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift)
310+
if ($state == $desc_committed || $state == $desc_finalized)
311+
dump_record $desc $info $prev_flags
312+
set var $prev_flags = $info->flags
256313
end
257-
if ($i == $end_idx)
314+
315+
set var $id = ($id + 1) & $id_mask
316+
if ($id == $end_id)
258317
loop_break
259318
end
260319
end

Documentation/admin-guide/kdump/vmcoreinfo.rst

Lines changed: 102 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -189,50 +189,123 @@ from this.
189189
Free areas descriptor. User-space tools use this value to iterate the
190190
free_area ranges. MAX_ORDER is used by the zone buddy allocator.
191191

192-
log_first_idx
192+
prb
193+
---
194+
195+
A pointer to the printk ringbuffer (struct printk_ringbuffer). This
196+
may be pointing to the static boot ringbuffer or the dynamically
197+
allocated ringbuffer, depending on when the the core dump occurred.
198+
Used by user-space tools to read the active kernel log buffer.
199+
200+
printk_rb_static
201+
----------------
202+
203+
A pointer to the static boot printk ringbuffer. If @prb has a
204+
different value, this is useful for viewing the initial boot messages,
205+
which may have been overwritten in the dynamically allocated
206+
ringbuffer.
207+
208+
clear_seq
209+
---------
210+
211+
The sequence number of the printk() record after the last clear
212+
command. It indicates the first record after the last
213+
SYSLOG_ACTION_CLEAR, like issued by 'dmesg -c'. Used by user-space
214+
tools to dump a subset of the dmesg log.
215+
216+
printk_ringbuffer
217+
-----------------
218+
219+
The size of a printk_ringbuffer structure. This structure contains all
220+
information required for accessing the various components of the
221+
kernel log buffer.
222+
223+
(printk_ringbuffer, desc_ring|text_data_ring|dict_data_ring|fail)
224+
-----------------------------------------------------------------
225+
226+
Offsets for the various components of the printk ringbuffer. Used by
227+
user-space tools to view the kernel log buffer without requiring the
228+
declaration of the structure.
229+
230+
prb_desc_ring
193231
-------------
194232

195-
Index of the first record stored in the buffer log_buf. Used by
196-
user-space tools to read the strings in the log_buf.
233+
The size of the prb_desc_ring structure. This structure contains
234+
information about the set of record descriptors.
197235

198-
log_buf
199-
-------
236+
(prb_desc_ring, count_bits|descs|head_id|tail_id)
237+
-------------------------------------------------
238+
239+
Offsets for the fields describing the set of record descriptors. Used
240+
by user-space tools to be able to traverse the descriptors without
241+
requiring the declaration of the structure.
242+
243+
prb_desc
244+
--------
245+
246+
The size of the prb_desc structure. This structure contains
247+
information about a single record descriptor.
248+
249+
(prb_desc, info|state_var|text_blk_lpos|dict_blk_lpos)
250+
------------------------------------------------------
251+
252+
Offsets for the fields describing a record descriptors. Used by
253+
user-space tools to be able to read descriptors without requiring
254+
the declaration of the structure.
255+
256+
prb_data_blk_lpos
257+
-----------------
258+
259+
The size of the prb_data_blk_lpos structure. This structure contains
260+
information about where the text or dictionary data (data block) is
261+
located within the respective data ring.
262+
263+
(prb_data_blk_lpos, begin|next)
264+
-------------------------------
200265

201-
Console output is written to the ring buffer log_buf at index
202-
log_first_idx. Used to get the kernel log.
266+
Offsets for the fields describing the location of a data block. Used
267+
by user-space tools to be able to locate data blocks without
268+
requiring the declaration of the structure.
203269

204-
log_buf_len
270+
printk_info
205271
-----------
206272

207-
log_buf's length.
273+
The size of the printk_info structure. This structure contains all
274+
the meta-data for a record.
208275

209-
clear_idx
210-
---------
276+
(printk_info, seq|ts_nsec|text_len|dict_len|caller_id)
277+
------------------------------------------------------
211278

212-
The index that the next printk() record to read after the last clear
213-
command. It indicates the first record after the last SYSLOG_ACTION
214-
_CLEAR, like issued by 'dmesg -c'. Used by user-space tools to dump
215-
the dmesg log.
279+
Offsets for the fields providing the meta-data for a record. Used by
280+
user-space tools to be able to read the information without requiring
281+
the declaration of the structure.
216282

217-
log_next_idx
218-
------------
283+
prb_data_ring
284+
-------------
219285

220-
The index of the next record to store in the buffer log_buf. Used to
221-
compute the index of the current buffer position.
286+
The size of the prb_data_ring structure. This structure contains
287+
information about a set of data blocks.
222288

223-
printk_log
224-
----------
289+
(prb_data_ring, size_bits|data|head_lpos|tail_lpos)
290+
---------------------------------------------------
225291

226-
The size of a structure printk_log. Used to compute the size of
227-
messages, and extract dmesg log. It encapsulates header information for
228-
log_buf, such as timestamp, syslog level, etc.
292+
Offsets for the fields describing a set of data blocks. Used by
293+
user-space tools to be able to access the data blocks without
294+
requiring the declaration of the structure.
229295

230-
(printk_log, ts_nsec|len|text_len|dict_len)
231-
-------------------------------------------
296+
atomic_long_t
297+
-------------
298+
299+
The size of the atomic_long_t structure. Used by user-space tools to
300+
be able to copy the full structure, regardless of its
301+
architecture-specific implementation.
302+
303+
(atomic_long_t, counter)
304+
------------------------
232305

233-
It represents field offsets in struct printk_log. User space tools
234-
parse it and check whether the values of printk_log's members have been
235-
changed.
306+
Offset for the long value of an atomic_long_t variable. Used by
307+
user-space tools to access the long value without requiring the
308+
architecture-specific declaration.
236309

237310
(free_area.free_list, MIGRATE_TYPES)
238311
------------------------------------

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13970,6 +13970,7 @@ PRINTK
1397013970
M: Petr Mladek <[email protected]>
1397113971
M: Sergey Senozhatsky <[email protected]>
1397213972
R: Steven Rostedt <[email protected]>
13973+
R: John Ogness <[email protected]>
1397313974
S: Maintained
1397413975
F: include/linux/printk.h
1397513976
F: kernel/printk/

0 commit comments

Comments
 (0)