root/drivers/block/genhd.c

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

DEFINITIONS

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

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