RFD: Rework/extending functionality of mdev

Natanael Copa ncopa at alpinelinux.org
Wed Mar 11 07:45:29 UTC 2015


On Tue, 10 Mar 2015 17:26:20 +0100
Harald Becker <ralda at gmx.de> wrote:

>  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

You don't want scan sysfs for devince entries. Instead you want trigger
hotplug events. Something like:

find /sys -type f -name uevent | while read entry; do
	echo add > "$entry"
done

> - as a hotplug handler for each event a process is forked passing 
> information in environment variables

You don't want fork a process for every hotplug event. Instead you want
catch the hotplug events with netlink.
 
> - when using netlink a long lived daemon read event messages from a 
> network socket to assemble same information as the hotplug handler

You don't want collect the same info twice. Instead you want a netlink
listener (long lived daemon) that is minimal. And then you want a
hotplug handler that deals with the events. That is what mdev does. It
even handles MODALIAS events which is not a "device entry"

> - 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

We can simplify what needs to happen at boot with:

- prepare /sys /proc /dev

- set up hotplug handler

- trigger hotplug events


You can currently do that very simple with existing mdev:

  # prepare /sys /proc /dev 
  mount ... /sys ...

  # set up hotplug handler
  echo "/sbin/mdev" > /proc/sys/kernel/hotplug

  # trigger hotplug events
  find /sys -type f -name uevent | while read entry; do
      echo add > "$entry"
  done
  

This works but will trigger tons of forks and cannot guarantee that the
events are handled in correct order - serialization problem. I think
mdev has a hack (/dev/mdev.seq) to resolve the serialization problem.

The performance is still bad due to all forks.

To avoid the many forks you need use a netlink listener. This will also
solve the serialization problem properly.

You can solve this by adding netlink support to mdev and turn it into a
daemon. Then the netlink listener and the event handler is in same
executable, similar to what udev does. This has a few drawbacks:

- the handler code will always be running. eg the mdev.conf parsing
  code will be in the daemon all the time. It can be discussed if this
  is a real problem or not because kernel memory manager will handle
  memory usage and reuse "inactive" memory properly.

- mdev is currently designed to exit. Turning it to a daemon will
  likely require some work for error handling.


I think it is a better idea to leave mdev as a short lived process
which exists when its done. We can do that by separating out the
netlink listener to a separate daemon which forks mdev and send a bulk
of events via pipe - as explained in my previous email.

...

> Both the sys file system scanner and a netlink daemon could easily 
> establish a pipe and then send device commands to the parser.
> 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.

You don't want "sysfs scanner" to send device commands anywhere. You
simply trigger the hotplug events with "echo add > /sys/...../uevent"
and then will netlink listener deal with it as if it was hotplugged.
 
> 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.

The netlink listener daemon will need to deal with the event handler (or
parser as you call it) dying. I mean, the handler (the parser) could
get some error, out of memory, someone broke mdev.conf or anything that
causes mdev to exit. If the child (the handler/parser) dies a new pipe
needs to be created and the handler/parser needs to be re-forked.

With that in mind, wouldn't it be better to have the timer code in the
handler/parser? When there comes no new messages from pipe within a
given time, the handler/parser just exists.

> 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 ...

named pipes will just make things more complicated.


-nc


More information about the busybox mailing list