root/drivers/block/genhd.c

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

DEFINITIONS

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

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

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