cleanup
[linux-2.4.21-pre4.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_EFI_PARTITION
47         efi_partition,          /* this must come before msdos */
48 #endif
49 #ifdef CONFIG_LDM_PARTITION
50         ldm_partition,          /* this must come before msdos */
51 #endif
52 #ifdef CONFIG_MSDOS_PARTITION
53         msdos_partition,
54 #endif
55 #ifdef CONFIG_OSF_PARTITION
56         osf_partition,
57 #endif
58 #ifdef CONFIG_SUN_PARTITION
59         sun_partition,
60 #endif
61 #ifdef CONFIG_AMIGA_PARTITION
62         amiga_partition,
63 #endif
64 #ifdef CONFIG_ATARI_PARTITION
65         atari_partition,
66 #endif
67 #ifdef CONFIG_MAC_PARTITION
68         mac_partition,
69 #endif
70 #ifdef CONFIG_SGI_PARTITION
71         sgi_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, int start, int size)
208 {
209 #ifndef CONFIG_DEVFS_FS
210         char buf[40];
211 #endif
212
213         hd->part[minor].start_sect = start;
214         hd->part[minor].nr_sects   = size;
215 #ifdef CONFIG_DEVFS_FS
216         printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
217 #else
218         if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
219             (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
220                 printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
221         else
222                 printk(" %s", disk_name(hd, minor, buf));
223 #endif
224 }
225
226 static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
227 {
228         devfs_handle_t de = NULL;
229         static int first_time = 1;
230         unsigned long first_sector;
231         struct block_device *bdev;
232         char buf[64];
233         int i;
234
235         if (first_time)
236                 printk(KERN_INFO "Partition check:\n");
237         first_time = 0;
238         first_sector = hd->part[MINOR(dev)].start_sect;
239
240         /*
241          * This is a kludge to allow the partition check to be
242          * skipped for specific drives (e.g. IDE CD-ROM drives)
243          */
244         if ((int)first_sector == -1) {
245                 hd->part[MINOR(dev)].start_sect = 0;
246                 return;
247         }
248
249         if (hd->de_arr)
250                 de = hd->de_arr[MINOR(dev) >> hd->minor_shift];
251         i = devfs_generate_path (de, buf, sizeof buf);
252 //jackl mark for card reader            
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 //jackl mark for card reader                            
265 //                      if (res < 0 &&  warn_no_part)
266 //                              printk(" unable to read partition table\n");
267                         goto setup_devfs;
268                 }
269         }
270
271         printk(" unknown partition table\n");
272 setup_devfs:
273         invalidate_bdev(bdev, 1);
274         truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
275         bdput(bdev);
276         i = first_part_minor - 1;
277         devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
278 }
279
280 #ifdef CONFIG_DEVFS_FS
281 static void devfs_register_partition (struct gendisk *dev, int minor, int part)
282 {
283         int devnum = minor >> dev->minor_shift;
284         devfs_handle_t dir;
285         unsigned int devfs_flags = DEVFS_FL_DEFAULT;
286         char devname[16];
287
288         if (dev->part[minor + part].de) return;
289         dir = devfs_get_parent (dev->part[minor].de);
290         if (!dir) return;
291         if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
292                 devfs_flags |= DEVFS_FL_REMOVABLE;
293         sprintf (devname, "part%d", part);
294         dev->part[minor + part].de =
295             devfs_register (dir, devname, devfs_flags,
296                             dev->major, minor + part,
297                             S_IFBLK | S_IRUSR | S_IWUSR,
298                             dev->fops, NULL);
299 }
300
301 static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
302
303 static void devfs_register_disc (struct gendisk *dev, int minor)
304 {
305         int pos = 0;
306         int devnum = minor >> dev->minor_shift;
307         devfs_handle_t dir, slave;
308         unsigned int devfs_flags = DEVFS_FL_DEFAULT;
309         char dirname[64], symlink[16];
310         static devfs_handle_t devfs_handle;
311
312         if (dev->part[minor].de) return;
313         if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
314                 devfs_flags |= DEVFS_FL_REMOVABLE;
315         if (dev->de_arr) {
316                 dir = dev->de_arr[devnum];
317                 if (!dir)  /*  Aware driver wants to block disc management  */
318                         return;
319                 pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
320                 if (pos < 0) return;
321                 strncpy (dirname + pos, "../", 3);
322         }
323         else {
324                 /*  Unaware driver: construct "real" directory  */
325                 sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
326                 dir = devfs_mk_dir (NULL, dirname + 3, NULL);
327         }
328         if (!devfs_handle)
329                 devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
330         dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
331         sprintf (symlink, "disc%d", dev->part[minor].number);
332         devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
333                           dirname + pos, &slave, NULL);
334         dev->part[minor].de =
335             devfs_register (dir, "disc", devfs_flags, dev->major, minor,
336                             S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
337         devfs_auto_unregister (dev->part[minor].de, slave);
338         if (!dev->de_arr)
339                 devfs_auto_unregister (slave, dir);
340 }
341 #endif  /*  CONFIG_DEVFS_FS  */
342
343 void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
344 {
345 #ifdef CONFIG_DEVFS_FS
346         int part;
347
348         if (!unregister)
349                 devfs_register_disc (dev, minor);
350         for (part = 1; part < dev->max_p; part++) {
351                 if ( unregister || (dev->part[minor].nr_sects < 1) ||
352                      (dev->part[part + minor].nr_sects < 1) ) {
353                         devfs_unregister (dev->part[part + minor].de);
354                         dev->part[part + minor].de = NULL;
355                         continue;
356                 }
357                 devfs_register_partition (dev, minor, part);
358         }
359         if (unregister) {
360                 devfs_unregister (dev->part[minor].de);
361                 dev->part[minor].de = NULL;
362                 devfs_dealloc_unique_number (&disc_numspace,
363                                              dev->part[minor].number);
364         }
365 #endif  /*  CONFIG_DEVFS_FS  */
366 }
367
368 /*
369  * This function will re-read the partition tables for a given device,
370  * and set things back up again.  There are some important caveats,
371  * however.  You must ensure that no one is using the device, and no one
372  * can start using the device while this function is being executed.
373  *
374  * Much of the cleanup from the old partition tables should have already been
375  * done
376  */
377
378 void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
379         struct block_device_operations *ops, long size)
380 {
381         if (!gdev)
382                 return;
383         grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
384 }
385
386 void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
387 {
388         int i;
389         int first_minor = drive << dev->minor_shift;
390         int end_minor   = first_minor + dev->max_p;
391
392         if(!dev->sizes)
393                 blk_size[dev->major] = NULL;
394
395         dev->part[first_minor].nr_sects = size;
396         /* No such device or no minors to use for partitions */
397         if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
398                 devfs_register_partitions (dev, first_minor, 0);
399         if (!size || minors == 1)
400                 return;
401
402         if (dev->sizes) {
403                 dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
404                 for (i = first_minor + 1; i < end_minor; i++)
405                         dev->sizes[i] = 0;
406         }
407         blk_size[dev->major] = dev->sizes;
408         check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
409
410         /*
411          * We need to set the sizes array before we will be able to access
412          * any of the partitions on this device.
413          */
414         if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
415                 for (i = first_minor; i < end_minor; i++)
416                         dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
417         }
418 }
419
420 unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
421 {
422         struct address_space *mapping = bdev->bd_inode->i_mapping;
423         int sect = PAGE_CACHE_SIZE / 512;
424         struct page *page;
425
426         page = read_cache_page(mapping, n/sect,
427                         (filler_t *)mapping->a_ops->readpage, NULL);
428         if (!IS_ERR(page)) {
429                 wait_on_page(page);
430                 if (!Page_Uptodate(page))
431                         goto fail;
432                 if (PageError(page))
433                         goto fail;
434                 p->v = page;
435                 return (unsigned char *)page_address(page) + 512 * (n % sect);
436 fail:
437                 page_cache_release(page);
438         }
439         p->v = NULL;
440         return NULL;
441 }