root/drivers/block/genhd.c

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

DEFINITIONS

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

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