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                         hd->sizes[current_minor] = p->nr_sects >> (BLOCK_SIZE_BITS - 9);
  94                         this_sector = first_sector + p->start_sect;
  95                         dev = ((hd->major) << 8) | current_minor;
  96                         brelse(bh);
  97                 } else
  98                         goto done;
  99         }
 100 done:
 101         brelse(bh);
 102 }
 103 
 104 static void check_partition(struct gendisk *hd, unsigned int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 105 {
 106         static int first_time = 1;
 107         int i, minor = current_minor;
 108         struct buffer_head *bh;
 109         struct partition *p;
 110         unsigned long first_sector;
 111         int mask = (1 << hd->minor_shift) - 1;
 112 
 113         if (first_time)
 114                 printk("Partition check:\n");
 115         first_time = 0;
 116         first_sector = hd->part[MINOR(dev)].start_sect;
 117 
 118         /*
 119          * This is a kludge to allow the partition check to be
 120          * skipped for specific drives (ie. IDE cd-rom drives)
 121          */
 122         if ((int)first_sector == -1) {
 123                 hd->part[MINOR(dev)].start_sect = 0;
 124                 return;
 125         }
 126 
 127         if (!(bh = bread(dev,0,1024))) {
 128                 printk("  unable to read partition table of device %04x\n",dev);
 129                 return;
 130         }
 131         printk("  %s%c:", hd->major_name, minor_name(hd, minor));
 132         current_minor += 4;  /* first "extra" minor (for extended partitions) */
 133         if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
 134                 p = (struct partition *) (0x1BE + bh->b_data);
 135                 for (i=1 ; i<=4 ; minor++,i++,p++) {
 136                         if (!p->nr_sects)
 137                                 continue;
 138                         add_partition(hd, minor, first_sector+p->start_sect, p->nr_sects);
 139                         if ((current_minor & 0x3f) >= 60)
 140                                 continue;
 141                         if (p->sys_ind == EXTENDED_PARTITION) {
 142                                 printk(" <");
 143                                 extended_partition(hd, (hd->major << 8) | minor);
 144                                 printk(" >");
 145                         }
 146                 }
 147                 /*
 148                  * check for Disk Manager partition table
 149                  */
 150                 if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
 151                         p = (struct partition *) (0x1BE + bh->b_data);
 152                         for (i = 4 ; i < 16 ; i++, current_minor++) {
 153                                 p--;
 154                                 if ((current_minor & mask) >= mask-2)
 155                                         break;
 156                                 if (!(p->start_sect && p->nr_sects))
 157                                         continue;
 158                                 add_partition(hd, current_minor, p->start_sect, p->nr_sects);
 159                         }
 160                 }
 161         } else
 162                 printk(" bad partition table");
 163         printk("\n");
 164         brelse(bh);
 165 }
 166 
 167 /* This function is used to re-read partition tables for removable disks.
 168    Much of the cleanup from the old partition tables should have already been
 169    done */
 170 
 171 /* This function will re-read the partition tables for a given device,
 172 and set things back up again.  There are some important caveats,
 173 however.  You must ensure that no one is using the device, and no one
 174 can start using the device while this function is being executed. */
 175 
 176 void resetup_one_dev(struct gendisk *dev, int drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 177 {
 178         int i;
 179         int start = drive<<dev->minor_shift;
 180         int j = start + dev->max_p;
 181         int major = dev->major << 8;
 182 
 183         current_minor = 1+(drive<<dev->minor_shift);
 184         check_partition(dev, major+(drive<<dev->minor_shift));
 185 
 186         for (i=start ; i < j ; i++)
 187                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 188 }
 189 
 190 static void setup_dev(struct gendisk *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192         int i;
 193         int j = dev->max_nr * dev->max_p;
 194         int major = dev->major << 8;
 195         int drive;
 196         
 197 
 198         for (i = 0 ; i < j; i++)  {
 199                 dev->part[i].start_sect = 0;
 200                 dev->part[i].nr_sects = 0;
 201         }
 202         dev->init();    
 203         for (drive=0 ; drive<dev->nr_real ; drive++) {
 204                 current_minor = 1+(drive<<dev->minor_shift);
 205                 check_partition(dev, major+(drive<<dev->minor_shift));
 206         }
 207         for (i=0 ; i < j ; i++)
 208                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 209         blk_size[dev->major] = dev->sizes;
 210 }
 211         
 212 void device_setup(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214         struct gendisk *p;
 215         int nr=0;
 216 
 217         for (p = gendisk_head ; p ; p=p->next) {
 218                 setup_dev(p);
 219                 nr += p->nr_real;
 220         }
 221                 
 222         if (ramdisk_size)
 223                 rd_load();
 224 }

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