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. sys_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                 if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
  58                         p = (struct partition *) (0x1BE + bh->b_data);
  59                 /*
  60                  * Process the first entry, which should be the real
  61                  * data partition.
  62                  */
  63                         if (p->sys_ind == EXTENDED_PARTITION ||
  64                             !(hd->part[current_minor].nr_sects = p->nr_sects))
  65                                 goto done;  /* shouldn't happen */
  66                         hd->part[current_minor].start_sect = this_sector + p->start_sect;
  67                         printk(" %s%c%d", hd->major_name,
  68                                 'a'+(current_minor >> hd->minor_shift),
  69                                 mask & current_minor);
  70                         current_minor++;
  71                         p++;
  72                 /*
  73                  * Process the second entry, which should be a link
  74                  * to the next logical partition.  Create a minor
  75                  * for this just long enough to get the next partition
  76                  * table.  The minor will be reused for the real
  77                  * data partition.
  78                  */
  79                         if (p->sys_ind != EXTENDED_PARTITION ||
  80                             !(hd->part[current_minor].nr_sects = p->nr_sects))
  81                                 goto done;  /* no more logicals in this partition */
  82                         hd->part[current_minor].start_sect = first_sector + p->start_sect;
  83                         this_sector = first_sector + p->start_sect;
  84                         dev = ((hd->major) << 8) | current_minor;
  85                         brelse(bh);
  86                 } else
  87                         goto done;
  88         }
  89 done:
  90         brelse(bh);
  91 }
  92 
  93 static void check_partition(struct gendisk *hd, unsigned int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  94 {
  95         static int first_time = 1;
  96         int i, minor = current_minor;
  97         struct buffer_head *bh;
  98         struct partition *p;
  99         unsigned long first_sector;
 100         int mask = (1 << hd->minor_shift) - 1;
 101 
 102         if (first_time)
 103                 printk("Partition check:\n");
 104         first_time = 0;
 105         first_sector = hd->part[MINOR(dev)].start_sect;
 106         if (!(bh = bread(dev,0,1024))) {
 107                 printk("  unable to read partition table of device %04x\n",dev);
 108                 return;
 109         }
 110         printk("  %s%c:", hd->major_name, 'a'+(minor >> hd->minor_shift));
 111         current_minor += 4;  /* first "extra" minor */
 112         if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
 113                 p = (struct partition *) (0x1BE + bh->b_data);
 114                 for (i=1 ; i<=4 ; minor++,i++,p++) {
 115                         if (!(hd->part[minor].nr_sects = p->nr_sects))
 116                                 continue;
 117                         hd->part[minor].start_sect = first_sector + p->start_sect;
 118                         printk(" %s%c%d", hd->major_name,'a'+(minor >> hd->minor_shift), i);
 119                         if ((current_minor & 0x3f) >= 60)
 120                                 continue;
 121                         if (p->sys_ind == EXTENDED_PARTITION) {
 122                                 printk(" <");
 123                                 extended_partition(hd, (hd->major << 8) | minor);
 124                                 printk(" >");
 125                         }
 126                 }
 127                 /*
 128                  * check for Disk Manager partition table
 129                  */
 130                 if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
 131                         p = (struct partition *) (0x1BE + bh->b_data);
 132                         for (i = 4 ; i < 16 ; i++, current_minor++) {
 133                                 p--;
 134                                 if ((current_minor & mask) >= mask-2)
 135                                         break;
 136                                 if (!(p->start_sect && p->nr_sects))
 137                                         continue;
 138                                 hd->part[current_minor].start_sect = p->start_sect;
 139                                 hd->part[current_minor].nr_sects = p->nr_sects;
 140                                 printk(" %s%c%d", hd->major_name,
 141                                         'a'+(current_minor >> hd->minor_shift),
 142                                         current_minor & mask);
 143                         }
 144                 }
 145         } else
 146                 printk(" bad partition table");
 147         printk("\n");
 148         brelse(bh);
 149 }
 150 
 151 /* This function is used to re-read partition tables for removable disks.
 152    Much of the cleanup from the old partition tables should have already been
 153    done */
 154 
 155 /* This function will re-read the partition tables for a given device,
 156 and set things back up again.  There are some important caveats,
 157 however.  You must ensure that no one is using the device, and no one
 158 can start using the device while this function is being executed. */
 159 
 160 void resetup_one_dev(struct gendisk *dev, int drive)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162         int i;
 163         int start = drive<<dev->minor_shift;
 164         int j = start + dev->max_p;
 165         int major = dev->major << 8;
 166 
 167         current_minor = 1+(drive<<dev->minor_shift);
 168         check_partition(dev, major+(drive<<dev->minor_shift));
 169 
 170         for (i=start ; i < j ; i++)
 171                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 172 }
 173 
 174 static void setup_dev(struct gendisk *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176         int i;
 177         int j = dev->max_nr * dev->max_p;
 178         int major = dev->major << 8;
 179         int drive;
 180         
 181 
 182         for (i = 0 ; i < j; i++)  {
 183                 dev->part[i].start_sect = 0;
 184                 dev->part[i].nr_sects = 0;
 185         }
 186         dev->init();    
 187         for (drive=0 ; drive<dev->nr_real ; drive++) {
 188                 current_minor = 1+(drive<<dev->minor_shift);
 189                 check_partition(dev, major+(drive<<dev->minor_shift));
 190         }
 191         for (i=0 ; i < j ; i++)
 192                 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 193         blk_size[dev->major] = dev->sizes;
 194 }
 195         
 196 /* This may be used only once, enforced by 'static int callable' */
 197 asmlinkage int sys_setup(void * BIOS)
     /* [previous][next][first][last][top][bottom][index][help] */
 198 {
 199         static int callable = 1;
 200         struct gendisk *p;
 201         int nr=0;
 202 
 203         if (!callable)
 204                 return -1;
 205         callable = 0;
 206 
 207         for (p = gendisk_head ; p ; p=p->next) {
 208                 setup_dev(p);
 209                 nr += p->nr_real;
 210         }
 211                 
 212         if (ramdisk_size)
 213                 rd_load();
 214         mount_root();
 215         return (0);
 216 }

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