root/drivers/block/genhd.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. print_minor_name
  2. add_partition
  3. extended_partition
  4. msdos_partition
  5. osf_partition
  6. check_partition
  7. resetup_one_dev
  8. setup_dev
  9. device_setup

   1 /*
   2  *  Code extracted from
   3  *  linux/kernel/hd.c
   4  *
   5  *  Copyright (C) 1991, 1992  Linus Torvalds
   6  *
   7  *
   8  *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
   9  *  in the early extended-partition checks and added DM partitions
  10  *
  11  *  Support for DiskManager v6.0x added by Mark Lord (mlord@bnr.ca)
  12  *  with information provided by OnTrack.  This now works for linux fdisk
  13  *  and LILO, as well as loadlin and bootln.  Note that disks other than
  14  *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
  15  *
  16  *  More flexible handling of extended partitions - aeb, 950831
  17  */
  18 
  19 #include <linux/config.h>
  20 #include <linux/fs.h>
  21 #include <linux/genhd.h>
  22 #include <linux/kernel.h>
  23 #include <linux/major.h>
  24 #include <linux/string.h>
  25 
  26 struct gendisk *gendisk_head = NULL;
  27 
  28 static int current_minor = 0;
  29 extern int *blk_size[];
  30 extern void rd_load(void);
  31 extern int ramdisk_size;
  32 
  33 static void print_minor_name (struct gendisk *hd, int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  34 {
  35         unsigned int unit = minor >> hd->minor_shift;
  36         unsigned int part = minor & ((1 << hd->minor_shift) - 1);
  37 
  38 #ifdef CONFIG_BLK_DEV_IDE
  39         /*
  40          * IDE devices use multiple major numbers, but the drives
  41          * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
  42          * This requires some creative handling here to find the
  43          * correct name to use, with some help from ide.c
  44          */
  45         if (!strcmp(hd->major_name,"ide")) {
  46                 char name[16];          /* more than large enough */
  47                 strcpy(name, hd->real_devices); /* courtesy ide.c */
  48                 name[strlen(name)-1] += unit;
  49                 printk(" %s", name);
  50         } else
  51 #endif
  52                 printk(" %s%c", hd->major_name, 'a' + unit);
  53         if (part)
  54                 printk("%d", part);
  55         else
  56                 printk(":");
  57 }
  58 
  59 static void add_partition (struct gendisk *hd, int minor, int start, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  60 {
  61         hd->part[minor].start_sect = start;
  62         hd->part[minor].nr_sects   = size;
  63         print_minor_name(hd, minor);
  64 }
  65 
  66 #ifdef CONFIG_MSDOS_PARTITION
  67 /*
  68  * Create devices for each logical partition in an extended partition.
  69  * The logical partitions form a linked list, with each entry being
  70  * a partition table with two entries.  The first entry
  71  * is the real data partition (with a start relative to the partition
  72  * table start).  The second is a pointer to the next logical partition
  73  * (with a start relative to the entire extended partition).
  74  * We do not create a Linux partition for the partition tables, but
  75  * only for the actual data partitions.
  76  */
  77 
  78 static void extended_partition(struct gendisk *hd, kdev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80         struct buffer_head *bh;
  81         struct partition *p;
  82         unsigned long first_sector, first_size, this_sector, this_size;
  83         int mask = (1 << hd->minor_shift) - 1;
  84         int i;
  85 
  86         first_sector = hd->part[MINOR(dev)].start_sect;
  87         first_size = hd->part[MINOR(dev)].nr_sects;
  88         this_sector = first_sector;
  89 
  90         while (1) {
  91                 if ((current_minor & mask) == 0)
  92                         return;
  93                 if (!(bh = bread(dev,0,1024)))
  94                         return;
  95           /*
  96            * This block is from a device that we're about to stomp on.
  97            * So make sure nobody thinks this block is usable.
  98            */
  99                 bh->b_dirt = 0;
 100                 bh->b_uptodate = 0;
 101                 bh->b_req = 0;
 102 
 103                 if (*(unsigned short *) (bh->b_data+510) != 0xAA55)
 104                         goto done;
 105 
 106                 p = (struct partition *) (0x1BE + bh->b_data);
 107 
 108                 this_size = hd->part[MINOR(dev)].nr_sects;
 109 
 110                 /*
 111                  * Usually, the first entry is the real data partition,
 112                  * the 2nd entry is the next extended partition, or empty,
 113                  * and the 3rd and 4th entries are unused.
 114                  * However, DRDOS sometimes has the extended partition as
 115                  * the first entry (when the data partition is empty),
 116                  * and OS/2 seems to use all four entries.
 117                  */
 118 
 119                 /* 
 120                  * First process the data partition(s)
 121                  */
 122                 for (i=0; i<4; i++, p++) {
 123                     if (!p->nr_sects || p->sys_ind == EXTENDED_PARTITION)
 124                       continue;
 125 
 126                     /* Check the 3rd and 4th entries -
 127                        these sometimes contain random garbage */
 128                     if (i >= 2
 129                         && p->start_sect + p->nr_sects > this_size
 130                         && (this_sector + p->start_sect < first_sector ||
 131                             this_sector + p->start_sect + p->nr_sects >
 132                              first_sector + first_size))
 133                       continue;
 134 
 135                     add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
 136                     current_minor++;
 137                     if ((current_minor & mask) == 0)
 138                       goto done;
 139                 }
 140                 /*
 141                  * Next, process the (first) extended partition, if present.
 142                  * (So far, there seems to be no reason to make
 143                  *  extended_partition()  recursive and allow a tree
 144                  *  of extended partitions.)
 145                  * It should be a link to the next logical partition.
 146                  * Create a minor for this just long enough to get the next
 147                  * partition table.  The minor will be reused for the next
 148                  * data partition.
 149                  */
 150                 p -= 4;
 151                 for (i=0; i<4; i++, p++)
 152                   if(p->nr_sects && p->sys_ind == EXTENDED_PARTITION)
 153                     break;
 154                 if (i == 4)
 155                   goto done;     /* nothing left to do */
 156 
 157                 hd->part[current_minor].nr_sects = p->nr_sects;
 158                 hd->part[current_minor].start_sect = first_sector + p->start_sect;
 159                 this_sector = first_sector + p->start_sect;
 160                 dev = MKDEV(hd->major, current_minor);
 161                 brelse(bh);
 162         }
 163 done:
 164         brelse(bh);
 165 }
 166 
 167 static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169         int i, minor = current_minor;
 170         struct buffer_head *bh;
 171         struct partition *p;
 172         unsigned char *data;
 173         int mask = (1 << hd->minor_shift) - 1;
 174 #ifdef CONFIG_BLK_DEV_IDE
 175         int tested_for_dm6 = 0;
 176 
 177 read_mbr:
 178 #endif
 179         if (!(bh = bread(dev,0,1024))) {
 180                 printk(" unable to read partition table\n");
 181                 return -1;
 182         }
 183         data = bh->b_data;
 184         bh->b_dirt = 0;         /* In some cases we modify the geometry    */
 185         bh->b_uptodate = 0;     /*  of the drive (below), so ensure that   */
 186         bh->b_req = 0;          /*  nobody else tries to re-use this data. */
 187 #ifdef CONFIG_BLK_DEV_IDE
 188 check_table:
 189 #endif
 190         if (*(unsigned short *)  (0x1fe + data) != 0xAA55) {
 191                 brelse(bh);
 192                 return 0;
 193         }
 194         p = (struct partition *) (0x1be + data);
 195 
 196 #ifdef CONFIG_BLK_DEV_IDE
 197         /*
 198          *  Check for Disk Manager v6.0x (or EZ-DRIVE) with geometry translation
 199          */
 200         if (!tested_for_dm6++) {        /* only check for DM6 *once* */
 201                 extern int ide_xlate_1024(kdev_t, int, const char *);
 202                 /* check for various "disk managers" which do strange things */
 203                 if (p->sys_ind == EZD_PARTITION) {
 204                         /*
 205                          * The remainder of the disk must be accessed using
 206                          * a translated geometry that reduces the number of 
 207                          * apparent cylinders to less than 1024 if possible.
 208                          *
 209                          * ide_xlate_1024() will take care of the necessary
 210                          * adjustments to fool fdisk/LILO and partition check.
 211                          */
 212                         if (ide_xlate_1024(dev, -1, " [EZD]")) {
 213                                 data += 512;
 214                                 goto check_table;
 215                         }
 216                 } else if (p->sys_ind == DM6_PARTITION) {
 217 
 218                         /*
 219                          * Everything on the disk is offset by 63 sectors,
 220                          * including a "new" MBR with its own partition table,
 221                          * and the remainder of the disk must be accessed using
 222                          * a translated geometry that reduces the number of 
 223                          * apparent cylinders to less than 1024 if possible.
 224                          *
 225                          * ide_xlate_1024() will take care of the necessary
 226                          * adjustments to fool fdisk/LILO and partition check.
 227                          */
 228                         if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
 229                                 brelse(bh);
 230                                 goto read_mbr;  /* start over with new MBR */
 231                         }
 232                 } else {
 233                         /* look for DM6 signature in MBR, courtesy of OnTrack */
 234                         unsigned int sig = *(unsigned short *)(data + 2);
 235                         if (sig <= 0x1ae
 236                          && *(unsigned short *)(data + sig) == 0x55AA
 237                          && (1 & *(unsigned char *)(data + sig + 2)) ) 
 238                         {
 239                                 (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
 240                         } else {
 241                                 /* look for DM6 AUX partition type in slot 1 */
 242                                 if (p->sys_ind == DM6_AUX1PARTITION
 243                                  || p->sys_ind == DM6_AUX3PARTITION)
 244                                 {
 245                                         (void)ide_xlate_1024(dev, 0, " [DM6:AUX]");
 246                                 }
 247                         }
 248                 }
 249         }
 250 #endif  /* CONFIG_BLK_DEV_IDE */
 251 
 252         current_minor += 4;  /* first "extra" minor (for extended partitions) */
 253         for (i=1 ; i<=4 ; minor++,i++,p++) {
 254                 if (!p->nr_sects)
 255                         continue;
 256                 add_partition(hd, minor, first_sector+p->start_sect, p->nr_sects);
 257                 if (p->sys_ind == EXTENDED_PARTITION) {
 258                         printk(" <");
 259                         /*
 260                          * If we are rereading the partition table, we need
 261                          * to set the size of the partition so that we will
 262                          * be able to bread the block containing the extended
 263                          * partition info.
 264                          */
 265                         hd->sizes[minor] = hd->part[minor].nr_sects 
 266                                 >> (BLOCK_SIZE_BITS - 9);
 267                         extended_partition(hd, MKDEV(hd->major, minor));
 268                         printk(" >");
 269                         /* prevent someone doing mkfs or mkswap on
 270                            an extended partition */
 271                         hd->part[minor].nr_sects = 0;
 272                 }
 273         }
 274         /*
 275          *  Check for old-style Disk Manager partition table
 276          */
 277         if (*(unsigned short *) (data+0xfc) == 0x55AA) {
 278                 p = (struct partition *) (0x1be + data);
 279                 for (i = 4 ; i < 16 ; i++, current_minor++) {
 280                         p--;
 281                         if ((current_minor & mask) == 0)
 282                                 break;
 283                         if (!(p->start_sect && p->nr_sects))
 284                                 continue;
 285                         add_partition(hd, current_minor, p->start_sect, p->nr_sects);
 286                 }
 287         }
 288         printk("\n");
 289         brelse(bh);
 290         return 1;
 291 }
 292 
 293 #endif /* CONFIG_MSDOS_PARTITION */
 294 
 295 #ifdef CONFIG_OSF_PARTITION
 296 
 297 static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
     /* [previous][next][first][last][top][bottom][index][help] */
 298 {
 299         int i;
 300         int mask = (1 << hd->minor_shift) - 1;
 301         struct buffer_head *bh;
 302         struct disklabel {
 303                 u32 d_magic;
 304                 u16 d_type,d_subtype;
 305                 u8 d_typename[16];
 306                 u8 d_packname[16];
 307                 u32 d_secsize;
 308                 u32 d_nsectors;
 309                 u32 d_ntracks;
 310                 u32 d_ncylinders;
 311                 u32 d_secpercyl;
 312                 u32 d_secprtunit;
 313                 u16 d_sparespertrack;
 314                 u16 d_sparespercyl;
 315                 u32 d_acylinders;
 316                 u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
 317                 u32 d_headswitch, d_trkseek, d_flags;
 318                 u32 d_drivedata[5];
 319                 u32 d_spare[5];
 320                 u32 d_magic2;
 321                 u16 d_checksum;
 322                 u16 d_npartitions;
 323                 u32 d_bbsize, d_sbsize;
 324                 struct d_partition {
 325                         u32 p_size;
 326                         u32 p_offset;
 327                         u32 p_fsize;
 328                         u8  p_fstype;
 329                         u8  p_frag;
 330                         u16 p_cpg;
 331                 } d_partitions[8];
 332         } * label;
 333         struct d_partition * partition;
 334 #define DISKLABELMAGIC (0x82564557UL)
 335 
 336         if (!(bh = bread(dev,0,1024))) {
 337                 printk("unable to read partition table\n");
 338                 return -1;
 339         }
 340         label = (struct disklabel *) (bh->b_data+64);
 341         partition = label->d_partitions;
 342         if (label->d_magic != DISKLABELMAGIC) {
 343                 printk("magic: %08x\n", label->d_magic);
 344                 brelse(bh);
 345                 return 0;
 346         }
 347         if (label->d_magic2 != DISKLABELMAGIC) {
 348                 printk("magic2: %08x\n", label->d_magic2);
 349                 brelse(bh);
 350                 return 0;
 351         }
 352         for (i = 0 ; i < label->d_npartitions; i++, partition++) {
 353                 if ((current_minor & mask) == 0)
 354                         break;
 355                 if (partition->p_size)
 356                         add_partition(hd, current_minor,
 357                                 first_sector+partition->p_offset,
 358                                 partition->p_size);
 359                 current_minor++;
 360         }
 361         printk("\n");
 362         brelse(bh);
 363         return 1;
 364 }
 365 
 366 #endif /* CONFIG_OSF_PARTITION */
 367 
 368 static void check_partition(struct gendisk *hd, kdev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 369 {
 370         static int first_time = 1;
 371         unsigned long first_sector;
 372 
 373         if (first_time)
 374                 printk("Partition check:\n");
 375         first_time = 0;
 376         first_sector = hd->part[MINOR(dev)].start_sect;
 377 
 378         /*
 379          * This is a kludge to allow the partition check to be
 380          * skipped for specific drives (e.g. IDE cd-rom drives)
 381          */
 382         if ((int)first_sector == -1) {
 383                 hd->part[MINOR(dev)].start_sect = 0;
 384                 return;
 385         }
 386 
 387         printk(" ");
 388         print_minor_name(hd, MINOR(dev));
 389 #ifdef CONFIG_MSDOS_PARTITION
 390         if (msdos_partition(hd, dev, first_sector))
 391                 return;
 392 #endif
 393 #ifdef CONFIG_OSF_PARTITION
 394         if (osf_partition(hd, dev, first_sector))
 395                 return;
 396 #endif
 397         printk(" unknown partition table\n");
 398 }
 399 
 400 /* This function is used to re-read partition tables for removable disks.
 401    Much of the cleanup from the old partition tables should have already been
 402    done */
 403 
 404 /* This function will re-read the partition tables for a given device,
 405 and set things back up again.  There are some important caveats,
 406 however.  You must ensure that no one is using the device, and no one
 407 can start using the device while this function is being executed. */
 408 
 409 void resetup_one_dev(struct gendisk *dev, int drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 410 {
 411         int i;
 412         int first_minor = drive << dev->minor_shift;
 413         int end_minor   = first_minor + dev->max_p;
 414 
 415         blk_size[dev->major] = NULL;
 416         current_minor = 1 + first_minor;
 417         check_partition(dev, MKDEV(dev->major, first_minor));
 418 
 419         /*
 420          * We need to set the sizes array before we will be able to access
 421          * any of the partitions on this device.
 422          */
 423         if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
 424                 for (i = first_minor; i < end_minor; i++)
 425                         dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 426                 blk_size[dev->major] = dev->sizes;
 427         }
 428 }
 429 
 430 static void setup_dev(struct gendisk *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 431 {
 432         int i, drive;
 433         int end_minor   = dev->max_nr * dev->max_p;
 434 
 435         blk_size[dev->major] = NULL;
 436         for (i = 0 ; i < end_minor; i++) {
 437                 dev->part[i].start_sect = 0;
 438                 dev->part[i].nr_sects = 0;
 439         }
 440         dev->init(dev); 
 441         for (drive = 0 ; drive < dev->nr_real ; drive++) {
 442                 int first_minor = drive << dev->minor_shift;
 443                 current_minor = 1 + first_minor;
 444                 check_partition(dev, MKDEV(dev->major, first_minor));
 445         }
 446         if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
 447                 for (i = 0; i < end_minor; i++)
 448                         dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 449                 blk_size[dev->major] = dev->sizes;
 450         }
 451 }
 452 
 453 void device_setup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 454 {
 455         extern void console_map_init(void);
 456         struct gendisk *p;
 457         int nr=0;
 458 
 459         console_map_init();
 460 
 461         for (p = gendisk_head ; p ; p=p->next) {
 462                 setup_dev(p);
 463                 nr += p->nr_real;
 464         }
 465                 
 466         if (ramdisk_size)
 467                 rd_load();
 468 }

/* [previous][next][first][last][top][bottom][index][help] */