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. is_extended_partition
  4. extended_partition
  5. msdos_partition
  6. osf_partition
  7. sun_partition
  8. check_partition
  9. resetup_one_dev
  10. setup_dev
  11. 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 #include <asm/system.h>
  27 
  28 #ifdef __alpha__
  29 /*
  30  * On the Alpha, we get unaligned access exceptions on
  31  *  p->nr_sects and p->start_sect, when the partition table
  32  *  is not on a 4-byte boundary, which is frequently the case.
  33  * This code uses unaligned load instructions to prevent
  34  *  such exceptions.
  35  */
  36 #include <asm/unaligned.h>
  37 #define NR_SECTS(p)     ldl_u(&p->nr_sects)
  38 #define START_SECT(p)   ldl_u(&p->start_sect)
  39 #else /* __alpha__ */
  40 #define NR_SECTS(p)     p->nr_sects
  41 #define START_SECT(p)   p->start_sect
  42 #endif /* __alpha__ */
  43 
  44 struct gendisk *gendisk_head = NULL;
  45 
  46 static int current_minor = 0;
  47 extern int *blk_size[];
  48 extern void rd_load(void);
  49 
  50 extern int chr_dev_init(void);
  51 extern int blk_dev_init(void);
  52 extern int scsi_dev_init(void);
  53 extern int net_dev_init(void);
  54 
  55 static void print_minor_name (struct gendisk *hd, int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57         unsigned int unit = minor >> hd->minor_shift;
  58         unsigned int part = minor & ((1 << hd->minor_shift) - 1);
  59 
  60 #ifdef CONFIG_BLK_DEV_IDE
  61         /*
  62          * IDE devices use multiple major numbers, but the drives
  63          * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
  64          * This requires some creative handling here to find the
  65          * correct name to use, with some help from ide.c
  66          */
  67         if (!strcmp(hd->major_name,"ide")) {
  68                 char name[16];          /* more than large enough */
  69                 strcpy(name, hd->real_devices); /* courtesy ide.c */
  70                 name[strlen(name)-1] += unit;
  71                 printk(" %s", name);
  72         } else
  73 #endif
  74                 printk(" %s%c", hd->major_name, 'a' + unit);
  75         if (part)
  76                 printk("%d", part);
  77         else
  78                 printk(":");
  79 }
  80 
  81 static void add_partition (struct gendisk *hd, int minor, int start, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         hd->part[minor].start_sect = start;
  84         hd->part[minor].nr_sects   = size;
  85         print_minor_name(hd, minor);
  86 }
  87 
  88 static inline int is_extended_partition(struct partition *p)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90         return (p->sys_ind == DOS_EXTENDED_PARTITION ||
  91                 p->sys_ind == LINUX_EXTENDED_PARTITION);
  92 }
  93 
  94 #ifdef CONFIG_MSDOS_PARTITION
  95 /*
  96  * Create devices for each logical partition in an extended partition.
  97  * The logical partitions form a linked list, with each entry being
  98  * a partition table with two entries.  The first entry
  99  * is the real data partition (with a start relative to the partition
 100  * table start).  The second is a pointer to the next logical partition
 101  * (with a start relative to the entire extended partition).
 102  * We do not create a Linux partition for the partition tables, but
 103  * only for the actual data partitions.
 104  */
 105 
 106 static void extended_partition(struct gendisk *hd, kdev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108         struct buffer_head *bh;
 109         struct partition *p;
 110         unsigned long first_sector, first_size, this_sector, this_size;
 111         int mask = (1 << hd->minor_shift) - 1;
 112         int i;
 113 
 114         first_sector = hd->part[MINOR(dev)].start_sect;
 115         first_size = hd->part[MINOR(dev)].nr_sects;
 116         this_sector = first_sector;
 117 
 118         while (1) {
 119                 if ((current_minor & mask) == 0)
 120                         return;
 121                 if (!(bh = bread(dev,0,1024)))
 122                         return;
 123           /*
 124            * This block is from a device that we're about to stomp on.
 125            * So make sure nobody thinks this block is usable.
 126            */
 127                 bh->b_state = 0;
 128 
 129                 if (*(unsigned short *) (bh->b_data+510) != 0xAA55)
 130                         goto done;
 131 
 132                 p = (struct partition *) (0x1BE + bh->b_data);
 133 
 134                 this_size = hd->part[MINOR(dev)].nr_sects;
 135 
 136                 /*
 137                  * Usually, the first entry is the real data partition,
 138                  * the 2nd entry is the next extended partition, or empty,
 139                  * and the 3rd and 4th entries are unused.
 140                  * However, DRDOS sometimes has the extended partition as
 141                  * the first entry (when the data partition is empty),
 142                  * and OS/2 seems to use all four entries.
 143                  */
 144 
 145                 /* 
 146                  * First process the data partition(s)
 147                  */
 148                 for (i=0; i<4; i++, p++) {
 149                     if (!NR_SECTS(p) || is_extended_partition(p))
 150                       continue;
 151 
 152                     /* Check the 3rd and 4th entries -
 153                        these sometimes contain random garbage */
 154                     if (i >= 2
 155                         && START_SECT(p) + NR_SECTS(p) > this_size
 156                         && (this_sector + START_SECT(p) < first_sector ||
 157                             this_sector + START_SECT(p) + NR_SECTS(p) >
 158                              first_sector + first_size))
 159                       continue;
 160 
 161                     add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
 162                     current_minor++;
 163                     if ((current_minor & mask) == 0)
 164                       goto done;
 165                 }
 166                 /*
 167                  * Next, process the (first) extended partition, if present.
 168                  * (So far, there seems to be no reason to make
 169                  *  extended_partition()  recursive and allow a tree
 170                  *  of extended partitions.)
 171                  * It should be a link to the next logical partition.
 172                  * Create a minor for this just long enough to get the next
 173                  * partition table.  The minor will be reused for the next
 174                  * data partition.
 175                  */
 176                 p -= 4;
 177                 for (i=0; i<4; i++, p++)
 178                   if(NR_SECTS(p) && is_extended_partition(p))
 179                     break;
 180                 if (i == 4)
 181                   goto done;     /* nothing left to do */
 182 
 183                 hd->part[current_minor].nr_sects = NR_SECTS(p);
 184                 hd->part[current_minor].start_sect = first_sector + START_SECT(p);
 185                 this_sector = first_sector + START_SECT(p);
 186                 dev = MKDEV(hd->major, current_minor);
 187                 brelse(bh);
 188         }
 189 done:
 190         brelse(bh);
 191 }
 192 
 193 static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
     /* [previous][next][first][last][top][bottom][index][help] */
 194 {
 195         int i, minor = current_minor;
 196         struct buffer_head *bh;
 197         struct partition *p;
 198         unsigned char *data;
 199         int mask = (1 << hd->minor_shift) - 1;
 200 #ifdef CONFIG_BLK_DEV_IDE
 201         int tested_for_dm6 = 0;
 202 
 203 read_mbr:
 204 #endif
 205         if (!(bh = bread(dev,0,1024))) {
 206                 printk(" unable to read partition table\n");
 207                 return -1;
 208         }
 209         data = bh->b_data;
 210         /* In some cases we modify the geometry    */
 211         /*  of the drive (below), so ensure that   */
 212         /*  nobody else tries to re-use this data. */
 213         bh->b_state = 0;
 214 #ifdef CONFIG_BLK_DEV_IDE
 215 check_table:
 216 #endif
 217         if (*(unsigned short *)  (0x1fe + data) != 0xAA55) {
 218                 brelse(bh);
 219                 return 0;
 220         }
 221         p = (struct partition *) (0x1be + data);
 222 
 223 #ifdef CONFIG_BLK_DEV_IDE
 224         /*
 225          *  Check for Disk Manager v6.0x (or EZ-DRIVE) with geometry translation
 226          */
 227         if (!tested_for_dm6++) {        /* only check for DM6 *once* */
 228                 extern int ide_xlate_1024(kdev_t, int, const char *);
 229                 /* check for various "disk managers" which do strange things */
 230                 if (p->sys_ind == EZD_PARTITION) {
 231                         /*
 232                          * The remainder of the disk must be accessed using
 233                          * a translated geometry that reduces the number of 
 234                          * apparent cylinders to less than 1024 if possible.
 235                          *
 236                          * ide_xlate_1024() will take care of the necessary
 237                          * adjustments to fool fdisk/LILO and partition check.
 238                          */
 239                         if (ide_xlate_1024(dev, -1, " [EZD]")) {
 240                                 data += 512;
 241                                 goto check_table;
 242                         }
 243                 } else if (p->sys_ind == DM6_PARTITION) {
 244 
 245                         /*
 246                          * Everything on the disk is offset by 63 sectors,
 247                          * including a "new" MBR with its own partition table,
 248                          * and the remainder of the disk must be accessed using
 249                          * a translated geometry that reduces the number of 
 250                          * apparent cylinders to less than 1024 if possible.
 251                          *
 252                          * ide_xlate_1024() will take care of the necessary
 253                          * adjustments to fool fdisk/LILO and partition check.
 254                          */
 255                         if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
 256                                 brelse(bh);
 257                                 goto read_mbr;  /* start over with new MBR */
 258                         }
 259                 } else {
 260                         /* look for DM6 signature in MBR, courtesy of OnTrack */
 261                         unsigned int sig = *(unsigned short *)(data + 2);
 262                         if (sig <= 0x1ae
 263                          && *(unsigned short *)(data + sig) == 0x55AA
 264                          && (1 & *(unsigned char *)(data + sig + 2)) ) 
 265                         {
 266                                 (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
 267                         } else {
 268                                 /* look for DM6 AUX partition type in slot 1 */
 269                                 if (p->sys_ind == DM6_AUX1PARTITION
 270                                  || p->sys_ind == DM6_AUX3PARTITION)
 271                                 {
 272                                         (void)ide_xlate_1024(dev, 0, " [DM6:AUX]");
 273                                 }
 274                         }
 275                 }
 276         }
 277 #endif  /* CONFIG_BLK_DEV_IDE */
 278 
 279         current_minor += 4;  /* first "extra" minor (for extended partitions) */
 280         for (i=1 ; i<=4 ; minor++,i++,p++) {
 281                 if (!NR_SECTS(p))
 282                         continue;
 283                 add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
 284                 if (is_extended_partition(p)) {
 285                         printk(" <");
 286                         /*
 287                          * If we are rereading the partition table, we need
 288                          * to set the size of the partition so that we will
 289                          * be able to bread the block containing the extended
 290                          * partition info.
 291                          */
 292                         hd->sizes[minor] = hd->part[minor].nr_sects 
 293                                 >> (BLOCK_SIZE_BITS - 9);
 294                         extended_partition(hd, MKDEV(hd->major, minor));
 295                         printk(" >");
 296                         /* prevent someone doing mkfs or mkswap on an
 297                            extended partition, but leave room for LILO */
 298                         if (hd->part[minor].nr_sects > 2)
 299                                 hd->part[minor].nr_sects = 2;
 300                 }
 301         }
 302         /*
 303          *  Check for old-style Disk Manager partition table
 304          */
 305         if (*(unsigned short *) (data+0xfc) == 0x55AA) {
 306                 p = (struct partition *) (0x1be + data);
 307                 for (i = 4 ; i < 16 ; i++, current_minor++) {
 308                         p--;
 309                         if ((current_minor & mask) == 0)
 310                                 break;
 311                         if (!(START_SECT(p) && NR_SECTS(p)))
 312                                 continue;
 313                         add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
 314                 }
 315         }
 316         printk("\n");
 317         brelse(bh);
 318         return 1;
 319 }
 320 
 321 #endif /* CONFIG_MSDOS_PARTITION */
 322 
 323 #ifdef CONFIG_OSF_PARTITION
 324 
 325 static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
     /* [previous][next][first][last][top][bottom][index][help] */
 326 {
 327         int i;
 328         int mask = (1 << hd->minor_shift) - 1;
 329         struct buffer_head *bh;
 330         struct disklabel {
 331                 u32 d_magic;
 332                 u16 d_type,d_subtype;
 333                 u8 d_typename[16];
 334                 u8 d_packname[16];
 335                 u32 d_secsize;
 336                 u32 d_nsectors;
 337                 u32 d_ntracks;
 338                 u32 d_ncylinders;
 339                 u32 d_secpercyl;
 340                 u32 d_secprtunit;
 341                 u16 d_sparespertrack;
 342                 u16 d_sparespercyl;
 343                 u32 d_acylinders;
 344                 u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
 345                 u32 d_headswitch, d_trkseek, d_flags;
 346                 u32 d_drivedata[5];
 347                 u32 d_spare[5];
 348                 u32 d_magic2;
 349                 u16 d_checksum;
 350                 u16 d_npartitions;
 351                 u32 d_bbsize, d_sbsize;
 352                 struct d_partition {
 353                         u32 p_size;
 354                         u32 p_offset;
 355                         u32 p_fsize;
 356                         u8  p_fstype;
 357                         u8  p_frag;
 358                         u16 p_cpg;
 359                 } d_partitions[8];
 360         } * label;
 361         struct d_partition * partition;
 362 #define DISKLABELMAGIC (0x82564557UL)
 363 
 364         if (!(bh = bread(dev,0,1024))) {
 365                 printk("unable to read partition table\n");
 366                 return -1;
 367         }
 368         label = (struct disklabel *) (bh->b_data+64);
 369         partition = label->d_partitions;
 370         if (label->d_magic != DISKLABELMAGIC) {
 371                 printk("magic: %08x\n", label->d_magic);
 372                 brelse(bh);
 373                 return 0;
 374         }
 375         if (label->d_magic2 != DISKLABELMAGIC) {
 376                 printk("magic2: %08x\n", label->d_magic2);
 377                 brelse(bh);
 378                 return 0;
 379         }
 380         for (i = 0 ; i < label->d_npartitions; i++, partition++) {
 381                 if ((current_minor & mask) == 0)
 382                         break;
 383                 if (partition->p_size)
 384                         add_partition(hd, current_minor,
 385                                 first_sector+partition->p_offset,
 386                                 partition->p_size);
 387                 current_minor++;
 388         }
 389         printk("\n");
 390         brelse(bh);
 391         return 1;
 392 }
 393 
 394 #endif /* CONFIG_OSF_PARTITION */
 395 
 396 #ifdef CONFIG_SUN_PARTITION
 397 
 398 static int sun_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400         int i, csum;
 401         unsigned short *ush;
 402         struct buffer_head *bh;
 403         struct sun_disklabel {
 404                 unsigned char info[128];   /* Informative text string */
 405                 unsigned char spare[292];  /* Boot information etc. */
 406                 unsigned short rspeed;     /* Disk rotational speed */
 407                 unsigned short pcylcount;  /* Physical cylinder count */
 408                 unsigned short sparecyl;   /* extra sects per cylinder */
 409                 unsigned char spare2[4];   /* More magic... */
 410                 unsigned short ilfact;     /* Interleave factor */
 411                 unsigned short ncyl;       /* Data cylinder count */
 412                 unsigned short nacyl;      /* Alt. cylinder count */
 413                 unsigned short ntrks;      /* Tracks per cylinder */
 414                 unsigned short nsect;      /* Sectors per track */
 415                 unsigned char spare3[4];   /* Even more magic... */
 416                 struct sun_partition {
 417                         unsigned long start_cylinder;
 418                         unsigned long num_sectors;
 419                 } partitions[8];
 420                 unsigned short magic;      /* Magic number */
 421                 unsigned short csum;       /* Label xor'd checksum */
 422         } * label;              
 423         struct sun_partition *p;
 424         unsigned long spc;
 425 #define SUN_LABEL_MAGIC  0xDABE
 426 
 427         if(!(bh = bread(dev, 0, 1024))) {
 428                 printk("Dev %d: unable to read partition table\n", dev);
 429                 return -1;
 430         }
 431         label = (struct sun_disklabel *) bh->b_data;
 432         p = label->partitions;
 433         if(label->magic != SUN_LABEL_MAGIC) {
 434                 printk("Dev %d Sun disklabel: bad magic %08x\n", dev, label->magic);
 435                 brelse(bh);
 436                 return 0;
 437         }
 438         /* Look at the checksum */
 439         ush = ((unsigned short *) (label+1)) - 1;
 440         for(csum = 0; ush >= ((unsigned short *) label);)
 441                 csum ^= *ush--;
 442         if(csum) {
 443                 printk("Dev %d Sun disklabel: Csum bad, label corrupted\n", dev);
 444                 brelse(bh);
 445                 return 0;
 446         }
 447         /* All Sun disks have 8 partition entries */
 448         spc = (label->ntrks * label->nsect);
 449         for(i=0; i < 8; i++, p++) {
 450                 unsigned long st_sector;
 451 
 452                 /* We register all partitions, even if zero size, so that
 453                  * the minor numbers end up ok as per SunOS interpretation.
 454                  */
 455                 st_sector = first_sector + (p->start_cylinder * spc);
 456                 add_partition(hd, current_minor, st_sector, p->num_sectors);
 457                 current_minor++;
 458         }
 459         printk("\n");
 460         brelse(bh);
 461         return 1;
 462 }
 463 
 464 #endif /* CONFIG_SUN_PARTITION */
 465 
 466 static void check_partition(struct gendisk *hd, kdev_t dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 467 {
 468         static int first_time = 1;
 469         unsigned long first_sector;
 470 
 471         if (first_time)
 472                 printk("Partition check:\n");
 473         first_time = 0;
 474         first_sector = hd->part[MINOR(dev)].start_sect;
 475 
 476         /*
 477          * This is a kludge to allow the partition check to be
 478          * skipped for specific drives (e.g. IDE cd-rom drives)
 479          */
 480         if ((int)first_sector == -1) {
 481                 hd->part[MINOR(dev)].start_sect = 0;
 482                 return;
 483         }
 484 
 485         printk(" ");
 486         print_minor_name(hd, MINOR(dev));
 487 #ifdef CONFIG_MSDOS_PARTITION
 488         if (msdos_partition(hd, dev, first_sector))
 489                 return;
 490 #endif
 491 #ifdef CONFIG_OSF_PARTITION
 492         if (osf_partition(hd, dev, first_sector))
 493                 return;
 494 #endif
 495 #ifdef CONFIG_SUN_PARTITION
 496         if(sun_partition(hd, dev, first_sector))
 497                 return;
 498 #endif
 499         printk(" unknown partition table\n");
 500 }
 501 
 502 /* This function is used to re-read partition tables for removable disks.
 503    Much of the cleanup from the old partition tables should have already been
 504    done */
 505 
 506 /* This function will re-read the partition tables for a given device,
 507 and set things back up again.  There are some important caveats,
 508 however.  You must ensure that no one is using the device, and no one
 509 can start using the device while this function is being executed. */
 510 
 511 void resetup_one_dev(struct gendisk *dev, int drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 512 {
 513         int i;
 514         int first_minor = drive << dev->minor_shift;
 515         int end_minor   = first_minor + dev->max_p;
 516 
 517         blk_size[dev->major] = NULL;
 518         current_minor = 1 + first_minor;
 519         check_partition(dev, MKDEV(dev->major, first_minor));
 520 
 521         /*
 522          * We need to set the sizes array before we will be able to access
 523          * any of the partitions on this device.
 524          */
 525         if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
 526                 for (i = first_minor; i < end_minor; i++)
 527                         dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 528                 blk_size[dev->major] = dev->sizes;
 529         }
 530 }
 531 
 532 static void setup_dev(struct gendisk *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 533 {
 534         int i, drive;
 535         int end_minor   = dev->max_nr * dev->max_p;
 536 
 537         blk_size[dev->major] = NULL;
 538         for (i = 0 ; i < end_minor; i++) {
 539                 dev->part[i].start_sect = 0;
 540                 dev->part[i].nr_sects = 0;
 541         }
 542         dev->init(dev); 
 543         for (drive = 0 ; drive < dev->nr_real ; drive++) {
 544                 int first_minor = drive << dev->minor_shift;
 545                 current_minor = 1 + first_minor;
 546                 check_partition(dev, MKDEV(dev->major, first_minor));
 547         }
 548         if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
 549                 for (i = 0; i < end_minor; i++)
 550                         dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 551                 blk_size[dev->major] = dev->sizes;
 552         }
 553 }
 554 
 555 void device_setup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 556 {
 557         extern void console_map_init(void);
 558         struct gendisk *p;
 559         int nr=0;
 560 
 561         chr_dev_init();
 562         blk_dev_init();
 563         sti();
 564 #ifdef CONFIG_SCSI
 565         scsi_dev_init();
 566 #endif
 567 #ifdef CONFIG_INET
 568         net_dev_init();
 569 #endif
 570         console_map_init();
 571 
 572         for (p = gendisk_head ; p ; p=p->next) {
 573                 setup_dev(p);
 574                 nr += p->nr_real;
 575         }
 576 #ifdef CONFIG_BLK_DEV_RAM
 577         rd_load();
 578 #endif
 579 }

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