root/drivers/block/genhd.c

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

DEFINITIONS

This source file includes following definitions.
  1. minor_name
  2. add_partition
  3. extended_partition
  4. check_partition
  5. resetup_one_dev
  6. setup_dev
  7. device_setup

   1 /*
   2  *  Code extracted from
   3  *  linux/kernel/hd.c
   4  *
   5  *  Copyright (C) 1991, 1992  Linus Torvalds
   6  */
   7 
   8 /*
   9  *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
  10  *  in the early extended-partition checks and added DM partitions
  11  */
  12 
  13 #include <linux/fs.h>
  14 #include <linux/genhd.h>
  15 #include <linux/kernel.h>
  16 #include <linux/major.h>
  17 
  18 struct gendisk *gendisk_head = NULL;
  19 
  20 static int current_minor = 0;
  21 extern int *blk_size[];
  22 extern void rd_load(void);
  23 extern int ramdisk_size;
  24 
  25 static char minor_name (struct gendisk *hd, int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27         char base_name = (hd->major == IDE1_MAJOR) ? 'c' : 'a';
  28         return base_name + (minor >> hd->minor_shift);
  29 }
  30 
  31 static void add_partition (struct gendisk *hd, int minor, int start, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33         hd->part[minor].start_sect = start;
  34         hd->part[minor].nr_sects   = size;
  35         printk(" %s%c%d", hd->major_name, minor_name(hd, minor),
  36                 minor & ((1 << hd->minor_shift) - 1));
  37 }
  38 /*
  39  * Create devices for each logical partition in an extended partition.
  40  * The logical partitions form a linked list, with each entry being
  41  * a partition table with two entries.  The first entry
  42  * is the real data partition (with a start relative to the partition
  43  * table start).  The second is a pointer to the next logical partition
  44  * (with a start relative to the entire extended partition).
  45  * We do not create a Linux partition for the partition tables, but
  46  * only for the actual data partitions.
  47  */
  48 
  49 static void extended_partition(struct gendisk *hd, int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51         struct buffer_head *bh;
  52         struct partition *p;
  53         unsigned long first_sector, this_sector;
  54         int mask = (1 << hd->minor_shift) - 1;
  55 
  56         first_sector = hd->part[MINOR(dev)].start_sect;
  57         this_sector = first_sector;
  58 
  59         while (1) {
  60                 if ((current_minor & mask) >= (4 + hd->max_p))
  61                         return;
  62                 if (!(bh = bread(dev,0,1024)))
  63                         return;
  64           /*
  65            * This block is from a device that we're about to stomp on.
  66            * So make sure nobody thinks this block is usable.
  67            */
  68                 bh->b_dirt = 0;
  69                 bh->b_uptodate = 0;
  70                 bh->b_req = 0;
  71                 if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
  72                         p = (struct partition *) (0x1BE + bh->b_data);
  73                 /*
  74                  * Process the first entry, which should be the real
  75                  * data partition.
  76                  */
  77                         if (p->sys_ind == EXTENDED_PARTITION || !p->nr_sects)
  78                                 goto done;  /* shouldn't happen */
  79                         add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
  80                         current_minor++;
  81                         p++;
  82                 /*
  83                  * Process the second entry, which should be a link
  84                  * to the next logical partition.  Create a minor
  85                  * for this just long enough to get the next partition
  86                  * table.  The minor will be reused for the real
  87                  * data partition.
  88                  */
  89                         if (p->sys_ind != EXTENDED_PARTITION ||
  90                             !(hd->part[current_minor].nr_sects = p->nr_sects))
  91                                 goto done;  /* no more logicals in this partition */
  92                         hd->part[current_minor].start_sect = first_sector + p->start_sect;
  93                         this_sector = first_sector + p->start_sect;
  94                         dev = ((hd->major) << 8) | current_minor;
  95                         brelse(bh);
  96                 } else
  97                         goto done;
  98         }
  99 done:
 100         brelse(bh);
 101 }
 102 
 103 static void check_partition(struct gendisk *hd, unsigned int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         static int first_time = 1;
 106         int i, minor = current_minor;
 107         struct buffer_head *bh;
 108         struct partition *p;
 109         unsigned long first_sector;
 110         int mask = (1 << hd->minor_shift) - 1;
 111 
 112         if (first_time)
 113                 printk("Partition check:\n");
 114         first_time = 0;
 115         first_sector = hd->part[MINOR(dev)].start_sect;
 116 
 117         /*
 118          * This is a kludge to allow the partition check to be
 119          * skipped for specific drives (ie. IDE cd-rom drives)
 120          */
 121         if ((int)first_sector == -1) {
 122                 hd->part[MINOR(dev)].start_sect = 0;
 123                 return;
 124         }
 125 
 126         if (!(bh = bread(dev,0,1024))) {
 127                 printk("  unable to read partition table of device %04x\n",dev);
 128                 return;
 129         }
 130         printk("  %s%c:", hd->major_name, minor_name(hd, minor));
 131         current_minor += 4;  /* first "extra" minor (for extended partitions) */
 132         if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
 133                 p = (struct partition *) (0x1BE + bh->b_data);
 134                 for (i=1 ; i<=4 ; minor++,i++,p++) {
 135                         if (!p->nr_sects)
 136                                 continue;
 137                         add_partition(hd, minor, first_sector+p->start_sect, p->nr_sects);
 138                         if ((current_minor & 0x3f) >= 60)
 139                                 continue;
 140                         if (p->sys_ind == EXTENDED_PARTITION) {
 141                                 printk(" <");
 142                                 extended_partition(hd, (hd->major << 8) | minor);
 143                                 printk(" >");
 144                         }
 145                 }
 146                 /*
 147                  * check for Disk Manager partition table
 148                  */
 149                 if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
 150                         p = (struct partition *) (0x1BE + bh->b_data);
 151                         for (i = 4 ; i < 16 ; i++, current_minor++) {
 152                                 p--;
 153                                 if ((current_minor & mask) >= mask-2)
 154                                         break;
 155                                 if (!(p->start_sect && p->nr_sects))
 156                                         continue;
 157                                 add_partition(hd, current_minor, p->start_sect, p->nr_sects);
 158                         }
 159                 }
 160         } else
 161                 printk(" bad partition table");
 162         printk("\n");
 163         brelse(bh);
 164 }
 165 
 166 /* This function is used to re-read partition tables for removable disks.
 167    Much of the cleanup from the old partition tables should have already been
 168    done */
 169 
 170 /* This function will re-read the partition tables for a given device,
 171 and set things back up again.  There are some important caveats,
 172 however.  You must ensure that no one is using the device, and no one
 173 can start using the device while this function is being executed. */
 174 
 175 void resetup_one_dev(struct gendisk *dev, int drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177         int i;
 178         int start = drive<<dev->minor_shift;
 179         int j = start + dev->max_p;
 180         int major = dev->major << 8;
 181 
 182         current_minor = 1+(drive<<dev->minor_shift);
 183         check_partition(dev, major+(drive<<dev->minor_shift));
 184 
 185         for (i=start ; i < j ; i++)
 186                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 187 }
 188 
 189 static void setup_dev(struct gendisk *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191         int i;
 192         int j = dev->max_nr * dev->max_p;
 193         int major = dev->major << 8;
 194         int drive;
 195         
 196 
 197         for (i = 0 ; i < j; i++)  {
 198                 dev->part[i].start_sect = 0;
 199                 dev->part[i].nr_sects = 0;
 200         }
 201         dev->init();    
 202         for (drive=0 ; drive<dev->nr_real ; drive++) {
 203                 current_minor = 1+(drive<<dev->minor_shift);
 204                 check_partition(dev, major+(drive<<dev->minor_shift));
 205         }
 206         for (i=0 ; i < j ; i++)
 207                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 208         blk_size[dev->major] = dev->sizes;
 209 }
 210         
 211 void device_setup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213         struct gendisk *p;
 214         int nr=0;
 215 
 216         for (p = gendisk_head ; p ; p=p->next) {
 217                 setup_dev(p);
 218                 nr += p->nr_real;
 219         }
 220                 
 221         if (ramdisk_size)
 222                 rd_load();
 223 }

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