import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / fs / partitions / check.c
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
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  */
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
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
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
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
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
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
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
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 }