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

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