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                         extended_partition(hd, (hd->major << 8) | minor);
 238                         printk(" >");
 239                         /* prevent someone doing mkfs or mkswap on
 240                            an extended partition */
 241                         hd->part[minor].nr_sects = 0;
 242                 }
 243         }
 244         /*
 245          *  Check for old-style Disk Manager partition table
 246          */
 247         if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
 248                 p = (struct partition *) (0x1be + bh->b_data);
 249                 for (i = 4 ; i < 16 ; i++, current_minor++) {
 250                         p--;
 251                         if ((current_minor & mask) >= mask-2)
 252                                 break;
 253                         if (!(p->start_sect && p->nr_sects))
 254                                 continue;
 255                         add_partition(hd, current_minor, p->start_sect, p->nr_sects);
 256                 }
 257         }
 258         printk("\n");
 259         brelse(bh);
 260         return 1;
 261 }
 262 
 263 #endif /* CONFIG_MSDOS_PARTITION */
 264 
 265 #ifdef CONFIG_OSF_PARTITION
 266 
 267 static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
     /* [previous][next][first][last][top][bottom][index][help] */
 268 {
 269         int i;
 270         struct buffer_head *bh;
 271         struct disklabel {
 272                 u32 d_magic;
 273                 u16 d_type,d_subtype;
 274                 u8 d_typename[16];
 275                 u8 d_packname[16];
 276                 u32 d_secsize;
 277                 u32 d_nsectors;
 278                 u32 d_ntracks;
 279                 u32 d_ncylinders;
 280                 u32 d_secpercyl;
 281                 u32 d_secprtunit;
 282                 u16 d_sparespertrack;
 283                 u16 d_sparespercyl;
 284                 u32 d_acylinders;
 285                 u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
 286                 u32 d_headswitch, d_trkseek, d_flags;
 287                 u32 d_drivedata[5];
 288                 u32 d_spare[5];
 289                 u32 d_magic2;
 290                 u16 d_checksum;
 291                 u16 d_npartitions;
 292                 u32 d_bbsize, d_sbsize;
 293                 struct d_partition {
 294                         u32 p_size;
 295                         u32 p_offset;
 296                         u32 p_fsize;
 297                         u8  p_fstype;
 298                         u8  p_frag;
 299                         u16 p_cpg;
 300                 } d_partitions[8];
 301         } * label;
 302         struct d_partition * partition;
 303 #define DISKLABELMAGIC (0x82564557UL)
 304 
 305         if (!(bh = bread(dev,0,1024))) {
 306                 printk("unable to read partition table\n");
 307                 return -1;
 308         }
 309         label = (struct disklabel *) (bh->b_data+64);
 310         partition = label->d_partitions;
 311         if (label->d_magic != DISKLABELMAGIC) {
 312                 printk("magic: %08x\n", label->d_magic);
 313                 brelse(bh);
 314                 return 0;
 315         }
 316         if (label->d_magic2 != DISKLABELMAGIC) {
 317                 printk("magic2: %08x\n", label->d_magic2);
 318                 brelse(bh);
 319                 return 0;
 320         }
 321         for (i = 0 ; i < label->d_npartitions; i++, partition++) {
 322                 if (partition->p_size)
 323                         add_partition(hd, current_minor,
 324                                 first_sector+partition->p_offset,
 325                                 partition->p_size);
 326                 current_minor++;
 327         }
 328         printk("\n");
 329         brelse(bh);
 330         return 1;
 331 }
 332 
 333 #endif /* CONFIG_OSF_PARTITION */
 334 
 335 static void check_partition(struct gendisk *hd, unsigned int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 336 {
 337         static int first_time = 1;
 338         unsigned long first_sector;
 339 
 340         if (first_time)
 341                 printk("Partition check:\n");
 342         first_time = 0;
 343         first_sector = hd->part[MINOR(dev)].start_sect;
 344 
 345         /*
 346          * This is a kludge to allow the partition check to be
 347          * skipped for specific drives (ie. IDE cd-rom drives)
 348          */
 349         if ((int)first_sector == -1) {
 350                 hd->part[MINOR(dev)].start_sect = 0;
 351                 return;
 352         }
 353 
 354         printk(" ");
 355         print_minor_name(hd, MINOR(dev));
 356 #ifdef CONFIG_MSDOS_PARTITION
 357         if (msdos_partition(hd, dev, first_sector))
 358                 return;
 359 #endif
 360 #ifdef CONFIG_OSF_PARTITION
 361         if (osf_partition(hd, dev, first_sector))
 362                 return;
 363 #endif
 364         printk(" unknown partition table\n");
 365 }
 366 
 367 /* This function is used to re-read partition tables for removable disks.
 368    Much of the cleanup from the old partition tables should have already been
 369    done */
 370 
 371 /* This function will re-read the partition tables for a given device,
 372 and set things back up again.  There are some important caveats,
 373 however.  You must ensure that no one is using the device, and no one
 374 can start using the device while this function is being executed. */
 375 
 376 void resetup_one_dev(struct gendisk *dev, int drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 377 {
 378         int i;
 379         int major       = dev->major << 8;
 380         int first_minor = drive << dev->minor_shift;
 381         int end_minor   = first_minor + dev->max_p;
 382 
 383         blk_size[dev->major] = NULL;
 384         current_minor = 1 + first_minor;
 385         check_partition(dev, major + first_minor);
 386 
 387         if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
 388                 for (i = first_minor; i < end_minor; i++)
 389                         dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 390                 blk_size[dev->major] = dev->sizes;
 391         }
 392 }
 393 
 394 static void setup_dev(struct gendisk *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 395 {
 396         int i, drive;
 397         int major       = dev->major << 8;
 398         int end_minor   = dev->max_nr * dev->max_p;
 399 
 400         blk_size[dev->major] = NULL;
 401         for (i = 0 ; i < end_minor; i++) {
 402                 dev->part[i].start_sect = 0;
 403                 dev->part[i].nr_sects = 0;
 404         }
 405         dev->init(dev); 
 406         for (drive = 0 ; drive < dev->nr_real ; drive++) {
 407                 int first_minor = drive << dev->minor_shift;
 408                 current_minor = 1 + first_minor;
 409                 check_partition(dev, major + first_minor);
 410         }
 411         if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
 412                 for (i = 0; i < end_minor; i++)
 413                         dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 414                 blk_size[dev->major] = dev->sizes;
 415         }
 416 }
 417         
 418 void device_setup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 419 {
 420         struct gendisk *p;
 421         int nr=0;
 422 
 423         for (p = gendisk_head ; p ; p=p->next) {
 424                 setup_dev(p);
 425                 nr += p->nr_real;
 426         }
 427                 
 428         if (ramdisk_size)
 429                 rd_load();
 430 }

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