It's Alright.

Replacing udev with static and mdev2009-11-28

I've been trying to cut down boot times on a new little laptop I got just recently (It's an Aspire One), and one of the big things was udev.

So, I started asking around and googling and everything else for lighterweight alternatives to udev, because in my experience with Linux so far, everything has some sort of "lightweight" alternative.

What I found was mdev. It's part of busybox. After some googling, I found only a small amount of documentation and I was pretty lost. Some IRC chats later, some more digging, and some trial and error, I got things working.

Read on to see how~

(btw this is on Arch Linux but things should be similar for most distros)

I had just finished learning all about mdev, and I ended up messing up my sysinit because I like to mess with it a lot. What I was playing with was the udevadm settle part, adding an & to the end. Recently I switched my sysinit scripts from bash to compiled C (I'll write more on this another time), and with bash the settle finished before it got to the mounting and fscking of drives. With compiled C, the script moves too fast, and what happened was the settle wasn't done finishing by the time the C binary got to mounting the drives.

What I found is that if the settle doesn't finish in time, the /dev stuff isn't there yet. So it tries mounting sd* but there is nothing in /dev (Except for some nodes the init script makes earlier, like null.), so it fails.

It says FSCK has failed, CTRL D for maintenance, etc... So I put in my password and I'm at the terminal. I had put the source code for my sysinit in my home directory, which is on another partition. But there's nothing in /dev to mount of course, so, now what? Then I remembered- mdev! The brilliant mdev! I ran "busybox mdev -s" and my /dev was populated. I was then able to mount my home partition and fix the code.

So, now having a little experience with what mdev does, I decided I would take the plunge and replace udev in my sysinit with mdev. I booted up, it mounted things okay, and then it tried to start X (Because I had automatic log in and X starting), and failed miserably. So then I took X out so I could at least get in, and I found it couldn't even make TTYs...

So there was some things mdev hadn't been doing. It hadn't been making symlinks from ttyn to vc/n, it hadn't been creating some of the video nodes I needed, other stuff. So then I learned about the mdev config file.

In the mdev config file, you can put device nodes, what their uid and gid should be, permissions of said node, symlinks to be made, and then any other commands you would like to be ran after or before the creation of whichever nodes.

If you do 'ls -la' in /dev, you can see all the numbers and things you need to make nodes with. So I decided what I would do is run udev at boot and then do '(cd /dev && ls -la > /tmp/devicelist)', and then I would do the same thing with mdev instead and do it as /tmp/devicelist2, so I could compare the two lists and find what all udev is doing differently, and put those things in my mdev config.

Well I did that, and there was... a lot. A lot of things to change.

I decided to put it off for awhile, it looked intimidating and scary. So in the mean time I decided to research /dev some, find out what all it does and what character and block devices really are, all that stuff. I became curious about static /dev systems, how they do it and everything.

One of the things I couldn't figure out was, why does it delete everything in /dev every time I reboot? And I realized because it's a "virtual" filesystem. So I asked around in #linux on freenode, where a very helpful guy named 'mulk' was. He told me he had his /dev writing to disk, and mine probably is too. I looked all through my rc.shutdown and I couldn't find where it deleted my /dev stuff. So I told him that, and he told me to check the startup scripts. I was doubtful, since I've been through my init scripts amillion times (Told you I rewrote them in C. And that was after rewriting them in bash several times, and then trying to rewrite them to work with dash...). What I found was that it mounts /dev in the beginning as a ramfs. Makes sense.

And here comes the brilliant idea of using a static /dev system with stuff generated by udev. I took out udev stuff from my sysinit, including the line that mounts /dev (Important), rebooted and got the error because it couldn't mount anything (Good). So then in the recovery terminal, I ran these three commands:

udevd &
udevadm trigger
udevadm settle

And so my /dev was populated... I rebooted again. Success. My /dev is no longer emptied out when I reboot, everything works good, and I don't have to run udev on boot anymore! How nice. Although, this still left me with the problem of hotplugging. Even though this is a laptop, sometimes I plug in an external CDROM drive or a flash drive. And so here is where mdev is still very useful.

First of all, you'll need to go ahead and make a symlink for busybox, so that we can launch mdev without doing "busybox" before it. So do:

cd /bin ln -s busybox mdev

Now we need to add hotplugging... You need to put 'echo /bin/mdev > /proc/sys/kernel/hotplug' in your rc.sysinit or whatever your init script is (If you don't know you can look in your /etc/inittab to find out where it is), it doesn't really matter where in your init script you put it, considering we already have a /dev and this is just for new devices; you could even do this after you've started X. I just put mine at the very end.

Then you can test it out by plugging stuff in and seeing if it makes the correct nodes in /dev. Mine worked out of the box, if you have problems you can always e-mail me/IM me. Contact page is going to be put up soon on the site :]