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