diff -urN C69-tty/drivers/base/Makefile C69-kobj_map/drivers/base/Makefile
--- C69-tty/drivers/base/Makefile	Mon May  5 03:27:59 2003
+++ C69-kobj_map/drivers/base/Makefile	Mon May  5 10:26:51 2003
@@ -2,5 +2,5 @@
 
 obj-y			:= core.o sys.o interface.o power.o bus.o \
 			   driver.o class.o platform.o \
-			   cpu.o firmware.o init.o
+			   cpu.o firmware.o init.o map.o
 obj-$(CONFIG_NUMA)	+= node.o  memblk.o
diff -urN C69-tty/drivers/base/map.c C69-kobj_map/drivers/base/map.c
--- C69-tty/drivers/base/map.c	Wed Dec 31 19:00:00 1969
+++ C69-kobj_map/drivers/base/map.c	Mon May  5 10:26:51 2003
@@ -0,0 +1,154 @@
+/*
+ *  linux/drivers/base/map.c
+ *
+ * (C) Copyright Al Viro 2002,2003
+ *	Released under GPL v2.
+ *
+ * NOTE: data structure needs to be changed.  It works, but for large dev_t
+ * it will be too slow.  It is isolated, though, so these changes will be
+ * local to that file.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kdev_t.h>
+#include <linux/kobject.h>
+#include <linux/kobj_map.h>
+
+struct kobj_map {
+	struct probe {
+		struct probe *next;
+		dev_t dev;
+		unsigned long range;
+		struct module *owner;
+		kobj_probe_t *get;
+		int (*lock)(dev_t, void *);
+		void *data;
+	} *probes[255];
+	struct rw_semaphore *sem;
+};
+
+static inline int dev_to_index(dev_t dev)
+{
+	return MAJOR(dev) % 255;
+}
+
+int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
+	     struct module *module, kobj_probe_t *probe,
+	     int (*lock)(dev_t, void *), void *data)
+{
+	unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
+	unsigned index = MAJOR(dev);
+	unsigned i;
+	struct probe *p;
+
+	if (n > 255)
+		n = 255;
+
+	p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);
+
+	if (p == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < n; i++, p++) {
+		p->owner = module;
+		p->get = probe;
+		p->lock = lock;
+		p->dev = dev;
+		p->range = range;
+		p->data = data;
+	}
+	down_write(domain->sem);
+	for (i = 0, p -= n; i < n; i++, p++, index++) {
+		struct probe **s = &domain->probes[index % 255];
+		while (*s && (*s)->range < range)
+			s = &(*s)->next;
+		p->next = *s;
+		*s = p;
+	}
+	up_write(domain->sem);
+	return 0;
+}
+
+void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
+{
+	unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
+	unsigned index = MAJOR(dev);
+	unsigned i;
+	struct probe *found = NULL;
+
+	if (n > 255)
+		n = 255;
+
+	down_write(domain->sem);
+	for (i = 0; i < n; i++, index++) {
+		struct probe **s;
+		for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
+			struct probe *p = *s;
+			if (p->dev == dev && p->range == range) {
+				*s = p->next;
+				if (!found)
+					found = p;
+				break;
+			}
+		}
+	}
+	up_write(domain->sem);
+	kfree(found);
+}
+
+struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
+{
+	struct kobject *kobj;
+	struct probe *p;
+	unsigned best = ~0U;
+
+retry:
+	down_read(domain->sem);
+	for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
+		struct kobject *(*probe)(dev_t, int *, void *);
+		struct module *owner;
+		void *data;
+
+		if (p->dev > dev || p->dev + p->range - 1 < dev)
+			continue;
+		if (p->range - 1 >= best)
+			break;
+		if (!try_module_get(p->owner))
+			continue;
+		owner = p->owner;
+		data = p->data;
+		probe = p->get;
+		best = p->range - 1;
+		*index = dev - p->dev;
+		if (p->lock && p->lock(dev, data) < 0) {
+			module_put(owner);
+			continue;
+		}
+		up_read(domain->sem);
+		kobj = probe(dev, index, data);
+		/* Currently ->owner protects _only_ ->probe() itself. */
+		module_put(owner);
+		if (kobj)
+			return kobj;
+		goto retry;
+	}
+	up_read(domain->sem);
+	return NULL;
+}
+
+struct kobj_map *kobj_map_init(kobj_probe_t *base_probe,
+		struct subsystem *s)
+{
+	struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
+	struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
+	int i;
+	memset(base, 0, sizeof(struct probe));
+	base->dev = 1;
+	base->range = ~0;
+	base->get = base_probe;
+	for (i = 0; i < 255; i++)
+		p->probes[i] = base;
+	p->sem = &s->rwsem;
+	return p;
+}
diff -urN C69-tty/drivers/block/genhd.c C69-kobj_map/drivers/block/genhd.c
--- C69-tty/drivers/block/genhd.c	Mon May  5 10:26:50 2003
+++ C69-kobj_map/drivers/block/genhd.c	Mon May  5 10:26:51 2003
@@ -13,13 +13,14 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/kmod.h>
+#include <linux/kobj_map.h>
 
 #define MAX_PROBE_HASH 255	/* random */
 
 static struct subsystem block_subsys;
 
 /*
- * Can be merged with blk_probe or deleted altogether. Later.
+ * Can be deleted altogether. Later.
  *
  * Modified under both block_subsys.rwsem and major_names_lock.
  */
@@ -31,27 +32,12 @@
 
 static spinlock_t major_names_lock = SPIN_LOCK_UNLOCKED;
 
-static struct blk_probe {
-	struct blk_probe *next;
-	dev_t dev;
-	unsigned long range;
-	struct module *owner;
-	struct kobject *(*get)(dev_t dev, int *part, void *data);
-	int (*lock)(dev_t, void *);
-	void *data;
-} *probes[MAX_PROBE_HASH];
-
 /* index in the above - for now: assume no multimajor ranges */
 static inline int major_to_index(int major)
 {
 	return major % MAX_PROBE_HASH;
 }
 
-static inline int dev_to_index(dev_t dev)
-{
-	return major_to_index(MAJOR(dev));
-}
-
 /* get block device names in somewhat random order */
 int get_blkdev_list(char *p)
 {
@@ -156,6 +142,8 @@
 	return ret;
 }
 
+static struct kobj_map *bdev_map;
+
 /*
  * Register device numbers dev..(dev+range-1)
  * range must be nonzero
@@ -165,42 +153,12 @@
 			 struct kobject *(*probe)(dev_t, int *, void *),
 			 int (*lock)(dev_t, void *), void *data)
 {
-	int index = dev_to_index(dev);
-	struct blk_probe *p = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
-	struct blk_probe **s;
-
-	if (p == NULL)
-		return;
-
-	p->owner = module;
-	p->get = probe;
-	p->lock = lock;
-	p->dev = dev;
-	p->range = range;
-	p->data = data;
-	down_write(&block_subsys.rwsem);
-	for (s = &probes[index]; *s && (*s)->range < range; s = &(*s)->next)
-		;
-	p->next = *s;
-	*s = p;
-	up_write(&block_subsys.rwsem);
+	kobj_map(bdev_map, dev, range, module, probe, lock, data);
 }
 
 void blk_unregister_region(dev_t dev, unsigned long range)
 {
-	int index = dev_to_index(dev);
-	struct blk_probe **s;
-
-	down_write(&block_subsys.rwsem);
-	for (s = &probes[index]; *s; s = &(*s)->next) {
-		struct blk_probe *p = *s;
-		if (p->dev == dev && p->range == range) {
-			*s = p->next;
-			kfree(p);
-			break;
-		}
-	}
-	up_write(&block_subsys.rwsem);
+	kobj_unmap(bdev_map, dev, range);
 }
 
 EXPORT_SYMBOL(blk_register_region);
@@ -256,46 +214,10 @@
  * This function gets the structure containing partitioning
  * information for the given device @dev.
  */
-struct gendisk *
-get_gendisk(dev_t dev, int *part)
+struct gendisk *get_gendisk(dev_t dev, int *part)
 {
-	int index = dev_to_index(dev);
-	struct kobject *kobj;
-	struct blk_probe *p;
-	unsigned best = ~0U;
-
-retry:
-	down_read(&block_subsys.rwsem);
-	for (p = probes[index]; p; p = p->next) {
-		struct kobject *(*probe)(dev_t, int *, void *);
-		struct module *owner;
-		void *data;
-
-		if (p->dev > dev || p->dev + p->range - 1 < dev)
-			continue;
-		if (p->range - 1 >= best)
-			break;
-		if (!try_module_get(p->owner))
-			continue;
-		owner = p->owner;
-		data = p->data;
-		probe = p->get;
-		best = p->range - 1;
-		*part = dev - p->dev;
-		if (p->lock && p->lock(dev, data) < 0) {
-			module_put(owner);
-			continue;
-		}
-		up_read(&block_subsys.rwsem);
-		kobj = probe(dev, part, data);
-		/* Currently ->owner protects _only_ ->probe() itself. */
-		module_put(owner);
-		if (kobj)
-			return to_disk(kobj);
-		goto retry;		/* this terminates: best decreases */
-	}
-	up_read(&block_subsys.rwsem);
-	return NULL;
+	struct kobject *kobj = kobj_lookup(bdev_map, dev, part);
+	return  kobj ? to_disk(kobj) : NULL;
 }
 
 #ifdef CONFIG_PROC_FS
@@ -378,14 +300,7 @@
 
 int __init device_init(void)
 {
-	struct blk_probe *base = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
-	int i;
-	memset(base, 0, sizeof(struct blk_probe));
-	base->dev = 1;
-	base->range = ~0;		/* range 1 .. ~0 */
-	base->get = base_probe;
-	for (i = 0; i < MAX_PROBE_HASH; i++)
-		probes[i] = base;	/* must remain last in chain */
+	bdev_map = kobj_map_init(base_probe, &block_subsys);
 	blk_dev_init();
 	subsystem_register(&block_subsys);
 	return 0;
diff -urN C69-tty/include/linux/kobj_map.h C69-kobj_map/include/linux/kobj_map.h
--- C69-tty/include/linux/kobj_map.h	Wed Dec 31 19:00:00 1969
+++ C69-kobj_map/include/linux/kobj_map.h	Mon May  5 10:26:51 2003
@@ -0,0 +1,12 @@
+#ifdef __KERNEL__
+
+typedef struct kobject *kobj_probe_t(dev_t, int *, void *);
+struct kobj_map;
+
+int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *,
+	     kobj_probe_t *, int (*)(dev_t, void *), void *);
+void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
+struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
+struct kobj_map *kobj_map_init(kobj_probe_t *, struct subsystem *);
+
+#endif
