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

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