2 * Code extracted from drivers/block/genhd.c
3 * Copyright (C) 1991-1998 Linus Torvalds
4 * Re-organised Feb 1998 Russell King
6 * We now have independent partition support from the
7 * block drivers, which allows all the partition code to
8 * be grouped in one location, and it to be mostly self
11 * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
14 #include <linux/config.h>
16 #include <linux/genhd.h>
17 #include <linux/kernel.h>
18 #include <linux/major.h>
19 #include <linux/blk.h>
20 #include <linux/init.h>
21 #include <linux/raid/md.h>
35 extern void device_init(void);
36 extern void md_setup_drive(void);
37 extern int *blk_size
[];
38 extern void rd_load(void);
39 extern void initrd_load(void);
41 struct gendisk
*gendisk_head
;
42 int warn_no_part
= 1; /*This is ugly: should make genhd removable media aware*/
44 static int (*check_part
[])(struct gendisk
*hd
, kdev_t dev
, unsigned long first_sect
, int first_minor
) = {
45 #ifdef CONFIG_ACORN_PARTITION
48 #ifdef CONFIG_MSDOS_PARTITION
51 #ifdef CONFIG_OSF_PARTITION
54 #ifdef CONFIG_SUN_PARTITION
57 #ifdef CONFIG_AMIGA_PARTITION
60 #ifdef CONFIG_ATARI_PARTITION
63 #ifdef CONFIG_MAC_PARTITION
66 #ifdef CONFIG_SGI_PARTITION
69 #ifdef CONFIG_ULTRIX_PARTITION
72 #ifdef CONFIG_IBM_PARTITION
79 * disk_name() is used by genhd.c and blkpg.c.
80 * It formats the devicename of the indicated disk into
81 * the supplied buffer (of size at least 32), and returns
82 * a pointer to that same buffer (for convenience).
84 char *disk_name (struct gendisk
*hd
, int minor
, char *buf
)
87 const char *maj
= hd
->major_name
;
88 int unit
= (minor
>> hd
->minor_shift
) + 'a';
90 part
= minor
& ((1 << hd
->minor_shift
) - 1);
91 if (hd
->part
[minor
].de
) {
94 pos
= devfs_generate_path (hd
->part
[minor
].de
, buf
, 64);
99 * IDE devices use multiple major numbers, but the drives
100 * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
101 * This requires special handling here.
129 if (hd
->major
>= SCSI_DISK1_MAJOR
&& hd
->major
<= SCSI_DISK7_MAJOR
) {
130 unit
= unit
+ (hd
->major
- SCSI_DISK1_MAJOR
+ 1) * 16;
133 sprintf(buf
, "sd%c%c", 'a' + unit
/ 26, 'a' + unit
% 26);
135 sprintf(buf
+ 4, "%d", part
);
139 if (hd
->major
>= COMPAQ_SMART2_MAJOR
&& hd
->major
<= COMPAQ_SMART2_MAJOR
+7) {
140 int ctlr
= hd
->major
- COMPAQ_SMART2_MAJOR
;
141 int disk
= minor
>> hd
->minor_shift
;
142 int part
= minor
& (( 1 << hd
->minor_shift
) - 1);
144 sprintf(buf
, "%s/c%dd%d", maj
, ctlr
, disk
);
146 sprintf(buf
, "%s/c%dd%dp%d", maj
, ctlr
, disk
, part
);
149 if (hd
->major
>= DAC960_MAJOR
&& hd
->major
<= DAC960_MAJOR
+7) {
150 int ctlr
= hd
->major
- DAC960_MAJOR
;
151 int disk
= minor
>> hd
->minor_shift
;
152 int part
= minor
& (( 1 << hd
->minor_shift
) - 1);
154 sprintf(buf
, "%s/c%dd%d", maj
, ctlr
, disk
);
156 sprintf(buf
, "%s/c%dd%dp%d", maj
, ctlr
, disk
, part
);
160 sprintf(buf
, "%s%c%d", maj
, unit
, part
);
162 sprintf(buf
, "%s%c", maj
, unit
);
167 * Add a partitions details to the devices partition description.
169 void add_gd_partition(struct gendisk
*hd
, int minor
, int start
, int size
)
171 #ifndef CONFIG_DEVFS_FS
175 hd
->part
[minor
].start_sect
= start
;
176 hd
->part
[minor
].nr_sects
= size
;
177 #ifdef CONFIG_DEVFS_FS
178 printk(" p%d", (minor
& ((1 << hd
->minor_shift
) - 1)));
180 if (hd
->major
>= COMPAQ_SMART2_MAJOR
+0 && hd
->major
<= COMPAQ_SMART2_MAJOR
+7)
181 printk(" p%d", (minor
& ((1 << hd
->minor_shift
) - 1)));
183 printk(" %s", disk_name(hd
, minor
, buf
));
187 int get_hardsect_size(kdev_t dev
)
189 if (hardsect_size
[MAJOR(dev
)] != NULL
)
190 return hardsect_size
[MAJOR(dev
)][MINOR(dev
)];
195 unsigned int get_ptable_blocksize(kdev_t dev
)
200 * See whether the low-level driver has given us a minumum blocksize.
201 * If so, check to see whether it is larger than the default of 1024.
203 if (!blksize_size
[MAJOR(dev
)])
207 * Check for certain special power of two sizes that we allow.
208 * With anything larger than 1024, we must force the blocksize up to
209 * the natural blocksize for the device so that we don't have to try
210 * and read partial sectors. Anything smaller should be just fine.
213 switch (blksize_size
[MAJOR(dev
)][MINOR(dev
)]) {
232 panic("Strange blocksize for partition table\n");
238 #ifdef CONFIG_PROC_FS
239 int get_partition_list(char * page
)
245 len
= sprintf(page
, "major minor #blocks name\n\n");
246 for (p
= gendisk_head
; p
; p
= p
->next
) {
247 for (n
=0; n
< (p
->nr_real
<< p
->minor_shift
); n
++) {
248 if (p
->part
[n
].nr_sects
&& len
< PAGE_SIZE
- 80) {
249 len
+= sprintf(page
+len
,
251 p
->major
, n
, p
->sizes
[n
],
252 disk_name(p
, n
, buf
));
260 static void check_partition(struct gendisk
*hd
, kdev_t dev
, int first_part_minor
)
262 devfs_handle_t de
= NULL
;
263 static int first_time
= 1;
264 unsigned long first_sector
;
269 printk(KERN_INFO
"Partition check:\n");
271 first_sector
= hd
->part
[MINOR(dev
)].start_sect
;
274 * This is a kludge to allow the partition check to be
275 * skipped for specific drives (e.g. IDE CD-ROM drives)
277 if ((int)first_sector
== -1) {
278 hd
->part
[MINOR(dev
)].start_sect
= 0;
283 de
= hd
->de_arr
[MINOR(dev
) >> hd
->minor_shift
];
284 i
= devfs_generate_path (de
, buf
, sizeof buf
);
286 printk(KERN_INFO
" /dev/%s:", buf
+ i
);
288 printk(KERN_INFO
" %s:", disk_name(hd
, MINOR(dev
), buf
));
289 for (i
= 0; check_part
[i
]; i
++)
290 if (check_part
[i
](hd
, dev
, first_sector
, first_part_minor
))
293 printk(" unknown partition table\n");
295 i
= first_part_minor
- 1;
296 devfs_register_partitions (hd
, i
, hd
->sizes
? 0 : 1);
299 #ifdef CONFIG_DEVFS_FS
300 static void devfs_register_partition (struct gendisk
*dev
, int minor
, int part
)
302 int devnum
= minor
>> dev
->minor_shift
;
304 unsigned int devfs_flags
= DEVFS_FL_DEFAULT
;
307 if (dev
->part
[minor
+ part
].de
) return;
308 dir
= devfs_get_parent (dev
->part
[minor
].de
);
310 if ( dev
->flags
&& (dev
->flags
[devnum
] & GENHD_FL_REMOVABLE
) )
311 devfs_flags
|= DEVFS_FL_REMOVABLE
;
312 sprintf (devname
, "part%d", part
);
313 dev
->part
[minor
+ part
].de
=
314 devfs_register (dir
, devname
, 0, devfs_flags
,
315 dev
->major
, minor
+ part
,
316 S_IFBLK
| S_IRUSR
| S_IWUSR
, 0, 0,
320 static void devfs_register_disc (struct gendisk
*dev
, int minor
)
323 int devnum
= minor
>> dev
->minor_shift
;
324 devfs_handle_t dir
, slave
;
325 unsigned int devfs_flags
= DEVFS_FL_DEFAULT
;
326 char dirname
[64], symlink
[16];
327 static unsigned int disc_counter
= 0;
328 static devfs_handle_t devfs_handle
= NULL
;
330 if (dev
->part
[minor
].de
) return;
331 if ( dev
->flags
&& (dev
->flags
[devnum
] & GENHD_FL_REMOVABLE
) )
332 devfs_flags
|= DEVFS_FL_REMOVABLE
;
334 dir
= dev
->de_arr
[devnum
];
335 if (!dir
) /* Aware driver wants to block disc management */
337 pos
= devfs_generate_path (dir
, dirname
+ 3, sizeof dirname
-3);
339 strncpy (dirname
+ pos
, "../", 3);
342 /* Unaware driver: construct "real" directory */
343 sprintf (dirname
, "../%s/disc%d", dev
->major_name
, devnum
);
344 dir
= devfs_mk_dir (NULL
, dirname
+ 3, 0, NULL
);
347 devfs_handle
= devfs_mk_dir (NULL
, "discs", 5, NULL
);
348 sprintf (symlink
, "disc%u", disc_counter
++);
349 devfs_mk_symlink (devfs_handle
, symlink
, 0, DEVFS_FL_DEFAULT
,
350 dirname
+ pos
, 0, &slave
, NULL
);
351 dev
->part
[minor
].de
=
352 devfs_register (dir
, "disc", 4, devfs_flags
, dev
->major
, minor
,
353 S_IFBLK
| S_IRUSR
| S_IWUSR
, 0, 0, dev
->fops
,NULL
);
354 devfs_auto_unregister (dev
->part
[minor
].de
, slave
);
356 devfs_auto_unregister (slave
, dir
);
358 #endif /* CONFIG_DEVFS_FS */
360 void devfs_register_partitions (struct gendisk
*dev
, int minor
, int unregister
)
362 #ifdef CONFIG_DEVFS_FS
366 devfs_register_disc (dev
, minor
);
367 for (part
= 1; part
< dev
->max_p
; part
++) {
368 if ( unregister
|| (dev
->part
[part
+ minor
].nr_sects
< 1) ) {
369 devfs_unregister (dev
->part
[part
+ minor
].de
);
370 dev
->part
[part
+ minor
].de
= NULL
;
373 devfs_register_partition (dev
, minor
, part
);
376 devfs_unregister (dev
->part
[minor
].de
);
377 dev
->part
[minor
].de
= NULL
;
379 #endif /* CONFIG_DEVFS_FS */
383 * This function will re-read the partition tables for a given device,
384 * and set things back up again. There are some important caveats,
385 * however. You must ensure that no one is using the device, and no one
386 * can start using the device while this function is being executed.
388 * Much of the cleanup from the old partition tables should have already been
392 void register_disk(struct gendisk
*gdev
, kdev_t dev
, unsigned minors
,
393 struct block_device_operations
*ops
, long size
)
397 grok_partitions(gdev
, MINOR(dev
)>>gdev
->minor_shift
, minors
, size
);
400 void grok_partitions(struct gendisk
*dev
, int drive
, unsigned minors
, long size
)
403 int first_minor
= drive
<< dev
->minor_shift
;
404 int end_minor
= first_minor
+ dev
->max_p
;
407 blk_size
[dev
->major
] = NULL
;
409 dev
->part
[first_minor
].nr_sects
= size
;
410 /* No Such Agen^Wdevice or no minors to use for partitions */
411 if (!size
|| minors
== 1)
414 blk_size
[dev
->major
] = NULL
;
415 check_partition(dev
, MKDEV(dev
->major
, first_minor
), 1 + first_minor
);
418 * We need to set the sizes array before we will be able to access
419 * any of the partitions on this device.
421 if (dev
->sizes
!= NULL
) { /* optional safeguard in ll_rw_blk.c */
422 for (i
= first_minor
; i
< end_minor
; i
++)
423 dev
->sizes
[i
] = dev
->part
[i
].nr_sects
>> (BLOCK_SIZE_BITS
- 9);
424 blk_size
[dev
->major
] = dev
->sizes
;
428 int __init
partition_setup(void)
432 #ifdef CONFIG_BLK_DEV_RAM
433 #ifdef CONFIG_BLK_DEV_INITRD
434 if (initrd_start
&& mount_initrd
) initrd_load();
439 #ifdef CONFIG_BLK_DEV_MD
445 __initcall(partition_setup
);