

Patch from Andries.Brouwer@cwi.nl

A patch for genhd.c:

- removed outdated comments
- removed MAX_BLKDEV

In genhd.c the variable MAX_BLKDEV was only the size of a hash
table, so I made it MAX_PROBE_HASH. It can be 1, or 23, or 256, or
whatever one wants.

Note that the current setup requires that every device number
in a given range is mapped by dev_to_index() to the same index
in the hash table, so this routine will have to be adapted in
case one wants to register multimajor ranges.

Discussion is possible about whether struct blk_probe needs
a dev_t or a kdev_t, but I left things this time.

If a range can end at precisely the end of [k]dev_t space,
the old code was wrong since (p->dev + p->range) would be 0.
That is why "p->dev + p->range <= dev" was replaced by
"p->dev + p->range - 1 < dev".




 block/genhd.c |   78 ++++++++++++++++++++++++++++------------------------------
 1 files changed, 38 insertions(+), 40 deletions(-)

diff -puN drivers/block/genhd.c~remove-MAX_BLKDEV-from-genhd drivers/block/genhd.c
--- 25/drivers/block/genhd.c~remove-MAX_BLKDEV-from-genhd	2003-02-23 16:20:09.000000000 -0800
+++ 25-akpm/drivers/block/genhd.c	2003-02-23 16:20:10.000000000 -0800
@@ -1,17 +1,5 @@
 /*
- *  Code extracted from
- *  linux/kernel/hd.c
- *
- *  Copyright (C) 1991-1998  Linus Torvalds
- *
- *  devfs support - jj, rgooch, 980122
- *
- *  Moved partition checking code to fs/partitions* - Russell King
- *  (linux@arm.uk.linux.org)
- */
-
-/*
- * TODO:  rip out the remaining init crap from this file  --hch
+ *  gendisk handling
  */
 
 #include <linux/config.h>
@@ -29,8 +17,9 @@
 
 static struct subsystem block_subsys;
 
+#define MAX_PROBE_HASH 23	/* random */
 
-struct blk_probe {
+static struct blk_probe {
 	struct blk_probe *next;
 	dev_t dev;
 	unsigned long range;
@@ -38,21 +27,27 @@ struct blk_probe {
 	struct gendisk *(*get)(dev_t dev, int *part, void *data);
 	int (*lock)(dev_t, void *);
 	void *data;
-} *probes[MAX_BLKDEV];
+} *probes[MAX_PROBE_HASH];
 
-/* index in the above */
+/* index in the above - for now: assume no multimajor ranges */
 static inline int dev_to_index(dev_t dev)
 {
-	return MAJOR(dev);
+	return MAJOR(dev) % MAX_PROBE_HASH;
 }
 
+/*
+ * Register device numbers dev..(dev+range-1)
+ * range must be nonzero
+ * The hash chain is sorted on range, so that subranges can override.
+ */
 void blk_register_region(dev_t dev, unsigned long range, struct module *module,
-		    struct gendisk *(*probe)(dev_t, int *, void *),
-		    int (*lock)(dev_t, void *), void *data)
+			 struct gendisk *(*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;
+
 	p->owner = module;
 	p->get = probe;
 	p->lock = lock;
@@ -71,6 +66,7 @@ void blk_unregister_region(dev_t dev, un
 {
 	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;
@@ -94,6 +90,7 @@ static struct gendisk *exact_match(dev_t
 static int exact_lock(dev_t dev, void *data)
 {
 	struct gendisk *p = data;
+
 	if (!get_disk(p))
 		return -1;
 	return 0;
@@ -109,14 +106,14 @@ static int exact_lock(dev_t dev, void *d
 void add_disk(struct gendisk *disk)
 {
 	disk->flags |= GENHD_FL_UP;
-	blk_register_region(MKDEV(disk->major, disk->first_minor), disk->minors,
-			NULL, exact_match, exact_lock, disk);
+	blk_register_region(MKDEV(disk->major, disk->first_minor),
+			    disk->minors, NULL, exact_match, exact_lock, disk);
 	register_disk(disk);
 	elv_register_queue(disk);
 }
 
 EXPORT_SYMBOL(add_disk);
-EXPORT_SYMBOL(del_gendisk);
+EXPORT_SYMBOL(del_gendisk);	/* in partitions/check.c */
 
 void unlink_gendisk(struct gendisk *disk)
 {
@@ -146,18 +143,17 @@ retry:
 		struct gendisk *(*probe)(dev_t, int *, void *);
 		struct module *owner;
 		void *data;
-		if (p->dev > dev || p->dev + p->range <= dev)
+
+		if (p->dev > dev || p->dev + p->range - 1 < dev)
 			continue;
-		if (p->range >= best) {
-			up_read(&block_subsys.rwsem);
-			return NULL;
-		}
+		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;
+		best = p->range - 1;
 		*part = dev - p->dev;
 		if (p->lock && p->lock(dev, data) < 0) {
 			module_put(owner);
@@ -169,7 +165,7 @@ retry:
 		module_put(owner);
 		if (disk)
 			return disk;
-		goto retry;
+		goto retry;		/* this terminates: best decreases */
 	}
 	up_read(&block_subsys.rwsem);
 	return NULL;
@@ -245,7 +241,7 @@ extern int blk_dev_init(void);
 
 static struct gendisk *base_probe(dev_t dev, int *part, void *data)
 {
-	char name[20];
+	char name[30];
 	sprintf(name, "block-major-%d", MAJOR(dev));
 	request_module(name);
 	return NULL;
@@ -256,11 +252,11 @@ 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 = MKDEV(1,0);
-	base->range = MKDEV(MAX_BLKDEV-1, 255) - base->dev + 1;
+	base->dev = 1;
+	base->range = ~0;		/* range 1 .. ~0 */
 	base->get = base_probe;
-	for (i = 1; i < MAX_BLKDEV; i++)
-		probes[i] = base;
+	for (i = 0; i < MAX_PROBE_HASH; i++)
+		probes[i] = base;	/* must remain last in chain */
 	blk_dev_init();
 	subsystem_register(&block_subsys);
 	return 0;
@@ -281,12 +277,14 @@ struct disk_attribute {
 	ssize_t (*show)(struct gendisk *, char *);
 };
 
-static ssize_t disk_attr_show(struct kobject * kobj, struct attribute * attr,
-			      char * page)
+static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
+			      char *page)
 {
-	struct gendisk * disk = to_disk(kobj);
-	struct disk_attribute * disk_attr = container_of(attr,struct disk_attribute,attr);
+	struct gendisk *disk = to_disk(kobj);
+	struct disk_attribute *disk_attr =
+		container_of(attr,struct disk_attribute,attr);
 	ssize_t ret = 0;
+
 	if (disk_attr->show)
 		ret = disk_attr->show(disk,page);
 	return ret;
@@ -303,11 +301,11 @@ static ssize_t disk_dev_read(struct gend
 }
 static ssize_t disk_range_read(struct gendisk * disk, char *page)
 {
-	return sprintf(page, "%d\n",disk->minors);
+	return sprintf(page, "%d\n", disk->minors);
 }
 static ssize_t disk_size_read(struct gendisk * disk, char *page)
 {
-	return sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk));
+	return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk));
 }
 
 static inline unsigned jiffies_to_msec(unsigned jif)

_
