genhd.c can now deal with NULL first extended partitions

Marty Leisner (leisner@sdsp.mc.xerox.com)
Wed, 6 Sep 1995 07:45:16 PDT


I hacked up genhd.c (I ended up using a diffirent algorithm
which I hope is simpler). I also put in more debug
code...

I have a strategy to read through BSD slices and give them
linux minor devices...

Most of the OSF code is of use for handling slices...probably
need to add:
CONFIG_BSD_SLICES
in order to activate the code (is this something
configurable or internal to the file?)

Having fdisk/kernel agree on what the devices are is going to be
somewhat of a problem...

For now, I think the kernel should print more extensive information
on each partition it finds...(i.e what it is if its known...)

I also added more debugging statements (normal) and more debugging
if you do #define's within this file (#define DEBUG_EXTENDED will
actually show the partition tables)

Here's the extended partition fixes to drivers/block/genhd.c wrt 1.3.20

--- genhd.c 1995/08/31 02:23:49 1.1
+++ genhd.c 1995/09/04 17:29:11 1.2
@@ -15,6 +15,13 @@
* with information provided by OnTrack. This now works for linux fdisk
* and LILO, as well as loadlin and bootln. Note that disks other than
* /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
+ *
+ * Marty Leisner (leisner@sdsp.mc.xerox.com) 9/95
+ * The old extended disk strategy missed first partition
+ * if it was empty.
+ *
+ * ToDo: Handle 386BSD partition slices
+ *
*/

#include <linux/config.h>
@@ -31,6 +38,12 @@
extern void rd_load(void);
extern int ramdisk_size;

+#if 0 /* change */
+#define debug_extended(a...) printk(## a)
+#else
+#define debug_extended(a...)
+#endif
+
static void print_minor_name (struct gendisk *hd, int minor)
{
unsigned int unit = minor >> hd->minor_shift;
@@ -57,14 +70,39 @@
printk(":");
}

+/* called for each sub partition */
static void add_partition (struct gendisk *hd, int minor, int start, int size)
{
hd->part[minor].start_sect = start;
hd->part[minor].nr_sects = size;
print_minor_name(hd, minor);
+ /* enable this is you want an indication of all the sizes
+ * of all the partitions
+ */
+#if 0
+ printk(" (%d,%d) ", start, size);
+#endif
}

#ifdef CONFIG_MSDOS_PARTITION
+/* #define DEBUG_EXTENDED for more information on bootup */
+#ifdef DEBUG_EXTENDED
+static void show_partitions(unsigned long start, struct partition *p)
+{
+ int i;
+
+ printk("\nSector partition table at %d\n", start);
+ printk("# Sysind start end\n");
+ for(i = 0; i <= 3; i++, p++) {
+ printk("#%d %10x%10ld%10ld\n",
+ i, p->sys_ind, p->start_sect,
+ p->nr_sects);
+ }
+}
+#else
+#define show_partitions(i, a)
+#endif
+
/*
* Create devices for each logical partition in an extended partition.
* The logical partitions form a linked list, with each entry being
@@ -80,35 +118,75 @@
{
struct buffer_head *bh;
struct partition *p;
- unsigned long first_sector, this_sector;
+ unsigned long first_sector; /* where base partition begins */
+ unsigned long this_sector; /* current place within extended partition */
+ unsigned long last_sector; /* where partition will end */
int mask = (1 << hd->minor_shift) - 1;

first_sector = hd->part[MINOR(dev)].start_sect;
- this_sector = first_sector;
+ last_sector = first_sector + hd->part[MINOR(dev)].nr_sects;
+
+ this_sector = 0;

+ debug_extended("first sector = %ld, last sector = %ld\n",
+ first_sector, last_sector);
+ /* read through linked list of extended partitions */
while (1) {
+ char *pdata;
+
+ /* what does this do? */
if ((current_minor & mask) >= (4 + hd->max_p))
return;
- if (!(bh = bread(dev,0,1024)))
+
+ /* read first block of new sector */
+ debug_extended("this sector = %ld, dev = %d\n", this_sector, dev);
+
+ /* are blocks 1k? */
+ bh = bread(dev, this_sector/2, 1024);
+ if(!bh)
return;
+
+ pdata = bh->b_data;
+
/*
* This block is from a device that we're about to stomp on.
* So make sure nobody thinks this block is usable.
+ * ml -- why does it make a difference?
+ * ml -- symbols for magic numbers (FIXME)
*/
bh->b_dirt = 0;
bh->b_uptodate = 0;
bh->b_req = 0;
- if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
- p = (struct partition *) (0x1BE + bh->b_data);
- /*
- * Process the first entry, which should be the real
- * data partition.
- */
- if (p->sys_ind == EXTENDED_PARTITION || !p->nr_sects)
- goto done; /* shouldn't happen */
- add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
- current_minor++;
- p++;
+ /* each partition table must (or is supposed to have this end marker */
+
+ p = (struct partition *) (0x1BE + pdata);
+ show_partitions(this_sector, p);
+ if (*(unsigned short *) (pdata + 0x1fe) != 0xAA55) {
+ printk("No end marker found in parition found %x\n", *(unsigned short *) (pdata + 0x1fe));
+ break;
+ }
+
+
+
+ if(p->sys_ind && p->nr_sects) {
+ /* sanity check -- does this make sense? */
+ if(p->nr_sects + p->start_sect > last_sector - first_sector) {
+ printk("Extended partition out of bounds: start = %d, size = %d, needs to by %d\n",
+ p->start_sect, p->nr_sects,
+ last_sector);
+ break;
+ }
+
+ /* there is a relavent partition here (non=zero indicator?) */
+#ifndef DEBUG_EXTENDED
+ add_partition(hd, current_minor, first_sector + this_sector + p->start_sect, p->nr_sects);
+#else
+ printk("Found partition at %d of%d sectors\n",
+ p->start_sect, p->nr_sects);
+#endif
+ }
+ current_minor++;
+ p++;
/*
* Process the second entry, which should be a link
* to the next logical partition. Create a minor
@@ -116,16 +194,17 @@
* table. The minor will be reused for the real
* data partition.
*/
- if (p->sys_ind != EXTENDED_PARTITION ||
- !(hd->part[current_minor].nr_sects = p->nr_sects))
- goto done; /* no more logicals in this partition */
- hd->part[current_minor].start_sect = first_sector + p->start_sect;
- this_sector = first_sector + p->start_sect;
- dev = ((hd->major) << 8) | current_minor;
- brelse(bh);
- } else
- goto done;
+ if (p->sys_ind != EXTENDED_PARTITION) {
+ debug_extended("ended partitions with %d\n", p->sys_ind);
+ break;
+ }
+
+ /* prepare for next partition */
+ this_sector = p->start_sect;
+ debug_extended("Next partition at %d\n", this_sector);
+ brelse(bh);
}
+ /* all error and normal returns have a block out */
done:
brelse(bh);
}
@@ -206,8 +285,8 @@
if ((current_minor & 0x3f) >= 60)
continue;
if (p->sys_ind == EXTENDED_PARTITION) {
- printk(" <");
- extended_partition(hd, (hd->major << 8) | minor);
+ printk(" < extended: ");
+ extended_partition(hd, (hd->major << 8) | minor);
printk(" >");
}
}

marty leisner@sdsp.mc.xerox.com
Member of the League for Programming Freedom (http://www.lpf.org)
Any sufficiently advanced technology is indistinguishable from magic
Arthur C. Clarke, The Lost Worlds of 2001