"15 partitions (at least for sd_mod devices) are too few," Jan Engelhardt suggested along with a patch to try and make the mounting of an unlimited number of partitions possible. H. Peter Anvin proposed as an alternative, "now when we have 20-bit minors, can't we simply recycle some of the higher bits for additional partitions, across the board? 63 partitions seem to have been sufficient; at least I haven't heard anyone complain about that for 15 years."
Alan Cox explained, "this was proposed ages ago. Al Viro vetoed sparse minors and it has been stuck this way ever since. If you have > 15 partitions use device mapper for it. I'd prefer it fixed but it's arguable that device mapper is the right way to punt all our partitioning to userspace".
From: Jan Engelhardt <jengelh@...> Subject: [code] Unlimited partitions, a try Date: Oct 5, 7:50 am 2007 15 partitions (at least for sd_mod devices) are too few. So I tried the following: after scanning the disk (sda), when we know the number of partitions P on a disk, create a new block device /dev/gd0 that is a copy of sda (in terms of disk->queue, etc.). This is done using alloc_disk(P). However, read() on gd0 will just return 0. It takes a `blockdev --rereadpt /dev/gd0` before the disk is accessible. And if I add a call to rescan inside gpdisk_new() it oopses (probably rightfully so). I do not know all the block layer magic, so expect some horrible code. Ideas, hints, anything is welcome. --- block/Makefile | 1 block/genhd.c | 5 + block/gpdisk.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/sd.c | 1 fs/partitions/check.c | 19 ++++++ include/linux/genhd.h | 16 +++++ include/scsi/sd.h | 3 + 7 files changed, 182 insertions(+), 2 deletions(-) Index: linux-2.6.23/block/Makefile =================================================================== --- linux-2.6.23.orig/block/Makefile +++ linux-2.6.23/block/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o +obj-${CONFIG_BLOCK} += gpdisk.o obj-$(CONFIG_BLK_DEV_BSG) += bsg.o obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o Index: linux-2.6.23/block/genhd.c =================================================================== --- linux-2.6.23.orig/block/genhd.c +++ linux-2.6.23/block/genhd.c @@ -744,6 +744,9 @@ struct gendisk *alloc_disk_node(int mino rand_initialize_disk(disk); INIT_WORK(&disk->async_notify, media_change_notify_thread); + atomic_set(&disk->gpdisk_enabled, false); + disk->gpdisk = NULL; + disk->gpdisk_parent = NULL; } return disk; } @@ -793,6 +796,8 @@ EXPORT_SYMBOL(set_device_ro); void set_disk_ro(struct gendisk *disk, int flag) { int i; + if (gpdisk_online(disk)) + set_disk_ro(disk->gpdisk, flag); disk->policy = flag; for (i = 0; i < disk->minors - 1; i++) if (disk->part[i]) disk->part[i]->policy = flag; Index: linux-2.6.23/block/gpdisk.c =================================================================== --- /dev/null +++ linux-2.6.23/block/gpdisk.c @@ -0,0 +1,139 @@ +#include <linux/genhd.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/idr.h> +#define MINOR_IS_ALLOCATED ((void *)0xB4C4) + +static unsigned int gpdisk_major = 0; +module_param(gpdisk_major, uint, S_IRUGO); + +static LIST_HEAD(gpdisk_regions); +static DEFINE_SPINLOCK(gpdisk_region_lock); +static DEFINE_SPINLOCK(gpdisk_id_lock); +static DEFINE_IDR(gpdisk_id_idr); + +static unsigned int gpdisk_first_minor = 0; + +static int gpdisk_get_region(unsigned int size) +{ + /* still to be done */ + unsigned int old; + + old = gpdisk_first_minor; + gpdisk_first_minor += size; + return old; +} + +static void gpdisk_put_region(unsigned int start, unsigned int n) +{ + /* same */ +} + +static int gpdisk_get_diskid(void) +{ + int new_id, ret; + + again: + ret = idr_pre_get(&gpdisk_id_idr, GFP_KERNEL); + if (ret == 0) + return -ENOMEM; + + spin_lock(&gpdisk_id_lock); + ret = idr_get_new(&gpdisk_id_idr, MINOR_IS_ALLOCATED, &new_id); + if (ret == -EAGAIN) { + spin_unlock(&gpdisk_id_lock); + cond_resched(); + goto again; + } + if (ret != 0) + goto out; + + ret = new_id; + out: + spin_unlock(&gpdisk_id_lock); + return ret; +} + +static void gpdisk_put_diskid(unsigned int id) +{ + idr_remove(&gpdisk_id_idr, id); +} + +void gpdisk_new(struct gendisk *disk, unsigned int minors) +{ + struct block_device *bdev; + struct gendisk *gpdisk; + int disk_id, minor_start; + + gpdisk = alloc_disk(minors); + if (gpdisk == NULL) + return; + + disk_id = gpdisk_get_diskid(); + if (disk_id < 0) + goto out; + + minor_start = gpdisk_get_region(minors); + if (minor_start < 0) + goto out2; + + disk->gpdisk = gpdisk; + disk->gpdisk_id = disk_id; + + sprintf(gpdisk->disk_name, "gd%u", disk_id); + gpdisk->gpdisk_parent = disk; + gpdisk->major = gpdisk_major; + gpdisk->first_minor = minor_start; + gpdisk->minors = minors; + gpdisk->fops = disk->fops; + + /* safe? */ + gpdisk->private_data = disk->private_data; + gpdisk->queue = disk->queue; + gpdisk->driverfs_dev = disk->driverfs_dev; + gpdisk->flags = disk->flags; + + add_disk(gpdisk); + return; + + out2: + gpdisk_put_diskid(disk_id); + out: + put_disk(gpdisk); + return; +} + +void gpdisk_release(struct gendisk *disk) +{ + gpdisk_put_region(disk->gpdisk->first_minor, disk->gpdisk->minors); + gpdisk_put_diskid(disk->gpdisk_id); +} + +static int __init gpdisk_init(void) +{ + int i; + + i = register_blkdev(gpdisk_major, "gpdisk"); + if (gpdisk_major == 0) { + /* dynamic major */ + if (i == 0) + return -ENODEV; + gpdisk_major = i; + } else { + /* fixed major */ + if (i != 0) + return -ENODEV; + } + + return 0; +} + +static void __exit gpdisk_exit(void) +{ + unregister_blkdev(gpdisk_major, "gpdisk"); +} + +module_init(gpdisk_init); +module_exit(gpdisk_exit); Index: linux-2.6.23/drivers/scsi/sd.c =================================================================== --- linux-2.6.23.orig/drivers/scsi/sd.c +++ linux-2.6.23/drivers/scsi/sd.c @@ -1610,6 +1610,7 @@ static int sd_probe(struct device *dev) gd = alloc_disk(16); if (!gd) goto out_free; + atomic_set(&gd->gpdisk_enabled, true); if (!idr_pre_get(&sd_index_idr, GFP_KERNEL)) goto out_put; Index: linux-2.6.23/fs/partitions/check.c =================================================================== --- linux-2.6.23.orig/fs/partitions/check.c +++ linux-2.6.23/fs/partitions/check.c @@ -168,7 +168,7 @@ check_partition(struct gendisk *hd, stru if (isdigit(state->name[strlen(state->name)-1])) sprintf(state->name, "p"); - state->limit = hd->minors; + state->limit = MAX_PART; i = res = err = 0; while (!res && check_part[i]) { memset(&state->parts, 0, sizeof(state->parts)); @@ -528,6 +528,7 @@ exit: int rescan_partitions(struct gendisk *disk, struct block_device *bdev) { struct parsed_partitions *state; + unsigned int max; int p, res; if (bdev->bd_part_count) @@ -536,6 +537,11 @@ int rescan_partitions(struct gendisk *di if (res) return res; bdev->bd_invalidated = 0; + if (gpdisk_online(disk)) { + gpdisk_release(disk); + del_gendisk(disk->gpdisk); + disk->gpdisk = NULL; + } for (p = 1; p < disk->minors; p++) delete_partition(disk, p); if (disk->fops->revalidate_disk) @@ -544,7 +550,8 @@ int rescan_partitions(struct gendisk *di return 0; if (IS_ERR(state)) /* I/O error reading the partition table */ return -EIO; - for (p = 1; p < state->limit; p++) { + max = min(disk->minors, state->next); + for (p = 1; p < max; p++) { sector_t size = state->parts[p].size; sector_t from = state->parts[p].from; if (!size) @@ -560,6 +567,8 @@ int rescan_partitions(struct gendisk *di #endif } kfree(state); + if (atomic_read(&disk->gpdisk_enabled) > 0) + gpdisk_new(disk, state->next); return 0; } @@ -588,6 +597,12 @@ void del_gendisk(struct gendisk *disk) { int p; + if (gpdisk_online(disk)) { + gpdisk_release(disk); + del_gendisk(disk->gpdisk); + disk->gpdisk = NULL; + } + /* invalidate stuff */ for (p = disk->minors - 1; p > 0; p--) { invalidate_partition(disk, p); Index: linux-2.6.23/include/linux/genhd.h =================================================================== --- linux-2.6.23.orig/include/linux/genhd.h +++ linux-2.6.23/include/linux/genhd.h @@ -67,6 +67,7 @@ struct partition { #include <linux/string.h> #include <linux/fs.h> #include <linux/workqueue.h> +#include <asm/atomic.h> struct partition { unsigned char boot_ind; /* 0x80 - active */ @@ -141,6 +142,10 @@ struct gendisk { struct disk_stats dkstats; #endif struct work_struct async_notify; + + struct gendisk *gpdisk, *gpdisk_parent; + unsigned int gpdisk_id; + atomic_t gpdisk_enabled; }; /* Structure for sysfs attributes on block devices */ @@ -255,11 +260,22 @@ static inline sector_t get_capacity(stru { return disk->capacity; } + +static inline bool gpdisk_online(const struct gendisk *disk) +{ + return atomic_read(&disk->gpdisk_enabled) > 0 && disk->gpdisk != NULL; +} + static inline void set_capacity(struct gendisk *disk, sector_t size) { disk->capacity = size; + if (gpdisk_online(disk)) + disk->gpdisk->capacity = size; } +extern void gpdisk_new(struct gendisk *, unsigned int); +extern void gpdisk_release(struct gendisk *); + #endif /* __KERNEL__ */ #ifdef CONFIG_SOLARIS_X86_PARTITION Index: linux-2.6.23/include/scsi/sd.h =================================================================== --- linux-2.6.23.orig/include/scsi/sd.h +++ linux-2.6.23/include/scsi/sd.h @@ -62,6 +62,9 @@ static void sd_print_sense_hdr(struct sc static void sd_print_result(struct scsi_disk *, int); #define sd_printk(prefix, sdsk, fmt, a...) \ + gpdisk_online((sdsk)->disk) ? \ + sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ + (sdsk)->disk->gpdisk->disk_name, ##a) : \ (sdsk)->disk ? \ sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ (sdsk)->disk->disk_name, ##a) : \ -
From: H. Peter Anvin <hpa@...> Subject: Re: [code] Unlimited partitions, a try Date: Oct 5, 6:11 pm 2007 Jan Engelhardt wrote: > 15 partitions (at least for sd_mod devices) are too few. Now when we have 20-bit minors, can't we simply recycle some of the higher bits for additional partitions, across the board? 63 partitions seem to have been sufficient; at least I haven't heard anyone complain about that for 15 years. -hpa -
From: Alan Cox <alan@...> Subject: Re: [code] Unlimited partitions, a try Date: Oct 5, 7:29 pm 2007 On Fri, 05 Oct 2007 15:11:52 -0700 "H. Peter Anvin" <hpa@zytor.com> wrote: > Jan Engelhardt wrote: > > 15 partitions (at least for sd_mod devices) are too few. > > Now when we have 20-bit minors, can't we simply recycle some of the > higher bits for additional partitions, across the board? 63 partitions > seem to have been sufficient; at least I haven't heard anyone complain > about that for 15 years. This was proposed ages ago. Al Viro vetoed sparse minors and it has been stuck this way ever since. If you have > 15 partitions use device mapper for it. I'd prefer it fixed but its arguable that device mapper is the right way to punt all our partitioning to userspace Alan -
From: H. Peter Anvin <hpa@...> Subject: Re: [code] Unlimited partitions, a try Date: Oct 5, 7:29 pm 2007 Alan Cox wrote: > On Fri, 05 Oct 2007 15:11:52 -0700 > "H. Peter Anvin" <hpa@zytor.com> wrote: > >> Jan Engelhardt wrote: >>> 15 partitions (at least for sd_mod devices) are too few. >> Now when we have 20-bit minors, can't we simply recycle some of the >> higher bits for additional partitions, across the board? 63 partitions >> seem to have been sufficient; at least I haven't heard anyone complain >> about that for 15 years. > > This was proposed ages ago. Al Viro vetoed sparse minors and it has been > stuck this way ever since. If you have > 15 partitions use device mapper > for it. I'd prefer it fixed but its arguable that device mapper is the > right way to punt all our partitioning to userspace Sure. However, that takes having that bit of userspace in even the most trivial configurations, and not just on bootup, but continuously. -hpa -
From: Bill Davidsen <davidsen@...> Subject: Re: [code] Unlimited partitions, a try Date: Oct 6, 3:33 pm 2007 H. Peter Anvin wrote: > Alan Cox wrote: >> On Fri, 05 Oct 2007 15:11:52 -0700 >> "H. Peter Anvin" <hpa@zytor.com> wrote: >> >>> Jan Engelhardt wrote: >>>> 15 partitions (at least for sd_mod devices) are too few. >>> Now when we have 20-bit minors, can't we simply recycle some of the >>> higher bits for additional partitions, across the board? 63 >>> partitions seem to have been sufficient; at least I haven't heard >>> anyone complain about that for 15 years. >> >> This was proposed ages ago. Al Viro vetoed sparse minors and it has been >> stuck this way ever since. If you have > 15 partitions use device mapper >> for it. I'd prefer it fixed but its arguable that device mapper is the >> right way to punt all our partitioning to userspace > > Sure. However, that takes having that bit of userspace in even the most > trivial configurations, and not just on bootup, but continuously. > I'm not sure that configurations requiring more than 15 partitions are properly described as "trivial." Which is not to disagree with your point about required user tools, but most systems needing such tools will be large and complex enough that a userspace solution will be acceptable. -- Bill Davidsen <davidsen@tmr.com> "We have more to fear from the bungling of the incompetent than from the machinations of the wicked." - from Slashdot -

Arbitrary limitations
Arbitary small numerical system limitations have no place in a modern OS. What next, 12 character file names? Stallman proclaimed such limitations unsatisfactory for the GNU system long ago.
http://archives.neohapsis.com/archives/linux/lsap/2002-q1/0100.html
Well, RMS is welcome to fix
Well, RMS is welcome to fix this (and maintain his own kernel tree if it doesn't go into mainline). :) For that matter, so are you. :)
(Not that you don't have a good point - I agree that limitations like this are unfortunate and should be avoided if possible -, but "RMS whined over things like this already" isn't really an argument...)
major minor numbers should be obsolete
If I recall correctly, back in the day devfs was arguably sold on at least the advantage of not having to resort to static major/minor numbers -- and udev could in theory incorporate that capability.
Don't get me wrong, breaking the major/minor number convention is gonna be very hard, but at some point I think we're better off reinventing device nodes as something very much like a symlink pointing to a distinct "path"/identifier in a separate namespace inside the kernel that accurately pinpoints the device it refers to. Presto, unlimited new-style device nodes, plus generating the device nodes (think udev) for all currently loaded drivers would be an idempotent operation.
Ideally, such a "path" stored in the device file representation would include some sort of path component named after the driver responsible for operating it. That way you could easily use a userspace command (readlink? haha) to identify which driver handles that device, and perhaps unload/reload the driver if the device malfunctions. I have to do that all the time for my cable modem, so I'd find that useful.
Solaris' /devices, is that you?
Sounds vaguely familiar....
--
Program Intellivision and play Space Patrol!
To be honest, this solution
To be honest, this solution is really ugly. You use symlinks to point to other locations?
Look at all these names! pci@1f,0/pci@1,1/ebus@1/ecpp@14,3043bc:ecpp0
Ugly like hell, please dont!
What's "ugly"?
The names certainly aren't pretty, but they are rather explicit and there are all those nice little symlinks hanging about. Not to mention that I saw these used over 12 years ago and they seem to be holding up quite well. How many iterations of this will Linux go through before it gets a stable interface?
Who needs more than 15?
I don't like limitations either.
Keep in mind, it isn't 15 partition total, its 15 partitions per disk drive.
Does anyone actually need more than 15 partitions per disk drive?
Somebody
Even though I don't, and you seem not to, it doesn't mean that someone may not need this. Yet another thing I agree with RMS on.
Maybe they do...
It's possible people legitimately want more than 15 partitions per drive. After all: http://www.news.com/Here-comes-the-terabyte-hard-drive/2100-1041_3-61474...
LVM ?
Maybe rather than 16 partitions they could use a bunch of Locigal Volumes .. it would give them other benefits also
I did. I had more than one
I did. I had more than one distro on my laptop, and setup gentoo with many partitions, like many people recomended at the time. Actually its not hard to go over 15, and that limit did cause a lot of people headaches when it came about. I know because I googled trying to find a way to fix it.
Re: Who needs more than 15?
It sound like:
- Nobody will ever need more than 640k RAM! - Bill Gates
ah ah ah
I do!
I have 4 disks of 400Go and made 14 partitions in each of the same size (thus 28Go each). The 15th is for boot.
With this, I can make 14 raid5 arrays that I can configure as physical volumes for LVM.
This is very convenient because I can add or remove those physical volumes in my volumes groups whenever needed.
I would have liked to be able to make more partitions because each physical volume is 28*3=84Go wich is enormous! more granularity would be appreciated.
jk
how does a 15 partition
how does a 15 partition limit interact with LVM or similar?
Device mapper (the kernel
Device mapper (the kernel part of LVM) can make arbitrary block subdevices of a block device. Its controled by user-space.
So a simple text file saying
subdevice01 0 1000
subdevice02 1001 4000
..
..
etc
will start as many subdevices as you want.
A user-space app that understands DOS partitions can do the same with normal partition tables.