Skip to content

Commit

Permalink
Merge tag 'driver-core-6.1-rc1' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/gregkh/driver-core

Pull driver core updates from Greg KH:
 "Here is the big set of driver core and debug printk changes for
  6.1-rc1. Included in here is:

   - dynamic debug updates for the core and the drm subsystem. The drm
     changes have all been acked by the relevant maintainers

   - kernfs fixes for syzbot reported problems

   - kernfs refactors and updates for cgroup requirements

   - magic number cleanups and removals from the kernel tree (they were
     not being used and they really did not actually do anything)

   - other tiny cleanups

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'driver-core-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (74 commits)
  docs: filesystems: sysfs: Make text and code for ->show() consistent
  Documentation: NBD_REQUEST_MAGIC isn't a magic number
  a.out: restore CMAGIC
  device property: Add const qualifier to device_get_match_data() parameter
  drm_print: add _ddebug descriptor to drm_*dbg prototypes
  drm_print: prefer bare printk KERN_DEBUG on generic fn
  drm_print: optimize drm_debug_enabled for jump-label
  drm-print: add drm_dbg_driver to improve namespace symmetry
  drm-print.h: include dyndbg header
  drm_print: wrap drm_*_dbg in dyndbg descriptor factory macro
  drm_print: interpose drm_*dbg with forwarding macros
  drm: POC drm on dyndbg - use in core, 2 helpers, 3 drivers.
  drm_print: condense enum drm_debug_category
  debugfs: use DEFINE_SHOW_ATTRIBUTE to define debugfs_regset32_fops
  driver core: use IS_ERR_OR_NULL() helper in device_create_groups_vargs()
  Documentation: ENI155_MAGIC isn't a magic number
  Documentation: NBD_REPLY_MAGIC isn't a magic number
  nbd: remove define-only NBD_MAGIC, previously magic number
  Documentation: FW_HEADER_MAGIC isn't a magic number
  Documentation: EEPROM_MAGIC_VALUE isn't a magic number
  ...
  • Loading branch information
torvalds committed Oct 8, 2022
2 parents d3dcbe2 + fda8c90 commit e8bc52c
Show file tree
Hide file tree
Showing 46 changed files with 1,318 additions and 694 deletions.
246 changes: 128 additions & 118 deletions Documentation/admin-guide/dynamic-debug-howto.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,143 +5,115 @@ Dynamic debug
Introduction
============

This document describes how to use the dynamic debug (dyndbg) feature.
Dynamic debug allows you to dynamically enable/disable kernel
debug-print code to obtain additional kernel information.

Dynamic debug is designed to allow you to dynamically enable/disable
kernel code to obtain additional kernel information. Currently, if
``CONFIG_DYNAMIC_DEBUG`` is set, then all ``pr_debug()``/``dev_dbg()`` and
``print_hex_dump_debug()``/``print_hex_dump_bytes()`` calls can be dynamically
enabled per-callsite.
If ``/proc/dynamic_debug/control`` exists, your kernel has dynamic
debug. You'll need root access (sudo su) to use this.

If you do not want to enable dynamic debug globally (i.e. in some embedded
system), you may set ``CONFIG_DYNAMIC_DEBUG_CORE`` as basic support of dynamic
debug and add ``ccflags := -DDYNAMIC_DEBUG_MODULE`` into the Makefile of any
modules which you'd like to dynamically debug later.

If ``CONFIG_DYNAMIC_DEBUG`` is not set, ``print_hex_dump_debug()`` is just
shortcut for ``print_hex_dump(KERN_DEBUG)``.

For ``print_hex_dump_debug()``/``print_hex_dump_bytes()``, format string is
its ``prefix_str`` argument, if it is constant string; or ``hexdump``
in case ``prefix_str`` is built dynamically.
Dynamic debug provides:

Dynamic debug has even more useful features:
* a Catalog of all *prdbgs* in your kernel.
``cat /proc/dynamic_debug/control`` to see them.

* Simple query language allows turning on and off debugging
statements by matching any combination of 0 or 1 of:
* a Simple query/command language to alter *prdbgs* by selecting on
any combination of 0 or 1 of:

- source filename
- function name
- line number (including ranges of line numbers)
- module name
- format string

* Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
which can be read to display the complete list of known debug
statements, to help guide you

Controlling dynamic debug Behaviour
===================================

The behaviour of ``pr_debug()``/``dev_dbg()`` are controlled via writing to a
control file in the 'debugfs' filesystem. Thus, you must first mount
the debugfs filesystem, in order to make use of this feature.
Subsequently, we refer to the control file as:
``<debugfs>/dynamic_debug/control``. For example, if you want to enable
printing from source file ``svcsock.c``, line 1603 you simply do::

nullarbor:~ # echo 'file svcsock.c line 1603 +p' >
<debugfs>/dynamic_debug/control

If you make a mistake with the syntax, the write will fail thus::

nullarbor:~ # echo 'file svcsock.c wtf 1 +p' >
<debugfs>/dynamic_debug/control
-bash: echo: write error: Invalid argument

Note, for systems without 'debugfs' enabled, the control file can be
found in ``/proc/dynamic_debug/control``.
- class name (as known/declared by each module)

Viewing Dynamic Debug Behaviour
===============================

You can view the currently configured behaviour of all the debug
statements via::
You can view the currently configured behaviour in the *prdbg* catalog::

nullarbor:~ # cat <debugfs>/dynamic_debug/control
:#> head -n7 /proc/dynamic_debug/control
# filename:lineno [module]function flags format
net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup =_ "SVCRDMA Module Removed, deregister RPC RDMA transport\012"
net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init =_ "\011max_inline : %d\012"
net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init =_ "\011sq_depth : %d\012"
net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init =_ "\011max_requests : %d\012"
...
init/main.c:1179 [main]initcall_blacklist =_ "blacklisting initcall %s\012
init/main.c:1218 [main]initcall_blacklisted =_ "initcall %s blacklisted\012"
init/main.c:1424 [main]run_init_process =_ " with arguments:\012"
init/main.c:1426 [main]run_init_process =_ " %s\012"
init/main.c:1427 [main]run_init_process =_ " with environment:\012"
init/main.c:1429 [main]run_init_process =_ " %s\012"

The 3rd space-delimited column shows the current flags, preceded by
a ``=`` for easy use with grep/cut. ``=p`` shows enabled callsites.

You can also apply standard Unix text manipulation filters to this
data, e.g.::
Controlling dynamic debug Behaviour
===================================

nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control | wc -l
62
The behaviour of *prdbg* sites are controlled by writing
query/commands to the control file. Example::

nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l
42
# grease the interface
:#> alias ddcmd='echo $* > /proc/dynamic_debug/control'

The third column shows the currently enabled flags for each debug
statement callsite (see below for definitions of the flags). The
default value, with no flags enabled, is ``=_``. So you can view all
the debug statement callsites with any non-default flags::
:#> ddcmd '-p; module main func run* +p'
:#> grep =p /proc/dynamic_debug/control
init/main.c:1424 [main]run_init_process =p " with arguments:\012"
init/main.c:1426 [main]run_init_process =p " %s\012"
init/main.c:1427 [main]run_init_process =p " with environment:\012"
init/main.c:1429 [main]run_init_process =p " %s\012"

nullarbor:~ # awk '$3 != "=_"' <debugfs>/dynamic_debug/control
# filename:lineno [module]function flags format
net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012"
Error messages go to console/syslog::

:#> ddcmd mode foo +p
dyndbg: unknown keyword "mode"
dyndbg: query parse failed
bash: echo: write error: Invalid argument

If debugfs is also enabled and mounted, ``dynamic_debug/control`` is
also under the mount-dir, typically ``/sys/kernel/debug/``.

Command Language Reference
==========================

At the lexical level, a command comprises a sequence of words separated
At the basic lexical level, a command is a sequence of words separated
by spaces or tabs. So these are all equivalent::

nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
<debugfs>/dynamic_debug/control
nullarbor:~ # echo -n ' file svcsock.c line 1603 +p ' >
<debugfs>/dynamic_debug/control
nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
<debugfs>/dynamic_debug/control
:#> ddcmd file svcsock.c line 1603 +p
:#> ddcmd "file svcsock.c line 1603 +p"
:#> ddcmd ' file svcsock.c line 1603 +p '

Command submissions are bounded by a write() system call.
Multiple commands can be written together, separated by ``;`` or ``\n``::

~# echo "func pnpacpi_get_resources +p; func pnp_assign_mem +p" \
> <debugfs>/dynamic_debug/control
:#> ddcmd "func pnpacpi_get_resources +p; func pnp_assign_mem +p"
:#> ddcmd <<"EOC"
func pnpacpi_get_resources +p
func pnp_assign_mem +p
EOC
:#> cat query-batch-file > /proc/dynamic_debug/control

If your query set is big, you can batch them too::
You can also use wildcards in each query term. The match rule supports
``*`` (matches zero or more characters) and ``?`` (matches exactly one
character). For example, you can match all usb drivers::

~# cat query-batch-file > <debugfs>/dynamic_debug/control
:#> ddcmd file "drivers/usb/*" +p # "" to suppress shell expansion

Another way is to use wildcards. The match rule supports ``*`` (matches
zero or more characters) and ``?`` (matches exactly one character). For
example, you can match all usb drivers::

~# echo "file drivers/usb/* +p" > <debugfs>/dynamic_debug/control

At the syntactical level, a command comprises a sequence of match
specifications, followed by a flags change specification::
Syntactically, a command is pairs of keyword values, followed by a
flags change or setting::

command ::= match-spec* flags-spec

The match-spec's are used to choose a subset of the known pr_debug()
callsites to which to apply the flags-spec. Think of them as a query
with implicit ANDs between each pair. Note that an empty list of
match-specs will select all debug statement callsites.
The match-spec's select *prdbgs* from the catalog, upon which to apply
the flags-spec, all constraints are ANDed together. An absent keyword
is the same as keyword "*".


A match specification comprises a keyword, which controls the
attribute of the callsite to be compared, and a value to compare
against. Possible keywords are:::
A match specification is a keyword, which selects the attribute of
the callsite to be compared, and a value to compare against. Possible
keywords are:::

match-spec ::= 'func' string |
'file' string |
'module' string |
'format' string |
'class' string |
'line' line-range

line-range ::= lineno |
Expand Down Expand Up @@ -203,6 +175,16 @@ format
format "nfsd: SETATTR" // a neater way to match a format with whitespace
format 'nfsd: SETATTR' // yet another way to match a format with whitespace

class
The given class_name is validated against each module, which may
have declared a list of known class_names. If the class_name is
found for a module, callsite & class matching and adjustment
proceeds. Examples::

class DRM_UT_KMS # a DRM.debug category
class JUNK # silent non-match
// class TLD_* # NOTICE: no wildcard in class names

line
The given line number or range of line numbers is compared
against the line number of each ``pr_debug()`` callsite. A single
Expand All @@ -228,17 +210,16 @@ of the characters::
The flags are::

p enables the pr_debug() callsite.
f Include the function name in the printed message
l Include line number in the printed message
m Include module name in the printed message
t Include thread ID in messages not generated from interrupt context
_ No flags are set. (Or'd with others on input)
_ enables no flags.

For ``print_hex_dump_debug()`` and ``print_hex_dump_bytes()``, only ``p`` flag
have meaning, other flags ignored.
Decorator flags add to the message-prefix, in order:
t Include thread ID, or <intr>
m Include module name
f Include the function name
l Include line number

For display, the flags are preceded by ``=``
(mnemonic: what the flags are currently equal to).
For ``print_hex_dump_debug()`` and ``print_hex_dump_bytes()``, only
the ``p`` flag has meaning, other flags are ignored.

Note the regexp ``^[-+=][flmpt_]+$`` matches a flags specification.
To clear all flags at once, use ``=_`` or ``-flmpt``.
Expand Down Expand Up @@ -313,45 +294,39 @@ For ``CONFIG_DYNAMIC_DEBUG`` kernels, any settings given at boot-time (or
enabled by ``-DDEBUG`` flag during compilation) can be disabled later via
the debugfs interface if the debug messages are no longer needed::

echo "module module_name -p" > <debugfs>/dynamic_debug/control
echo "module module_name -p" > /proc/dynamic_debug/control

Examples
========

::

// enable the message at line 1603 of file svcsock.c
nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
<debugfs>/dynamic_debug/control
:#> ddcmd 'file svcsock.c line 1603 +p'

// enable all the messages in file svcsock.c
nullarbor:~ # echo -n 'file svcsock.c +p' >
<debugfs>/dynamic_debug/control
:#> ddcmd 'file svcsock.c +p'

// enable all the messages in the NFS server module
nullarbor:~ # echo -n 'module nfsd +p' >
<debugfs>/dynamic_debug/control
:#> ddcmd 'module nfsd +p'

// enable all 12 messages in the function svc_process()
nullarbor:~ # echo -n 'func svc_process +p' >
<debugfs>/dynamic_debug/control
:#> ddcmd 'func svc_process +p'

// disable all 12 messages in the function svc_process()
nullarbor:~ # echo -n 'func svc_process -p' >
<debugfs>/dynamic_debug/control
:#> ddcmd 'func svc_process -p'

// enable messages for NFS calls READ, READLINK, READDIR and READDIR+.
nullarbor:~ # echo -n 'format "nfsd: READ" +p' >
<debugfs>/dynamic_debug/control
:#> ddcmd 'format "nfsd: READ" +p'

// enable messages in files of which the paths include string "usb"
nullarbor:~ # echo -n 'file *usb* +p' > <debugfs>/dynamic_debug/control
:#> ddcmd 'file *usb* +p' > /proc/dynamic_debug/control

// enable all messages
nullarbor:~ # echo -n '+p' > <debugfs>/dynamic_debug/control
:#> ddcmd '+p' > /proc/dynamic_debug/control

// add module, function to all enabled messages
nullarbor:~ # echo -n '+mf' > <debugfs>/dynamic_debug/control
:#> ddcmd '+mf' > /proc/dynamic_debug/control

// boot-args example, with newlines and comments for readability
Kernel command line: ...
Expand All @@ -364,3 +339,38 @@ Examples
dyndbg="file init/* +p #cmt ; func parse_one +p"
// enable pr_debugs in 2 functions in a module loaded later
pc87360.dyndbg="func pc87360_init_device +p; func pc87360_find +p"

Kernel Configuration
====================

Dynamic Debug is enabled via kernel config items::

CONFIG_DYNAMIC_DEBUG=y # build catalog, enables CORE
CONFIG_DYNAMIC_DEBUG_CORE=y # enable mechanics only, skip catalog

If you do not want to enable dynamic debug globally (i.e. in some embedded
system), you may set ``CONFIG_DYNAMIC_DEBUG_CORE`` as basic support of dynamic
debug and add ``ccflags := -DDYNAMIC_DEBUG_MODULE`` into the Makefile of any
modules which you'd like to dynamically debug later.


Kernel *prdbg* API
==================

The following functions are cataloged and controllable when dynamic
debug is enabled::

pr_debug()
dev_dbg()
print_hex_dump_debug()
print_hex_dump_bytes()

Otherwise, they are off by default; ``ccflags += -DDEBUG`` or
``#define DEBUG`` in a source file will enable them appropriately.

If ``CONFIG_DYNAMIC_DEBUG`` is not set, ``print_hex_dump_debug()`` is
just a shortcut for ``print_hex_dump(KERN_DEBUG)``.

For ``print_hex_dump_debug()``/``print_hex_dump_bytes()``, format string is
its ``prefix_str`` argument, if it is constant string; or ``hexdump``
in case ``prefix_str`` is built dynamically.
1 change: 0 additions & 1 deletion Documentation/driver-api/driver-model/devres.rst
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ IOMAP
devm_ioremap()
devm_ioremap_uc()
devm_ioremap_wc()
devm_ioremap_np()
devm_ioremap_resource() : checks resource, requests memory region, ioremaps
devm_ioremap_resource_wc()
devm_platform_ioremap_resource() : calls devm_ioremap_resource() for platform device
Expand Down
2 changes: 1 addition & 1 deletion Documentation/filesystems/sysfs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ A very simple (and naive) implementation of a device attribute is::
static ssize_t show_name(struct device *dev, struct device_attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name);
return sysfs_emit(buf, "%s\n", dev->name);
}

static ssize_t store_name(struct device *dev, struct device_attribute *attr,
Expand Down
Loading

0 comments on commit e8bc52c

Please sign in to comment.