about summary refs log tree commit diff
path: root/doc/mdevd.html
blob: dfb44a3582c9985b0a96bde233658ec11335cd6a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Language" content="en" />
    <title>mdevd: the mdevd program</title>
    <meta name="Description" content="mdevd: the mdevd program" />
    <meta name="Keywords" content="mdevd linux administration root utilities devd mdev uevent netlink hotplug manager" />
    <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
  </head>
<body>

<p>
<a href="index.html">mdevd</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>

<h1> The <tt>mdevd</tt> program </h1>

<p>
<tt>mdevd</tt> is a uevent manager. It connects to the netlink and reads
a series of uevents; for every uevent it reads, it performs
actions according to its configuration file. Actions can
be inserting a kernel module, creating or modifying device
entries in <tt>/dev</tt>, etc.
</p>

<p>
 <tt>mdevd</tt>'s configuration file uses the exact same
format as
<a href="https://git.busybox.net/busybox/plain/docs/mdev.txt">mdev</a>.
The differences between mdevd and mdev are:
</p>

<ul>
 <li> mdev needs to be registered as a hotplug manager and the
kernel spawns an instance of mdev per uevent; for every uevent,
mdev has to parse its configuration file. By contrast, mdevd is
a daemon: it's long-lived, and there is only one instance,
reading a series of uevents and
performing actions without forking; the configuration file is
read and parsed only once. </li>
 <li> Even though mdev can now be run as a daemon, via the <tt>-d</tt>
option, there are still <a href="index.html#mdev">technical advantages</a>
to running mdevd over mdev. </li>
</ul>

<h2> Interface </h2>

<pre>
     mdevd [ -v <em>verbosity</em> ] [ -D <em>notif</em> ] [ -o <em>outputfd</em> ] [ -O <em>nlgroups</em> ] [ -b <em>kbufsz</em> ] [ -f <em>conffile</em> ] [ -n ] [ -s <em>slashsys</em> ] [ -d <em>slashdev</em> ] [ -F <em>fwbase</em> ] [ -C ]
</pre>

<ul>
 <li> mdevd reads and parses its configuration file <tt>/etc/mdev.conf</tt>. </li>
 <li> It then connects to the netlink and reads from it, waiting for uevents.
 <li> It exits 0 on a SIGTERM. </li>
</ul>

<h2> Exit codes </h2>

<ul>
 <li> 0: SIGTERM received, clean exit </li>
 <li> 1: received an invalid event </li>
 <li> 2: syntax error in the configuration file </li>
 <li> 100: wrong usage </li>
 <li> 111: system call failed </li>
</ul>

<h2> Signals </h2>

<p>
 mdevd reacts to the following signals:
</p>

<ul>
 <li> SIGHUP: re-read the configuration file </li>
 <li> SIGTERM: exit as soon as possible </li>
</ul>

<h2> Options </h2>

<ul>
 <li> <tt>-v</tt>&nbsp;<em>verbosity</em>&nbsp;: be more or less verbose.
Default verbosity is 1. 0 will only print fatal error messages, 3 or more
is seriously verbose debugging. </li>
 <li> <tt>-D</tt>&nbsp;<em>notif</em>&nbsp;: when ready
(actually listening to the netlink),
write a newline to file descriptor <em>notif</em> then close it.
This allows mdevd to use the
<a href="//skarnet.org/software/s6/notifywhenup.html">s6 mechanism to notify
readiness</a>. <em>notif</em> cannot be lesser than 3.
If this option is not given, no readiness notification is sent. </li>
 <li> <tt>-o</tt>&nbsp;<em>outputfd</em>&nbsp;: send a copy of the complete
uevent, with possible new fields, to file descriptor <em>outputfd</em>,
<strong>after</strong> mdevd has handled them. (This can serve as a
synchronization mechanism with an external program that needs a device to
have been properly configured by the device manager before acting on the
device.)
The uevent is sent with the kernel format: fields are separated by a null
character. The uevent is terminated by an additional null character.
<em>outputfd</em> cannot be lesser than 3 and cannot be the same as <em>notif</em>.
If for any reason, at any point, mdevd fails to write to <em>outputfd</em>,
it stops writing, until it is restarted. (This is to preserve mdevd's memory
stability guarantee.) By default, the uevents are not written anywhere. </li>
 <li> <tt>-O</tt>&nbsp;<em>nlgroups</em>&nbsp;: after mdevd has handled the
uevents, rebroadcast them to the netlink groups identified by the mask
<em>nlgroups</em>. Bit 0 of <em>nlgroups</em> is always ignored (because
netlink group 1 is the one used by the kernel to send the original uevents and
that mdevd listens to, and we don't want to loopback on it). </li>
 <li> <tt>-b</tt>&nbsp;<em>kbufsz</em>&nbsp;: try and reserve a kernel buffer of
<em>kbufsz</em> bytes for the netlink queue. Too large a buffer wastes kernel memory;
too small a buffer risks losing events. The default is 500 kB, which should be
enough for most systems; if you're getting "No buffer space available" errors
from mdevd at coldplug time, try increasing this number. </li>
 <li> <tt>-n</tt>&nbsp;: dry run. mdevd will not create or delete
device nodes, and it will not spawn commands. Instead, it will print to stdout
the actions it would have performed. </li>
 <li> <tt>-f</tt>&nbsp;<em>conffile</em>&nbsp;: read the configuration
file from <em>conffile</em>. Default is <tt>/etc/mdev.conf</tt>.
<em>conffile</em> must be an absolute path. </li>
 <li> <tt>-s</tt>&nbsp;<em>slashsys</em>&nbsp;: assume the sysfs
pseudo-filesystem is mounted on <em>slashsys</em>. Default is <tt>/sys</tt>.
<em>slashsys</em> must be an absolute path. </li>
 <li> <tt>-d</tt>&nbsp;<em>slashdev</em>&nbsp;: assume the device nodes
are to be found in  <em>slashdev</em>. Default is <tt>/dev</tt>.
<em>slashdev</em> must be an absolute path. </li>
 <li> <tt>-F</tt>&nbsp;<em>fwbase</em>&nbsp;: assume the firmware files, if any,
are to be found in  <em>fwbase</em>. Default is <tt>/lib/firmware</tt>.
<em>fwbase</em> must be an absolute path. </li>
 <li> <tt>-C</tt>&nbsp;: after initialization (when mdevd is ready), invoke
<a href="mdevd-coldplug.html">mdevd-coldplug</a>, so that a coldplug is
automatically performed when mdevd starts. This option should only be used
in situations where a drop-in replacement for <tt>mdev -d</tt> is needed, because
it has the drawback of performing a coldplug every time mdevd is started &mdash;
including when mdevd is killed and restarted. By default, mdevd does not perform
a coldplug when it starts, and it is up to the administrator to properly organize
their boot scripts to run <a href="mdevd-coldplug.html">mdevd-coldplug</a> once,
at boot time, when mdevd is ready. The <tt>examples/s6-rc</tt> subdirectory of
the mdevd package shows a way to do this with the
<a href="//skarnet.org/softwre/s6-rc/">s6-rc</a> service manager. </li>
</ul>

<h2> Configuration file </h2>

<p>
 mdevd uses mdev's configuration file format.
A good <tt>mdev.conf</tt> example is available
<a href="https://github.com/slashbeast/mdev-like-a-boss/blob/master/mdev.conf">here</a>.
</p>

<p>
 If mdevd cannot find its configuration file, it will use a simple, basic default
configuration where it can create device nodes as root or delete them, and does
nothing else.
</p>

<h3> execline command support </h3>

<p>
 In addition to the traditional shell command spawning via the <tt>@</tt>,
<tt>$</tt> and <tt>*</tt> directives, mdevd also supports spawning a command
with the
<a href="https://skarnet.org/software/execline/execlineb.html">execlineb</a>
launcher:
</p>

<ul>
 <li> <tt>+<em>cmd</em></tt>&nbsp;: spawns <tt>execlineb -Pc <em>cmd</em></tt>
when this line catches an event that has <tt>ACTION=add</tt>. This is the
equivalent of <tt>@<em>cmd</em></tt>. </li>
 <li> <tt>-<em>cmd</em></tt>&nbsp;: spawns <tt>execlineb -Pc <em>cmd</em></tt>
when this line catches an event that has <tt>ACTION=remove</tt>. This is the
equivalent of <tt>$<em>cmd</em></tt>. </li>
 <li> <tt>&amp;<em>cmd</em></tt>&nbsp;: spawns <tt>execlineb -Pc <em>cmd</em></tt>
when this line catches an event no matter its action type. This is the
equivalent of <tt>*<em>cmd</em></tt>. </li>
</ul>

<p>
 Note that unlike <tt>/bin/sh</tt>, <tt>execlineb</tt> is spawned without an
absolute path, so in order for <tt>+</tt>, <tt>-</tt> and <tt>&amp;</tt> to
work, the <tt>execlineb</tt> command must be available in mdevd's PATH.
</p>

<h2> Notes </h2>

<ul>
 <li> The <tt>examples/</tt> subdirectory of the mdevd package contains
examples on how to run mdevd under various init systems / supervisors. These
examples do not show how to run mdevd as a logged service, because mdevd
should normally be run early in the system's boot up sequence, before
mounting the disks - so the presence of a mounted partition suitable for
logging is not guaranteed. In normal use, mdevd is quite terse, so it
runs smoothly without a dedicated logger, with its error messages
going to the catch-all logger. </li>
</ul>

</body>
</html>