1 /*
2 * Code extracted from drivers/block/genhd.c
3 * Copyright (C) 1991-1998 Linus Torvalds
4 * Re-organised Feb 1998 Russell King
5 *
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
9 * contained.
10 *
11 * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
12 */
13
14 #include <linux/config.h>
15 #include <linux/fs.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>
22
23 #include "check.h"
24
25 #include "acorn.h"
26 #include "amiga.h"
27 #include "atari.h"
28 #include "ldm.h"
29 #include "mac.h"
30 #include "msdos.h"
31 #include "osf.h"
32 #include "sgi.h"
33 #include "sun.h"
34 #include "ibm.h"
35 #include "ultrix.h"
36 #include "efi.h"
37
38 extern int *blk_size[];
39
40 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
41
42 static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
43 #ifdef CONFIG_ACORN_PARTITION
44 acorn_partition,
45 #endif
46 #ifdef CONFIG_SGI_PARTITION
47 sgi_partition,
48 #endif
49 #ifdef CONFIG_EFI_PARTITION
50 efi_partition, /* this must come before msdos */
51 #endif
52 #ifdef CONFIG_LDM_PARTITION
53 ldm_partition, /* this must come before msdos */
54 #endif
55 #ifdef CONFIG_MSDOS_PARTITION
56 msdos_partition,
57 #endif
58 #ifdef CONFIG_OSF_PARTITION
59 osf_partition,
60 #endif
61 #ifdef CONFIG_SUN_PARTITION
62 sun_partition,
63 #endif
64 #ifdef CONFIG_AMIGA_PARTITION
65 amiga_partition,
66 #endif
67 #ifdef CONFIG_ATARI_PARTITION
68 atari_partition,
69 #endif
70 #ifdef CONFIG_MAC_PARTITION
71 mac_partition,
72 #endif
73 #ifdef CONFIG_ULTRIX_PARTITION
74 ultrix_partition,
75 #endif
76 #ifdef CONFIG_IBM_PARTITION
77 ibm_partition,
78 #endif
79 NULL
80 };
81
82 /*
83 * This is ucking fugly but its probably the best thing for 2.4.x
84 * Take it as a clear reminder that: 1) we should put the device name
85 * generation in the object kdev_t points to in 2.5.
86 * and 2) ioctls better work on half-opened devices.
87 */
88
89 #ifdef CONFIG_ARCH_S390
90 int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
91 int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
92 unsigned int no, unsigned long data);
93 EXPORT_SYMBOL(genhd_dasd_name);
94 EXPORT_SYMBOL(genhd_dasd_ioctl);
95 #endif
96
97 /*
98 * disk_name() is used by partition check code and the md driver.
99 * It formats the devicename of the indicated disk into
100 * the supplied buffer (of size at least 32), and returns
101 * a pointer to that same buffer (for convenience).
102 */
103
disk_name(struct gendisk * hd,int minor,char * buf)104 char *disk_name (struct gendisk *hd, int minor, char *buf)
105 {
106 const char *maj = hd->major_name;
107 unsigned int unit = (minor >> hd->minor_shift);
108 unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
109
110 if ((unit < hd->nr_real) && hd->part[minor].de) {
111 int pos;
112
113 pos = devfs_generate_path (hd->part[minor].de, buf, 64);
114 if (pos >= 0)
115 return buf + pos;
116 }
117
118 #ifdef CONFIG_ARCH_S390
119 if (genhd_dasd_name
120 && genhd_dasd_name (buf, unit, part, hd) == 0)
121 return buf;
122 #endif
123 /*
124 * IDE devices use multiple major numbers, but the drives
125 * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
126 * This requires special handling here.
127 */
128 switch (hd->major) {
129 case IDE9_MAJOR:
130 unit += 2;
131 case IDE8_MAJOR:
132 unit += 2;
133 case IDE7_MAJOR:
134 unit += 2;
135 case IDE6_MAJOR:
136 unit += 2;
137 case IDE5_MAJOR:
138 unit += 2;
139 case IDE4_MAJOR:
140 unit += 2;
141 case IDE3_MAJOR:
142 unit += 2;
143 case IDE2_MAJOR:
144 unit += 2;
145 case IDE1_MAJOR:
146 unit += 2;
147 case IDE0_MAJOR:
148 maj = "hd";
149 break;
150 case MD_MAJOR:
151 sprintf(buf, "%s%d", maj, unit);
152 return buf;
153 }
154 if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
155 unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
156 if (unit+'a' > 'z') {
157 unit -= 26;
158 sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
159 if (part)
160 sprintf(buf + 4, "%d", part);
161 return buf;
162 }
163 }
164 if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
165 int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
166 if (part == 0)
167 sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
168 else
169 sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
170 return buf;
171 }
172 if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
173 int ctlr = hd->major - COMPAQ_CISS_MAJOR;
174 if (part == 0)
175 sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
176 else
177 sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
178 return buf;
179 }
180 if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
181 int ctlr = hd->major - DAC960_MAJOR;
182 if (part == 0)
183 sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
184 else
185 sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
186 return buf;
187 }
188 if (hd->major == ATARAID_MAJOR) {
189 int disk = minor >> hd->minor_shift;
190 int part = minor & (( 1 << hd->minor_shift) - 1);
191 if (part == 0)
192 sprintf(buf, "%s/d%d", maj, disk);
193 else
194 sprintf(buf, "%s/d%dp%d", maj, disk, part);
195 return buf;
196 }
197 if (part)
198 sprintf(buf, "%s%c%d", maj, unit+'a', part);
199 else
200 sprintf(buf, "%s%c", maj, unit+'a');
201 return buf;
202 }
203
204 /*
205 * Add a partitions details to the devices partition description.
206 */
add_gd_partition(struct gendisk * hd,int minor,unsigned int start,unsigned int size)207 void add_gd_partition(struct gendisk *hd, int minor, unsigned int start,
208 unsigned int size)
209 {
210 #ifndef CONFIG_DEVFS_FS
211 char buf[40];
212 #endif
213
214 hd->part[minor].start_sect = start;
215 hd->part[minor].nr_sects = size;
216 #ifdef CONFIG_DEVFS_FS
217 printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
218 #else
219 if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
220 (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
221 printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
222 else
223 printk(" %s", disk_name(hd, minor, buf));
224 #endif
225 }
226
check_partition(struct gendisk * hd,kdev_t dev,int first_part_minor)227 static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
228 {
229 devfs_handle_t de = NULL;
230 static int first_time = 1;
231 unsigned long first_sector;
232 struct block_device *bdev;
233 char buf[64];
234 int i;
235
236 if (first_time)
237 printk(KERN_INFO "Partition check:\n");
238 first_time = 0;
239 first_sector = hd->part[MINOR(dev)].start_sect;
240
241 /*
242 * This is a kludge to allow the partition check to be
243 * skipped for specific drives (e.g. IDE CD-ROM drives)
244 */
245 if ((int)first_sector == -1) {
246 hd->part[MINOR(dev)].start_sect = 0;
247 return;
248 }
249
250 if (hd->de_arr)
251 de = hd->de_arr[MINOR(dev) >> hd->minor_shift];
252 i = devfs_generate_path (de, buf, sizeof buf);
253 if (i >= 0)
254 printk(KERN_INFO " /dev/%s:", buf + i);
255 else
256 printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
257 bdev = bdget(kdev_t_to_nr(dev));
258 bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
259 bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
260 for (i = 0; check_part[i]; i++) {
261 int res;
262 res = check_part[i](hd, bdev, first_sector, first_part_minor);
263 if (res) {
264 if (res < 0 && warn_no_part)
265 printk(" unable to read partition table\n");
266 goto setup_devfs;
267 }
268 }
269
270 printk(" unknown partition table\n");
271 setup_devfs:
272 invalidate_bdev(bdev, 1);
273 truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
274 bdput(bdev);
275 i = first_part_minor - 1;
276 devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
277 }
278
279 #ifdef CONFIG_DEVFS_FS
devfs_register_partition(struct gendisk * dev,int minor,int part)280 static void devfs_register_partition (struct gendisk *dev, int minor, int part)
281 {
282 int devnum = minor >> dev->minor_shift;
283 devfs_handle_t dir;
284 unsigned int devfs_flags = DEVFS_FL_DEFAULT;
285 char devname[16];
286
287 if (dev->part[minor + part].de) return;
288 dir = devfs_get_parent (dev->part[minor].de);
289 if (!dir) return;
290 if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
291 devfs_flags |= DEVFS_FL_REMOVABLE;
292 sprintf (devname, "part%d", part);
293 dev->part[minor + part].de =
294 devfs_register (dir, devname, devfs_flags,
295 dev->major, minor + part,
296 S_IFBLK | S_IRUSR | S_IWUSR,
297 dev->fops, NULL);
298 }
299
300 static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
301
devfs_register_disc(struct gendisk * dev,int minor)302 static void devfs_register_disc (struct gendisk *dev, int minor)
303 {
304 int pos = 0;
305 int devnum = minor >> dev->minor_shift;
306 devfs_handle_t dir, slave;
307 unsigned int devfs_flags = DEVFS_FL_DEFAULT;
308 char dirname[64], symlink[16];
309 static devfs_handle_t devfs_handle;
310
311 if (dev->part[minor].de) return;
312 if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
313 devfs_flags |= DEVFS_FL_REMOVABLE;
314 if (dev->de_arr) {
315 dir = dev->de_arr[devnum];
316 if (!dir) /* Aware driver wants to block disc management */
317 return;
318 pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
319 if (pos < 0) return;
320 strncpy (dirname + pos, "../", 3);
321 }
322 else {
323 /* Unaware driver: construct "real" directory */
324 sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
325 dir = devfs_mk_dir (NULL, dirname + 3, NULL);
326 }
327 if (!devfs_handle)
328 devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
329 dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
330 sprintf (symlink, "disc%d", dev->part[minor].number);
331 devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
332 dirname + pos, &slave, NULL);
333 dev->part[minor].de =
334 devfs_register (dir, "disc", devfs_flags, dev->major, minor,
335 S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
336 devfs_auto_unregister (dev->part[minor].de, slave);
337 if (!dev->de_arr)
338 devfs_auto_unregister (slave, dir);
339 }
340 #endif /* CONFIG_DEVFS_FS */
341
devfs_register_partitions(struct gendisk * dev,int minor,int unregister)342 void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
343 {
344 #ifdef CONFIG_DEVFS_FS
345 int part;
346
347 if (!unregister)
348 devfs_register_disc (dev, minor);
349 for (part = 1; part < dev->max_p; part++) {
350 if ( unregister || (dev->part[minor].nr_sects < 1) ||
351 (dev->part[part + minor].nr_sects < 1) ) {
352 devfs_unregister (dev->part[part + minor].de);
353 dev->part[part + minor].de = NULL;
354 continue;
355 }
356 devfs_register_partition (dev, minor, part);
357 }
358 if (unregister) {
359 devfs_unregister (dev->part[minor].de);
360 dev->part[minor].de = NULL;
361 devfs_dealloc_unique_number (&disc_numspace,
362 dev->part[minor].number);
363 }
364 #endif /* CONFIG_DEVFS_FS */
365 }
366
367 /*
368 * This function will re-read the partition tables for a given device,
369 * and set things back up again. There are some important caveats,
370 * however. You must ensure that no one is using the device, and no one
371 * can start using the device while this function is being executed.
372 *
373 * Much of the cleanup from the old partition tables should have already been
374 * done
375 */
376
register_disk(struct gendisk * gdev,kdev_t dev,unsigned minors,struct block_device_operations * ops,long size)377 void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
378 struct block_device_operations *ops, long size)
379 {
380 if (!gdev)
381 return;
382 grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
383 }
384
grok_partitions(struct gendisk * dev,int drive,unsigned minors,long size)385 void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
386 {
387 int i;
388 int first_minor = drive << dev->minor_shift;
389 int end_minor = first_minor + dev->max_p;
390
391 if(!dev->sizes)
392 blk_size[dev->major] = NULL;
393
394 dev->part[first_minor].nr_sects = size;
395 /* No such device or no minors to use for partitions */
396 if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
397 devfs_register_partitions (dev, first_minor, 0);
398 if (!size || minors == 1)
399 return;
400
401 if (dev->sizes) {
402 dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
403 for (i = first_minor + 1; i < end_minor; i++)
404 dev->sizes[i] = 0;
405 }
406 blk_size[dev->major] = dev->sizes;
407 check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
408
409 /*
410 * We need to set the sizes array before we will be able to access
411 * any of the partitions on this device.
412 */
413 if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
414 for (i = first_minor; i < end_minor; i++)
415 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
416 }
417 }
418
read_dev_sector(struct block_device * bdev,unsigned long n,Sector * p)419 unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
420 {
421 struct address_space *mapping = bdev->bd_inode->i_mapping;
422 int sect = PAGE_CACHE_SIZE / 512;
423 struct page *page;
424
425 page = read_cache_page(mapping, n/sect,
426 (filler_t *)mapping->a_ops->readpage, NULL);
427 if (!IS_ERR(page)) {
428 wait_on_page(page);
429 if (!Page_Uptodate(page))
430 goto fail;
431 if (PageError(page))
432 goto fail;
433 p->v = page;
434 return (unsigned char *)page_address(page) + 512 * (n % sect);
435 fail:
436 page_cache_release(page);
437 }
438 p->v = NULL;
439 return NULL;
440 }
441