function old new delta packed_usage 28634 28822 +188 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
		
			
				
	
	
		
			152 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
-------------
 | 
						|
 MDEV Primer
 | 
						|
-------------
 | 
						|
 | 
						|
For those of us who know how to use mdev, a primer might seem lame.  For
 | 
						|
everyone else, mdev is a weird black box that they hear is awesome, but can't
 | 
						|
seem to get their head around how it works.  Thus, a primer.
 | 
						|
 | 
						|
-----------
 | 
						|
 Basic Use
 | 
						|
-----------
 | 
						|
 | 
						|
Mdev has two primary uses: initial population and dynamic updates.  Both
 | 
						|
require sysfs support in the kernel and have it mounted at /sys.  For dynamic
 | 
						|
updates, you also need to have hotplugging enabled in your kernel.
 | 
						|
 | 
						|
Here's a typical code snippet from the init script:
 | 
						|
[0] mount -t proc proc /proc
 | 
						|
[1] mount -t sysfs sysfs /sys
 | 
						|
[2] echo /sbin/mdev > /proc/sys/kernel/hotplug
 | 
						|
[3] mdev -s
 | 
						|
 | 
						|
Alternatively, without procfs the above becomes:
 | 
						|
[1] mount -t sysfs sysfs /sys
 | 
						|
[2] sysctl -w kernel.hotplug=/sbin/mdev
 | 
						|
[3] mdev -s
 | 
						|
 | 
						|
 | 
						|
Of course, a more "full" setup would entail executing this before the previous
 | 
						|
code snippet:
 | 
						|
[4] mount -t tmpfs -o size=64k,mode=0755 tmpfs /dev
 | 
						|
[5] mkdir /dev/pts
 | 
						|
[6] mount -t devpts devpts /dev/pts
 | 
						|
 | 
						|
The simple explanation here is that [1] you need to have /sys mounted before
 | 
						|
executing mdev.  Then you [2] instruct the kernel to execute /sbin/mdev whenever
 | 
						|
a device is added or removed so that the device node can be created or
 | 
						|
destroyed.  Then you [3] seed /dev with all the device nodes that were created
 | 
						|
while the system was booting.
 | 
						|
 | 
						|
For the "full" setup, you want to [4] make sure /dev is a tmpfs filesystem
 | 
						|
(assuming you're running out of flash).  Then you want to [5] create the
 | 
						|
/dev/pts mount point and finally [6] mount the devpts filesystem on it.
 | 
						|
 | 
						|
-------------
 | 
						|
 MDEV Config   (/etc/mdev.conf)
 | 
						|
-------------
 | 
						|
 | 
						|
Mdev has an optional config file for controlling ownership/permissions of
 | 
						|
device nodes if your system needs something more than the default root/root
 | 
						|
660 permissions.
 | 
						|
 | 
						|
The file has the format:
 | 
						|
	[-]<device regex>	<uid>:<gid> <permissions>
 | 
						|
or
 | 
						|
	@<maj[,min1[-min2]]>	<uid>:<gid> <permissions>
 | 
						|
or
 | 
						|
	$envvar=<regex>		<uid>:<gid> <permissions>
 | 
						|
 | 
						|
For example:
 | 
						|
	hd[a-z][0-9]* 0:3 660
 | 
						|
 | 
						|
The config file parsing stops at the first matching line.  If no line is
 | 
						|
matched, then the default of 0:0 660 is used.  To set your own default, simply
 | 
						|
create your own total match like so:
 | 
						|
 | 
						|
	.* 1:1 777
 | 
						|
 | 
						|
You can rename/move device nodes by using the next optional field.
 | 
						|
 | 
						|
	<device regex> <uid>:<gid> <permissions> [=path]
 | 
						|
 | 
						|
So if you want to place the device node into a subdirectory, make sure the path
 | 
						|
has a trailing /.  If you want to rename the device node, just place the name.
 | 
						|
	hda 0:3 660 =drives/
 | 
						|
This will move "hda" into the drives/ subdirectory.
 | 
						|
	hdb 0:3 660 =cdrom
 | 
						|
This will rename "hdb" to "cdrom".
 | 
						|
 | 
						|
Similarly, ">path" renames/moves the device but it also creates
 | 
						|
a direct symlink /dev/DEVNAME to the renamed/moved device.
 | 
						|
 | 
						|
You can also prevent creation of device nodes with the 4th field as "!":
 | 
						|
	tty[a-z]. 0:0 660 !
 | 
						|
	pty[a-z]. 0:0 660 !
 | 
						|
 | 
						|
If you also enable support for executing your own commands, then the file has
 | 
						|
the format:
 | 
						|
	<device regex> <uid>:<gid> <permissions> [=path] [@|$|*<command>]
 | 
						|
    or
 | 
						|
	<device regex> <uid>:<gid> <permissions> [>path] [@|$|*<command>]
 | 
						|
    or
 | 
						|
	<device regex> <uid>:<gid> <permissions> [!] [@|$|*<command>]
 | 
						|
 | 
						|
For example:
 | 
						|
---8<---
 | 
						|
# block devices
 | 
						|
([hs]d[a-z])		root:disk	660	>disk/%1/0
 | 
						|
([hs]d[a-z])([0-9]+)	root:disk	660	>disk/%1/%2
 | 
						|
mmcblk([0-9]+)		root:disk	660	>disk/mmc/%1/0
 | 
						|
mmcblk([0-9]+)p([0-9]+)	root:disk	660	>disk/mmc/%1/%2
 | 
						|
# network devices
 | 
						|
(tun|tap)		root:network	660	>net/%1
 | 
						|
---8<---
 | 
						|
 | 
						|
The special characters have the meaning:
 | 
						|
	@ Run after creating the device.
 | 
						|
	$ Run before removing the device.
 | 
						|
	* Run both after creating and before removing the device.
 | 
						|
 | 
						|
The command is executed via the system() function (which means you're giving a
 | 
						|
command to the shell), so make sure you have a shell installed at /bin/sh.  You
 | 
						|
should also keep in mind that the kernel executes hotplug helpers with stdin,
 | 
						|
stdout, and stderr connected to /dev/null.
 | 
						|
 | 
						|
For your convenience, the shell env var $MDEV is set to the device name.  So if
 | 
						|
the device "hdc" was matched, MDEV would be set to "hdc".
 | 
						|
 | 
						|
----------
 | 
						|
 FIRMWARE
 | 
						|
----------
 | 
						|
 | 
						|
Some kernel device drivers need to request firmware at runtime in order to
 | 
						|
properly initialize a device.  Place all such firmware files into the
 | 
						|
/lib/firmware/ directory.  At runtime, the kernel will invoke mdev with the
 | 
						|
filename of the firmware which mdev will load out of /lib/firmware/ and into
 | 
						|
the kernel via the sysfs interface.  The exact filename is hardcoded in the
 | 
						|
kernel, so look there if you need to know how to name the file in userspace.
 | 
						|
 | 
						|
------------
 | 
						|
 SEQUENCING
 | 
						|
------------
 | 
						|
 | 
						|
Kernel does not serialize hotplug events. It increments SEQNUM environmental
 | 
						|
variable for each successive hotplug invocation. Normally, mdev doesn't care.
 | 
						|
This may reorder hotplug and hot-unplug events, with typical symptoms of
 | 
						|
device nodes sometimes not created as expected.
 | 
						|
 | 
						|
However, if /dev/mdev.seq file is found, mdev will compare its
 | 
						|
contents with SEQNUM. It will retry up to two seconds, waiting for them
 | 
						|
to match. If they match exactly (not even trailing '\n' is allowed),
 | 
						|
or if two seconds pass, mdev runs as usual, then it rewrites /dev/mdev.seq
 | 
						|
with SEQNUM+1.
 | 
						|
 | 
						|
IOW: this will serialize concurrent mdev invocations.
 | 
						|
 | 
						|
If you want to activate this feature, execute "echo >/dev/mdev.seq" prior to
 | 
						|
setting mdev to be the hotplug handler. This writes single '\n' to the file.
 | 
						|
NB: mdev recognizes /dev/mdev.seq consisting of single '\n' character
 | 
						|
as a special case. IOW: this will not make your first hotplug event
 | 
						|
to stall for two seconds.
 |