This patch allows to use majors 12, 14, 38, and 39 in addition to major 0 for unnamed block devices, thus letting you to mount 1279 virtual filesystems. diff -ur -X dontdiff linux-2.4.19-pre7/fs/dcache.c linux-2.4.19-pre7-p3/fs/dcache.c --- linux-2.4.19-pre7/fs/dcache.c Tue Apr 23 17:08:47 2002 +++ linux-2.4.19-pre7-p3/fs/dcache.c Wed Apr 24 16:34:11 2002 @@ -1285,4 +1285,5 @@ mnt_init(mempages); bdev_cache_init(); cdev_cache_init(); + majorhog_init(); } diff -ur -X dontdiff linux-2.4.19-pre7/fs/super.c linux-2.4.19-pre7-p3/fs/super.c --- linux-2.4.19-pre7/fs/super.c Tue Apr 23 17:08:48 2002 +++ linux-2.4.19-pre7-p3/fs/super.c Wed Apr 24 16:41:19 2002 @@ -566,7 +566,16 @@ * filesystems which don't use real block-devices. -- jrs */ -enum {Max_anon = 256}; +enum {Max_Maj = 5}; +enum {Max_anon = 256 * Max_Maj}; + +static unsigned unnamed_dev_majors[Max_Maj] = { + UNNAMED_MAJOR, 12, 14, 38, 39, +}; + +static int unnamed_dev_nmaj = 1; /* Actually used */ +static unsigned unnamed_maj_in_use[Max_Maj] = { UNNAMED_MAJOR, }; + static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))]; static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */ @@ -576,9 +585,24 @@ */ static void put_anon_dev(kdev_t dev) { - spin_lock(&unnamed_dev_lock); - clear_bit(MINOR(dev), unnamed_dev_in_use); - spin_unlock(&unnamed_dev_lock); + int i; + + if (!dev) + return; /* or better BUG()? */ + + for (i = 0; i < unnamed_dev_nmaj; i++) { + if (unnamed_maj_in_use[i] == MAJOR(dev)) { + spin_lock(&unnamed_dev_lock); + if (!test_and_clear_bit(i * 256 + MINOR(dev), + unnamed_dev_in_use)) { + printk(KERN_WARNING "VFS: put_unnamed_dev:" + " freeing unused device %s\n", + kdevname(dev)); + } + spin_unlock(&unnamed_dev_lock); + break; + } + } } /** @@ -607,7 +631,7 @@ int (*compare)(struct super_block *,void *), void *data) { struct super_block *s = alloc_super(); - kdev_t dev; + unsigned xbit; struct list_head *p; if (!s) @@ -627,17 +651,17 @@ } spin_lock(&unnamed_dev_lock); - dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon); - if (dev == Max_anon) { + xbit = find_first_zero_bit(unnamed_dev_in_use, unnamed_dev_nmaj * 256); + if (xbit == unnamed_dev_nmaj * 256) { spin_unlock(&unnamed_dev_lock); spin_unlock(&sb_lock); destroy_super(s); return ERR_PTR(-EMFILE); } - set_bit(dev, unnamed_dev_in_use); + set_bit(xbit, unnamed_dev_in_use); spin_unlock(&unnamed_dev_lock); - s->s_dev = dev; + s->s_dev = MKDEV(unnamed_maj_in_use[xbit/256], xbit & 255); insert_super(s, type); return s; } @@ -859,3 +883,38 @@ { return do_kern_mount(type->name, 0, (char *)type->name, NULL); } + +/* + * The majorhog part grabs more unnamed majors for safety. + */ +static int majorhog_open(struct inode *inode, struct file *file) +{ + return -EDOM; /* Something rididculous for identification */ +} + +static struct block_device_operations majorhog_fops = { + open: majorhog_open, +}; + +/* + * XXX This is not compatible with devfs. When devfs is being mounted, + * we may get here, so we cannot call devfs_register_blkdev(). + */ +void majorhog_init(void) +{ + int i, j; + + j = 1; + for (i = 1; i < Max_Maj; i++) { + if (register_blkdev(unnamed_dev_majors[i], + "unnamed", &majorhog_fops) == 0) { + unnamed_maj_in_use[j++] = unnamed_dev_majors[i]; + } else { + printk(KERN_WARNING "Unable to hog major number %d\n", + unnamed_dev_majors[i]); + } + } + unnamed_dev_nmaj = j; + + set_bit(0, unnamed_dev_in_use); +} diff -ur -X dontdiff linux-2.4.19-pre7/include/linux/fs.h linux-2.4.19-pre7-p3/include/linux/fs.h --- linux-2.4.19-pre7/include/linux/fs.h Tue Apr 23 17:08:58 2002 +++ linux-2.4.19-pre7-p3/include/linux/fs.h Wed Apr 24 16:57:13 2002 @@ -206,6 +206,7 @@ extern void buffer_init(unsigned long); extern void inode_init(unsigned long); extern void mnt_init(unsigned long); +extern void majorhog_init(void); /* bh state bits */ enum bh_state_bits {