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

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