[PATCH] Speed up modprobe and MAKEDEV

Jakub Jelinek jakub at redhat.com
Wed Oct 1 16:52:15 UTC 2008


Hi!

Given the recent 5sec boot efforts http://lwn.net/Articles/299483/
and Mandriva follow-ups on that http://lwn.net/Articles/300873/,
I thought I'd share my modprobe and MAKEDEV speedup patches with
a wider community so folks can experiment with them, especially seeing
Mandriva folks playing with turning modprobe into a daemon because of its
slowness.

modprobe is quite slow, as it on every invocation sources a ~ 7500
line long modules.alias file from which it calls fnmatch on the wildcards
from every line, and a ~ 350KB modules.dep file which it searches through
for module dependencies, but usually those files are just generated by
depmod -a and never modified by humans afterwards.  This patch in depmod -a
in addition to generation of the text files writes more compact binary files
which are only used if the text file hasn't been modified and allow much
faster searching for aliases or dependencies.
MAKEDEV sources almost 500KB of config files on every invocation, and the
inner loop is terribly inefficient.  The second patch allows it to shrink
the files to 55KB while expressing the same info and makes the inner loop
more efficient.  Depending on how many modprobe and MAKEDEV invocations
are done on your box during bootup, this can or might not make meassurable
difference.

The modprobe patch has been actually posted almost a year ago privately,
but nothing has been changed upstream, below is an updated version, retested
against latest rawhide module-init-tools, the MAKEDEV patch is actually from
last week.  IMHO the binary caches for modprobe are better than
having thousands of symlinks around (given 7500 wildcards where for many of
them a few dozens of symlinks would be needed), especially if the symlinks
would be included in rpm package, but I can be of course convinced
otherwise.  In any case, the module-init-tools contains a bunch of speedups
that are IMHO desirable anyway, even without the modules.{dep,alias}cache
files.

	Jakub
-------------- next part --------------
For modules.dep depmod -a also creates modules.depcache which is just  
a simple hash table with chains and a dumb fast compression of strings,
so that modules.depcache is roughly 3 times smaller than modules.dep.
The hash function already makes no difference between _ and -, so for dep
lookups all it needs is compute the hash, walk the chain, comparing full
32-bit hash value and if that hits, compare also modname string, on success
just return that and its dependencies.

For modules.alias it creates modules.aliascache, which contains a tree.
Each tree node has 0 or more associated fnmatch wildcards that need to be
fnmatched at that level unconditionally, then some fixed number of
characters and prefixes of up to that length can be binary searched to
find further node.  The further node can be of 3 types - either again
a normal range node, or just a pointer to a result (if all chars have been
already compared), or an entry containing remaining chars to strncmp and
pointer to result.  Guess better is just to read the algorithm in modprobe.c
for details.  When reading modules.alias, modprobe always calls fnmatch
on all patterns in there and fnmatch is quite expensive.  With
modules.aliascache, for some strings which don't have any wildcards in it,
fnmatch isn't called at all, otherwise it is called only on wildcards where
its prefix consisting of non-wildcard chars matches the input.

Both modules.depcache and modules.aliascache contain a file header, which
embeds a version number, endianity and mtime/ino/size of the corresponding
modules.{dep,alias} file - in case it is hand edited later, modprobe won't
use the cache which will be stale in that case, until regenerated.

In addition to these changes there are some small cleanups here and there,
e.g. as modprobe and depmod aren't threaded we can speed things up quite a
lot by using _unlocked functions, or there is no point for every
getline_wrapped to malloc new chunk of memory and let the caller free it
(almost) immediately again.

vanilla, modules.dep (time to handle ~ 1600 dep searches):
real    0m6.554s
user    0m6.424s
sys     0m0.128s

patched + modules.depcache
real    0m0.042s
user    0m0.008s
sys     0m0.034s

vanilla, modules.alias (time to handle ~ 6400 alias searches):
real    1m22.548s
user    1m21.554s
sys     0m0.965s

patched + modules.aliascache
real    0m0.552s
user    0m0.438s
sys     0m0.114s

time of modprobe pci:v0000EA60d00009897svAsdBbcCscDiE
real    0m0.034s
user    0m0.028s
sys     0m0.006s
vs.
real    0m0.007s
user    0m0.004s
sys     0m0.003s

--- module-init-tools-3.4.1/depmod.c.jj	2008-10-01 17:31:35.000000000 +0200
+++ module-init-tools-3.4.1/depmod.c	2008-10-01 17:32:14.000000000 +0200
@@ -24,6 +24,7 @@
 #include "depmod.h"
 #include "moduleops.h"
 #include "tables.h"
+#include "cache.h"
 
 #include "testing.h"
 
@@ -503,6 +504,443 @@ static void output_deps(struct module *m
 	}
 }
 
+static const char *base_dirname;
+
+struct depcache_dir
+{
+	const char *name;
+	struct depcache_dir *next, *same_dir;
+	unsigned int count, len;
+	int idx;
+};
+
+struct depcache_string
+{
+	struct depcache_string *next;
+	unsigned int hash;
+	unsigned int offset;
+	unsigned int size;
+	struct depcache_dir dir;
+	char name[];
+};
+
+struct depcache_strings
+{
+	struct depcache_string *hash[251];
+	struct depcache_dir *dirs[256];
+	struct depcache_dir dir0;
+	unsigned int dircount;
+	unsigned int count;
+	unsigned int offset;
+};
+
+static void
+depcache_add_string(struct depcache_strings *strings, const char *name)
+{
+	size_t len = strlen(name);
+	unsigned int hash = dep_cache_hash(name, len);
+	struct depcache_string **string = &strings->hash[hash % 251], *s;
+
+	while (*string != NULL) {
+		if ((*string)->hash == hash
+		    && strcmp((*string)->name, name) == 0)
+			return;
+		string = &(*string)->next;
+	}
+
+	s = NOFAIL(malloc(sizeof(struct depcache_string) + len + 1));
+	s->next = NULL;
+	s->hash = hash;
+	s->offset = -1;
+	s->size = len + 1;
+	memcpy(s->name, name, len + 1);
+	strings->count++;
+	*string = s;
+}
+
+static int
+depcache_dir_cmp(const void *a, const void *b)
+{
+	const struct depcache_dir *dira = a;
+	const struct depcache_dir *dirb = b;
+
+	if (dira->count > dirb->count)
+		return -1;
+	if (dira->count < dirb->count)
+		return 1;
+	if (dira->len > dirb->len)
+		return -1;
+	if (dira->len < dirb->len)
+		return 1;
+	return 0;
+}
+
+static void
+depcache_finalize_strings(struct depcache_strings *strings)
+{
+	unsigned int hash, dhash, offset, k, l;
+	size_t dircount = 0;
+	struct depcache_dir *dirhash[251], **dh, **dhs, *d;
+	int count;
+
+	memset (dirhash, '\0', sizeof (dirhash));
+	for (hash = 0; hash < 251; hash++) {
+		struct depcache_string *string = strings->hash[hash];
+
+		while (string != NULL) {
+			char *p = strrchr(string->name, '/');
+			if (p != NULL) {
+				dhash = dep_cache_hash(string->name,
+						       p - string->name + 1);
+				for (dh = &dirhash[dhash % 251];
+				     *dh; dh = &(*dh)->next) {
+					if ((*dh)->len != p - string->name + 1)
+						continue;
+					if (memcmp(string->name, (*dh)->name,
+						   (*dh)->len) != 0)
+						continue;
+					string->dir.same_dir = (*dh)->same_dir;
+					(*dh)->same_dir = &string->dir;
+					++(*dh)->count;
+					break;
+				}
+				if (*dh == NULL) {
+					string->dir.name = string->name;
+					string->dir.next = *dh;
+					string->dir.count = 1;
+					string->dir.len = p - string->name + 1;
+					string->dir.idx = -1;
+					string->dir.same_dir = NULL;
+					*dh = &string->dir;
+					++dircount;
+				}
+			}
+			string = string->next;
+		}
+	}
+
+	/* Compute the length of directory prefix common to
+	   all entries.  */
+	strings->dircount = 1;
+	strings->dirs[0] = &strings->dir0;
+	strings->dir0.len = -1;
+	for (dhash = 0, k = 0; dhash < 251; dhash++) {
+		d = dirhash[dhash];
+		while (d != NULL) {
+			if (strings->dir0.len == -1) {
+				strings->dir0.name = d->name;
+				strings->dir0.len = d->len;
+			} else {
+				int i;
+				for (i = 0; i < d->len
+					    && i < strings->dir0.len; ++i) {
+					if (strings->dir0.name[i]
+					    != d->name[i])
+						break;
+				}
+				if (i < strings->dir0.len) {
+					while (i > 0
+					       && strings->dir0.name[i - 1]
+						  != '/')
+						--i;
+					strings->dir0.len = i;
+					if (i == 0)
+						goto no_dir0;
+				}
+			}
+			d = d->next;
+		}
+	}
+no_dir0:;
+	/* Assign the remaining up to 255 directory table
+	   entries, starting with most often used ones.  */
+	dhs = NOFAIL(malloc(sizeof(*dhs) * dircount));
+	count = 128;
+	while (strings->dircount < 256) {
+		for (dhash = 0, k = 0; dhash < 251; dhash++) {
+			d = dirhash[dhash];
+			while (d != NULL) {
+				if (d->idx == -1)
+					dhs[k++] = d;
+				d = d->next;
+			}
+		}
+
+		qsort(dhs, k, sizeof(*dhs), depcache_dir_cmp);
+
+		for (l = 0; l < count && l < k; ++l) {
+			strings->dirs[strings->dircount] = dhs[l];
+			dhs[l]->idx = strings->dircount++;
+			for (d = dhs[l]->same_dir; d; d = d->same_dir) {
+				d->len = dhs[l]->len;
+				d->idx = dhs[l]->idx;
+			}
+			if (strings->dircount == 256)
+				goto idx_done;
+		}
+		if (l == k)
+			goto idx_done;
+		count /= 2;
+		memset(dirhash, '\0', sizeof(dirhash));
+		for (; l < k; ++l) {
+			unsigned m = dhs[l]->len;
+			if (m != 0) {
+				--m;
+				while (m > 0)
+					if (dhs[l]->name[m - 1] == '/')
+						break;
+					else
+						--m;
+			}
+			if (m == 0) {
+				dhs[l]->len = 0;
+				dhs[l]->idx = 0;
+				for (d = dhs[l]->same_dir; d;
+				     d = d->same_dir) {
+					d->len = dhs[l]->len;
+					d->idx = dhs[l]->idx;
+				}
+				continue;
+			} else {
+				dhs[l]->len = m;
+				dhash = dep_cache_hash(dhs[l]->name,
+						       dhs[l]->len);
+				for (dh = &dirhash[dhash % 251];
+				     *dh; dh = &(*dh)->next) {
+					if ((*dh)->len != dhs[l]->len)
+						continue;
+					if (memcmp((*dh)->name, dhs[l]->name,
+						   (*dh)->len) != 0)
+						continue;
+					(*dh)->count += dhs[l]->count;
+					for (dh = &(*dh)->same_dir;
+					     *dh; dh = &(*dh)->same_dir);
+					*dh = dhs[l];
+					break;
+				}
+				if (*dh == NULL) {
+					*dh = dhs[l];
+					dhs[l]->next = NULL;
+				}
+			}
+		}
+	}
+idx_done:;
+	free(dhs);
+	offset = strings->dircount * sizeof(unsigned int) * 2;
+	offset += strings->dir0.len;
+	for (k = 1; k < strings->dircount; ++k)
+		offset += strings->dirs[k]->len - strings->dir0.len;
+	for (hash = 0; hash < 251; hash++) {
+		struct depcache_string *string = strings->hash[hash];
+
+		while (string != NULL) {
+			if (string->dir.idx == -1)
+				string->dir.idx = 0;
+			string->size -= string->dir.len - 1;
+			string->offset = offset;
+			offset += string->size;
+			string = string->next;
+		}
+	}
+}
+
+static void
+depcache_output_strings(struct depcache_strings *strings, unsigned int offset,
+			FILE *out)
+{
+	unsigned int hash, k;
+
+	offset += strings->dircount * sizeof(unsigned int) * 2;
+	fwrite_unlocked(&offset, 1, sizeof(offset), out);
+	fwrite_unlocked(&strings->dir0.len, 1, sizeof(strings->dir0.len), out);
+	offset += strings->dir0.len;
+	for (k = 1; k < strings->dircount; ++k) {
+		fwrite_unlocked(&offset, 1, sizeof(offset), out);
+		fwrite_unlocked(&strings->dirs[k]->len, 1,
+				sizeof(strings->dirs[k]->len), out);
+		offset += strings->dirs[k]->len - strings->dir0.len;
+	}
+	fwrite_unlocked(strings->dir0.name, strings->dir0.len, 1, out);
+	for (k = 1; k < strings->dircount; ++k)
+		fwrite_unlocked(strings->dirs[k]->name + strings->dir0.len,
+				strings->dirs[k]->len - strings->dir0.len,
+				1, out);
+	for (hash = 0; hash < 251; hash++) {
+		struct depcache_string *string = strings->hash[hash];
+
+		while (string != NULL) {
+			unsigned int len = strings->dirs[string->dir.idx]->len;
+			fputc_unlocked(string->dir.idx, out);
+			fwrite_unlocked(string->name + len, string->size - 1,
+					1, out);
+			string = string->next;
+		}
+	}
+}
+
+static unsigned int
+depcache_string_offset(struct depcache_strings *strings, const char *name,
+		       unsigned int *end)
+{
+	size_t len = strlen(name);
+	unsigned int hash = dep_cache_hash(name, len);
+	struct depcache_string *string = strings->hash[hash % 251];
+
+	while (string != NULL) {
+		if (string->hash == hash
+		    && strcmp(string->name, name) == 0) {
+			if (end)
+				*end = string->offset + string->size - 1;
+			return string->offset;
+		}
+		string = string->next;
+	}
+	abort();
+}
+
+static int primes[] = { 61, 127, 251, 509, 1021, 2039, 4093, 8191,
+			16381, 32749, 65521, 131071 };
+
+static void output_depcache(struct module *modules, FILE *out)
+{
+	struct module *i;
+	unsigned int count, n;
+	struct dep_cache_entry **dce;
+	struct dep_cache header;
+	unsigned int *dce_offsets, offset;
+	unsigned int *hashtab, *hashtab_idx;
+	struct depcache_strings strings;
+	size_t base_dirname_len = strlen(base_dirname);
+	char dep_filename[base_dirname_len + sizeof "/modules.dep"];
+	struct stat st;
+
+	/* Don't output a binary file to stdout.  */
+	if (out == stdout)
+		return;
+
+	memcpy(dep_filename, base_dirname, base_dirname_len);
+	strcpy(dep_filename + base_dirname_len, "/modules.dep");
+	if (stat(dep_filename, &st) < 0)
+		return;
+
+	memset(&strings, 0, sizeof(strings));
+
+	for (i = modules, count = 0; i; i = i->next) {
+		depcache_add_string(&strings, i->pathname + skipchars);
+		count++;
+	}
+	depcache_finalize_strings(&strings);
+
+	dce = NOFAIL(malloc((sizeof(*dce) + sizeof(*dce_offsets)) * count));
+	dce_offsets = (unsigned int *) (dce + count);
+
+	for (i = modules, n = 0; i; i = i->next, n++) {
+		unsigned int ndependencies = 0, k, end;
+		struct list_head *j, *tmp;
+		const char *modname, *p;
+
+		order_dep_list(i, i);
+
+		list_for_each_safe(j, tmp, &i->dep_list)
+			ndependencies++;
+
+		dce[n] = NOFAIL(malloc(sizeof(struct dep_cache_entry)
+				       + ndependencies * sizeof(int)));
+		modname = strrchr(i->pathname + skipchars, '/');
+		if (modname == NULL)
+			modname = i->pathname + skipchars;
+		else
+			modname++;
+		p = strchr(modname, '.');
+		dce[n]->modname_len = p ? p - modname : strlen(modname);
+		dce[n]->hash = dep_cache_hash(modname, dce[n]->modname_len);
+		dce[n]->next = 0xffffffff;
+		dce[n]->fullname
+		  = depcache_string_offset(&strings, i->pathname + skipchars,
+					   &end);
+		dce[n]->modname = end - strlen(modname);
+		k = 0;
+		list_for_each_safe(j, tmp, &i->dep_list) {
+			struct module *dep
+				= list_entry(j, struct module, dep_list);
+			dce[n]->dependencies[k++]
+			  = depcache_string_offset(&strings,
+						   dep->pathname + skipchars,
+						   NULL);
+			list_del_init(j);
+		}
+		dce[n]->num_dependencies = k;
+	}
+
+	memset(&header, 0, sizeof(header));
+	memcpy(header.magic, "mod-dep-cache", sizeof(header.magic));
+	header.version = 1;
+	header.endian = 0x12345678;
+	for (n = 0; n < (sizeof(primes) / sizeof(primes[0])) - 1; n++)
+		if (count < primes[n])
+			break;
+	header.hash_size = primes[n];
+	header.hash_offset = sizeof(header);
+	header.moddep_mtime_high = (st.st_mtime >> 16) >> 16;
+	header.moddep_mtime_low = st.st_mtime;
+	header.moddep_size = st.st_size;
+	header.moddep_ino = st.st_ino;
+	hashtab = NOFAIL(malloc(2 * header.hash_size * sizeof(*hashtab)));
+	hashtab_idx = hashtab + header.hash_size;
+	memset(hashtab_idx, 0xff, header.hash_size * sizeof(*hashtab));
+	for (n = 0; n < count; n++) {
+		unsigned int *p
+		  = &hashtab_idx[dce[n]->hash % header.hash_size];
+
+		while (*p != 0xffffffff)
+			p = &dce[*p]->next;
+		*p = n;
+	}
+
+	offset = sizeof(header) + header.hash_size * sizeof(*hashtab);
+	memset(dce_offsets, 0xff, sizeof(*dce_offsets) * count);
+	for (n = 0; n < header.hash_size; n++) {
+		unsigned int p = hashtab_idx[n];
+		if (p == 0xffffffff)
+			hashtab[n] = p;
+		else
+			hashtab[n] = offset;
+		while (p != 0xffffffff) {
+			dce_offsets[p] = offset;
+			offset += sizeof(**dce)
+				  + dce[p]->num_dependencies
+				    * sizeof(dce[p]->dependencies[0]);
+			p = dce[p]->next;
+		}
+	}
+
+	header.dir_table_offset = offset;
+	fwrite_unlocked(&header, sizeof(header), 1, out);
+	fwrite_unlocked(hashtab, sizeof(*hashtab), header.hash_size, out);
+
+	for (n = 0; n < header.hash_size; n++) {
+		unsigned int p = hashtab_idx[n];
+		while (p != 0xffffffff) {
+			unsigned int nextp = dce[p]->next, k;
+			if (nextp != 0xffffffff)
+				dce[p]->next = dce_offsets[dce[p]->next];
+			dce[p]->modname += offset;
+			dce[p]->fullname += offset;
+			for (k = 0; k < dce[p]->num_dependencies; k++)
+				dce[p]->dependencies[k] += offset;
+			fwrite_unlocked(dce[p],
+					sizeof(**dce)
+					+ dce[p]->num_dependencies
+					  * sizeof(dce[p]->dependencies[0]),
+					1, out);
+			p = nextp;
+		}
+	}
+
+	depcache_output_strings(&strings, header.dir_table_offset, out);
+}
+
 static int smells_like_module(const char *name)
 {
 	return ends_in(name,".ko") || ends_in(name, ".ko.gz");
@@ -744,11 +1182,65 @@ static const char *next_string(const cha
 	return string;
 }
 
+struct aliascache_ent
+{
+	const char *wildcard;
+	unsigned int modname_idx;
+};
+
+struct aliascache_ent *aliascache;
+size_t aliascache_allocated;
+size_t aliascache_count;
+
+/* Careful!  Don't munge - in [ ] as per Debian Bug#350915 */
+static char *underscores(char *string)
+{
+	if (string) {
+		unsigned int i;
+		int inbracket = 0;
+		for (i = 0; string[i]; i++) {
+			switch (string[i]) {
+			case '[':
+				inbracket++;
+				break;
+			case ']':
+				inbracket--;
+				break;
+			case '-':
+				if (!inbracket)
+					string[i] = '_';
+			}
+		}
+		if (inbracket)
+			warn("Unmatched bracket in %s\n", string);
+	}
+	return string;
+}
+
+static void aliascache_add(const char *wildcard, unsigned int modname_idx)
+{
+	char *p;
+	if (aliascache_allocated == aliascache_count) {
+		if (aliascache_allocated)
+			aliascache_allocated *= 2;
+		else
+			aliascache_allocated = 128;
+		aliascache = NOFAIL(realloc(aliascache,
+					    aliascache_allocated
+					    * sizeof(*aliascache)));
+	}
+	p = NOFAIL(strdup(wildcard));
+	underscores(p);
+	aliascache[aliascache_count].wildcard = p;
+	aliascache[aliascache_count++].modname_idx = modname_idx;
+}
+
 static void output_aliases(struct module *modules, FILE *out)
 {
 	struct module *i;
 	const char *p;
 	unsigned long size;
+	unsigned int modname_idx = 0;
 
 	fprintf(out, "# Aliases extracted from modules themselves.\n");
 	for (i = modules; i; i = i->next) {
@@ -759,17 +1251,401 @@ static void output_aliases(struct module
 		/* Grab from old-style .modalias section. */
 		for (p = i->ops->get_aliases(i, &size);
 		     p;
-		     p = next_string(p, &size))
+		     p = next_string(p, &size)) {
 			fprintf(out, "alias %s %s\n", p, modname);
+			aliascache_add(p, modname_idx);
+		}
 
 		/* Grab form new-style .modinfo section. */
 		for (p = i->ops->get_modinfo(i, &size);
 		     p;
 		     p = next_string(p, &size)) {
-			if (strncmp(p, "alias=", strlen("alias=")) == 0)
+			if (strncmp(p, "alias=", strlen("alias=")) == 0) {
 				fprintf(out, "alias %s %s\n",
 					p + strlen("alias="), modname);
+				aliascache_add(p + strlen("alias="),
+					       modname_idx);
+			}
+		}
+
+		modname_idx += strlen(modname) + 1;
+	}
+}
+
+static int aliascache_cmp(const void *p1, const void *p2)
+{
+	const struct aliascache_ent *ac1 = p1;
+	const struct aliascache_ent *ac2 = p2;
+	return strcmp(ac1->wildcard, ac2->wildcard);
+}
+
+struct aliascache_range
+{
+	struct alias_cache_range header;
+	unsigned int first, last, offset, depth;
+	unsigned int wild_size;
+	struct aliascache_range *array[];
+};
+
+static struct aliascache_range *aliascache_create_range(unsigned int depth,
+							unsigned int first,
+							unsigned int last,
+							unsigned int *offset,
+							unsigned int *singles)
+{
+	unsigned int wild[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	unsigned int ends[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	unsigned int dups[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	unsigned int i, j, k, l, wildc, endc, size, normc, nodups;
+	struct aliascache_range *ret;
+
+	for (i = first; i <= last; i++) {
+		for (j = 0; j < 10; j++) {
+			switch (aliascache[i].wildcard[depth + j]) {
+			case '\0':
+				ends[j]++;
+				if (i != first
+				    && strcmp(&aliascache[i].wildcard[depth],
+					      &aliascache[i - 1].wildcard[depth])
+				       == 0)
+					dups[j]++;
+				j = 51;
+				break;
+			case '\\':
+			case '?':
+			case '*':
+			case '[':
+				wild[j]++;
+				j = 52;
+				break;
+			default:
+				break;
+			}
+			if (i != first && j < 51
+			    && strncmp(&aliascache[i].wildcard[depth],
+				       &aliascache[i - 1].wildcard[depth],
+				       j + 1) == 0)
+				dups[j]++;
+		}
+	}
+
+	if (ends[0] == last + 1 - first) {
+		nodups = 1;
+		normc = last + 1 - first;
+		wildc = 0;
+		i = 0;
+	} else {
+		nodups = 0;
+		for (j = 0; j < 10; j++)
+			if (wild[j] != 0 || ends[j] != 0)
+				break;
+		wildc = 0;
+		endc = 0;
+		for (i = j; i < 10; i++) {
+			endc += ends[i];
+			if (wildc + wild[i] > 5 + wild[j])
+				break;
+			if (last + 1 - first - wildc < endc * 2)
+				break;
+			wildc += wild[i];
+		}
+		if (i == 0) {
+			i = 1;
+			wildc += wild[0];
+		}
+		normc = last + 1 - first - dups[i - 1] - wildc;
+	}
+	if (i == 10 && wildc == 0 && normc == 1) {
+		for (; i < 50; i++) {
+			if (aliascache[first].wildcard[depth + i]
+			    != aliascache[last].wildcard[depth + i])
+				break;
+			switch (aliascache[first].wildcard[depth + i]) {
+			case '\0':
+			case '\\':
+			case '?':
+			case '*':
+			case '[':
+				break;
+			default:
+				continue;
+			}
+			break;
+		}
+	}
+	size = sizeof(struct alias_cache_range);
+	size += (normc + wildc) * sizeof(unsigned int);
+	size += normc * i;
+	ret = NOFAIL(calloc(sizeof(*ret)
+			    + normc * sizeof(ret->array[0]), 1));
+	ret->header.nchars = i;
+	ret->header.count_normal = normc;
+	ret->header.count_wild = wildc;
+	ret->first = first;
+	ret->last = last;
+	ret->offset = *offset;
+	ret->depth = depth;
+	*offset += size;
+	for (i = first; i <= last; i++) {
+		for (j = 0; j < ret->header.nchars; j++) {
+			switch (aliascache[i].wildcard[depth + j]) {
+			case '\0':
+				j = 51;
+				break;
+			case '\\':
+			case '?':
+			case '*':
+			case '[':
+				j = 52;
+				ret->wild_size += strlen(aliascache[i].wildcard
+							 + depth) + 1;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+	*offset = (*offset + ret->wild_size + 3) & ~3;
+	for (i = first, k = 0; i <= last; i++) {
+		for (j = 0; j < ret->header.nchars; j++) {
+			switch (aliascache[i].wildcard[depth + j]) {
+			case '\0':
+				j = 51;
+				break;
+			case '\\':
+			case '?':
+			case '*':
+			case '[':
+				j = 52;
+				break;
+			default:
+				break;
+			}
+		}
+		if (j == 52 + 1)
+			continue;
+		for (l = i; l < last; l++)
+			if (strncmp(&aliascache[i].wildcard[depth],
+				    &aliascache[l + 1].wildcard[depth],
+				    ret->header.nchars) != 0)
+				break;
+		if ((j == 51 + 1 && i == l) || j == 0) {
+			ret->array[k] = (void *) 1UL;
+			l = i;
+		} else if (i == l
+			 && !aliascache[l].wildcard[depth
+						    + ret->header.nchars])
+			/* One string, exactly nchars long.  */
+			ret->array[k] = (void *) 1UL;
+		else if (i == l) {
+			const char *p;
+			/* Only one entry.  If it has no wildcards,
+			   create the special singles entry.  */
+			for (j = ret->header.nchars;
+			     ret->array[k] == NULL; j++)
+				switch (aliascache[i].wildcard[depth + j]) {
+				case '\0':
+					p = aliascache[i].wildcard;
+					p += depth + ret->header.nchars;
+					*singles += sizeof(unsigned int);
+					*singles += strlen(p) + 1;
+					*singles = (*singles + 3) & ~3;
+					ret->array[k] = (void *) 2UL;
+					break;
+				case '\\':
+				case '?':
+				case '*':
+				case '[':
+					goto create_range;
+				default:
+					break;
+			}
+		} else if (j == 51 + 1) {
+			size_t len = strlen(aliascache[i].wildcard);
+			ret->array[k]
+			  = aliascache_create_range(len, i, l, offset,
+						    singles);
+		}
+		if (ret->array[k] == NULL) {
+create_range:
+			ret->array[k]
+			  = aliascache_create_range(depth + ret->header.nchars,
+						    i, l, offset, singles);
+		}
+		k++;
+		i = l;
+	}
+	if (k != normc)
+		abort();
+
+	return ret;
+}
+
+struct aliascache_write_info
+{
+	FILE *out;
+	unsigned int singles, offset;
+	char *singles_buf;
+};
+
+static void aliascache_write_range(struct aliascache_write_info *info,
+				   struct aliascache_range *range)
+{
+	size_t size;
+	char *buf, *strings, *wildcards;
+	unsigned int *arr, i, j, k, l, m;
+
+	size = sizeof(range->header);
+	size += (range->header.count_normal + range->header.count_wild)
+		* sizeof(unsigned int);
+	size += range->header.count_normal * range->header.nchars;
+	size += range->wild_size;
+	size = (size + 3) & ~3;
+	buf = NOFAIL(malloc(size));
+	memcpy(buf, &range->header, sizeof(range->header));
+	arr = (unsigned int *) (buf + sizeof(range->header));
+	strings = (char *) (arr + (range->header.count_normal
+				   + range->header.count_wild));
+	wildcards = strings
+		    + range->header.count_normal * range->header.nchars;
+	memset (wildcards + range->wild_size, '\0',
+		(buf + size) - (wildcards + range->wild_size));
+
+	m = range->header.count_normal;
+	for (i = range->first, k = 0; i <= range->last; i++) {
+		const char *p = &aliascache[i].wildcard[range->depth];
+		for (j = 0; j < range->header.nchars; j++) {
+			switch (p[j]) {
+			case '\0':
+				j = 51;
+				break;
+			case '\\':
+			case '?':
+			case '*':
+			case '[':
+				j = 52;
+				break;
+			default:
+				break;
+			}
 		}
+		if (j == 52 + 1) {
+			size_t len = strlen(p);
+			memcpy(wildcards, p, len + 1);
+			wildcards += len + 1;
+			arr[m++] = aliascache[i].modname_idx + info->offset;
+		} else if (j == 0) {
+			if (range->array[k] != (void *) 1UL)
+				abort();
+			arr[k++] = aliascache[i].modname_idx + info->offset;
+		} else {
+			strncpy(strings, p, range->header.nchars);
+			strings += range->header.nchars;
+			for (l = i; l < range->last; l++)
+				if (strncmp(p,
+					    &aliascache[l + 1].wildcard[range->depth],
+					    range->header.nchars) != 0)
+					break;
+			if (range->array[k] == (void *) 1UL) {
+				if (i != l)
+					abort();
+				arr[k] = aliascache[i].modname_idx
+					 + info->offset;
+			} else if (range->array[k] == (void *) 2UL) {
+				size_t len = strlen(p + range->header.nchars);
+				char *r;
+				if (i != l)
+					abort();
+				*(unsigned int *) info->singles_buf
+				  = aliascache[i].modname_idx + info->offset;
+				r = info->singles_buf + sizeof(unsigned int);
+				memcpy(r, p + range->header.nchars, len + 1);
+				r += len + 1;
+				arr[k] = info->singles;
+				len += sizeof(unsigned int) + 1;
+				len = (len + 3) & ~3;
+				memset(r, '\0', (info->singles_buf + len) - r);
+				info->singles_buf += len;
+				info->singles += len;
+			} else
+				arr[k] = range->array[k]->offset;
+			k++;
+			i = l;
+		}
+	}
+
+	if (k != range->header.count_normal
+	    || m != k + range->header.count_wild)
+		abort();
+	fwrite_unlocked(buf, size, 1, info->out);
+	free(buf);
+
+	for (k = 0; k < range->header.count_normal; k++)
+		if (range->array[k] != (void *) 1UL
+		    && range->array[k] != (void *) 2UL)
+			aliascache_write_range(info, range->array[k]);
+}
+
+static void output_aliascache(struct module *modules, FILE *out)
+{
+	struct module *i;
+	struct aliascache_range *root;
+	struct alias_cache header;
+	unsigned int offset = sizeof (header), singles = 0;
+	struct aliascache_write_info info;
+	char *singles_buf;
+	size_t base_dirname_len = strlen(base_dirname);
+	char alias_filename[base_dirname_len + sizeof "/modules.alias"];
+	struct stat st;
+
+	/* Don't output a binary file to stdout.  */
+	if (out == stdout || aliascache_count == 0)
+		return;
+
+	memcpy(alias_filename, base_dirname, base_dirname_len);
+	strcpy(alias_filename + base_dirname_len, "/modules.alias");
+	if (stat(alias_filename, &st) < 0)
+		return;
+
+	qsort(aliascache, aliascache_count, sizeof(*aliascache),
+	      aliascache_cmp);
+
+	root = aliascache_create_range(0, 0, aliascache_count - 1,
+				       &offset, &singles);
+
+	memset(&header, 0, sizeof(header));
+	memcpy(header.magic, "mod-alias-cache", sizeof(header.magic));
+	header.version = 1;
+	header.endian = 0x12345678;
+	header.modalias_mtime_high = (st.st_mtime >> 16) >> 16;
+	header.modalias_mtime_low = st.st_mtime;
+	header.modalias_size = st.st_size;
+	header.modalias_ino = st.st_ino;
+	header.singles = offset;
+	offset += singles;
+	header.strings = offset;
+	fwrite_unlocked(&header, sizeof(header), 1, out);
+
+	singles_buf = NOFAIL(malloc(singles));
+	info.out = out;
+	info.singles = header.singles;
+	info.offset = header.strings;
+	info.singles_buf = singles_buf;
+	aliascache_write_range(&info, root);
+	if (info.singles != header.strings
+	    || info.singles_buf != singles_buf + singles)
+		abort();
+
+	fwrite_unlocked(singles_buf, singles, 1, out);
+
+	for (i = modules; i; i = i->next) {
+		char modname[strlen(i->pathname)+1];
+		size_t len;
+
+		filename2modname(modname, i->pathname);
+		underscores(modname);
+		len = strlen(modname);
+		fwrite_unlocked(modname, len + 1, 1, out);
 	}
 }
 
@@ -790,6 +1666,8 @@ static struct depfile depfiles[] = {
 	{ "modules.seriomap", output_serio_table },
 	{ "modules.alias", output_aliases },
 	{ "modules.symbols", output_symbols },
+	{ "modules.depcache", output_depcache },
+	{ "modules.aliascache", output_aliascache },
 };
 
 /* If we can't figure it out, it's safe to say "true". */
@@ -841,10 +1719,10 @@ static int depfile_out_of_date(const cha
 static int fgetc_wrapped(FILE *file, unsigned int *linenum)
 {
 	for (;;) {
-		int ch = fgetc(file);
+		int ch = fgetc_unlocked(file);
 		if (ch != '\\')
 			return ch;
-		ch = fgetc(file);
+		ch = fgetc_unlocked(file);
 		if (ch != '\n')
 			return ch;
 		if (linenum)
@@ -854,24 +1732,23 @@ static int fgetc_wrapped(FILE *file, uns
 
 static char *getline_wrapped(FILE *file, unsigned int *linenum)
 {
-	int size = 1024;
+	static int size;
 	int i = 0;
-	char *buf = NOFAIL(malloc(size));
+	static char *buf;
 	for(;;) {
 		int ch = fgetc_wrapped(file, linenum);
 		if (i == size) {
-			size *= 2;
+			size = size ? size * 2 : 1024;
 			buf = NOFAIL(realloc(buf, size));
 		}
 		if (ch < 0 && i == 0) {
-			free(buf);
 			return NULL;
 		}
 		if (ch < 0 || ch == '\n') {
 			if (linenum)
 				(*linenum)++;
 			buf[i] = '\0';
-			return NOFAIL(realloc(buf, i+1));
+			return buf;
 		}
 		buf[i++] = ch;
 	}
@@ -983,8 +1860,6 @@ static int read_config_file(const char *
                         }
                 } else
                         grammar(cmd, filename, linenum);
-
-                free(line);
         }
         fclose(cfile);
         return 1;
@@ -1176,6 +2051,8 @@ int main(int argc, char *argv[])
 	}
 	parse_modules(list);
 
+	base_dirname = dirname;
+
 	for (i = 0; i < sizeof(depfiles)/sizeof(depfiles[0]); i++) {
 		FILE *out;
 		struct depfile *d = &depfiles[i];
@@ -1201,6 +2078,7 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	base_dirname = NULL;
 	free(dirname);
 	free(version);
 	
--- module-init-tools-3.4.1/modprobe.c.jj	2008-10-01 17:31:35.000000000 +0200
+++ module-init-tools-3.4.1/modprobe.c	2008-10-01 17:32:14.000000000 +0200
@@ -38,6 +38,7 @@
 #include <asm/unistd.h>
 #include <sys/wait.h>
 #include <syslog.h>
+#include "cache.h"
 
 #define streq(a,b) (strcmp((a),(b)) == 0)
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -66,16 +67,14 @@ static int log;
 
 static void message(const char *prefix, const char *fmt, va_list *arglist)
 {
-	char *buf, *buf2;
+	char *buf;
 
 	vasprintf(&buf, fmt, *arglist);
-	asprintf(&buf2, "%s%s", prefix, buf);
 
 	if (log)
-		syslog(LOG_NOTICE, "%s", buf2);
+		syslog(LOG_NOTICE, "%s%s", prefix, buf);
 	else
-		fprintf(stderr, "%s", buf2);
-	free(buf2);
+		fprintf(stderr, "%s%s", prefix, buf);
 	free(buf);
 }
 
@@ -129,10 +128,10 @@ static void print_usage(const char *prog
 static int fgetc_wrapped(FILE *file, unsigned int *linenum)
 {
 	for (;;) {
-	  	int ch = fgetc(file);
+	  	int ch = fgetc_unlocked(file);
 		if (ch != '\\')
 			return ch;
-		ch = fgetc(file);
+		ch = fgetc_unlocked(file);
 		if (ch != '\n')
 			return ch;
 		if (linenum)
@@ -142,24 +141,23 @@ static int fgetc_wrapped(FILE *file, uns
 
 static char *getline_wrapped(FILE *file, unsigned int *linenum)
 {
-	int size = 1024;
+	static int size;
 	int i = 0;
-	char *buf = NOFAIL(malloc(size));
+	static char *buf;
 	for(;;) {
 		int ch = fgetc_wrapped(file, linenum);
 		if (i == size) {
-			size *= 2;
+			size = size ? size * 2 : 1024;
 			buf = NOFAIL(realloc(buf, size));
 		}
 		if (ch < 0 && i == 0) {
-			free(buf);
 			return NULL;
 		}
 		if (ch < 0 || ch == '\n') {
 			if (linenum)
 				(*linenum)++;
 			buf[i] = '\0';
-			return NOFAIL(realloc(buf, i+1));
+			return buf;
 		}
 		buf[i++] = ch;
 	}
@@ -281,9 +279,10 @@ static int add_modules_dep_line(char *li
 	else
 		modname = line;
 
-	len = strlen(modname);
 	if (strchr(modname, '.'))
 		len = strchr(modname, '.') - modname;
+	else
+		len = strlen(modname);
 	if (!modname_equal(modname, name, len))
 		return 0;
 
@@ -303,29 +302,107 @@ static int add_modules_dep_line(char *li
 	return 1;
 }
 
+static void add_depcache_module(struct dep_cache *header, const char *depcache,
+			        unsigned int stroff, struct list_head *list)
+{
+	unsigned int diridx = (unsigned char) depcache[stroff];
+	unsigned int *dirtab
+	  = (unsigned int *) (depcache + header->dir_table_offset);
+	size_t len = strlen(depcache + stroff + 1);
+	char name[dirtab[2 * diridx + 1] + len + 1], *p;
+	memcpy(name, depcache + dirtab[0], dirtab[1]);
+	p = name + dirtab[1];
+	if (diridx != 0) {
+		memcpy(p, depcache + dirtab[2 * diridx],
+		       dirtab[2 * diridx + 1] - dirtab[1]);
+		p += dirtab[2 * diridx + 1] - dirtab[1];
+	}
+	memcpy(p, depcache + stroff + 1, len + 1);
+	add_module(name, (p - name) + len, list);
+}
+
 static void read_depends(const char *dirname,
 			 const char *start_name,
+			 int avoid_cache,
 			 struct list_head *list)
 {
-	char *modules_dep_name;
+	char *modules_dep_name, *modules_depcache_name;
 	char *line;
 	FILE *modules_dep;
-	int done = 0;
+	int depcache_fd;
+	const char *depcache = MAP_FAILED;
+	struct stat dep_st, depcache_st;
 
 	asprintf(&modules_dep_name, "%s/%s", dirname, "modules.dep");
-	modules_dep = fopen(modules_dep_name, "r");
-	if (!modules_dep)
-		fatal("Could not load %s: %s\n",
-		      modules_dep_name, strerror(errno));
-
-	/* Stop at first line, as we can have duplicates (eg. symlinks
-           from boot/ */
-	while (!done && (line = getline_wrapped(modules_dep, NULL)) != NULL) {
-		done = add_modules_dep_line(line, start_name, list);
-		free(line);
+	asprintf(&modules_depcache_name, "%s/%s", dirname, "modules.depcache");
+	if (avoid_cache)
+		depcache_fd = -1;
+	else
+		depcache_fd = open(modules_depcache_name, O_RDONLY);
+	if (depcache_fd != -1) {
+		struct dep_cache *header;
+		unsigned int *hashtab, hash, entoff;
+		struct dep_cache_entry *ent;
+
+		if (stat(modules_dep_name, &dep_st) < 0
+		    || fstat(depcache_fd, &depcache_st) < 0
+		    || depcache_st.st_size < sizeof(struct dep_cache))
+			goto use_modules_dep;
+		depcache = mmap(NULL, depcache_st.st_size, PROT_READ,
+				MAP_PRIVATE, depcache_fd, 0);
+		if (depcache == MAP_FAILED)
+			goto use_modules_dep;
+		header = (struct dep_cache *) depcache;
+		if (memcmp(header->magic, "mod-dep-cache",
+			   sizeof(header->magic)) != 0
+		    || header->version != 1
+		    || header->endian != 0x12345678
+		    || header->moddep_mtime_high
+		       != (unsigned int) ((dep_st.st_mtime >> 16) >> 16)
+		    || header->moddep_mtime_low
+		       != (unsigned int) dep_st.st_mtime
+		    || header->moddep_size != dep_st.st_size
+		    || header->moddep_ino != dep_st.st_ino)
+			goto use_modules_dep;
+		hashtab = (unsigned int *) (depcache
+					    + header->hash_offset);
+		hash = dep_cache_hash(start_name, strlen(start_name));
+		for (entoff = hashtab[hash % header->hash_size];
+		     entoff != 0xffffffff; entoff = ent->next) {
+			ent = (struct dep_cache_entry *)
+			      (depcache + entoff);
+			if (modname_equal(depcache + ent->modname, start_name,
+					  ent->modname_len)) {
+				int i;
+				add_depcache_module(header, depcache,
+						    ent->fullname, list);
+				for (i = 0; i < ent->num_dependencies; ++i)
+					add_depcache_module(header, depcache,
+							    ent->dependencies[i],
+							    list);
+				break;
+			}
+		}
+	} else {
+use_modules_dep:
+		modules_dep = fopen(modules_dep_name, "r");
+		if (!modules_dep)
+			fatal("Could not load %s: %s\n",
+			      modules_dep_name, strerror(errno));
+
+		/* Stop at first line, as we can have duplicates (eg. symlinks
+		   from boot/ */
+		while ((line = getline_wrapped(modules_dep, NULL)) != NULL)
+			if (add_modules_dep_line(line, start_name, list))
+				break;
+		fclose(modules_dep);
 	}
-	fclose(modules_dep);
+	if (depcache != MAP_FAILED)
+		munmap((char *) depcache, depcache_st.st_size);
+	if (depcache_fd != 0)
+		close(depcache_fd);
 	free(modules_dep_name);
+	free(modules_depcache_name);
 }
 
 /* We use error numbers in a loose translation... */
@@ -391,18 +468,15 @@ again:
 				if (streq(entry, "Loading")
 				    || streq(entry, "Unloading")) {
 					usleep(100000);
-					free(line);
 					fclose(proc_modules);
 					goto again;
 				}
 			}
 
 		out:
-			free(line);
 			fclose(proc_modules);
 			return 1;
 		}
-		free(line);
 	}
 	fclose(proc_modules);
 	return 0;
@@ -1106,7 +1180,7 @@ static int do_wildcard(const char *dirna
 		/* Ignore lines without : or which start with a # */
 		ptr = strchr(line, ':');
 		if (ptr == NULL || line[strspn(line, "\t ")] == '#')
-			goto next;
+			continue;
 		*ptr = '\0';
 
 		/* "type" must match complete directory component(s). */
@@ -1117,8 +1191,6 @@ static int do_wildcard(const char *dirna
 			if (fnmatch(wcard, modname, 0) == 0)
 				printf("%s\n", line);
 		}
-	next:
-		free(line);
 	}
 
 	free(wcard);
@@ -1240,8 +1312,6 @@ static int read_config_file(const char *
 			}
 		} else
 			grammar(cmd, filename, linenum);
-
-		free(line);
 	}
 	fclose(cfile);
 	return 1;
@@ -1290,6 +1360,148 @@ static int read_config(const char *filen
 	return ret;
 }
 
+static int find_aliascache(const struct alias_cache *header,
+			   const char *name,
+			   const struct alias_cache_range *range,
+			   struct module_alias **aliases)
+{
+	unsigned int i, lo, hi, mid;
+	int r;
+	const char *str, *str2, *strtab, *wild, *realname;
+	const unsigned int *table;
+	size_t len;
+	
+	table = (const unsigned int *) (range + 1);
+	strtab = (const char *) (table + range->count_normal
+				 + range->count_wild);
+	wild = strtab + (range->count_normal * range->nchars);
+
+	/* First, run fnmatch on all wildcards at this level.  */
+	for (i = 0; i < range->count_wild; i++) {
+		if (fnmatch(wild, name, 0) == 0) {
+			realname = ((const char *) header)
+				   + table[range->count_normal + i];
+			*aliases = add_alias(realname, *aliases);
+		}
+		wild = strchr(wild, '\0') + 1;
+	}
+
+	/* nchars == 0 is special, there are multiple non-wildcard
+	   symbols with the same wildcard.  Either all of them
+	   match, or none.  */
+	if (range->nchars == 0) {
+		if (name[0] != '\0')
+			return 0;
+		for (i = 0; i < range->count_normal; i++) {
+			realname = ((const char *) header) + table[i];
+			*aliases = add_alias(realname, *aliases);
+		}
+		return 0;
+	}
+
+	/* Binary search.  */
+	lo = 0;
+	str = NULL;
+	hi = range->count_normal;
+	r = 1;
+	mid = lo;
+	while (lo < hi) {
+		mid = (lo + hi) / 2;
+		str = strtab + mid * range->nchars;
+		r = strncmp(str, name, range->nchars);
+		if (r == 0)
+			break;
+		else if (r > 0)
+			hi = mid;
+		else
+			lo = mid + 1;
+	}
+	if (r != 0)
+		return 0;
+
+	if (table[mid] >= header->strings) {
+		len = strlen(name);
+		if (len <= range->nchars) {
+			realname = ((const char *) header) + table[mid];
+			*aliases = add_alias(realname, *aliases);
+		}
+	} else if (table[mid] >= header->singles) {
+		str2 = ((const char *) header) + table[mid]
+		       + sizeof(unsigned int);
+		if (strcmp (str2, name + range->nchars) == 0) {
+			realname = ((const char *) header)
+				   + *(const unsigned int *)
+				      (((const char *) header) + table[mid]);
+			*aliases = add_alias(realname, *aliases);
+		}
+	} else {
+		const struct alias_cache_range *range2;
+		range2 = (const struct alias_cache_range *)
+			 (((const char *) header) + table[mid]);
+		len = strlen(name);
+		return find_aliascache(header,
+				       name + (len > range->nchars
+					       ? range->nchars : len),
+				       range2, aliases);
+	}
+	return 0;
+}
+
+static int read_aliases(const char *aliasfilename,
+			const char *name,
+			int removing,
+			struct module_options **options,
+			struct module_command **commands,
+			struct module_alias **aliases,
+			struct module_blacklist **blacklist)
+{
+	char *aliascache_name;
+	int aliascache_fd;
+	const char *aliascache = MAP_FAILED;
+	struct stat alias_st, aliascache_st;
+	int ret;
+
+	asprintf(&aliascache_name, "%scache", aliasfilename);
+	aliascache_fd = open(aliascache_name, O_RDONLY);
+	if (aliascache_fd != -1) {
+		struct alias_cache *header;
+		struct alias_cache_range *range;
+
+		if (stat(aliasfilename, &alias_st) < 0
+		    || fstat(aliascache_fd, &aliascache_st) < 0
+		    || aliascache_st.st_size < sizeof(struct alias_cache))
+			goto use_modules_alias;
+		aliascache = mmap(NULL, aliascache_st.st_size, PROT_READ,
+				  MAP_PRIVATE, aliascache_fd, 0);
+		if (aliascache == MAP_FAILED)
+			goto use_modules_alias;
+		header = (struct alias_cache *) aliascache;
+		if (memcmp(header->magic, "mod-alias-cache",
+			   sizeof(header->magic)) != 0
+		    || header->version != 1
+		    || header->endian != 0x12345678
+		    || header->modalias_mtime_high
+		       != (unsigned int) ((alias_st.st_mtime >> 16) >> 16)
+		    || header->modalias_mtime_low
+		       != (unsigned int) alias_st.st_mtime
+		    || header->modalias_size != alias_st.st_size
+		    || header->modalias_ino != alias_st.st_ino)
+			goto use_modules_alias;
+		range = (struct alias_cache_range *) (void *) (header + 1);
+		ret = find_aliascache(header, name, range, aliases);
+	} else {
+use_modules_alias:
+		ret = read_config(aliasfilename, name, 0, removing, options,
+				  commands, aliases, blacklist);
+	}
+	if (aliascache != MAP_FAILED)
+		munmap((void *) aliascache, aliascache_st.st_size);
+	if (aliascache_fd != -1)
+		close(aliascache_fd);
+	free(aliascache_name);
+	return ret;
+}
+
 static const char *default_configs[] = 
 {
 	"/etc/modprobe.conf",
@@ -1355,8 +1567,6 @@ static int read_kcmdline(int dump_only, 
 						       opt, *options);
 			}
 		}
-
-		free(line);
 	}
 	fclose(kcmdline);
 	return 1;
@@ -1745,14 +1955,14 @@ int main(int argc, char *argv[])
 
 		if (!aliases) {
 			/* We only use canned aliases as last resort. */
-			read_depends(dirname, modulearg, &list);
+			read_depends(dirname, modulearg, 0, &list);
 
 			if (list_empty(&list)
 			    && !find_command(modulearg, commands))
 			{
-				read_config(aliasfilename, modulearg, 0,
-					    remove, &modoptions, &commands,
-					    &aliases, &blacklist);
+				read_aliases(aliasfilename, modulearg,
+					     remove, &modoptions, &commands,
+					     &aliases, &blacklist);
 			}
 		}
 
@@ -1769,7 +1979,8 @@ int main(int argc, char *argv[])
 				opts = add_extra_options(modulearg,
 							 opts, modoptions);
 
-				read_depends(dirname, aliases->module, &list);
+				read_depends(dirname, aliases->module,
+					     0, &list);
 				handle_module(aliases->module, &list, newname,
 					      remove, opts, first_time, err,
 					      dry_run, verbose, modoptions,
--- module-init-tools-3.4.1/cache.h.jj	2008-10-01 17:32:14.000000000 +0200
+++ module-init-tools-3.4.1/cache.h	2008-10-01 17:32:14.000000000 +0200
@@ -0,0 +1,57 @@
+#ifndef MODINITTOOLS_CACHE_H
+#define MODINITTOOLS_CACHE_H
+
+struct dep_cache {
+	char magic[sizeof "mod-dep-cache"];
+	unsigned char version;
+	unsigned char pad;
+	unsigned int endian;
+	unsigned int moddep_mtime_high;
+	unsigned int moddep_mtime_low;
+	unsigned int moddep_size;
+	unsigned int moddep_ino;
+	unsigned int hash_size;
+	unsigned int hash_offset;
+	unsigned int dir_table_offset;
+};
+
+struct dep_cache_entry {
+	unsigned int hash;
+	unsigned int next;
+	unsigned int modname;
+	unsigned int modname_len;
+	unsigned int fullname;
+	unsigned int num_dependencies;
+	unsigned int dependencies[];
+};
+
+static inline unsigned int dep_cache_hash (const char *str, size_t len)
+{
+  size_t n = 0;
+  unsigned int r = 0;
+
+  for (n = 0; n < len; n++, str++)
+    r = r * 67 + (*str == '-' ? '_' : *str) - 113;
+  return r + len;
+}
+
+struct alias_cache {
+	char magic[sizeof "mod-alias-cache"];
+	unsigned char version;
+	unsigned char pad[3];
+	unsigned int endian;
+	unsigned int modalias_mtime_high;
+	unsigned int modalias_mtime_low;
+	unsigned int modalias_size;
+	unsigned int modalias_ino;
+	unsigned int singles;
+	unsigned int strings;
+};
+
+struct alias_cache_range {
+	unsigned int nchars;
+	unsigned int count_normal;
+	unsigned int count_wild;
+};
+
+#endif /* MODINITTOOLS_CACHE_H */
-------------- next part --------------
On i686, if I run 64 times /sbin/MAKEDEV, vanilla time is:
real    0m3.100s
user    0m2.925s
sys     0m0.164s
the patched MAKEDEV with original /etc/makedev.d is:
real    0m0.897s
user    0m0.746s
sys     0m0.152s
and finally patched MAKEDEV with the new /etc/makedev.d config files is:
real    0m0.195s
user    0m0.116s
sys     0m0.069s

--- MAKEDEV-3.23/MAKEDEV.c.jj	2008-09-19 03:03:54.000000000 +0200
+++ MAKEDEV-3.23/MAKEDEV.c	2008-09-27 08:33:15.000000000 +0200
@@ -17,6 +17,7 @@
  * Red Hat Author(s): Nalin Dahyabhai <nalin at redhat.com>
  */
 
+#define _GNU_SOURCE
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
@@ -78,6 +79,11 @@ struct device_entry {
 				   * which will not change for any device which
 				   * this entry will create */
 	unsigned int base;        /* number to start formatting names with */
+	unsigned int modulo;	  /* if using two format specifiers, number
+				     of second number increases before first
+				     number is increased */
+	unsigned int base2;	  /* base for the second number if two format
+				     specifiers are used */
 	const char *link_target;  /* target for a symlink, if it is one */
 	struct device_entry *next;
 };
@@ -89,6 +95,7 @@ struct dirlist_entry {
 
 struct macro {
 	const char *name, *expansion;
+	unsigned int name_len, expansion_len;
 	struct macro *next;
 };
 
@@ -141,7 +148,7 @@ makenodes(const char *directory, const c
 	char path[PATH_MAX], pattern[PATH_MAX], tmp[PATH_MAX], ctx[PATH_MAX];
 	mode_t mode;
 	dev_t dev;
-	unsigned int mul, frlen, dirlen, i;
+	unsigned int mul, num1, num2, frlen, dirlen, i;
 	int ret = 0;
 
 	/* Compute the lengths of our fixed-length strings, because we'll be
@@ -150,26 +157,44 @@ makenodes(const char *directory, const c
 	dirlen = strlen(directory);
 
 	/* Limit the number of devices we'll create per entry. */
+	num1 = 0;
+	num2 = 0;
 	for (mul = 0; (max != 0) && (mul < entry->num); max--, mul++) {
-		memset(pattern, '\0', sizeof(pattern));
-		memset(path, '\0', sizeof(path));
-		memset(tmp, '\0', sizeof(tmp));
-		memset(ctx, '\0', sizeof(ctx));
-
 		/* Build the file name. */
-		snprintf(pattern, sizeof(pattern), "%s/%s", directory,
-			 entry->name);
+		snprintf(pattern, sizeof(pattern), "%%s/%s", entry->name);
 
 		/* If this is not the first device, and there's not some format
 		 * specifier in there, append a "%d", which makes things like
 		 * hda/hda1 really easy to do. */
 		if (mul > 0) {
-			if (strchr(pattern, '%') == NULL) {
+			if (strchr(pattern + 3, '%') == NULL) {
 				strncat(pattern, "%d",
 					sizeof(pattern) - 1 - strlen(pattern));
 			}
 		}
-		snprintf(path, sizeof(path), pattern, mul + entry->base);
+		if (entry->modulo) {
+			/* Similarly, when using 2 format specifiers and
+			   the string contains %|, ignore everything afterwards
+			   if num1 is 0.  */
+			char *p = pattern + 2;
+			while ((p = strchr (p + 1, '%')) != NULL
+			       && p[1] != '|')
+				;
+			if (p) {
+				if (num1 == 0)
+					*p = '\0';
+				else
+					memmove (p, p + 2, strlen(p + 2) + 1);
+			}
+		}
+		snprintf(path, sizeof(path), pattern, directory,
+			 num2 + entry->base, num1 + entry->base2);
+
+		num1++;
+		if (entry->modulo && num1 == entry->modulo) {
+			num1 = 0;
+			num2++;
+		}
 
 		/* Check if the target matches the fragment. */
 		if (strncmp(fragment, path + dirlen + 1, frlen) != 0) {
@@ -183,7 +208,7 @@ makenodes(const char *directory, const c
 			if ((i == 0) || (path[i] != '/')) {
 				continue;
 			}
-			strncpy(tmp, path, i);
+			memcpy(tmp, path, i);
 			tmp[i] = '\0';
 			if ((lstat(tmp, &st) != -1) || (errno != ENOENT)) {
 				snprintf(ctx, sizeof(ctx), "%s",
@@ -416,13 +441,14 @@ makenodes(const char *directory, const c
 
 		/* We're creating symlinks today. */
 		if (entry->type == LINK) {
+			ssize_t len;
 			/* Check that we aren't trying anything unnecessary. */
-			memset(tmp, '\0', sizeof(tmp));
-			if (lstat(path, &st) == 0)
-			if (S_ISLNK(st.st_mode))
-			if (readlink(path, tmp, sizeof(tmp) - 1) != -1)
-			if (strcmp(tmp, entry->link_target) == 0)
-			if (secontextverify("MAKEDEV", ctx, st.st_mode) == 0) {
+			if (lstat(path, &st) == 0
+			    && S_ISLNK(st.st_mode)
+			    && (len = readlink(path, tmp, sizeof(tmp) - 1)) != -1
+			    && (tmp[len] = '\0',
+				strcmp(tmp, entry->link_target)) == 0
+			    && secontextverify("MAKEDEV", ctx, st.st_mode) == 0) {
 				/* We know how to create this, but didn't need
 				 * to, as it was already there. */
 				ret = 1;
@@ -577,20 +603,26 @@ makedevices(const char *directory, const
 			if (((flags & NOFOLLOW) == 0) &&
 			    (entry->type == LINK)) {
 				char *p = buf;
+				size_t len = strlen(entry->name);
 				/* Build the link target's name. */
-				memset(buf, '\0', sizeof(buf));
-				strncpy(buf, entry->name, sizeof(buf) - 1);
-				if (strrchr(buf, '/') != NULL) {
-					p = strrchr(buf, '/') + 1;
-					strncpy(p, entry->link_target,
-						sizeof(buf) - 1 - (p - buf));
-				} else {
-					strncpy(buf, entry->link_target,
-						sizeof(buf) - 1);
-				}
+				if (len >= sizeof(buf)) {
+					memcpy(buf, entry->name, sizeof(buf) - 1);
+					buf[sizeof(buf) - 1] = '\0';
+				} else
+					memcpy(buf, entry->name, len + 1);
+				if ((p = strrchr(buf, '/')) != NULL)
+					p++;
+				else
+					p = buf;
+				len = strlen(entry->link_target);
+				if ((p - buf) + len >= sizeof(buf)) {
+					memcpy(p, entry->link_target,
+					       sizeof(buf) - 1 - (p - buf));
+					buf[sizeof(buf) - 1] = '\0';
+				} else
+					memcpy(p, entry->link_target, len + 1);
 				/* Strip out empty path components. */
-				while (strstr(buf, "//") != NULL) {
-					p = strstr(buf, "//");
+				while ((p = strstr(buf, "//")) != NULL) {
 					memmove(p, p + 1, strlen(p));
 				}
 				/* Replace "/foo/../" with "/" by removing the
@@ -669,33 +701,37 @@ makedevices(const char *directory, const
 	}
 }
 
+static char *
+stralloc (const char *p, const char *q)
+{
+	char *ret;
+	if (q == p)
+		return NULL;
+	ret = malloc(q - p + 1);
+	if (ret == NULL)
+		return NULL;
+	memcpy(ret, p, q - p);
+	ret[q - p] = '\0';
+	return ret;
+}
+
 static void
-read_config_line(const char *path, const char *pline)
+read_config_line(const char *path, const char *pline, size_t pline_len)
 {
-	char *p, *q;
-	char buf[LINE_MAX], line[LINE_MAX];
+	const char *p, *q;
+	char *tmp, *r;
+	char buf[LINE_MAX], buf2[LINE_MAX];
 	struct device_entry *entry = NULL;
 	struct macro *macro = NULL;
 	enum entry_type type = -1;
 
 	/* Expand macros. This is not as elegant as it could be, but it should
 	 * suffice for our use here. */
-	strncpy(line, pline, sizeof(line) - 1);
-	line[sizeof(line) - 1] = '\0';
-	while (strchr(line, '$') != NULL) {
-		strncpy(buf, line, sizeof(buf) - 1);
-		buf[sizeof(buf) - 1] = '\0';
-		p = strchr(buf, '$');
+	tmp = buf;
+	p = pline;
+	while ((p = strchr(p, '$')) != NULL) {
 		for (macro = macros; macro != NULL; macro = macro->next) {
-			if (!strncmp(p + 1, macro->name, strlen(macro->name))) {
-				q = p + strlen(p) + strlen(macro->expansion) -
-				   (1 + strlen(macro->name));
-				memmove(p + strlen(macro->expansion),
-					p + 1 + strlen(macro->name),
-					strlen(p + 1 + strlen(macro->name)));
-				memcpy(p, macro->expansion,
-				       strlen(macro->expansion));
-				q[0] = '\0';
+			if (!strncmp(p + 1, macro->name, macro->name_len)) {
 				break;
 			}
 		}
@@ -704,13 +740,37 @@ read_config_line(const char *path, const
 				pline);
 			exit(6);
 		}
-		macro = NULL;
-		strncpy(line, buf, sizeof(line) - 1);
-		line[sizeof(line) - 1] = '\0';
+		memcpy(tmp, pline, p - pline);
+		r = tmp + (p - pline);
+		if ((p - pline) + macro->expansion_len > sizeof(buf)) {
+			memcpy(r, macro->expansion,
+			       sizeof(buf) - (p - pline) - 1);
+			tmp[sizeof(buf) - 1] = '\0';
+		} else {
+			memcpy(r, macro->expansion, macro->expansion_len);
+			r += macro->expansion_len;
+			if (pline_len - (1 + macro->name_len)
+			    + macro->expansion_len > sizeof(buf)) {
+				memcpy(r, p + 1 + macro->name_len,
+				       sizeof(buf) - (r - tmp) - 1);
+				tmp[sizeof(buf) - 1] = '\0';
+			} else
+				memcpy(r, p + 1 + macro->name_len,
+				       pline_len - (p - pline) - 1);
+		}
+		pline_len += macro->expansion_len - macro->name_len - 1;
+		if (pline_len >= sizeof(buf))
+			pline_len = sizeof(buf) - 1;
+		p = tmp + (p - pline);
+		pline = tmp;
+		if (tmp == buf)
+			tmp = buf2;
+		else
+			tmp = buf;
 	}
 
 	/* First, skip leading whitespace. */
-	for (p = line; (*p != '\0') && isspace(*p); p++) {
+	for (p = pline; (*p != '\0') && isspace(*p); p++) {
 		continue;
 	}
 
@@ -759,6 +819,7 @@ read_config_line(const char *path, const
 		memset(entry, 0, sizeof(struct device_entry));
 		entry->type = type;
 		entry->name_prefix_length = -1;
+		macro = NULL;
 		break;
 	case MACRO:
 		macro = malloc(sizeof(struct macro));
@@ -775,15 +836,14 @@ read_config_line(const char *path, const
 		for (p++; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		macro->name = strdup(buf);
-		if ((macro->name == NULL) || (strlen(macro->name) == 0)) {
+		macro->name_len = q - p;
+		macro->name = stralloc(p, q);
+		if (macro->name == NULL) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"bad macro name in \"%s\"\n", path, line);
+				"bad macro name in \"%s\"\n", path, pline);
 			exit(7);
 		}
 		p = q;
@@ -792,18 +852,14 @@ read_config_line(const char *path, const
 		for (; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
-		strncpy(buf, p, sizeof(buf) - 1);
-		buf[sizeof(buf) - 1] = '\0';
-		macro->expansion = strdup(buf);
+		macro->expansion = strdup(p);
 
 		if ((macro->expansion == NULL) ||
-		    (strlen(macro->expansion) == 0)) {
+		    ((macro->expansion_len = strlen(macro->expansion)) == 0)) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"bad expansion in \"%s\"\n", path, line);
+				"bad expansion in \"%s\"\n", path, pline);
 			exit(7);
 		}
-		p = q;
 
 		macro->next = macros;
 		macros = macro;
@@ -811,7 +867,7 @@ read_config_line(const char *path, const
 		return;
 	}
 
-	if ((entry->type == BLOCK) || (entry->type == CHAR)) {
+	else if ((entry->type == BLOCK) || (entry->type == CHAR)) {
 		/* Now read the permissions. */
 		for (p++; (*p != '\0') && isspace(*p); p++) {
 			continue;
@@ -826,15 +882,13 @@ read_config_line(const char *path, const
 		for (; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		entry->user = strdup(buf);
-		if ((entry->user == NULL) || (strlen(entry->user) == 0)) {
+		entry->user = stralloc(p, q);
+		if (entry->user == NULL) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"unknown user in \"%s\"\n", path, line);
+				"unknown user in \"%s\"\n", path, pline);
 			exit(7);
 		}
 		p = q;
@@ -843,15 +897,13 @@ read_config_line(const char *path, const
 		for (; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		entry->group = strdup(buf);
-		if ((entry->group == NULL) || (strlen(entry->group) == 0)) {
+		entry->group = stralloc(p, q);
+		if (entry->group == NULL) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"unknown group in \"%s\"\n", path, line);
+				"unknown group in \"%s\"\n", path, pline);
 			exit(7);
 		}
 		p = q;
@@ -867,7 +919,7 @@ read_config_line(const char *path, const
 		}
 		if (entry->major <= 0) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"bad major in \"%s\"\n", path, line);
+				"bad major in \"%s\"\n", path, pline);
 			exit(7);
 		}
 
@@ -882,7 +934,7 @@ read_config_line(const char *path, const
 		}
 		if (entry->minor < 0) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"bad minor in \"%s\"\n", path, line);
+				"bad minor in \"%s\"\n", path, pline);
 			exit(7);
 		}
 
@@ -897,7 +949,7 @@ read_config_line(const char *path, const
 		}
 		if (entry->minor_step < 0) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"bad step in \"%s\"\n", path, line);
+				"bad step in \"%s\"\n", path, pline);
 			exit(7);
 		}
 
@@ -912,7 +964,7 @@ read_config_line(const char *path, const
 		}
 		if (entry->num <= 0) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"bad count in \"%s\"\n", path, line);
+				"bad count in \"%s\"\n", path, pline);
 			exit(7);
 		}
 
@@ -920,12 +972,15 @@ read_config_line(const char *path, const
 		for (; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		entry->name = strdup(buf);
+		entry->name = stralloc(p, q);
+		if (entry->name == NULL) {
+			fprintf(stderr, "error parsing \"%s\": "
+				"unknown name in \"%s\"\n", path, pline);
+			exit(7);
+		}
 		p = q;
 
 		entry->name_prefix_length = strcspn(entry->name, "%");
@@ -934,75 +989,82 @@ read_config_line(const char *path, const
 		for (; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		if (strstr(entry->name, "%c")) {
-			entry->base = buf[0];
-		} else {
-			entry->base = atoi(buf);
-		}
-	}
 
-	if (entry->type == LINK) {
-		/* Read the link's name. */
-		for (p++; (*p != '\0') && isspace(*p); p++) {
-			continue;
-		}
-		memset(buf, '\0', sizeof(buf));
-		for (q = p; (*q != '\0') && !isspace(*q); q++) {
-			continue;
-		}
-		memcpy(buf, p, q - p);
-		entry->name = strdup(buf);
-		p = q;
+		if (strncmp(entry->name + entry->name_prefix_length, "%c", 2)
+		    == 0)
+			entry->base = p[0];
+		else
+			entry->base = atoi(p);
 
-		/* Read the link's target's name. */
-		for (; (*p != '\0') && isspace(*p); p++) {
-			continue;
-		}
-		memset(buf, '\0', sizeof(buf));
-		for (q = p; (*q != '\0') && !isspace(*q); q++) {
-			continue;
-		}
-		memcpy(buf, p, q - p);
-		entry->link_target = strdup(buf);
-		p = q;
+		if (q != p) {
+			p = q;
 
-		entry->num = 1;
+			/* Now read the (optional) modulo. */
+			for (; (*p != '\0') && isspace(*p); p++) {
+				continue;
+			}
+			for (q = p; (*q != '\0') && !isspace(*q); q++) {
+				continue;
+			}
+			entry->modulo = atoi(p);
+
+			if (entry->modulo) {
+				p = q;
+
+				/* Now read the (optional) second base. */
+				for (; (*p != '\0') && isspace(*p); p++) {
+					continue;
+				}
+				for (q = p; (*q != '\0') && !isspace(*q); q++) {
+					continue;
+				}
+
+				if (strstr(entry->name
+					   + entry->name_prefix_length + 1,
+					   "%c"))
+					entry->base2 = p[0];
+				else
+					entry->base2 = atoi(p);
+			}
+		}
 	}
 
-	if (entry->type == ALIAS) {
-		/* Read the alias's name. */
+	else if (entry->type == LINK || entry->type == ALIAS) {
+		/* Read the link's (or alias') name. */
 		for (p++; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		entry->name = strdup(buf);
+		entry->name = stralloc(p, q);
+		if (entry->name == NULL) {
+			fprintf(stderr, "error parsing \"%s\": "
+				"unknown name in \"%s\"\n", path, pline);
+			exit(7);
+		}
 		p = q;
 
-		/* Read the target's name. */
+		/* Read the link's (or alias') target's name. */
 		for (; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		entry->link_target = strdup(buf);
-		p = q;
-
+		entry->link_target = stralloc(p, q);
+		if (entry->link_target == NULL) {
+			fprintf(stderr, "error parsing \"%s\": "
+				"unknown link target in \"%s\"\n", path, pline);
+			exit(7);
+		}
 		entry->num = 1;
 	}
 
-	if (entry->type == SOCKET) {
+	else if (entry->type == SOCKET) {
 		/* Now read the permissions. */
 		for (p++; (*p != '\0') && isspace(*p); p++) {
 			continue;
@@ -1017,15 +1079,13 @@ read_config_line(const char *path, const
 		for (; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		entry->user = strdup(buf);
-		if ((entry->user == NULL) || (strlen(entry->user) == 0)) {
+		entry->user = stralloc(p, q);
+		if (entry->user == NULL) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"unknown user in \"%s\"\n", path, line);
+				"unknown user in \"%s\"\n", path, pline);
 			exit(7);
 		}
 		p = q;
@@ -1034,15 +1094,13 @@ read_config_line(const char *path, const
 		for (; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		entry->group = strdup(buf);
-		if ((entry->group == NULL) || (strlen(entry->group) == 0)) {
+		entry->group = stralloc(p, q);
+		if (entry->group == NULL) {
 			fprintf(stderr, "error parsing \"%s\": "
-				"unknown group in \"%s\"\n", path, line);
+				"unknown group in \"%s\"\n", path, pline);
 			exit(7);
 		}
 		p = q;
@@ -1051,14 +1109,15 @@ read_config_line(const char *path, const
 		for (; (*p != '\0') && isspace(*p); p++) {
 			continue;
 		}
-		memset(buf, '\0', sizeof(buf));
 		for (q = p; (*q != '\0') && !isspace(*q); q++) {
 			continue;
 		}
-		memcpy(buf, p, q - p);
-		entry->name = strdup(buf);
-		p = q;
-
+		entry->name = stralloc(p, q);
+		if (entry->name == NULL) {
+			fprintf(stderr, "error parsing \"%s\": "
+				"unknown name in \"%s\"\n", path, pline);
+			exit(7);
+		}
 		entry->num = 1;
 	}
 
@@ -1085,8 +1144,8 @@ read_config_single_file(const char *path
 		exit(4);
 	}
 
-	while (fgets(buf, sizeof(buf), fp) != NULL) {
-		int l = strlen(buf);
+	while (fgets_unlocked(buf, sizeof(buf), fp) != NULL) {
+		size_t l = strlen(buf);
 
 		while ((l > 0) &&
 		       ((buf[l - 1] == '\n') || (buf[l - 1] == '\r'))) {
@@ -1094,7 +1153,7 @@ read_config_single_file(const char *path
 			buf[l] = '\0';
 		}
 
-		read_config_line(path, buf);
+		read_config_line(path, buf, l);
 	}
 
 	fclose(fp);
--- MAKEDEV-3.23/gendac960.jj	2008-09-19 03:03:54.000000000 +0200
+++ MAKEDEV-3.23/gendac960	2008-09-27 09:20:39.000000000 +0200
@@ -1,14 +1,9 @@
 #!//bin/sh
 for ctr in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
-if [ $ctr -lt 8 ] ; then
-maj=`expr $ctr + 48`
-else
-maj=`expr $ctr - 8 + 136`
-fi
-for ld in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ; do
-for part in 0 1 2 3 4 5 6 7; do
-	min=`expr $ld \* 8 + $part`
-	printf 'b $STORAGE            %4s %3s  1   1 rd/c%sd%sp%s\n' $maj $min $ctr $ld $part | sed 's/p0$//g'
-done
-done
+	if [ $ctr -lt 8 ] ; then
+		maj=`expr $ctr + 48`
+	else
+		maj=`expr $ctr - 8 + 136`
+	fi
+	printf 'b $STORAGE            %4s 0    1 256 rd/c%sd%%d%%|p%%d 0 8\n' $maj $ctr
 done
--- MAKEDEV-3.23/gencciss.jj	2008-09-19 03:03:54.000000000 +0200
+++ MAKEDEV-3.23/gencciss	2008-09-27 09:15:16.000000000 +0200
@@ -1,10 +1,5 @@
 #!//bin/sh
 for ctr in 0 1 2 3 4 5 6 7; do
-maj=`expr $ctr + 104`
-for ld in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
-for part in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
-	min=`expr $ld \* 16 + $part`
-	printf 'b $STORAGE            %4s %3s  1   1 cciss/c%sd%sp%s\n' $maj $min $ctr $ld $part | sed 's/p0$//g'
-done
-done
+	maj=`expr $ctr + 104`
+	printf 'b $STORAGE            %4s 0    1 256 cciss/c%sd%%d%%|p%%d 0 16\n' $maj $ctr
 done
--- MAKEDEV-3.23/genida.jj	2008-09-19 03:03:54.000000000 +0200
+++ MAKEDEV-3.23/genida	2008-09-27 09:16:26.000000000 +0200
@@ -1,10 +1,5 @@
 #!//bin/sh
 for ctr in 0 1 2 3 4 5 6 7; do
-maj=`expr $ctr + 72`
-for ld in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
-for part in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
-	min=`expr $ld \* 16 + $part`
-	printf 'b $STORAGE            %4s %3s  1   1 ida/c%sd%sp%s\n' $maj $min $ctr $ld $part | sed 's/p0$//g'
-done
-done
+	maj=`expr $ctr + 72`
+	printf 'b $STORAGE            %4s 0    1 256 ida/c%sd%%d%%|p%%d 0 16\n' $maj $ctr
 done
--- MAKEDEV-3.23/makedev.d/02linux-2.6.x.jj	2008-09-19 03:03:54.000000000 +0200
+++ MAKEDEV-3.23/makedev.d/02linux-2.6.x	2008-09-27 09:10:57.000000000 +0200
@@ -7,40 +7,40 @@
 
 c $KMEM                  1   2  1   1 kmem
 
-b $FLOPPY                2   0  1   4 fd%d 0
+b $FLOPPY                2   0  1   4 fd%d
 b $FLOPPY                2 128  1   4 fd%d 4
 
-b $FLOPPY                2   4  1   4 fd%dd360  0
-b $FLOPPY                2  20  1   4 fd%dh360  0
-b $FLOPPY                2  48  1   4 fd%dh410  0
-b $FLOPPY                2  64  1   4 fd%dh420  0
-b $FLOPPY                2  24  1   4 fd%dh720  0
-b $FLOPPY                2  80  1   4 fd%dh880  0
-b $FLOPPY                2   8  1   4 fd%dh1200 0
-b $FLOPPY                2  40  1   4 fd%dh1440 0
-b $FLOPPY                2  56  1   4 fd%dh1476 0
-b $FLOPPY                2  72  1   4 fd%dh1494 0
-b $FLOPPY                2  92  1   4 fd%dh1660 0
-
-b $FLOPPY                2  12  1   4 fd%du360  0
-b $FLOPPY                2  16  1   4 fd%du720  0
-b $FLOPPY                2 120  1   4 fd%du800  0
-b $FLOPPY                2  52  1   4 fd%du820  0
-b $FLOPPY                2  68  1   4 fd%du830  0
-b $FLOPPY                2  84  1   4 fd%du1040 0
-b $FLOPPY                2  88  1   4 fd%du1120 0
-b $FLOPPY                2  28  1   4 fd%du1440 0
-b $FLOPPY                2 124  1   4 fd%du1660 0
-b $FLOPPY                2  44  1   4 fd%du1680 0
-b $FLOPPY                2  60  1   4 fd%du1722 0
-b $FLOPPY                2  76  1   4 fd%du1743 0
-b $FLOPPY                2  96  1   4 fd%du1760 0
-b $FLOPPY                2 116  1   4 fd%du1840 0
-b $FLOPPY                2 100  1   4 fd%du1920 0
-b $FLOPPY                2  32  1   4 fd%du2880 0
-b $FLOPPY                2 104  1   4 fd%du3200 0
-b $FLOPPY                2 108  1   4 fd%du3520 0
-b $FLOPPY                2 112  1   4 fd%du3840 0
+b $FLOPPY                2   4  1   4 fd%dd360
+b $FLOPPY                2  20  1   4 fd%dh360
+b $FLOPPY                2  48  1   4 fd%dh410
+b $FLOPPY                2  64  1   4 fd%dh420
+b $FLOPPY                2  24  1   4 fd%dh720
+b $FLOPPY                2  80  1   4 fd%dh880
+b $FLOPPY                2   8  1   4 fd%dh1200
+b $FLOPPY                2  40  1   4 fd%dh1440
+b $FLOPPY                2  56  1   4 fd%dh1476
+b $FLOPPY                2  72  1   4 fd%dh1494
+b $FLOPPY                2  92  1   4 fd%dh1660
+
+b $FLOPPY                2  12  1   4 fd%du360
+b $FLOPPY                2  16  1   4 fd%du720
+b $FLOPPY                2 120  1   4 fd%du800
+b $FLOPPY                2  52  1   4 fd%du820
+b $FLOPPY                2  68  1   4 fd%du830
+b $FLOPPY                2  84  1   4 fd%du1040
+b $FLOPPY                2  88  1   4 fd%du1120
+b $FLOPPY                2  28  1   4 fd%du1440
+b $FLOPPY                2 124  1   4 fd%du1660
+b $FLOPPY                2  44  1   4 fd%du1680
+b $FLOPPY                2  60  1   4 fd%du1722
+b $FLOPPY                2  76  1   4 fd%du1743
+b $FLOPPY                2  96  1   4 fd%du1760
+b $FLOPPY                2 116  1   4 fd%du1840
+b $FLOPPY                2 100  1   4 fd%du1920
+b $FLOPPY                2  32  1   4 fd%du2880
+b $FLOPPY                2 104  1   4 fd%du3200
+b $FLOPPY                2 108  1   4 fd%du3520
+b $FLOPPY                2 112  1   4 fd%du3840
 
 b $FLOPPY                2 132  1   4 fd%dd360  4
 b $FLOPPY                2 148  1   4 fd%dh360  4
@@ -74,7 +74,7 @@ b $FLOPPY                2 232  1   4 fd
 b $FLOPPY                2 236  1   4 fd%du3520 4
 b $FLOPPY                2 240  1   4 fd%du3840 4
 
-b $FLOPPY                2   4  1   4 fd%dCompaQ 0
+b $FLOPPY                2   4  1   4 fd%dCompaQ
 b $FLOPPY                2 132  1   4 fd%dCompaQ 4
 
 c $CONSOLE              10   4  1   1 amigamouse
@@ -139,7 +139,7 @@ b $STORAGE              23   0  1   1 mc
 
 b $STORAGE              24   0  1   1 cdu535
 
-b $STORAGE              25   0  1   4 sbpcd%d 0
+b $STORAGE              25   0  1   4 sbpcd%d
 
 b $STORAGE              26   0  1   4 sbpcd%d 4
 
@@ -158,22 +158,7 @@ c $ROOT                 41   0  1   1 ya
 b $STORAGE              41   0  1   1 bpcd
 
 c $SERIAL               44   0  1  64 cui%d
-b $STORAGE              44   0  1  16 ftla
-b $STORAGE              44  16  1  16 ftlb
-b $STORAGE              44  32  1  16 ftlc
-b $STORAGE              44  48  1  16 ftld
-b $STORAGE              44  64  1  16 ftle
-b $STORAGE              44  80  1  16 ftlf
-b $STORAGE              44  96  1  16 ftlg
-b $STORAGE              44 112  1  16 ftlh
-b $STORAGE              44 128  1  16 ftli
-b $STORAGE              44 144  1  16 ftlj
-b $STORAGE              44 160  1  16 ftlk
-b $STORAGE              44 176  1  16 ftll
-b $STORAGE              44 192  1  16 ftlm
-b $STORAGE              44 208  1  16 ftln
-b $STORAGE              44 224  1  16 ftlo
-b $STORAGE              44 240  1  16 ftlp
+b $STORAGE              44   0  1 256 ftl%c%|%d a 16
 
 c $ROOT                 45   0  1  64 isdn%d
 c $ROOT                 45  64  1  64 isdnctrl%d
@@ -183,265 +168,47 @@ c $ROOT                 53   3  1   3 ic
 c $ROOT                 55   0  1   1 dsp56k
 
 # Here there be dragons.
-b $STORAGE              65   0  1  16 sdq
-b $STORAGE              65  16  1  16 sdr
-b $STORAGE              65  32  1  16 sds
-b $STORAGE              65  48  1  16 sdt
-b $STORAGE              65  64  1  16 sdu
-b $STORAGE              65  80  1  16 sdv
-b $STORAGE              65  96  1  16 sdw
-b $STORAGE              65 112  1  16 sdx
-b $STORAGE              65 128  1  16 sdy
-b $STORAGE              65 144  1  16 sdz
-b $STORAGE              65 160  1  16 sdaa
-b $STORAGE              65 176  1  16 sdab
-b $STORAGE              65 192  1  16 sdac
-b $STORAGE              65 208  1  16 sdad
-b $STORAGE              65 224  1  16 sdae
-b $STORAGE              65 240  1  16 sdaf
-
-b $STORAGE              66   0  1  16 sdag
-b $STORAGE              66  16  1  16 sdah
-b $STORAGE              66  32  1  16 sdai
-b $STORAGE              66  48  1  16 sdaj
-b $STORAGE              66  64  1  16 sdak
-b $STORAGE              66  80  1  16 sdal
-b $STORAGE              66  96  1  16 sdam
-b $STORAGE              66 112  1  16 sdan
-b $STORAGE              66 128  1  16 sdao
-b $STORAGE              66 144  1  16 sdap
-b $STORAGE              66 160  1  16 sdaq
-b $STORAGE              66 176  1  16 sdar
-b $STORAGE              66 192  1  16 sdas
-b $STORAGE              66 208  1  16 sdat
-b $STORAGE              66 224  1  16 sdau
-b $STORAGE              66 240  1  16 sdav
-
-b $STORAGE              67   0  1  16 sdaw
-b $STORAGE              67  16  1  16 sdax
-b $STORAGE              67  32  1  16 sday
-b $STORAGE              67  48  1  16 sdaz
-b $STORAGE              67  64  1  16 sdba
-b $STORAGE              67  80  1  16 sdbb
-b $STORAGE              67  96  1  16 sdbc
-b $STORAGE              67 112  1  16 sdbd
-b $STORAGE              67 128  1  16 sdbe
-b $STORAGE              67 144  1  16 sdbf
-b $STORAGE              67 160  1  16 sdbg
-b $STORAGE              67 176  1  16 sdbh
-b $STORAGE              67 192  1  16 sdbi
-b $STORAGE              67 208  1  16 sdbj
-b $STORAGE              67 224  1  16 sdbk
-b $STORAGE              67 240  1  16 sdbl
-
-b $STORAGE              68   0  1  16 sdbm
-b $STORAGE              68  16  1  16 sdbn
-b $STORAGE              68  32  1  16 sdbo
-b $STORAGE              68  48  1  16 sdbp
-b $STORAGE              68  64  1  16 sdbq
-b $STORAGE              68  80  1  16 sdbr
-b $STORAGE              68  96  1  16 sdbs
-b $STORAGE              68 112  1  16 sdbt
-b $STORAGE              68 128  1  16 sdbu
-b $STORAGE              68 144  1  16 sdbv
-b $STORAGE              68 160  1  16 sdbw
-b $STORAGE              68 176  1  16 sdbx
-b $STORAGE              68 192  1  16 sdby
-b $STORAGE              68 208  1  16 sdbz
-b $STORAGE              68 224  1  16 sdca
-b $STORAGE              68 240  1  16 sdcb
-
-b $STORAGE              69   0  1  16 sdcc
-b $STORAGE              69  16  1  16 sdcd
-b $STORAGE              69  32  1  16 sdce
-b $STORAGE              69  48  1  16 sdcf
-b $STORAGE              69  64  1  16 sdcg
-b $STORAGE              69  80  1  16 sdch
-b $STORAGE              69  96  1  16 sdci
-b $STORAGE              69 112  1  16 sdcj
-b $STORAGE              69 128  1  16 sdck
-b $STORAGE              69 144  1  16 sdcl
-b $STORAGE              69 160  1  16 sdcm
-b $STORAGE              69 176  1  16 sdcn
-b $STORAGE              69 192  1  16 sdco
-b $STORAGE              69 208  1  16 sdcp
-b $STORAGE              69 224  1  16 sdcq
-b $STORAGE              69 240  1  16 sdcr
-
-b $STORAGE              70   0  1  16 sdcs
-b $STORAGE              70  16  1  16 sdct
-b $STORAGE              70  32  1  16 sdcu
-b $STORAGE              70  48  1  16 sdcv
-b $STORAGE              70  64  1  16 sdcw
-b $STORAGE              70  80  1  16 sdcx
-b $STORAGE              70  96  1  16 sdcy
-b $STORAGE              70 112  1  16 sdcz
-b $STORAGE              70 128  1  16 sdda
-b $STORAGE              70 144  1  16 sddb
-b $STORAGE              70 160  1  16 sddc
-b $STORAGE              70 176  1  16 sddd
-b $STORAGE              70 192  1  16 sdde
-b $STORAGE              70 208  1  16 sddf
-b $STORAGE              70 224  1  16 sddg
-b $STORAGE              70 240  1  16 sddh
-
-b $STORAGE              71   0  1  16 sddi
-b $STORAGE              71  16  1  16 sddj
-b $STORAGE              71  32  1  16 sddk
-b $STORAGE              71  48  1  16 sddl
-b $STORAGE              71  64  1  16 sddm
-b $STORAGE              71  80  1  16 sddn
-b $STORAGE              71  96  1  16 sddo
-b $STORAGE              71 112  1  16 sddp
-b $STORAGE              71 128  1  16 sddq
-b $STORAGE              71 144  1  16 sddr
-b $STORAGE              71 160  1  16 sdds
-b $STORAGE              71 176  1  16 sddt
-b $STORAGE              71 192  1  16 sddu
-b $STORAGE              71 208  1  16 sddv
-b $STORAGE              71 224  1  16 sddw
-b $STORAGE              71 240  1  16 sddx
-
-
-b $STORAGE              80   0  1  16 i2o/hda
-b $STORAGE              80  16  1  16 i2o/hdb
-b $STORAGE              80  32  1  16 i2o/hdc
-b $STORAGE              80  48  1  16 i2o/hdd
-b $STORAGE              80  64  1  16 i2o/hde
-b $STORAGE              80  80  1  16 i2o/hdf
-b $STORAGE              80  96  1  16 i2o/hdg
-b $STORAGE              80 112  1  16 i2o/hdh
-b $STORAGE              80 128  1  16 i2o/hdi
-b $STORAGE              80 144  1  16 i2o/hdj
-b $STORAGE              80 160  1  16 i2o/hdk
-b $STORAGE              80 176  1  16 i2o/hdl
-b $STORAGE              80 192  1  16 i2o/hdm
-b $STORAGE              80 208  1  16 i2o/hdn
-b $STORAGE              80 224  1  16 i2o/hdo
-b $STORAGE              80 240  1  16 i2o/hdp
-
-b $STORAGE              81   0  1  16 i2o/hdq
-b $STORAGE              81  16  1  16 i2o/hdr
-b $STORAGE              81  32  1  16 i2o/hds
-b $STORAGE              81  48  1  16 i2o/hdt
-b $STORAGE              81  64  1  16 i2o/hdu
-b $STORAGE              81  80  1  16 i2o/hdv
-b $STORAGE              81  96  1  16 i2o/hdw
-b $STORAGE              81 112  1  16 i2o/hdx
-b $STORAGE              81 128  1  16 i2o/hdy
-b $STORAGE              81 144  1  16 i2o/hdz
-b $STORAGE              81 160  1  16 i2o/hdaa
-b $STORAGE              81 176  1  16 i2o/hdab
-b $STORAGE              81 192  1  16 i2o/hdac
-b $STORAGE              81 208  1  16 i2o/hdad
-b $STORAGE              81 224  1  16 i2o/hdae
-b $STORAGE              81 240  1  16 i2o/hdaf
+b $STORAGE              65   0  1 160 sd%c%|%d q 16
+b $STORAGE              65 160  1  96 sda%c%|%d a 16
+
+b $STORAGE              66   0  1 256 sda%c%|%d g 16
+
+b $STORAGE              67   0  1  64 sda%c%|%d w 16
+b $STORAGE              67  64  1 192 sdb%c%|%d a 16
+
+b $STORAGE              68   0  1 224 sdb%c%|%d m 16
+b $STORAGE              68 224  1  32 sdc%c%|%d a 16
+
+b $STORAGE              69   0  1 256 sdc%c%|%d c 16
+
+b $STORAGE              70   0  1 128 sdc%c%|%d s 16
+b $STORAGE              70 128  1 128 sdd%c%|%d a 16
+
+b $STORAGE              71   0  1 256 sdd%c%|%d i 16
+
+b $STORAGE              80   0  1 256 i2o/hd%c%|%d a 16
+
+b $STORAGE              81   0  1 160 i2o/hd%c%|%d q 16
+b $STORAGE              81 160  1  96 i2o/hda%c%|%d a 16
 
 c $CONSOLE              82   0  1   4 winradio%d
 
-b $STORAGE              82   0  1  16 i2o/hdag
-b $STORAGE              82  16  1  16 i2o/hdah
-b $STORAGE              82  32  1  16 i2o/hdai
-b $STORAGE              82  48  1  16 i2o/hdaj
-b $STORAGE              82  64  1  16 i2o/hdak
-b $STORAGE              82  80  1  16 i2o/hdal
-b $STORAGE              82  96  1  16 i2o/hdam
-b $STORAGE              82 112  1  16 i2o/hdan
-b $STORAGE              82 128  1  16 i2o/hdao
-b $STORAGE              82 144  1  16 i2o/hdap
-b $STORAGE              82 160  1  16 i2o/hdaq
-b $STORAGE              82 176  1  16 i2o/hdar
-b $STORAGE              82 192  1  16 i2o/hdas
-b $STORAGE              82 208  1  16 i2o/hdat
-b $STORAGE              82 224  1  16 i2o/hdau
-b $STORAGE              82 240  1  16 i2o/hdav
+b $STORAGE              82   0  1 256 i2o/hda%c%|%d g 16
 
 c $CONSOLE              83   0  1  16 mga_vid%d
 
-b $STORAGE              83   0  1  16 i2o/hdaw
-b $STORAGE              83  16  1  16 i2o/hdax
-b $STORAGE              83  32  1  16 i2o/hday
-b $STORAGE              83  48  1  16 i2o/hdaz
-b $STORAGE              83  64  1  16 i2o/hdba
-b $STORAGE              83  80  1  16 i2o/hdbb
-b $STORAGE              83  96  1  16 i2o/hdbc
-b $STORAGE              83 112  1  16 i2o/hdbd
-b $STORAGE              83 128  1  16 i2o/hdbe
-b $STORAGE              83 144  1  16 i2o/hdbf
-b $STORAGE              83 160  1  16 i2o/hdbg
-b $STORAGE              83 176  1  16 i2o/hdbh
-b $STORAGE              83 192  1  16 i2o/hdbi
-b $STORAGE              83 208  1  16 i2o/hdbj
-b $STORAGE              83 224  1  16 i2o/hdbk
-b $STORAGE              83 240  1  16 i2o/hdbl
-
-b $STORAGE              84   0  1  16 i2o/hdbm
-b $STORAGE              84  16  1  16 i2o/hdbn
-b $STORAGE              84  32  1  16 i2o/hdbo
-b $STORAGE              84  48  1  16 i2o/hdbp
-b $STORAGE              84  64  1  16 i2o/hdbq
-b $STORAGE              84  80  1  16 i2o/hdbr
-b $STORAGE              84  96  1  16 i2o/hdbs
-b $STORAGE              84 112  1  16 i2o/hdbt
-b $STORAGE              84 128  1  16 i2o/hdbu
-b $STORAGE              84 144  1  16 i2o/hdbv
-b $STORAGE              84 160  1  16 i2o/hdbw
-b $STORAGE              84 176  1  16 i2o/hdbx
-b $STORAGE              84 192  1  16 i2o/hdby
-b $STORAGE              84 208  1  16 i2o/hdbz
-b $STORAGE              84 224  1  16 i2o/hdca
-b $STORAGE              84 240  1  16 i2o/hdcb
-
-b $STORAGE              85   0  1  16 i2o/hdcc
-b $STORAGE              85  16  1  16 i2o/hdcd
-b $STORAGE              85  32  1  16 i2o/hdce
-b $STORAGE              85  48  1  16 i2o/hdcf
-b $STORAGE              85  64  1  16 i2o/hdcg
-b $STORAGE              85  80  1  16 i2o/hdch
-b $STORAGE              85  96  1  16 i2o/hdci
-b $STORAGE              85 112  1  16 i2o/hdcj
-b $STORAGE              85 128  1  16 i2o/hdck
-b $STORAGE              85 144  1  16 i2o/hdcl
-b $STORAGE              85 160  1  16 i2o/hdcm
-b $STORAGE              85 176  1  16 i2o/hdcn
-b $STORAGE              85 192  1  16 i2o/hdco
-b $STORAGE              85 208  1  16 i2o/hdcp
-b $STORAGE              85 224  1  16 i2o/hdcq
-b $STORAGE              85 240  1  16 i2o/hdcr
-
-b $STORAGE              86   0  1  16 i2o/hdcs
-b $STORAGE              86  16  1  16 i2o/hdct
-b $STORAGE              86  32  1  16 i2o/hdcu
-b $STORAGE              86  48  1  16 i2o/hdcv
-b $STORAGE              86  64  1  16 i2o/hdcw
-b $STORAGE              86  80  1  16 i2o/hdcx
-b $STORAGE              86  96  1  16 i2o/hdcy
-b $STORAGE              86 112  1  16 i2o/hdcz
-b $STORAGE              86 128  1  16 i2o/hdda
-b $STORAGE              86 144  1  16 i2o/hddb
-b $STORAGE              86 160  1  16 i2o/hddc
-b $STORAGE              86 176  1  16 i2o/hddd
-b $STORAGE              86 192  1  16 i2o/hdde
-b $STORAGE              86 208  1  16 i2o/hddf
-b $STORAGE              86 224  1  16 i2o/hddg
-b $STORAGE              86 240  1  16 i2o/hddh
-
-b $STORAGE              87   0  1  16 i2o/hddi
-b $STORAGE              87  16  1  16 i2o/hddj
-b $STORAGE              87  32  1  16 i2o/hddk
-b $STORAGE              87  48  1  16 i2o/hddl
-b $STORAGE              87  64  1  16 i2o/hddm
-b $STORAGE              87  80  1  16 i2o/hddn
-b $STORAGE              87  96  1  16 i2o/hddo
-b $STORAGE              87 112  1  16 i2o/hddp
-b $STORAGE              87 128  1  16 i2o/hddq
-b $STORAGE              87 144  1  16 i2o/hddr
-b $STORAGE              87 160  1  16 i2o/hdds
-b $STORAGE              87 176  1  16 i2o/hddt
-b $STORAGE              87 192  1  16 i2o/hddu
-b $STORAGE              87 208  1  16 i2o/hddv
-b $STORAGE              87 224  1  16 i2o/hddw
-b $STORAGE              87 240  1  16 i2o/hddx
+b $STORAGE              83   0  1  64 i2o/hda%c%|%d w 16
+b $STORAGE              83  64  1 192 i2o/hdb%c%|%d a 16
+
+b $STORAGE              84   0  1 224 i2o/hdb%c%|%d m 16
+b $STORAGE              84 224  1  32 i2o/hdc%c%|%d a 16
+
+b $STORAGE              85   0  1 256 i2o/hdc%c%|%d c 16
+
+b $STORAGE              86   0  1 128 i2o/hdc%c%|%d s 16
+b $STORAGE              86 128  1 128 i2o/hdd%c%|%d a 16
+
+b $STORAGE              87   0  1 256 i2o/hdd%c%|%d i 16
 
 # devices.txt gives us 64 numbered dasd devices, with apparently up to three
 # lettered partitions on each; the older s390-specific file used 64 lettered
@@ -452,315 +219,46 @@ b $STORAGE              94   1  4  64 da
 b $STORAGE              94   2  4  64 dasd%db
 b $STORAGE              94   3  4  64 dasd%dc
 
-b $STORAGE              96   0  1  16 inftla
-b $STORAGE              96  16  1  16 inftlb
-b $STORAGE              96  32  1  16 inftlc
-b $STORAGE              96  48  1  16 inftld
-b $STORAGE              96  64  1  16 inftle
-b $STORAGE              96  80  1  16 inftlf
-b $STORAGE              96  96  1  16 inftlg
-b $STORAGE              96 112  1  16 inftlh
-b $STORAGE              96 128  1  16 inftli
-b $STORAGE              96 144  1  16 inftlj
-b $STORAGE              96 160  1  16 inftlk
-b $STORAGE              96 176  1  16 inftll
-b $STORAGE              96 192  1  16 inftlm
-b $STORAGE              96 208  1  16 inftln
-b $STORAGE              96 224  1  16 inftlo
-b $STORAGE              96 240  1  16 inftlp
-
-b $STORAGE             101   0  1   1 amiraid/ar0
-b $STORAGE             101   1  1  15 amiraid/ar0p%d
-b $STORAGE             101  16  1   1 amiraid/ar1
-b $STORAGE             101  17  1  15 amiraid/ar1p%d
-b $STORAGE             101  32  1   1 amiraid/ar2
-b $STORAGE             101  33  1  15 amiraid/ar2p%d
-b $STORAGE             101  48  1   1 amiraid/ar3
-b $STORAGE             101  49  1  15 amiraid/ar3p%d
-b $STORAGE             101  64  1   1 amiraid/ar4
-b $STORAGE             101  65  1  15 amiraid/ar4p%d
-b $STORAGE             101  80  1   1 amiraid/ar5
-b $STORAGE             101  81  1  15 amiraid/ar5p%d
-b $STORAGE             101  96  1   1 amiraid/ar6
-b $STORAGE             101  97  1  15 amiraid/ar6p%d
-b $STORAGE             101 112  1   1 amiraid/ar7
-b $STORAGE             101 113  1  15 amiraid/ar7p%d
-b $STORAGE             101 128  1   1 amiraid/ar8
-b $STORAGE             101 129  1  15 amiraid/ar8p%d
-b $STORAGE             101 144  1   1 amiraid/ar9
-b $STORAGE             101 145  1  15 amiraid/ar9p%d
-b $STORAGE             101 160  1   1 amiraid/ar10
-b $STORAGE             101 161  1  15 amiraid/ar10p%d
-b $STORAGE             101 176  1   1 amiraid/ar11
-b $STORAGE             101 177  1  15 amiraid/ar11p%d
-b $STORAGE             101 192  1   1 amiraid/ar12
-b $STORAGE             101 193  1  15 amiraid/ar12p%d
-b $STORAGE             101 208  1   1 amiraid/ar13
-b $STORAGE             101 209  1  15 amiraid/ar13p%d
-b $STORAGE             101 224  1   1 amiraid/ar14
-b $STORAGE             101 225  1  15 amiraid/ar14p%d
-b $STORAGE             101 240  1   1 amiraid/ar15
-b $STORAGE             101 241  1  15 amiraid/ar15p%d
-
-b $STORAGE             112   0  1   8 iseries/vda
-b $STORAGE             112   8  1   8 iseries/vdb
-b $STORAGE             112  16  1   8 iseries/vdc
-b $STORAGE             112  24  1   8 iseries/vdd
-b $STORAGE             112  32  1   8 iseries/vde
-b $STORAGE             112  40  1   8 iseries/vdf
-b $STORAGE             112  48  1   8 iseries/vdg
-b $STORAGE             112  56  1   8 iseries/vdh
-b $STORAGE             112  64  1   8 iseries/vdi
-b $STORAGE             112  72  1   8 iseries/vdj
-b $STORAGE             112  80  1   8 iseries/vdk
-b $STORAGE             112  88  1   8 iseries/vdl
-b $STORAGE             112  96  1   8 iseries/vdm
-b $STORAGE             112 104  1   8 iseries/vdn
-b $STORAGE             112 112  1   8 iseries/vdo
-b $STORAGE             112 120  1   8 iseries/vdp
-b $STORAGE             112 128  1   8 iseries/vdq
-b $STORAGE             112 136  1   8 iseries/vdr
-b $STORAGE             112 144  1   8 iseries/vds
-b $STORAGE             112 152  1   8 iseries/vdt
-b $STORAGE             112 160  1   8 iseries/vdu
-b $STORAGE             112 168  1   8 iseries/vdv
-b $STORAGE             112 176  1   8 iseries/vdw
-b $STORAGE             112 184  1   8 iseries/vdx
-b $STORAGE             112 192  1   8 iseries/vdy
-b $STORAGE             112 200  1   8 iseries/vdz
-b $STORAGE             112 208  1   8 iseries/vdaa
-b $STORAGE             112 216  1   8 iseries/vdab
-b $STORAGE             112 224  1   8 iseries/vdac
-b $STORAGE             112 232  1   8 iseries/vdad
-b $STORAGE             112 240  1   8 iseries/vdae
-b $STORAGE             112 248  1   8 iseries/vdaf
+b $STORAGE              96   0  1 256 inftl%c%|%d a 16
+
+b $STORAGE             101   0  1 256 amiraid/ar%d%|p%d 0 16
+
+b $STORAGE             112   0  1 208 iseries/vd%c%|%d a 8
+b $STORAGE             112 208  1  48 iseries/vda%c%|%d a 8
 
 b $STORAGE             113   0  1   8 iseries/vcd%c a
 
 b $STORAGE             115   0  1 256 nwfs/v%d
 
-b $STORAGE             116   0 16  16 umem/d%d
-b $STORAGE             116   1  1  15 umem/d0p%d
-b $STORAGE             116  17  1  15 umem/d1p%d
-b $STORAGE             116  33  1  15 umem/d2p%d
-b $STORAGE             116  49  1  15 umem/d3p%d
-b $STORAGE             116  65  1  15 umem/d4p%d
-b $STORAGE             116  81  1  15 umem/d5p%d
-b $STORAGE             116  97  1  15 umem/d6p%d
-b $STORAGE             116 113  1  15 umem/d7p%d
-b $STORAGE             116 129  1  15 umem/d8p%d
-b $STORAGE             116 145  1  15 umem/d9p%d
-b $STORAGE             116 161  1  15 umem/d10p%d
-b $STORAGE             116 177  1  15 umem/d11p%d
-b $STORAGE             116 193  1  15 umem/d12p%d
-b $STORAGE             116 209  1  15 umem/d13p%d
-b $STORAGE             116 225  1  15 umem/d14p%d
-b $STORAGE             116 241  1  15 umem/d15p%d
-
-b $STORAGE             128   0  1  16 sddy
-b $STORAGE             128  16  1  16 sddz
-b $STORAGE             128  32  1  16 sdea
-b $STORAGE             128  48  1  16 sdeb
-b $STORAGE             128  64  1  16 sdec
-b $STORAGE             128  80  1  16 sded
-b $STORAGE             128  96  1  16 sdee
-b $STORAGE             128 112  1  16 sdef
-b $STORAGE             128 128  1  16 sdeg
-b $STORAGE             128 144  1  16 sdeh
-b $STORAGE             128 160  1  16 sdei
-b $STORAGE             128 176  1  16 sdej
-b $STORAGE             128 192  1  16 sdek
-b $STORAGE             128 208  1  16 sdel
-b $STORAGE             128 224  1  16 sdem
-b $STORAGE             128 240  1  16 sden
-
-b $STORAGE             129   0  1  16 sdeo
-b $STORAGE             129  16  1  16 sdep
-b $STORAGE             129  32  1  16 sdeq
-b $STORAGE             129  48  1  16 sder
-b $STORAGE             129  64  1  16 sdes
-b $STORAGE             129  80  1  16 sdet
-b $STORAGE             129  96  1  16 sdeu
-b $STORAGE             129 112  1  16 sdev
-b $STORAGE             129 128  1  16 sdew
-b $STORAGE             129 144  1  16 sdex
-b $STORAGE             129 160  1  16 sdey
-b $STORAGE             129 176  1  16 sdez
-b $STORAGE             129 192  1  16 sdfa
-b $STORAGE             129 208  1  16 sdfb
-b $STORAGE             129 224  1  16 sdfc
-b $STORAGE             129 240  1  16 sdfd
-
-b $STORAGE             130   0  1  16 sdfe
-b $STORAGE             130  16  1  16 sdff
-b $STORAGE             130  32  1  16 sdfg
-b $STORAGE             130  48  1  16 sdfh
-b $STORAGE             130  64  1  16 sdfi
-b $STORAGE             130  80  1  16 sdfj
-b $STORAGE             130  96  1  16 sdfk
-b $STORAGE             130 112  1  16 sdfl
-b $STORAGE             130 128  1  16 sdfm
-b $STORAGE             130 144  1  16 sdfn
-b $STORAGE             130 160  1  16 sdfo
-b $STORAGE             130 176  1  16 sdfp
-b $STORAGE             130 192  1  16 sdfq
-b $STORAGE             130 208  1  16 sdfr
-b $STORAGE             130 224  1  16 sdfs
-b $STORAGE             130 240  1  16 sdft
-
-b $STORAGE             131   0  1  16 sdfu
-b $STORAGE             131  16  1  16 sdfv
-b $STORAGE             131  32  1  16 sdfw
-b $STORAGE             131  48  1  16 sdfx
-b $STORAGE             131  64  1  16 sdfy
-b $STORAGE             131  80  1  16 sdfz
-b $STORAGE             131  96  1  16 sdga
-b $STORAGE             131 112  1  16 sdgb
-b $STORAGE             131 128  1  16 sdgc
-b $STORAGE             131 144  1  16 sdgd
-b $STORAGE             131 160  1  16 sdge
-b $STORAGE             131 176  1  16 sdgf
-b $STORAGE             131 192  1  16 sdgg
-b $STORAGE             131 208  1  16 sdgh
-b $STORAGE             131 224  1  16 sdgi
-b $STORAGE             131 240  1  16 sdgj
-
-b $STORAGE             132   0  1  16 sdgk
-b $STORAGE             132  16  1  16 sdgl
-b $STORAGE             132  32  1  16 sdgm
-b $STORAGE             132  48  1  16 sdgn
-b $STORAGE             132  64  1  16 sdgo
-b $STORAGE             132  80  1  16 sdgp
-b $STORAGE             132  96  1  16 sdgq
-b $STORAGE             132 112  1  16 sdgr
-b $STORAGE             132 128  1  16 sdgs
-b $STORAGE             132 144  1  16 sdgt
-b $STORAGE             132 160  1  16 sdgu
-b $STORAGE             132 176  1  16 sdgv
-b $STORAGE             132 192  1  16 sdgw
-b $STORAGE             132 208  1  16 sdgx
-b $STORAGE             132 224  1  16 sdgy
-b $STORAGE             132 240  1  16 sdgz
-
-b $STORAGE             133   0  1  16 sdha
-b $STORAGE             133  16  1  16 sdhb
-b $STORAGE             133  32  1  16 sdhc
-b $STORAGE             133  48  1  16 sdhd
-b $STORAGE             133  64  1  16 sdhe
-b $STORAGE             133  80  1  16 sdhf
-b $STORAGE             133  96  1  16 sdhg
-b $STORAGE             133 112  1  16 sdhh
-b $STORAGE             133 128  1  16 sdhi
-b $STORAGE             133 144  1  16 sdhj
-b $STORAGE             133 160  1  16 sdhk
-b $STORAGE             133 176  1  16 sdhl
-b $STORAGE             133 192  1  16 sdhm
-b $STORAGE             133 208  1  16 sdhn
-b $STORAGE             133 224  1  16 sdho
-b $STORAGE             133 240  1  16 sdhp
-
-b $STORAGE             134   0  1  16 sdhq
-b $STORAGE             134  16  1  16 sdhr
-b $STORAGE             134  32  1  16 sdhs
-b $STORAGE             134  48  1  16 sdht
-b $STORAGE             134  64  1  16 sdhu
-b $STORAGE             134  80  1  16 sdhv
-b $STORAGE             134  96  1  16 sdhw
-b $STORAGE             134 112  1  16 sdhx
-b $STORAGE             134 128  1  16 sdhy
-b $STORAGE             134 144  1  16 sdhz
-b $STORAGE             134 160  1  16 sdia
-b $STORAGE             134 176  1  16 sdib
-b $STORAGE             134 192  1  16 sdic
-b $STORAGE             134 208  1  16 sdid
-b $STORAGE             134 224  1  16 sdie
-b $STORAGE             134 240  1  16 sdif
-
-b $STORAGE             135   0  1  16 sdig
-b $STORAGE             135  16  1  16 sdih
-b $STORAGE             135  32  1  16 sdii
-b $STORAGE             135  48  1  16 sdij
-b $STORAGE             135  64  1  16 sdik
-b $STORAGE             135  80  1  16 sdil
-b $STORAGE             135  96  1  16 sdim
-b $STORAGE             135 112  1  16 sdin
-b $STORAGE             135 128  1  16 sdio
-b $STORAGE             135 144  1  16 sdip
-b $STORAGE             135 160  1  16 sdiq
-b $STORAGE             135 176  1  16 sdir
-b $STORAGE             135 192  1  16 sdis
-b $STORAGE             135 208  1  16 sdit
-b $STORAGE             135 224  1  16 sdiu
-b $STORAGE             135 240  1  16 sdiv
-
-b $STORAGE             153   0 16  16 emd/%d
-b $STORAGE             153   1  1  15 emd/0p%d 1
-b $STORAGE             153  17  1  15 emd/1p%d 1
-b $STORAGE             153  33  1  15 emd/2p%d 1
-b $STORAGE             153  49  1  15 emd/3p%d 1
-b $STORAGE             153  65  1  15 emd/4p%d 1
-b $STORAGE             153  81  1  15 emd/5p%d 1
-b $STORAGE             153  97  1  15 emd/6p%d 1
-b $STORAGE             153 113  1  15 emd/7p%d 1
-b $STORAGE             153 129  1  15 emd/8p%d 1
-b $STORAGE             153 145  1  15 emd/9p%d 1
-b $STORAGE             153 161  1  15 emd/10p%d 1
-b $STORAGE             153 177  1  15 emd/11p%d 1
-b $STORAGE             153 193  1  15 emd/12p%d 1
-b $STORAGE             153 209  1  15 emd/13p%d 1
-b $STORAGE             153 225  1  15 emd/14p%d 1
-b $STORAGE             153 241  1  15 emd/15p%d 1
-
-b $STORAGE             160   0  1   1 sx8/0
-b $STORAGE             160   1  1  31 sx8/0p%d 1
-b $STORAGE             160  32  1   1 sx8/1
-b $STORAGE             160  33  1  31 sx8/1p%d 1
-b $STORAGE             160  64  1   1 sx8/2
-b $STORAGE             160  65  1  31 sx8/2p%d 1
-b $STORAGE             160  96  1   1 sx8/3
-b $STORAGE             160  97  1  31 sx8/3p%d 1
-b $STORAGE             160 128  1   1 sx8/4
-b $STORAGE             160 129  1  31 sx8/4p%d 1
-b $STORAGE             160 160  1   1 sx8/5
-b $STORAGE             160 161  1  31 sx8/5p%d 1
-b $STORAGE             160 192  1   1 sx8/6
-b $STORAGE             160 193  1  31 sx8/6p%d 1
-b $STORAGE             160 224  1   1 sx8/7
-b $STORAGE             160 225  1  31 sx8/7p%d 1
-
-b $STORAGE             161   0  1   1 sx8/8
-b $STORAGE             161   1  1  31 sx8/8p%d 1
-b $STORAGE             161  32  1   1 sx8/9
-b $STORAGE             161  33  1  31 sx8/9p%d 1
-b $STORAGE             161  64  1   1 sx8/10
-b $STORAGE             161  65  1  31 sx8/10p%d 1
-b $STORAGE             161  96  1   1 sx8/11
-b $STORAGE             161  97  1  31 sx8/11p%d 1
-b $STORAGE             161 128  1   1 sx8/12
-b $STORAGE             161 129  1  31 sx8/12p%d 1
-b $STORAGE             161 160  1   1 sx8/13
-b $STORAGE             161 161  1  31 sx8/13p%d 1
-b $STORAGE             161 192  1   1 sx8/14
-b $STORAGE             161 193  1  31 sx8/14p%d 1
-b $STORAGE             161 224  1   1 sx8/15
-b $STORAGE             161 225  1  31 sx8/15p%d 1
-
-b $STORAGE             180   0  1   8 uba
-b $STORAGE             180   8  1   8 ubb
-b $STORAGE             180  16  1   8 ubc
-b $STORAGE             180  24  1   8 ubd
-b $STORAGE             180  32  1   8 ube
-b $STORAGE             180  40  1   8 ubf
-b $STORAGE             180  48  1   8 ubg
-b $STORAGE             180  56  1   8 ubh
-b $STORAGE             180  64  1   8 ubi
-b $STORAGE             180  72  1   8 ubj
-b $STORAGE             180  80  1   8 ubk
-b $STORAGE             180  88  1   8 ubl
-b $STORAGE             180  96  1   8 ubm
-b $STORAGE             180 104  1   8 ubn
-b $STORAGE             180 112  1   8 ubo
-b $STORAGE             180 120  1   8 ubp
+b $STORAGE             116   0  1 256 umem/d%d%|p%d 0 16
+
+b $STORAGE             128   0  1  32 sdd%c%|%d y 16
+b $STORAGE             128  32  1 224 sde%c%|%d a 16
+
+b $STORAGE             129   0  1 192 sde%c%|%d o 16
+b $STORAGE             129 192  1  64 sdf%c%|%d a 16
+
+b $STORAGE             130   0  1 256 sdf%c%|%d e 16
+
+b $STORAGE             131   0  1  96 sdf%c%|%d u 16
+b $STORAGE             131  96  1 160 sdg%c%|%d a 16
+
+b $STORAGE             132   0  1 256 sdg%c%|%d k 16
+
+b $STORAGE             133   0  1 256 sdh%c%|%d a 16
+
+b $STORAGE             134   0  1 160 sdh%c%|%d q 16
+b $STORAGE             134 160  1  96 sdi%c%|%d a 16
+
+b $STORAGE             135   0  1 256 sdi%c%|%d g 16
+
+b $STORAGE             153   0  1 256 emd/%d%|p%d 0 16
+
+b $STORAGE             160   0  1 256 sx8/%d%|p%d 0 16
+
+b $STORAGE             161   0  1 256 sx8/%d%|p%d 8 16
+
+b $STORAGE             180   0  1 128 ub%c%|%d a 8
 
 c $CONSOLE             195   0  1 255 nvidia%d
 c $CONSOLE             195 255  1   1 nvidiactl
@@ -774,22 +272,7 @@ c $STORAGE             200   5  1   1 vx
 
 # We can skip 201 because Veritas user-land handles it.
 
-b $STORAGE             202   0  1  16 xvda
-b $STORAGE             202  16  1  16 xvdb
-b $STORAGE             202  32  1  16 xvdc
-b $STORAGE             202  48  1  16 xvdd
-b $STORAGE             202  64  1  16 xvde
-b $STORAGE             202  80  1  16 xvdf
-b $STORAGE             202  96  1  16 xvdg
-b $STORAGE             202 112  1  16 xvdh
-b $STORAGE             202 128  1  16 xvdi
-b $STORAGE             202 144  1  16 xvdj
-b $STORAGE             202 160  1  16 xvdk
-b $STORAGE             202 176  1  16 xvdl
-b $STORAGE             202 192  1  16 xvdm
-b $STORAGE             202 208  1  16 xvdn
-b $STORAGE             202 224  1  16 xvdo
-b $STORAGE             202 240  1  16 xvdp
+b $STORAGE             202   0  1 256 xvd%c%|%d a 16
 
 c $ROOT                207   0  1   1 cpqhealth/cpqw
 c $ROOT                207   1  1   1 cpqhealth/crom
@@ -804,14 +287,14 @@ c $ROOT                207   9  1   1 cp
 c $ROOT                207  10  1   1 cpqhealth/cram
 c $ROOT                207  11  1   1 cpqhealth/cpci
 
-c $ROOT                230   0  1  32 iseries/vt%d 0
-c $ROOT                230  32  1  32 iseries/vt%dl 0
-c $ROOT                230  64  1  32 iseries/vt%dm 0
-c $ROOT                230  96  1  32 iseries/vt%da 0
-c $ROOT                230 128  1  32 iseries/nvt%d 0
-c $ROOT                230 160  1  32 iseries/nvt%dl 0
-c $ROOT                230 192  1  32 iseries/nvt%dm 0
-c $ROOT                230 224  1  32 iseries/nvt%da 0
+c $ROOT                230   0  1  32 iseries/vt%d
+c $ROOT                230  32  1  32 iseries/vt%dl
+c $ROOT                230  64  1  32 iseries/vt%dm
+c $ROOT                230  96  1  32 iseries/vt%da
+c $ROOT                230 128  1  32 iseries/nvt%d
+c $ROOT                230 160  1  32 iseries/nvt%dl
+c $ROOT                230 192  1  32 iseries/nvt%dm
+c $ROOT                230 224  1  32 iseries/nvt%da
 
 c $ROOT                231   0  1  64 infiniband/umad%d
 c $ROOT                231  64  1  64 infiniband/issm%d
--- MAKEDEV-3.23/makedev.d/linux-2.6.x.jj	2008-09-19 03:03:54.000000000 +0200
+++ MAKEDEV-3.23/makedev.d/linux-2.6.x	2008-09-27 08:47:59.000000000 +0200
@@ -19,39 +19,11 @@ c $ROOT                  1  11  1   1 km
 b $STORAGE               1   0  1 128 ram%d
 b $STORAGE               1 250  1   1 initrd
 
-c $PTY                   2   0  1  16 ptyp%x
-c $PTY                   2  16  1  16 ptyq%x
-c $PTY                   2  32  1  16 ptyr%x
-c $PTY                   2  48  1  16 ptys%x
-c $PTY                   2  64  1  16 ptyt%x
-c $PTY                   2  80  1  16 ptyu%x
-c $PTY                   2  96  1  16 ptyv%x
-c $PTY                   2 112  1  16 ptyw%x
-c $PTY                   2 128  1  16 ptyx%x
-c $PTY                   2 144  1  16 ptyy%x
-c $PTY                   2 160  1  16 ptyz%x
-c $PTY                   2 176  1  16 ptya%x
-c $PTY                   2 192  1  16 ptyb%x
-c $PTY                   2 208  1  16 ptyc%x
-c $PTY                   2 224  1  16 ptyd%x
-c $PTY                   2 240  1  16 ptye%x
-
-c $PTY                   3   0  1  16 ttyp%x
-c $PTY                   3  16  1  16 ttyq%x
-c $PTY                   3  32  1  16 ttyr%x
-c $PTY                   3  48  1  16 ttys%x
-c $PTY                   3  64  1  16 ttyt%x
-c $PTY                   3  80  1  16 ttyu%x
-c $PTY                   3  96  1  16 ttyv%x
-c $PTY                   3 112  1  16 ttyw%x
-c $PTY                   3 128  1  16 ttyx%x
-c $PTY                   3 144  1  16 ttyy%x
-c $PTY                   3 160  1  16 ttyz%x
-c $PTY                   3 176  1  16 ttya%x
-c $PTY                   3 192  1  16 ttyb%x
-c $PTY                   3 208  1  16 ttyc%x
-c $PTY                   3 224  1  16 ttyd%x
-c $PTY                   3 240  1  16 ttye%x
+c $PTY                   2   0  1 176 pty%c%x p 16
+c $PTY                   2 176  1  80 pty%c%x a 16
+
+c $PTY                   3   0  1 176 tty%c%x p 16
+c $PTY                   3 176  1  80 tty%c%x a 16
 
 # See fs/partitions/check.c in the kernel sources for the source of this
 # limitation.
@@ -75,22 +47,7 @@ c $VCSA                  7 128  1  64 vc
 
 b $STORAGE               7   0  1 256 loop%d
 
-b $STORAGE               8   0  1  16 sda
-b $STORAGE               8  16  1  16 sdb
-b $STORAGE               8  32  1  16 sdc
-b $STORAGE               8  48  1  16 sdd
-b $STORAGE               8  64  1  16 sde
-b $STORAGE               8  80  1  16 sdf
-b $STORAGE               8  96  1  16 sdg
-b $STORAGE               8 112  1  16 sdh
-b $STORAGE               8 128  1  16 sdi
-b $STORAGE               8 144  1  16 sdj
-b $STORAGE               8 160  1  16 sdk
-b $STORAGE               8 176  1  16 sdl
-b $STORAGE               8 192  1  16 sdm
-b $STORAGE               8 208  1  16 sdn
-b $STORAGE               8 224  1  16 sdo
-b $STORAGE               8 240  1  16 sdp
+b $STORAGE               8   0  1 256 sd%c%|%d a 16
 
 c $STORAGE               9   0  1  32 st%d
 c $STORAGE               9  32  1  32 st%dl
@@ -183,10 +140,7 @@ c $ROOT                 10 208  1   1 co
 c $ROOT                 10 209  1   1 compaq/cpqrid
 c $ROOT                 10 210  1   1 impi/bt
 c $ROOT                 10 211  1   1 impi/smic
-c $ROOT                 10 212  1   1 watchdogs/0
-c $ROOT                 10 213  1   1 watchdogs/1
-c $ROOT                 10 214  1   1 watchdogs/2
-c $ROOT                 10 215  1   1 watchdogs/3
+c $ROOT                 10 212  1   4 watchdogs/%d
 c $ROOT                 10 216  1   1 fujitsu/apanel
 c $ROOT                 10 217  1   1 ni/natmotn
 c $ROOT                 10 218  1   1 kchuid
@@ -214,8 +168,7 @@ c $CONSOLE              13  32  1  31 in
 c $CONSOLE              13  63  1   1 input/mice
 c $CONSOLE              13  64  1  32 input/event%d
 
-b $STORAGE              13   0  1  64 xda
-b $STORAGE              13  64  1  64 xdb
+b $STORAGE              13   0  1 128 xd%c%|%d a 16
 
 c $CONSOLE              14   0  1   1 mixer
 c $CONSOLE              14   1  1   1 sequencer
@@ -377,10 +330,7 @@ b $STORAGE              43   0  1 128 nb
 c $SERIAL               44   0  1  64 cui%d
 c $ROOT                 45 128  1  64 ippp%d
 c $ROOT                 45 255  1   1 isdninfo
-b $STORAGE              45   0  1  16 pda
-b $STORAGE              45  16  1  16 pdb
-b $STORAGE              45  32  1  16 pdc
-b $STORAGE              45  48  1  16 pdd
+b $STORAGE              45   0  1  64 pd%c%|%d a 16
 
 c $SERIAL               46   0  1  16 ttyR%d
 b $STORAGE              46   0  1   4 pcd%d
@@ -512,22 +462,7 @@ c $STORAGE              97   0  1   4 pg
 
 c $ROOT                 98   0  1   4 comedi%d
 
-b $STORAGE              98   0  1  16 ubda
-b $STORAGE              98  16  1  16 ubdb
-b $STORAGE              98  32  1  16 ubdc
-b $STORAGE              98  48  1  16 ubdd
-b $STORAGE              98  64  1  16 ubde
-b $STORAGE              98  80  1  16 ubdf
-b $STORAGE              98  96  1  16 ubdg
-b $STORAGE              98 112  1  16 ubdh
-b $STORAGE              98 128  1  16 ubdi
-b $STORAGE              98 144  1  16 ubdj
-b $STORAGE              98 160  1  16 ubdk
-b $STORAGE              98 176  1  16 ubdl
-b $STORAGE              98 192  1  16 ubdm
-b $STORAGE              98 208  1  16 ubdn
-b $STORAGE              98 224  1  16 ubdo
-b $STORAGE              98 240  1  16 ubdp
+b $STORAGE              98   0  1 256 ubd%c%|%d a 16
 
 c $PRINTER              99   0  1   8 parport%d
 b $STORAGE              99   0  1   1 jsfd
@@ -539,22 +474,7 @@ c $ROOT                101   1  1  16 md
 
 c $ROOT                102   0  1   4 tlk%d
 
-b $STORAGE             102   0  1  16 cbd/a
-b $STORAGE             102  16  1  16 cbd/b
-b $STORAGE             102  32  1  16 cbd/c
-b $STORAGE             102  48  1  16 cbd/d
-b $STORAGE             102  64  1  16 cbd/e
-b $STORAGE             102  80  1  16 cbd/f
-b $STORAGE             102  96  1  16 cbd/g
-b $STORAGE             102 112  1  16 cbd/h
-b $STORAGE             102 128  1  16 cbd/i
-b $STORAGE             102 144  1  16 cbd/j
-b $STORAGE             102 160  1  16 cbd/k
-b $STORAGE             102 176  1  16 cbd/l
-b $STORAGE             102 192  1  16 cbd/m
-b $STORAGE             102 208  1  16 cbd/n
-b $STORAGE             102 224  1  16 cbd/o
-b $STORAGE             102 240  1  16 cbd/p
+b $STORAGE             102   0  1 256 cbd/%c%|%d a 16
 
 c $STORAGE             103   0  1   2 nnpfs%d
 b $ROOT                103   0  1   1 audit
@@ -704,9 +624,9 @@ c $SERIAL              189   0  1  16 cu
 c $CONSOLE             190   0  1  16 kctt%d
 
 c $ROOT                192   0  1   1 profile
-c $ROOT                192   1  1  16 profile%d 0
+c $ROOT                192   1  1  16 profile%d
 c $ROOT                193   0  1   1 trace
-c $ROOT                193   1  1  16 trace%d 0
+c $ROOT                193   1  1  16 trace%d
 
 c $CONSOLE             194   0 16  16 mvideo/status%d
 c $CONSOLE             194   1 16  16 mvideo/stream%d
@@ -734,13 +654,13 @@ c $ROOT                203   0  1  16 cp
 
 b $ROOT                203   0  1  16 cpu/%d/cpuid
 
-c $SERIAL              204   0  1   4 ttyLU%d 0
-c $SERIAL              204   4  1   1 ttyFB%d 0
-c $SERIAL              204   5  1   3 ttySA%d 0
-c $SERIAL              204   8  1   4 ttySC%d 0
-c $SERIAL              204  12  1   4 ttyFW%d 0
-c $SERIAL              204  16  1  16 ttyAM%d 0
-c $SERIAL              204  32  1   8 ttyDB%d 0
+c $SERIAL              204   0  1   4 ttyLU%d
+c $SERIAL              204   4  1   1 ttyFB%d
+c $SERIAL              204   5  1   3 ttySA%d
+c $SERIAL              204   8  1   4 ttySC%d
+c $SERIAL              204  12  1   4 ttyFW%d
+c $SERIAL              204  16  1  16 ttyAM%d
+c $SERIAL              204  32  1   8 ttyDB%d
 c $TTY                 204  40  1   1 ttySG0
 c $SERIAL              204  41  1   3 ttySMX%d
 c $SERIAL              204  44  1   2 ttyMM%d
@@ -754,41 +674,41 @@ c $SERIAL              204 154  1  16 tt
 c $SERIAL              204 170  1  16 ttyNX%d
 c $SERIAL              204 186  1   1 ttyJ0
 
-c $SERIAL              205   0  1   4 culu%d 0
-c $SERIAL              205   4  1   1 cufb%d 0
-c $SERIAL              205   5  1   3 cusa%d 0
-c $SERIAL              205   8  1   4 cusc%d 0
-c $SERIAL              205  12  1   4 cufw%d 0
-c $SERIAL              205  16  1  16 cuam%d 0
-c $SERIAL              205  32  1   8 cudb%d 0
+c $SERIAL              205   0  1   4 culu%d
+c $SERIAL              205   4  1   1 cufb%d
+c $SERIAL              205   5  1   3 cusa%d
+c $SERIAL              205   8  1   4 cusc%d
+c $SERIAL              205  12  1   4 cufw%d
+c $SERIAL              205  16  1  16 cuam%d
+c $SERIAL              205  32  1   8 cudb%d
 c $TTY                 205  40  1   1 cusg0
-c $SERIAL              205  41  1   3 ttycusmx%d 0
+c $SERIAL              205  41  1   3 ttycusmx%d
 c $SERIAL              205  44  1   5 cucpm%d
 c $SERIAL              205  50  1  32 cuioc4%d
 c $SERIAL              205  82  1   2 cuvr%d
 
-c $STORAGE             206   0  1  32 osst%d 0
-c $STORAGE             206  32  1  32 osst%dl 0
-c $STORAGE             206  64  1  32 osst%dm 0
-c $STORAGE             206  96  1  32 osst%da 0
-c $STORAGE             206 128  1  32 nosst%d 0
-c $STORAGE             206 160  1  32 nosst%dl 0
-c $STORAGE             206 196  1  32 nosst%dm 0
-c $STORAGE             206 224  1  32 nosst%da 0
+c $STORAGE             206   0  1  32 osst%d
+c $STORAGE             206  32  1  32 osst%dl
+c $STORAGE             206  64  1  32 osst%dm
+c $STORAGE             206  96  1  32 osst%da
+c $STORAGE             206 128  1  32 nosst%d
+c $STORAGE             206 160  1  32 nosst%dl
+c $STORAGE             206 196  1  32 nosst%dm
+c $STORAGE             206 224  1  32 nosst%da
 
 c $SERIAL              208   0  1 256 ttyU%d
 c $SERIAL              209   0  1 256 cuu%d
 
-c $SERIAL              210   0 10   4 sbei/wxcfg%d 0
-c $SERIAL              210   1 10   4 sbei/dld%d 0
-c $SERIAL              210   2  1   4 sbei/wan0%d 0
-c $SERIAL              210   6  1   4 sbei/wanc0%d 0
-c $SERIAL              210  12  1   4 sbei/wan1%d 0
-c $SERIAL              210  16  1   4 sbei/wanc1%d 0
-c $SERIAL              210  22  1   4 sbei/wan2%d 0
-c $SERIAL              210  26  1   4 sbei/wanc2%d 0
-c $SERIAL              210  32  1   4 sbei/wan3%d 0
-c $SERIAL              210  36  1   4 sbei/wanc3%d 0
+c $SERIAL              210   0 10   4 sbei/wxcfg%d
+c $SERIAL              210   1 10   4 sbei/dld%d
+c $SERIAL              210   2  1   4 sbei/wan0%d
+c $SERIAL              210   6  1   4 sbei/wanc0%d
+c $SERIAL              210  12  1   4 sbei/wan1%d
+c $SERIAL              210  16  1   4 sbei/wanc1%d
+c $SERIAL              210  22  1   4 sbei/wan2%d
+c $SERIAL              210  26  1   4 sbei/wanc2%d
+c $SERIAL              210  32  1   4 sbei/wan3%d
+c $SERIAL              210  36  1   4 sbei/wanc3%d
 
 c $SERIAL              211   0  1   8 addinum/cpci1500/%d
 
@@ -835,22 +755,22 @@ c $SERIAL              217   0  1  16 cu
 c $ROOT                218   0  1  16 logicalco/bci/%d
 c $ROOT                219   0  1  16 logicalco/dci1300/%d
 
-c $ROOT                220   0  2  16 myricom/gm%d 0
-c $ROOT                220   1  2  16 myricom/gmp%d 0
+c $ROOT                220   0  2  16 myricom/gm%d
+c $ROOT                220   1  2  16 myricom/gmp%d
 
-c $ROOT                221   0  1   4 bus/vme/m%d 0
-c $ROOT                221   4  1   4 bus/vme/s%d 0
+c $ROOT                221   0  1   4 bus/vme/m%d
+c $ROOT                221   4  1   4 bus/vme/s%d
 c $ROOT                221   8  1   1 bus/vme/ctl
 
 c $SERIAL              224   0  1 255 ttyY%d
 c $SERIAL              225   0  1 255 cuy%d
 
-c $CONSOLE             226   0  1   4 dri/card%d 0
+c $CONSOLE             226   0  1   4 dri/card%d
 
 c $ROOT                227   1  1  32 3270/tty%d 1
 c $ROOT                228   0  1  33 3270/tub
 
-c $ROOT                229   0  1  32 iseries/vtty%d 0
+c $ROOT                229   0  1  32 iseries/vtty%d
 
 c $ROOT                232   0 10   3 biometric/sensor%d/fingerprint
 c $ROOT                232   1 10   3 biometric/sensor%d/iris
@@ -860,27 +780,12 @@ c $ROOT                232   4 10   3 bi
 c $ROOT                232   5 10   3 biometric/sensor%d/hand
 
 c $ROOT                233   0  1   1 ipath
-c $ROOT                233   1  1   4 ipath%d 0
+c $ROOT                233   1  1   4 ipath%d
 c $ROOT                233 129  1   1 ipath_sma
 c $ROOT                233 130  1   1 ipath_diag
 
-c $ROOT                256   0  1 1028 ttyEQ%d
+c $ROOT                256   0  1 128 ttyEQ%d
 
-b $ROOT                256   0  1  16 rfda
-b $ROOT                256  16  1  16 rfdb
-b $ROOT                256  32  1  16 rfdc
-b $ROOT                256  48  1  16 rfdd
-b $ROOT                256  64  1  16 rfde
-b $ROOT                256  80  1  16 rfdf
-b $ROOT                256  96  1  16 rfdg
-b $ROOT                256 112  1  16 rfdh
-b $ROOT                256 128  1  16 rfdi
-b $ROOT                256 144  1  16 rfdj
-b $ROOT                256 160  1  16 rfdk
-b $ROOT                256 176  1  16 rfdl
-b $ROOT                256 192  1  16 rfdm
-b $ROOT                256 208  1  16 rfdn
-b $ROOT                256 224  1  16 rfdo
-b $ROOT                256 240  1  16 rfdp
+b $ROOT                256   0  1 256 rfd%c%|%d a 16
 
 c $ROOT                257   0  1   1 ptlsec
 


More information about the fedora-devel-list mailing list