RFD: Rework/extending functionality of mdev
Harald Becker
ralda at gmx.de
Tue Mar 10 16:26:20 UTC 2015
Hi,
getting hints and ideas from Laurent and Natanael, I found we can get
most flexibility, when when try to do some modularization of the steps
done by mdev.
At fist there are two different kinds of work to deal with:
1) The overall operation and usage of netlink
2) Extending the mdev.conf syntax
Both are independent so first look at the overall operation ... and we
are currently looking at operation/functionality. This neither means
they are all separate programs/applets. We may put several
functionalities in one applet and distinguish by some options. First
look at, what to do, then decide how to implement:
mdev needs to do the following steps:
- on startup the sys file system is scanned for device entries
- as a hotplug handler for each event a process is forked passing
information in environment variables
- when using netlink a long lived daemon read event messages from a
network socket to assemble same information as the hotplug handler
- when all information for an event has been gathered, mdev needs to
search it's configuration table for the required entry, and then ...
- ... do the required operations for the device entry
That is scanning the sys file system, hotplug event handler and netlink
event daemon trigger operation of the mdev parser. Forking a conf file
parser for each event is much overhead on system startup, when many
event arrive in short amount of time. There we would benefit from a
single process reading from a pipe, dieing when there are no more events
and reestablish when new events arrive.
Both the sys file system scanner and a netlink daemon could easily
establish a pipe and then send device commands to the parser. The parser
reads mdev.conf once and creates a in memory table, then reads commands
from the pipe and scans the memory table for the right entry. When EOF
on pipe read, the parser can exit successfully.
The sys file system scanner (startup = mdev -s) can create the pipe,
then scan the sysfs and send the commands to the parser. When done, the
pipe can be closed and after waiting for the parser process just exit.
The netlink daemon, can establish the netlink socket, then read events
an sanitize the messages. When there is any message for the parser, a
pipe is created and messages can be passed to the parser. When netlink
is idle for some amount of time, it can close the pipe and check the
child status.
Confusion arise only on the hotplug handler part, as here a new process
is started for every event by the kernel. Forking a pipe to send this to
the parser would double the overhead. But leaving the parser running for
some amount of time, would only work with a named fifo, startup of the
parser when required and adds timeout management to the parser ...
... but ok, do we look at an alternative: Consider a small long lived
daemon, which create a named fifo and then poll this fifo until data get
available. On hotplug event a small helper is started, which read it's
information, serializes then write the command to the fifo and exit. The
long lived daemon sees the data (but does not read), then forks a parser
and gives the read end of the pipe to the the parser. The parser reads
mdev.conv once, then processes commands from the fifo. Now we are at the
situation where the timeout needs to be checked in the parser. When
there are no more events on the fifo the parser just dies successfully
(freeing used memory). This will be detected by the small long lived
daemon, which check the exit status and can act on failures (e.g. run a
failure script). On successful exit of the parser the daemon starts
again waiting for data on the fifo (which he still hold open for reading
and writing). This way the hotplug helper will benefit from a single run
parser on startup, but memory used by the conf parser is freed during
normal system operation. The doubling of the timeout management in
netlink daemon and parser can be intentional when different timeouts are
used. Where a small duration for the idle timeout of netlink can be
chosen, the parser itself does use a higher timeout, which only triggers
when the hotplug helper method is used.
yes, there are some rough corners, but we are at the phase of brain
storming. Beside those corners do we get a modular system, which avoid
respawning/rereading the conf table for every event, but frees memory
when there are no more events. Even the hotplug helper method will
benefit, as the helper process can exit, as soon as the command has been
written to the fifo. The parser reads serialized commands from the pipe
and process required actions.
May be we should consider using that small parser helper daemon and the
named fifo in all cases. sys file system scanner, hotplug helper and
netlink daemon will then just use the fifo. This would even allow to use
the same fifo to activate the mdev parser from a user space program
(including single parser start for multiple events).
Don't be afraid about the many functions. We can put this together in
one program and make mdev a wrapper around this. The question is, do we
want to do this? the memory usage may be smaller when the fifo helper
daemon and/or the netlink reader daemon are separate programs. On the
other side the code of BB will always be loaded and should be reused,
even on NOMMU systems, so the code size does not matter much, only stack
and data sizes. The data sizes are kept es small as possible in the long
lived processes, but the BB infrastructure may add some overhead (how
many? does that matter?).
With mdev as a wrapper we could have:
mdev (no parameter)
- hotplug helper
(how to get FIFO_PATH? use always default?)
mdev -i
- do the initial operations from mdev.conf
(e.g. mounts, subdirs, symlinks)
mdev -f [FIFO_PATH]
- start the fifo helper daemon and create the fifo
(suggesting default FIFO_PATH /dev/ctl/mdev)
mdev -h [FIFO_PATH]
- install mdev as a hotplug helper
(needs to give FIFO_PATH to the hotplug helper, how?)
mdev -n [FIFO_PATH]
- start the netlink reader daemon
mdev -s [FIFO_PATH]
- scan the sys file system and populate device filesystem
mdev -p
- mdev.conf parser, reading from stdin (no fifo, no helper daemons)
This way you may implement your own hotplug handling but continue to use
the mdev.conf functionality.
The options i f h and s may be combined, same for i f n and s, for which
will allow to startup the system with a single call, doing init, loading
required daemon(s), and scan sys file system for initial population. h n
and s include f, when fifo does not exist.
Alternative to FIFO_PATH: Setting "#fifo" option in /etc/mdev.conf and
let all programs use this value. As default use /dev/ctl/mdev or
/dev/.mdev-fifo (when /dev/ctl does not exist). Don't use /run,
/var/run, or /tmp as default, are they writable at this time? /dev
should be, as we are populating the device nodes. Sound simple but needs
to look in mdev.conf for fifo name on every hotplug event -> better to
always use /dev/.mdev-fifo? Suggestions?
Also Natanaels idea of modprobe has not bean dropped. This could be done
in a similar way. May be it is wise to synchronize this with the mdev
parser and use only one fifo to the parser, forwarding the requests to
modprobe (simple pipe, modprobe reads from pipe until EOF).
--
Harald
More information about the busybox
mailing list