mdev

Rob Landley rob at landley.net
Sat Apr 18 02:54:10 UTC 2009


On Friday 17 April 2009 04:03:55 Vladimir Dronnikov wrote:
> >> All hotplug processing could then be moved to a separate applet
> >> (hotplug, say), make_device() would be shared among them.
> >
> > Unfortunately, it's not that simple.  The mdev -s code is one way to
> > trigger /dev creation fro the information the kernel exports in sysfs,
> > and the hotplug stuff is another way of feeding essentially the same
> > information in to the same code.  Both of these code paths have to create
> > the same device nodes and parse the same config file, so splitting them
> > isn't as much fun as you'd think.
>
> So the two parts should be placed in the same mdev.c: just copy-paste
> mdev_main() and rename one copy to hotplug_main(). Then remove
> unnecessary branches from either. I want them share make_device(), but
> do not want to struggle in the trade for "mdev -s"
> speed/functionality.

So you want them to share code, but not worry about a speed/functionality 
tradeoff between two different users of the share code which have conflicting 
goals.  And you believe refactoring will achieve this, when the current 
differences are in a single main() function which has a single if() block for 
the one case, and a single else block for the other.

Good luck?

> >> I do not concern "mdev -s" coldplug speed.
> >
> > The reason mdev was written in the first place is that the coldplug speed
> > was abysmal.  I had a shell script version that did it back in 2005 (it
> > came first), and it was converted to C because it could take 10 seconds
> > to run.
>
> I meant speed here is not of my primary concern. And you here do not
> concern of missing events, right?

I don't understand what you mean there.

> mdev doesn't not call make_device() 
> for those devices that have no "dev" entries. How to be with serials
> ports and network interfaces?

Serial ports have dev entries, network interfaces never did.

Right now, if you haven't got _either_ a device name _or_ a major/minor to 
match on (neither of which you have if you have in the absence of a device 
node), then there's no way for the current config file to identify the device 
and thus attach behavior to its events.  That's one of the fundamental design 
assumptions.

I pointed you at a standalone hotplug.  You can also have a hotplug script 
that does various things and then calls mdev at the end.  (You always could, 
you don't need to modify mdev for this.  The original hotplug userspace 
infrastructure the kernel guys came up with _was_ a shell script.)

> On modular kernels the former never get 
> appeared, the latter never get a chance to be netif'ed or initialized.
> Embedded people might have compiled their kernels moduleless and
> all-inclusive, but I don't.

So you choose to configure your system in such a way that you're fighting the 
design assumptions of mdev, and you choose A) not to wrap mdev with a shell 
script that can add arbitrary behavior to hotplug events, B) use a tool such 
as udev that's a heck of a lot more complicated because it _doesn't_ make 
simplifying design assumptions.

> This contradiction makes me shut-up for "mdev -s" (coldplug) part of
> mdev -- I don't want users to hate me for changes they don't need.

Too late, they already made solar sad when they ripped out the original mmap 
implementation of /etc/mdev.conf parsing and replaced it something that not 
only re-reads the config file for every single device inserted by mdev -s, 
but performs a half-dozen malloc()s per line it reads from the config file, 
and then frees them again.

The silly part is that the code that uses the output of that then does a 
strdup() on the results, even though they don't get freed until the next time 
the parsing code gets called.  For example, as far as I can tell:

--- mdev.new	2009-04-17 20:41:22.000000000 -0500
+++ util-linux/mdev.c	2009-04-17 21:21:57.000000000 -0500
@@ -234,7 +234,7 @@
 				/* Are we running this command now?
 				 * Run $cmd on delete, @cmd on create, *cmd on both
 				 */
-				if (s2-s != delete) command = xstrdup(val + 1);
+				if (s2-s != delete) command = val + 1;
 			}
 		}
 
@@ -275,7 +275,6 @@
 			free(s1);
 			unsetenv("MDEV");
 			free(s);
-			free(command);
 		}
 
 		if (delete) {


Should still work just fine.  (But this is from a fairly quick glance at the 
current code, I could be missing something subtle.)

> So 
> I want coldplug to not change. But the hotplug part of mdev surely
> should be changed: added at least $MODALIAS support. Or $FIRMWARE is
> quite useless, since firmware is binary data needed by modules.

If FIRMWARE support should be in the C code (instead of a wrapper script that 
calls mdev at the end), the MODALIAS support should be too.

That said, what's wrong with something like (off the top of my head, 
untested):

cat > /sbin/hotplug << EOF
#!/bin/sh

# Do we need to load firmware?

if [ ! -z "$FIRMWARE" ] && [ "$ACTION" == add ] &&
   [ -e "/lib/firmware/$FIRMWARE" ]
then
  cd "/sys/$DEVPATH" || exit 1

  # Tell kernel we're loading as soon as it's ready to accept data.
  # (Time out after 30 seconds.)
  X = 0
  while [ $X -lt 300 ]
  do
    (echo -n 1 > loading ) 2>/dev/null && break
    X=$[$X+1]
    sleep 0.1
  done

  # Feed in the firmware.
  cat "/lib/firmware/$FIRMWARE" > /sys/$DEVPATH/data &&
    echo 0 > loading ||
    echo 1 > loading
fi

# Call mdev to handle anything it's interested in about this event.

cd /
exec mdev
EOF

I.E. is it really _necessary_ to add this sort of thing to mdev?  Or can't you 
just have a hotplug shell script that falls _back_ to mdev once it's figured 
out it isn't doing something else?  (This doesn't affect the mdev -s path at 
all, this is just the script getting called as the hotplug event and calling 
mdev as necessary.)

> > If you didn't care at all about speed, what you'd do is iterate through
> > /dev and echo "add" to each uevent file to trigger a new hotplug event
> > after boot.
>
> That is udev's approach. Slow, yet reliable.

I was with you up until the word "yet".

> >> I can live with shell script
> >> enumeration of uevent files, thus totally do not need "mdev -s"
> >> portion. But I urgently need hotplug portion. In order to not fork a
> >> new applet I was "tuning" mdev itself. We should definitely separate
> >> mdev into {cold,hot}plug parts, so people can what they need.
> >
> > That seems a significant step in the wrong direction to me.  You're
> > turning one applet into two, but making them share the biggest and most
> > complicated parts of their code.
>
> What else to do if mdev's purity is a saint cow, Rob?

Simplicity, not purity.  And it's not a sacred cow, I'd just like to make sure 
there isn't a _better_ alternative.

> Denys proposed to use any environment variable matching -- that way we
> could get rid of $MODALIAS and $FIRMWARE processing in C. What do you
> think of?

That's what I was thinking of when I talked about changing the config file 
syntax, but the only reason I was going there is I'd been away from the 
problem domain long enough that I'd forgotten one of the original design 
ideas was to _wrap_ mdev with a hotplug handler that does things that it 
isn't interested in.  (Calling mdev from a wrapper script doesn't require any 
modification to mdev.)

Rob
-- 
Latency is more important than throughput. It's that simple. - Linus Torvalds


More information about the busybox mailing list