But if your virtual machine is hosting a qemu guest, then in that guest a fork/exec can take 0.2 of a second, and MAKEDEV generic-i386 can take a couple of hours. (This is because the kqemu kernel module is not available, http://www.linuxquestions.org/questions/linux-virtualization-and-cloud-90/qemu-running-on-ubuntu-vmware-guest-cannot-find-dev-kvm-936253/).
The first hacky-hack to cut down on the number of fork/exec is to stop calling sed quite so often, cue this patch (requires MAKEDEV to run under bash).
--- /sbin/MAKEDEV 2009-07-30 08:39:09.000000000 -0700
+++ /MAKEDEV 2014-02-21 06:31:43.000000000 -0800
@@ -1,4 +1,4 @@
-#! /bin/sh -
+#! /bin/bash -
# $Id$
#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
@@ -116,7 +116,9 @@
devicename () { # translate device names to something safe
# A-Z is not full alphabet in all locales (e.g. in et_EE)
- echo "$*" | LC_ALL=C sed -e 's/[^A-Za-z0-9_]/_/g'
+ #echo "$*" | LC_ALL=C sed -e 's/[^A-Za-z0-9_]/_/g'
+ echo "${*//[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]/_}"
+
}
makedev () { # usage: makedev name [bcu] major minor owner group mode
@@ -231,12 +233,14 @@
exec 3<$procfs/devices
while read major device extra <&3
do
- device=`echo $device | sed 's#/.*##'`
+ #device=`echo $device | sed 's#/.*##'`
+ device="${device%%/*}"
case "$major" in
Character|Block|'')
;;
*)
- safedevname=`devicename $device`
+ safedevname="${device//[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234566
+789]/_}"
eval "major_$safedevname=$major"
devices="$devices $device"
;;
@@ -247,7 +251,8 @@
Major () {
device=$2
- devname=`devicename $1`
+ devname="${1//[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234566
+789]/_}"
if [ "$opt_d" ]
then
echo -1 # don't care
@@ -2149,7 +2154,8 @@
exec 3<$procfs/devices
while read major device extra <&3
do
- device=`echo $device | sed 's#/.*##'`
+ # device=`echo $device | sed 's#/.*##'`
+ device="${device%%/*}"
case "$major" in
Character|Block|'')
;;
The next hack is to stop the 5 or 6 fork/exec when MAKEDEV deletes a device node, creates a (temporary device node), chmods it, chowns it, and renames it.
How do we do that? We run MAKEDEV -n so that it does none of these and then feed the output to a perl script which will do them.
Sadly perl has no native mknod call and there are no libraries in this environment, and so I use perl's blessed syscall function with a hard-wired syscall 133 for mknod (as it is, on my kernel):
time /MAKEDEV -n generic-i386 | perl -ne '
print;
umask(0);
($c, $f, $node, $major, $minor, $own, $perm) = split;
if ($node eq "->") {
symlink($major, $f) || die "sym: $!";
} else {
# system("mknod",$f,$node,$major,$minor) && die "mknod($f,$node,$major,$minor): $? $!";
# chmod(oct($perm), $f) || die "chmod: $!";
$n=0;
$n=0010000 if ($node eq "f");
$n=0020000 if ($node eq "c");
$n=0060000 if ($node eq "b");
$n=0140000 if ($node eq "s");
if (syscall(133, $f, oct($perm) | $n, (($minor & 0xff) | (($major & 0xfff) << 8)
| (( ($minor & ~0xff)) << 12)
| (( ($major & ~0xfff)) << 32))) == -1) { die "syscall: $!"; }
($user,$group)=split(/:/,$own);
$user=getpwnam($user);
$group=getgrnam($group);
chown($user,$group,$f) || die "chown: $own $!";
}
'
Leaving in the system("mknod,...) took around 24 minutes, but moving straight to syscall(mknod,...) takes1 minute 8 seconds.
I did toy with having bash use printf or something to pack a binary tar archive (or even getting perl to pack a tar archive) to pipe to tar -x, but... this will have to do for now.
I suspect this depends on a bug in MAKEDEV which seems to still create sub-directories needed even in -n mode.
It would have been better to pipe the output to a c program which would parse it, I will do that, another day...