2000-10-30 09:07:14

by Adam J. Richter

[permalink] [raw]
Subject: Patch: modularizing partition parsing in linux-2.4.0-test10-pre6

Ages ago, I modularized the partition parsing code and
posted the patch to linux-kernel. I received a few suggestions
for some small improvements, and I confess it took me a while
to get around to producing a new patch. Anyhow, here is the
new partitioning modularization patch. It now longer has any
"#ifdef MODULE" code in it. It just has one module-centric
SMP-safe initialization scheme.

I would appreciate it if people would try this patch
and make sure that it works for them.

Adam J. Richter __ ______________ 4880 Stevens Creek Blvd, Suite 104
[email protected] \ / San Jose, California 95129-1034
+1 408 261-6630 | g g d r a s i l United States of America
fax +1 408 261-6631 "Free Software For The Rest Of Us."

----------------------CUT HERE--------------------------------

diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/Config.in linux/fs/partitions/Config.in
--- linux-2.4.0-test10-pre6/fs/partitions/Config.in Sun Jul 9 22:21:41 2000
+++ linux/fs/partitions/Config.in Sat Oct 28 22:57:06 2000
@@ -3,7 +3,7 @@
#
bool 'Advanced partition selection' CONFIG_PARTITION_ADVANCED
if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then
- bool ' Acorn partition support' CONFIG_ACORN_PARTITION
+ tristate ' Acorn partition support' CONFIG_ACORN_PARTITION
if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
# bool ' Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA
bool ' ICS partition support' CONFIG_ACORN_PARTITION_ICS
@@ -11,22 +11,22 @@
bool ' PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
bool ' RISCiX partition support' CONFIG_ACORN_PARTITION_RISCIX
fi
- bool ' Alpha OSF partition support' CONFIG_OSF_PARTITION
- bool ' Amiga partition table support' CONFIG_AMIGA_PARTITION
- bool ' Atari partition table support' CONFIG_ATARI_PARTITION
+ tristate ' Alpha OSF partition support' CONFIG_OSF_PARTITION
+ tristate ' Amiga partition table support' CONFIG_AMIGA_PARTITION
+ tristate ' Atari partition table support' CONFIG_ATARI_PARTITION
if [ "$CONFIG_ARCH_S390" = "y" ]; then
bool ' IBM disk label and partition support' CONFIG_IBM_PARTITION
fi
- bool ' Macintosh partition map support' CONFIG_MAC_PARTITION
- bool ' PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
- if [ "$CONFIG_MSDOS_PARTITION" = "y" ]; then
+ tristate ' Macintosh partition map support' CONFIG_MAC_PARTITION
+ tristate ' PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
+ if [ "$CONFIG_MSDOS_PARTITION" != "n" ]; then
bool ' BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
bool ' Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
fi
- bool ' SGI partition support' CONFIG_SGI_PARTITION
- bool ' Ultrix partition table support' CONFIG_ULTRIX_PARTITION
- bool ' Sun partition tables support' CONFIG_SUN_PARTITION
+ tristate ' SGI partition support' CONFIG_SGI_PARTITION
+ tristate ' Ultrix partition table support' CONFIG_ULTRIX_PARTITION
+ tristate ' Sun partition tables support' CONFIG_SUN_PARTITION
else
if [ "$ARCH" = "alpha" ]; then
define_bool CONFIG_OSF_PARTITION y
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/Makefile linux/fs/partitions/Makefile
--- linux-2.4.0-test10-pre6/fs/partitions/Makefile Tue Jul 18 22:49:47 2000
+++ linux/fs/partitions/Makefile Fri Jul 14 09:59:40 2000
@@ -14,7 +14,7 @@
obj-$(CONFIG_AMIGA_PARTITION) += amiga.o
obj-$(CONFIG_ATARI_PARTITION) += atari.o
obj-$(CONFIG_MAC_PARTITION) += mac.o
-obj-$(CONFIG_MSDOS_PARTITION) += msdos.o
+obj-$(CONFIG_MSDOS_PARTITION) += msdos_part.o
obj-$(CONFIG_OSF_PARTITION) += osf.o
obj-$(CONFIG_SGI_PARTITION) += sgi.o
obj-$(CONFIG_SUN_PARTITION) += sun.o
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/acorn.c linux/fs/partitions/acorn.c
--- linux-2.4.0-test10-pre6/fs/partitions/acorn.c Mon Sep 18 15:15:26 2000
+++ linux/fs/partitions/acorn.c Sat Oct 28 22:54:04 2000
@@ -478,8 +478,9 @@
*
* Returns: -1 on error, 0 if not ADFS format, 1 if ok.
*/
-int acorn_partition(struct gendisk *hd, kdev_t dev,
- unsigned long first_sect, int first_minor)
+static int
+acorn_partition(struct gendisk *hd, kdev_t dev,
+ unsigned long first_sect, int first_minor)
{
int r = 0, i;

@@ -492,3 +493,6 @@
printk("\n");
return r;
}
+
+#define check_partition acorn_partition
+#include "partition_module.h"
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/amiga.c linux/fs/partitions/amiga.c
--- linux-2.4.0-test10-pre6/fs/partitions/amiga.c Wed Feb 16 15:42:06 2000
+++ linux/fs/partitions/amiga.c Sat Oct 28 22:54:04 2000
@@ -30,8 +30,9 @@
return sum;
}

-int
-amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+static int
+amiga_partition(struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector, int first_part_minor)
{
struct buffer_head *bh;
struct RigidDiskBlock *rdb;
@@ -118,3 +119,6 @@
set_blocksize(dev,old_blocksize);
return res;
}
+
+#define check_partition amiga_partition
+#include "partition_module.h"
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/atari.c linux/fs/partitions/atari.c
--- linux-2.4.0-test10-pre6/fs/partitions/atari.c Sat Oct 28 22:45:50 2000
+++ linux/fs/partitions/atari.c Sat Oct 28 22:54:04 2000
@@ -33,8 +33,9 @@
be32_to_cpu((pi)->st) <= (hdsiz) && \
be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))

-int atari_partition (struct gendisk *hd, kdev_t dev,
- unsigned long first_sector, int minor)
+static int
+atari_partition (struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector, int minor)
{
int m_lim = minor + hd->max_p;
struct buffer_head *bh;
@@ -62,7 +63,6 @@
/* if there's no valid primary partition, assume that no Atari
format partition table (there's no reliable magic or the like
:-() */
- brelse(bh);
return 0;
}

@@ -176,3 +176,5 @@
return 1;
}

+#define check_partition atari_partition
+#include "partition_module.h"
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/check.c linux/fs/partitions/check.c
--- linux-2.4.0-test10-pre6/fs/partitions/check.c Sat Oct 28 22:45:50 2000
+++ linux/fs/partitions/check.c Tue Oct 3 16:36:39 2000
@@ -19,6 +19,7 @@
#include <linux/blk.h>
#include <linux/init.h>
#include <linux/raid/md.h>
+#include <linux/smp_lock.h>

#include "check.h"

@@ -29,9 +30,9 @@
#include "msdos.h"
#include "osf.h"
#include "sgi.h"
-#include "sun.h"
#include "ibm.h"
#include "ultrix.h"
+#include "sun.h"

extern void device_init(void);
extern int *blk_size[];
@@ -41,39 +42,13 @@
struct gendisk *gendisk_head;
int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/

-static int (*check_part[])(struct gendisk *hd, kdev_t dev, unsigned long first_sect, int first_minor) = {
-#ifdef CONFIG_ACORN_PARTITION
- acorn_partition,
-#endif
-#ifdef CONFIG_MSDOS_PARTITION
- msdos_partition,
-#endif
-#ifdef CONFIG_OSF_PARTITION
- osf_partition,
-#endif
-#ifdef CONFIG_SUN_PARTITION
- sun_partition,
-#endif
-#ifdef CONFIG_AMIGA_PARTITION
- amiga_partition,
-#endif
-#ifdef CONFIG_ATARI_PARTITION
- atari_partition,
-#endif
-#ifdef CONFIG_MAC_PARTITION
- mac_partition,
-#endif
-#ifdef CONFIG_SGI_PARTITION
- sgi_partition,
-#endif
-#ifdef CONFIG_ULTRIX_PARTITION
- ultrix_partition,
-#endif
-#ifdef CONFIG_IBM_PARTITION
- ibm_partition,
+static DECLARE_MUTEX(part_ops_mutex);
+static struct partition_ops *part_ops = NULL;
+
+#if defined CONFIG_BLK_DEV_LVM || defined CONFIG_BLK_DEV_LVM_MODULE
+#include <linux/lvm.h>
+void (*lvm_hd_name_ptr) (char *, int) = NULL;
#endif
- NULL
-};

/*
* disk_name() is used by genhd.c and blkpg.c.
@@ -99,6 +74,13 @@
* IDE devices use multiple major numbers, but the drives
* are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
* This requires special handling here.
+#if defined CONFIG_BLK_DEV_LVM || defined CONFIG_BLK_DEV_LVM_MODULE
+ case LVM_BLK_MAJOR:
+ *buf = 0;
+ if ( lvm_hd_name_ptr != NULL)
+ (lvm_hd_name_ptr) ( buf, minor);
+ return buf;
+#endif
*/
switch (hd->major) {
case IDE9_MAJOR:
@@ -278,6 +260,7 @@
unsigned long first_sector;
char buf[64];
int i;
+ struct partition_ops *ops;

if (first_time)
printk(KERN_INFO "Partition check:\n");
@@ -300,12 +283,13 @@
printk(KERN_INFO " /dev/%s:", buf + i);
else
printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
- for (i = 0; check_part[i]; i++)
- if (check_part[i](hd, dev, first_sector, first_part_minor))
+ down(&part_ops_mutex);
+ for (ops = part_ops; ops != NULL; ops = ops->next)
+ if ((*ops->check)(hd, dev, first_sector, first_part_minor))
goto setup_devfs;
-
printk(" unknown partition table\n");
setup_devfs:
+ up(&part_ops_mutex);
i = first_part_minor - 1;
devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
}
@@ -338,8 +322,8 @@
devfs_handle_t dir, slave;
unsigned int devfs_flags = DEVFS_FL_DEFAULT;
char dirname[64], symlink[16];
- static unsigned int disc_counter;
- static devfs_handle_t devfs_handle;
+ static unsigned int disc_counter = 0;
+ static devfs_handle_t devfs_handle = NULL;

if (dev->part[minor].de) return;
if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
@@ -411,6 +395,29 @@
grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
}

+void register_partition_ops(struct partition_ops *ops)
+{
+ down(&part_ops_mutex);
+ ops->next = part_ops;
+ part_ops = ops;
+ up(&part_ops_mutex);
+}
+
+void unregister_partition_ops(struct partition_ops *ops)
+{
+ struct partition_ops **tmp;
+ down(&part_ops_mutex);
+ for (tmp = &part_ops; *tmp != NULL; tmp = &(*tmp)->next) {
+ if (*tmp == ops) {
+ *tmp = ops->next;
+ break;
+ }
+ }
+ up(&part_ops_mutex);
+}
+
+
+
void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
{
int i;
@@ -439,6 +446,9 @@
}
}

+/* Warning: partition_setup must be called before the initialization
+ routines in the individual modules, so it must be linked before
+ them. */
int __init partition_setup(void)
{
device_init();
@@ -454,3 +464,9 @@
}

__initcall(partition_setup);
+EXPORT_SYMBOL(get_ptable_blocksize);
+EXPORT_SYMBOL(add_gd_partition);
+EXPORT_SYMBOL(warn_no_part);
+EXPORT_SYMBOL(get_hardsect_size);
+EXPORT_SYMBOL(register_partition_ops);
+EXPORT_SYMBOL(unregister_partition_ops);
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/ibm.c linux/fs/partitions/ibm.c
--- linux-2.4.0-test10-pre6/fs/partitions/ibm.c Wed Apr 12 09:47:30 2000
+++ linux/fs/partitions/ibm.c Sat Oct 28 22:54:04 2000
@@ -43,7 +43,7 @@
return ibm_partition_none;
}

-void
+static void
ibm_partition (struct gendisk *hd, kdev_t dev)
{
struct buffer_head *bh;
@@ -120,3 +120,5 @@
bforget(bh);
}

+#define check_partition ibm_partition
+#include "partition_module.h"
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/mac.c linux/fs/partitions/mac.c
--- linux-2.4.0-test10-pre6/fs/partitions/mac.c Sun Sep 17 09:51:57 2000
+++ linux/fs/partitions/mac.c Sat Oct 28 22:54:04 2000
@@ -36,7 +36,9 @@
stg[i] = 0;
}

-int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor)
+static int
+mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec,
+ int first_part_minor)
{
struct buffer_head *bh;
int blk, blocks_in_map;
@@ -152,3 +154,5 @@
return 1;
}

+#define check_partition mac_partition
+#include "partition_module.h"
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/msdos.c linux/fs/partitions/msdos.c
--- linux-2.4.0-test10-pre6/fs/partitions/msdos.c Tue Jul 18 23:29:16 2000
+++ linux/fs/partitions/msdos.c Wed Dec 31 16:00:00 1969
@@ -1,515 +0,0 @@
-/*
- * fs/partitions/msdos.c
- *
- * Code extracted from drivers/block/genhd.c
- * Copyright (C) 1991-1998 Linus Torvalds
- *
- * Thanks to Branko Lankester, [email protected], who found a bug
- * in the early extended-partition checks and added DM partitions
- *
- * Support for DiskManager v6.0x added by Mark Lord,
- * 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).
- *
- * More flexible handling of extended partitions - aeb, 950831
- *
- * Check partition table on IDE disks for common CHS translations
- *
- * Re-organised Feb 1998 Russell King
- */
-
-#include <linux/config.h>
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-
-#ifdef CONFIG_BLK_DEV_IDE
-#include <linux/ide.h> /* IDE xlate */
-#endif /* CONFIG_BLK_DEV_IDE */
-
-#include <asm/system.h>
-
-#include "check.h"
-#include "msdos.h"
-
-#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
-extern void md_autodetect_dev(kdev_t dev);
-#endif
-
-static int current_minor;
-
-/*
- * Many architectures don't like unaligned accesses, which is
- * frequently the case with the nr_sects and start_sect partition
- * table entries.
- */
-#include <asm/unaligned.h>
-
-#define SYS_IND(p) (get_unaligned(&p->sys_ind))
-#define NR_SECTS(p) ({ __typeof__(p->nr_sects) __a = \
- get_unaligned(&p->nr_sects); \
- le32_to_cpu(__a); \
- })
-
-#define START_SECT(p) ({ __typeof__(p->start_sect) __a = \
- get_unaligned(&p->start_sect); \
- le32_to_cpu(__a); \
- })
-
-static inline int is_extended_partition(struct partition *p)
-{
- return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
- SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
- SYS_IND(p) == LINUX_EXTENDED_PARTITION);
-}
-
-/*
- * Create devices for each logical partition in an extended partition.
- * The logical partitions form a linked list, with each entry being
- * a partition table with two entries. The first entry
- * is the real data partition (with a start relative to the partition
- * table start). The second is a pointer to the next logical partition
- * (with a start relative to the entire extended partition).
- * We do not create a Linux partition for the partition tables, but
- * only for the actual data partitions.
- */
-
-static void extended_partition(struct gendisk *hd, kdev_t dev)
-{
- struct buffer_head *bh;
- struct partition *p;
- unsigned long first_sector, first_size, this_sector, this_size;
- int mask = (1 << hd->minor_shift) - 1;
- int sector_size = get_hardsect_size(dev) / 512;
- int loopct = 0; /* number of links followed
- without finding a data partition */
- int i;
-
- first_sector = hd->part[MINOR(dev)].start_sect;
- first_size = hd->part[MINOR(dev)].nr_sects;
- this_sector = first_sector;
-
- while (1) {
- if (++loopct > 100)
- return;
- if ((current_minor & mask) == 0)
- return;
- if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
- return;
-
- if ((*(__u16 *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
- goto done;
-
- p = (struct partition *) (0x1BE + bh->b_data);
-
- this_size = hd->part[MINOR(dev)].nr_sects;
-
- /*
- * Usually, the first entry is the real data partition,
- * the 2nd entry is the next extended partition, or empty,
- * and the 3rd and 4th entries are unused.
- * However, DRDOS sometimes has the extended partition as
- * the first entry (when the data partition is empty),
- * and OS/2 seems to use all four entries.
- */
-
- /*
- * First process the data partition(s)
- */
- for (i=0; i<4; i++, p++) {
- if (!NR_SECTS(p) || is_extended_partition(p))
- continue;
-
- /* Check the 3rd and 4th entries -
- these sometimes contain random garbage */
- if (i >= 2
- && START_SECT(p) + NR_SECTS(p) > this_size
- && (this_sector + START_SECT(p) < first_sector ||
- this_sector + START_SECT(p) + NR_SECTS(p) >
- first_sector + first_size))
- continue;
-
- add_gd_partition(hd, current_minor,
- this_sector+START_SECT(p)*sector_size,
- NR_SECTS(p)*sector_size);
-#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
- if (SYS_IND(p) == LINUX_RAID_PARTITION) {
- md_autodetect_dev(MKDEV(hd->major,current_minor));
- }
-#endif
-
- current_minor++;
- loopct = 0;
- if ((current_minor & mask) == 0)
- goto done;
- }
- /*
- * Next, process the (first) extended partition, if present.
- * (So far, there seems to be no reason to make
- * extended_partition() recursive and allow a tree
- * of extended partitions.)
- * It should be a link to the next logical partition.
- * Create a minor for this just long enough to get the next
- * partition table. The minor will be reused for the next
- * data partition.
- */
- p -= 4;
- for (i=0; i<4; i++, p++)
- if(NR_SECTS(p) && is_extended_partition(p))
- break;
- if (i == 4)
- goto done; /* nothing left to do */
-
- hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
- hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
- this_sector = first_sector + START_SECT(p) * sector_size;
- dev = MKDEV(hd->major, current_minor);
-
- /* Use bforget(), as we have changed the disk geometry */
- bforget(bh);
- }
-done:
- bforget(bh);
-}
-
-static inline struct buffer_head *
-get_partition_table_block(struct gendisk *hd, int minor, int blocknr) {
- kdev_t dev = MKDEV(hd->major, minor);
- return bread(dev, blocknr, get_ptable_blocksize(dev));
-}
-
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-
-/* [email protected]: Solaris has a nasty indicator: 0x82 which also
- indicates linux swap. Be careful before believing this is Solaris. */
-
-static void
-solaris_x86_partition(struct gendisk *hd, int minor) {
- long offset = hd->part[minor].start_sect;
-
- struct buffer_head *bh;
- struct solaris_x86_vtoc *v;
- struct solaris_x86_slice *s;
- int i;
- char buf[40];
-
- if(!(bh = get_partition_table_block(hd, minor, 0)))
- return;
- v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
- if(v->v_sanity != SOLARIS_X86_VTOC_SANE) {
- brelse(bh);
- return;
- }
- printk(" %s: <solaris:", disk_name(hd, minor, buf));
- if(v->v_version != 1) {
- printk(" cannot handle version %ld vtoc>\n", v->v_version);
- brelse(bh);
- return;
- }
- for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
- s = &v->v_slice[i];
-
- if (s->s_size == 0)
- continue;
- printk(" [s%d]", i);
- /* solaris partitions are relative to current MS-DOS
- * one but add_gd_partition starts relative to sector
- * zero of the disk. Therefore, must add the offset
- * of the current partition */
- add_gd_partition(hd, current_minor, s->s_start+offset, s->s_size);
- current_minor++;
- }
- brelse(bh);
- printk(" >\n");
-}
-#endif
-
-#ifdef CONFIG_BSD_DISKLABEL
-static void
-check_and_add_bsd_partition(struct gendisk *hd,
- struct bsd_partition *bsd_p, int minor) {
- struct hd_struct *lin_p;
- /* check relative position of partitions. */
- for (lin_p = hd->part + 1 + minor;
- lin_p - hd->part - minor < current_minor; lin_p++) {
- /* no relationship -> try again */
- if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset ||
- lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
- continue;
- /* equal -> no need to add */
- if (lin_p->start_sect == bsd_p->p_offset &&
- lin_p->nr_sects == bsd_p->p_size)
- return;
- /* bsd living within dos partition */
- if (lin_p->start_sect <= bsd_p->p_offset && lin_p->start_sect
- + lin_p->nr_sects >= bsd_p->p_offset + bsd_p->p_size) {
-#ifdef DEBUG_BSD_DISKLABEL
- printk("w: %d %ld+%ld,%d+%d",
- lin_p - hd->part,
- lin_p->start_sect, lin_p->nr_sects,
- bsd_p->p_offset, bsd_p->p_size);
-#endif
- break;
- }
- /* ouch: bsd and linux overlap. Don't even try for that partition */
-#ifdef DEBUG_BSD_DISKLABEL
- printk("???: %d %ld+%ld,%d+%d",
- lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
- bsd_p->p_offset, bsd_p->p_size);
-#endif
- printk("???");
- return;
- } /* if the bsd partition is not currently known to linux, we end
- * up here
- */
- add_gd_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size);
- current_minor++;
-}
-
-/*
- * Create devices for BSD partitions listed in a disklabel, under a
- * dos-like partition. See extended_partition() for more information.
- */
-static void bsd_disklabel_partition(struct gendisk *hd, int minor, int type) {
- struct buffer_head *bh;
- struct bsd_disklabel *l;
- struct bsd_partition *p;
- int max_partitions;
- int mask = (1 << hd->minor_shift) - 1;
- char buf[40];
-
- if (!(bh = get_partition_table_block(hd, minor, 0)))
- return;
- l = (struct bsd_disklabel *) (bh->b_data+512);
- if (l->d_magic != BSD_DISKMAGIC) {
- brelse(bh);
- return;
- }
- printk(" %s:", disk_name(hd, minor, buf));
- printk((type == OPENBSD_PARTITION) ? " <openbsd:" :
- (type == NETBSD_PARTITION) ? " <netbsd:" : " <bsd:");
-
- max_partitions = ((type == OPENBSD_PARTITION) ? OPENBSD_MAXPARTITIONS
- : BSD_MAXPARTITIONS);
- if (l->d_npartitions < max_partitions)
- max_partitions = l->d_npartitions;
- for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
- if ((current_minor & mask) >= (4 + hd->max_p))
- break;
-
- if (p->p_fstype != BSD_FS_UNUSED)
- check_and_add_bsd_partition(hd, p, minor);
- }
-
- /* Use bforget(), as we have changed the disk setup */
- bforget(bh);
-
- printk(" >\n");
-}
-#endif
-
-#ifdef CONFIG_UNIXWARE_DISKLABEL
-/*
- * Create devices for Unixware partitions listed in a disklabel, under a
- * dos-like partition. See extended_partition() for more information.
- */
-static void unixware_partition(struct gendisk *hd, int minor) {
- struct buffer_head *bh;
- struct unixware_disklabel *l;
- struct unixware_slice *p;
- int mask = (1 << hd->minor_shift) - 1;
- char buf[40];
-
- if (!(bh = get_partition_table_block(hd, minor, 14)))
- return;
- l = (struct unixware_disklabel *) (bh->b_data+512);
- if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
- le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
- brelse(bh);
- return;
- }
- printk(" %s: <unixware:", disk_name(hd, minor, buf));
- p = &l->vtoc.v_slice[1];
- /* I omit the 0th slice as it is the same as whole disk. */
- while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
- if ((current_minor & mask) == 0)
- break;
-
- if (p->s_label != UNIXWARE_FS_UNUSED) {
- add_gd_partition(hd, current_minor, START_SECT(p),
- NR_SECTS(p));
- current_minor++;
- }
- p++;
- }
- /* Use bforget, as we have changed the disk setup */
- bforget(bh);
- printk(" >\n");
-}
-#endif
-
-int msdos_partition(struct gendisk *hd, kdev_t dev,
- unsigned long first_sector, int first_part_minor) {
- int i, minor = current_minor = first_part_minor;
- struct buffer_head *bh;
- struct partition *p;
- unsigned char *data;
- int mask = (1 << hd->minor_shift) - 1;
- int sector_size = get_hardsect_size(dev) / 512;
-#ifdef CONFIG_BLK_DEV_IDE
- int tested_for_xlate = 0;
-
-read_mbr:
-#endif /* CONFIG_BLK_DEV_IDE */
- if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
- if (warn_no_part) printk(" unable to read partition table\n");
- return -1;
- }
- data = bh->b_data;
-#ifdef CONFIG_BLK_DEV_IDE
-check_table:
-#endif /* CONFIG_BLK_DEV_IDE */
- /* Use bforget(), because we may have changed the disk geometry */
- if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
- bforget(bh);
- return 0;
- }
- p = (struct partition *) (0x1be + data);
-
-#ifdef CONFIG_BLK_DEV_IDE
- if (!tested_for_xlate++) { /* Do this only once per disk */
- /*
- * Look for various forms of IDE disk geometry translation
- */
- unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
- int heads = 0;
- /*
- * The i386 partition handling programs very often
- * make partitions end on cylinder boundaries.
- * There is no need to do so, and Linux fdisk doesnt always
- * do this, and Windows NT on Alpha doesnt do this either,
- * but still, this helps to guess #heads.
- */
- for (i = 0; i < 4; i++) {
- struct partition *q = &p[i];
- if (NR_SECTS(q)) {
- if ((q->sector & 63) == 1 &&
- (q->end_sector & 63) == 63)
- heads = q->end_head + 1;
- break;
- }
- }
- if (SYS_IND(p) == EZD_PARTITION) {
- /*
- * Accesses to sector 0 must go to sector 1 instead.
- */
- if (ide_xlate_1024(dev, -1, heads, " [EZD]")) {
- data += 512;
- goto check_table;
- }
- } else if (SYS_IND(p) == DM6_PARTITION) {
-
- /*
- * Everything on the disk is offset by 63 sectors,
- * including a "new" MBR with its own partition table.
- */
- if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]")) {
- bforget(bh);
- goto read_mbr; /* start over with new MBR */
- }
- } else if (sig <= 0x1ae &&
- data[sig] == 0xAA && data[sig+1] == 0x55 &&
- (data[sig+2] & 1)) {
- /* DM6 signature in MBR, courtesy of OnTrack */
- (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
- } else if (SYS_IND(p) == DM6_AUX1PARTITION ||
- SYS_IND(p) == DM6_AUX3PARTITION) {
- /*
- * DM6 on other than the first (boot) drive
- */
- (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
- } else {
- (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
- }
- }
-#endif /* CONFIG_BLK_DEV_IDE */
-
- /* Look for partitions in two passes:
- First find the primary partitions, and the DOS-type extended partitions.
- On the second pass look inside *BSD and Unixware and Solaris partitions. */
-
- current_minor += 4; /* first "extra" minor (for extended partitions) */
- for (i=1 ; i<=4 ; minor++,i++,p++) {
- if (!NR_SECTS(p))
- continue;
- add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size,
- NR_SECTS(p)*sector_size);
-#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
- if (SYS_IND(p) == LINUX_RAID_PARTITION) {
- md_autodetect_dev(MKDEV(hd->major,minor));
- }
-#endif
- if (is_extended_partition(p)) {
- printk(" <");
- /*
- * If we are rereading the partition table, we need
- * to set the size of the partition so that we will
- * be able to bread the block containing the extended
- * partition info.
- */
- hd->sizes[minor] = hd->part[minor].nr_sects
- >> (BLOCK_SIZE_BITS - 9);
- extended_partition(hd, MKDEV(hd->major, minor));
- printk(" >");
- /* prevent someone doing mkfs or mkswap on an
- extended partition, but leave room for LILO */
- if (hd->part[minor].nr_sects > 2)
- hd->part[minor].nr_sects = 2;
- }
- }
-
- /*
- * Check for old-style Disk Manager partition table
- */
- if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
- p = (struct partition *) (0x1be + data);
- for (i = 4 ; i < 16 ; i++, current_minor++) {
- p--;
- if ((current_minor & mask) == 0)
- break;
- if (!(START_SECT(p) && NR_SECTS(p)))
- continue;
- add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
- }
- }
- printk("\n");
-
- /* second pass - output for each on a separate line */
- minor -= 4;
- p = (struct partition *) (0x1be + data);
- for (i=1 ; i<=4 ; minor++,i++,p++) {
- if (!NR_SECTS(p))
- continue;
-#ifdef CONFIG_BSD_DISKLABEL
- if (SYS_IND(p) == BSD_PARTITION ||
- SYS_IND(p) == NETBSD_PARTITION ||
- SYS_IND(p) == OPENBSD_PARTITION)
- bsd_disklabel_partition(hd, minor, SYS_IND(p));
-#endif
-#ifdef CONFIG_UNIXWARE_DISKLABEL
- if (SYS_IND(p) == UNIXWARE_PARTITION)
- unixware_partition(hd, minor);
-#endif
-#ifdef CONFIG_SOLARIS_X86_PARTITION
- if(SYS_IND(p) == SOLARIS_X86_PARTITION)
- solaris_x86_partition(hd, minor);
-#endif
- }
-
- bforget(bh);
- return 1;
-}
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/msdos_part.c linux/fs/partitions/msdos_part.c
--- linux-2.4.0-test10-pre6/fs/partitions/msdos_part.c Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/msdos_part.c Mon Oct 30 00:47:18 2000
@@ -0,0 +1,517 @@
+/*
+ * fs/partitions/msdos.c
+ *
+ * Code extracted from drivers/block/genhd.c
+ * Copyright (C) 1991-1998 Linus Torvalds
+ *
+ * Thanks to Branko Lankester, [email protected], who found a bug
+ * in the early extended-partition checks and added DM partitions
+ *
+ * Support for DiskManager v6.0x added by Mark Lord,
+ * 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).
+ *
+ * More flexible handling of extended partitions - aeb, 950831
+ *
+ * Check partition table on IDE disks for common CHS translations
+ *
+ * Re-organised Feb 1998 Russell King
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/ide.h> /* IDE xlate */
+
+#include <asm/system.h>
+
+#include "check.h"
+#include "msdos.h"
+
+#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
+extern void md_autodetect_dev(kdev_t dev);
+#endif
+
+static int current_minor;
+
+/*
+ * Many architectures don't like unaligned accesses, which is
+ * frequently the case with the nr_sects and start_sect partition
+ * table entries.
+ */
+#include <asm/unaligned.h>
+
+#define SYS_IND(p) (get_unaligned(&p->sys_ind))
+#define NR_SECTS(p) ({ __typeof__(p->nr_sects) __a = \
+ get_unaligned(&p->nr_sects); \
+ le32_to_cpu(__a); \
+ })
+
+#define START_SECT(p) ({ __typeof__(p->start_sect) __a = \
+ get_unaligned(&p->start_sect); \
+ le32_to_cpu(__a); \
+ })
+
+static inline int is_extended_partition(struct partition *p)
+{
+ return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
+ SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
+ SYS_IND(p) == LINUX_EXTENDED_PARTITION);
+}
+
+/*
+ * Create devices for each logical partition in an extended partition.
+ * The logical partitions form a linked list, with each entry being
+ * a partition table with two entries. The first entry
+ * is the real data partition (with a start relative to the partition
+ * table start). The second is a pointer to the next logical partition
+ * (with a start relative to the entire extended partition).
+ * We do not create a Linux partition for the partition tables, but
+ * only for the actual data partitions.
+ */
+
+static void extended_partition(struct gendisk *hd, kdev_t dev)
+{
+ struct buffer_head *bh;
+ struct partition *p;
+ unsigned long first_sector, first_size, this_sector, this_size;
+ int mask = (1 << hd->minor_shift) - 1;
+ int sector_size = get_hardsect_size(dev) / 512;
+ int loopct = 0; /* number of links followed
+ without finding a data partition */
+ int i;
+
+ first_sector = hd->part[MINOR(dev)].start_sect;
+ first_size = hd->part[MINOR(dev)].nr_sects;
+ this_sector = first_sector;
+
+ while (1) {
+ if (++loopct > 100)
+ return;
+ if ((current_minor & mask) == 0)
+ return;
+ if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+ return;
+
+ if ((*(__u16 *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
+ goto done;
+
+ p = (struct partition *) (0x1BE + bh->b_data);
+
+ this_size = hd->part[MINOR(dev)].nr_sects;
+
+ /*
+ * Usually, the first entry is the real data partition,
+ * the 2nd entry is the next extended partition, or empty,
+ * and the 3rd and 4th entries are unused.
+ * However, DRDOS sometimes has the extended partition as
+ * the first entry (when the data partition is empty),
+ * and OS/2 seems to use all four entries.
+ */
+
+ /*
+ * First process the data partition(s)
+ */
+ for (i=0; i<4; i++, p++) {
+ if (!NR_SECTS(p) || is_extended_partition(p))
+ continue;
+
+ /* Check the 3rd and 4th entries -
+ these sometimes contain random garbage */
+ if (i >= 2
+ && START_SECT(p) + NR_SECTS(p) > this_size
+ && (this_sector + START_SECT(p) < first_sector ||
+ this_sector + START_SECT(p) + NR_SECTS(p) >
+ first_sector + first_size))
+ continue;
+
+ add_gd_partition(hd, current_minor,
+ this_sector+START_SECT(p)*sector_size,
+ NR_SECTS(p)*sector_size);
+#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
+ if (SYS_IND(p) == LINUX_RAID_PARTITION) {
+ md_autodetect_dev(MKDEV(hd->major,current_minor));
+ }
+#endif
+
+ current_minor++;
+ loopct = 0;
+ if ((current_minor & mask) == 0)
+ goto done;
+ }
+ /*
+ * Next, process the (first) extended partition, if present.
+ * (So far, there seems to be no reason to make
+ * extended_partition() recursive and allow a tree
+ * of extended partitions.)
+ * It should be a link to the next logical partition.
+ * Create a minor for this just long enough to get the next
+ * partition table. The minor will be reused for the next
+ * data partition.
+ */
+ p -= 4;
+ for (i=0; i<4; i++, p++)
+ if(NR_SECTS(p) && is_extended_partition(p))
+ break;
+ if (i == 4)
+ goto done; /* nothing left to do */
+
+ hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
+ hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
+ this_sector = first_sector + START_SECT(p) * sector_size;
+ dev = MKDEV(hd->major, current_minor);
+
+ /* Use bforget(), as we have changed the disk geometry */
+ bforget(bh);
+ }
+done:
+ bforget(bh);
+}
+
+static inline struct buffer_head *
+get_partition_table_block(struct gendisk *hd, int minor, int blocknr) {
+ kdev_t dev = MKDEV(hd->major, minor);
+ return bread(dev, blocknr, get_ptable_blocksize(dev));
+}
+
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+
+/* [email protected]: Solaris has a nasty indicator: 0x82 which also
+ indicates linux swap. Be careful before believing this is Solaris. */
+
+static void
+solaris_x86_partition(struct gendisk *hd, int minor) {
+ long offset = hd->part[minor].start_sect;
+
+ struct buffer_head *bh;
+ struct solaris_x86_vtoc *v;
+ struct solaris_x86_slice *s;
+ int i;
+ char buf[40];
+
+ if(!(bh = get_partition_table_block(hd, minor, 0)))
+ return;
+ v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
+ if(v->v_sanity != SOLARIS_X86_VTOC_SANE) {
+ brelse(bh);
+ return;
+ }
+ printk(" %s: <solaris:", disk_name(hd, minor, buf));
+ if(v->v_version != 1) {
+ printk(" cannot handle version %ld vtoc>\n", v->v_version);
+ brelse(bh);
+ return;
+ }
+ for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
+ s = &v->v_slice[i];
+
+ if (s->s_size == 0)
+ continue;
+ printk(" [s%d]", i);
+ /* solaris partitions are relative to current MS-DOS
+ * one but add_gd_partition starts relative to sector
+ * zero of the disk. Therefore, must add the offset
+ * of the current partition */
+ add_gd_partition(hd, current_minor, s->s_start+offset, s->s_size);
+ current_minor++;
+ }
+ brelse(bh);
+ printk(" >\n");
+}
+#endif
+
+#ifdef CONFIG_BSD_DISKLABEL
+static void
+check_and_add_bsd_partition(struct gendisk *hd,
+ struct bsd_partition *bsd_p, int minor) {
+ struct hd_struct *lin_p;
+ /* check relative position of partitions. */
+ for (lin_p = hd->part + 1 + minor;
+ lin_p - hd->part - minor < current_minor; lin_p++) {
+ /* no relationship -> try again */
+ if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset ||
+ lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
+ continue;
+ /* equal -> no need to add */
+ if (lin_p->start_sect == bsd_p->p_offset &&
+ lin_p->nr_sects == bsd_p->p_size)
+ return;
+ /* bsd living within dos partition */
+ if (lin_p->start_sect <= bsd_p->p_offset && lin_p->start_sect
+ + lin_p->nr_sects >= bsd_p->p_offset + bsd_p->p_size) {
+#ifdef DEBUG_BSD_DISKLABEL
+ printk("w: %d %ld+%ld,%d+%d",
+ lin_p - hd->part,
+ lin_p->start_sect, lin_p->nr_sects,
+ bsd_p->p_offset, bsd_p->p_size);
+#endif
+ break;
+ }
+ /* ouch: bsd and linux overlap. Don't even try for that partition */
+#ifdef DEBUG_BSD_DISKLABEL
+ printk("???: %d %ld+%ld,%d+%d",
+ lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
+ bsd_p->p_offset, bsd_p->p_size);
+#endif
+ printk("???");
+ return;
+ } /* if the bsd partition is not currently known to linux, we end
+ * up here
+ */
+ add_gd_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size);
+ current_minor++;
+}
+
+/*
+ * Create devices for BSD partitions listed in a disklabel, under a
+ * dos-like partition. See extended_partition() for more information.
+ */
+static void bsd_disklabel_partition(struct gendisk *hd, int minor, int type) {
+ struct buffer_head *bh;
+ struct bsd_disklabel *l;
+ struct bsd_partition *p;
+ int max_partitions;
+ int mask = (1 << hd->minor_shift) - 1;
+ char buf[40];
+
+ if (!(bh = get_partition_table_block(hd, minor, 0)))
+ return;
+ l = (struct bsd_disklabel *) (bh->b_data+512);
+ if (l->d_magic != BSD_DISKMAGIC) {
+ brelse(bh);
+ return;
+ }
+ printk(" %s:", disk_name(hd, minor, buf));
+ printk((type == OPENBSD_PARTITION) ? " <openbsd:" :
+ (type == NETBSD_PARTITION) ? " <netbsd:" : " <bsd:");
+
+ max_partitions = ((type == OPENBSD_PARTITION) ? OPENBSD_MAXPARTITIONS
+ : BSD_MAXPARTITIONS);
+ if (l->d_npartitions < max_partitions)
+ max_partitions = l->d_npartitions;
+ for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
+ if ((current_minor & mask) >= (4 + hd->max_p))
+ break;
+
+ if (p->p_fstype != BSD_FS_UNUSED)
+ check_and_add_bsd_partition(hd, p, minor);
+ }
+
+ /* Use bforget(), as we have changed the disk setup */
+ bforget(bh);
+
+ printk(" >\n");
+}
+#endif
+
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+/*
+ * Create devices for Unixware partitions listed in a disklabel, under a
+ * dos-like partition. See extended_partition() for more information.
+ */
+static void unixware_partition(struct gendisk *hd, int minor) {
+ struct buffer_head *bh;
+ struct unixware_disklabel *l;
+ struct unixware_slice *p;
+ int mask = (1 << hd->minor_shift) - 1;
+ char buf[40];
+
+ if (!(bh = get_partition_table_block(hd, minor, 14)))
+ return;
+ l = (struct unixware_disklabel *) (bh->b_data+512);
+ if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
+ le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
+ brelse(bh);
+ return;
+ }
+ printk(" %s: <unixware:", disk_name(hd, minor, buf));
+ p = &l->vtoc.v_slice[1];
+ /* I omit the 0th slice as it is the same as whole disk. */
+ while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
+ if ((current_minor & mask) == 0)
+ break;
+
+ if (p->s_label != UNIXWARE_FS_UNUSED) {
+ add_gd_partition(hd, current_minor, START_SECT(p),
+ NR_SECTS(p));
+ current_minor++;
+ }
+ p++;
+ }
+ /* Use bforget, as we have changed the disk setup */
+ bforget(bh);
+ printk(" >\n");
+}
+#endif
+
+static int
+msdos_partition(struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector, int first_part_minor) {
+ int i, minor = current_minor = first_part_minor;
+ struct buffer_head *bh;
+ struct partition *p;
+ unsigned char *data;
+ int mask = (1 << hd->minor_shift) - 1;
+ int sector_size = get_hardsect_size(dev) / 512;
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ int tested_for_xlate = 0;
+
+read_mbr:
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_IDE_MODULE) */
+ if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
+ if (warn_no_part) printk(" unable to read partition table\n");
+ return -1;
+ }
+ data = bh->b_data;
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+check_table:
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_IDE_MODULE) */
+ /* Use bforget(), because we may have changed the disk geometry */
+ if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+ bforget(bh);
+ return 0;
+ }
+ p = (struct partition *) (0x1be + data);
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ if (!tested_for_xlate++) { /* Do this only once per disk */
+ /*
+ * Look for various forms of IDE disk geometry translation
+ */
+ unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
+ int heads = 0;
+ /*
+ * The i386 partition handling programs very often
+ * make partitions end on cylinder boundaries.
+ * There is no need to do so, and Linux fdisk doesnt always
+ * do this, and Windows NT on Alpha doesnt do this either,
+ * but still, this helps to guess #heads.
+ */
+ for (i = 0; i < 4; i++) {
+ struct partition *q = &p[i];
+ if (NR_SECTS(q)) {
+ if ((q->sector & 63) == 1 &&
+ (q->end_sector & 63) == 63)
+ heads = q->end_head + 1;
+ break;
+ }
+ }
+ if (SYS_IND(p) == EZD_PARTITION) {
+ /*
+ * Accesses to sector 0 must go to sector 1 instead.
+ */
+ if (ide_xlate_1024(dev, -1, heads, " [EZD]")) {
+ data += 512;
+ goto check_table;
+ }
+ } else if (SYS_IND(p) == DM6_PARTITION) {
+
+ /*
+ * Everything on the disk is offset by 63 sectors,
+ * including a "new" MBR with its own partition table.
+ */
+ if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]")) {
+ bforget(bh);
+ goto read_mbr; /* start over with new MBR */
+ }
+ } else if (sig <= 0x1ae &&
+ data[sig] == 0xAA && data[sig+1] == 0x55 &&
+ (data[sig+2] & 1)) {
+ /* DM6 signature in MBR, courtesy of OnTrack */
+ (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
+ } else if (SYS_IND(p) == DM6_AUX1PARTITION ||
+ SYS_IND(p) == DM6_AUX3PARTITION) {
+ /*
+ * DM6 on other than the first (boot) drive
+ */
+ (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
+ } else {
+ (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
+ }
+ }
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_IDE_MODULE) */
+
+ /* Look for partitions in two passes:
+ First find the primary partitions, and the DOS-type extended partitions.
+ On the second pass look inside *BSD and Unixware and Solaris partitions. */
+
+ current_minor += 4; /* first "extra" minor (for extended partitions) */
+ for (i=1 ; i<=4 ; minor++,i++,p++) {
+ if (!NR_SECTS(p))
+ continue;
+ add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size,
+ NR_SECTS(p)*sector_size);
+#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
+ if (SYS_IND(p) == LINUX_RAID_PARTITION) {
+ md_autodetect_dev(MKDEV(hd->major,minor));
+ }
+#endif
+ if (is_extended_partition(p)) {
+ printk(" <");
+ /*
+ * If we are rereading the partition table, we need
+ * to set the size of the partition so that we will
+ * be able to bread the block containing the extended
+ * partition info.
+ */
+ hd->sizes[minor] = hd->part[minor].nr_sects
+ >> (BLOCK_SIZE_BITS - 9);
+ extended_partition(hd, MKDEV(hd->major, minor));
+ printk(" >");
+ /* prevent someone doing mkfs or mkswap on an
+ extended partition, but leave room for LILO */
+ if (hd->part[minor].nr_sects > 2)
+ hd->part[minor].nr_sects = 2;
+ }
+ }
+
+ /*
+ * Check for old-style Disk Manager partition table
+ */
+ if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+ p = (struct partition *) (0x1be + data);
+ for (i = 4 ; i < 16 ; i++, current_minor++) {
+ p--;
+ if ((current_minor & mask) == 0)
+ break;
+ if (!(START_SECT(p) && NR_SECTS(p)))
+ continue;
+ add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
+ }
+ }
+ printk("\n");
+
+ /* second pass - output for each on a separate line */
+ minor -= 4;
+ p = (struct partition *) (0x1be + data);
+ for (i=1 ; i<=4 ; minor++,i++,p++) {
+ if (!NR_SECTS(p))
+ continue;
+#ifdef CONFIG_BSD_DISKLABEL
+ if (SYS_IND(p) == BSD_PARTITION ||
+ SYS_IND(p) == NETBSD_PARTITION ||
+ SYS_IND(p) == OPENBSD_PARTITION)
+ bsd_disklabel_partition(hd, minor, SYS_IND(p));
+#endif
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+ if (SYS_IND(p) == UNIXWARE_PARTITION)
+ unixware_partition(hd, minor);
+#endif
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+ if(SYS_IND(p) == SOLARIS_X86_PARTITION)
+ solaris_x86_partition(hd, minor);
+#endif
+ }
+
+ bforget(bh);
+ return 1;
+}
+
+#define check_partition msdos_partition
+#include "partition_module.h"
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/osf.c linux/fs/partitions/osf.c
--- linux-2.4.0-test10-pre6/fs/partitions/osf.c Wed Feb 16 15:42:06 2000
+++ linux/fs/partitions/osf.c Sat Oct 28 22:54:04 2000
@@ -17,8 +17,9 @@
#include "check.h"
#include "osf.h"

-int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
- int current_minor)
+static int
+osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+ int current_minor)
{
int i;
int mask = (1 << hd->minor_shift) - 1;
@@ -84,3 +85,5 @@
return 1;
}

+#define check_partition osf_partition
+#include "partition_module.h"
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/partition_module.h linux/fs/partitions/partition_module.h
--- linux-2.4.0-test10-pre6/fs/partitions/partition_module.h Wed Dec 31 16:00:00 1969
+++ linux/fs/partitions/partition_module.h Sat Oct 28 22:50:50 2000
@@ -0,0 +1,43 @@
+/* Copyright 2000 Yggdrasil Computing, Inc.
+ Written by Adam J. Richter
+
+ This file may be copied under the terms and conditions of version
+ 2 of the GNU General Public License, as published by the Free
+ Software Foundation (Cambridge, Massachussetts, USA).
+
+*/
+
+/*
+ This file should be #include'ed by each partition handling module,
+ each of which #define check_partition to the name of its partition
+ checking routine, like so:
+
+ #define check_partition msdos_partition
+ #include "partition_module.h"
+
+*/
+
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
+
+static struct partition_ops ops = {
+ check_partition,
+ NULL
+};
+
+static int __init
+init_partitioning(void)
+{
+ register_partition_ops(&ops);
+ return 0;
+}
+
+static void __exit
+cleanup_partitioning(void)
+{
+ unregister_partition_ops(&ops);
+}
+
+module_init(init_partitioning);
+module_exit(cleanup_partitioning);
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/sgi.c linux/fs/partitions/sgi.c
--- linux-2.4.0-test10-pre6/fs/partitions/sgi.c Sun Mar 12 19:39:39 2000
+++ linux/fs/partitions/sgi.c Sat Oct 28 22:54:04 2000
@@ -17,7 +17,9 @@
#include "check.h"
#include "sgi.h"

-int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int current_minor)
+static int
+sgi_partition(struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector, int current_minor)
{
int i, csum, magic;
unsigned int *ui, start, blocks, cs;
@@ -84,3 +86,6 @@
brelse(bh);
return 1;
}
+
+#define check_partition sgi_partition
+#include "partition_module.h"
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/sun.c linux/fs/partitions/sun.c
--- linux-2.4.0-test10-pre6/fs/partitions/sun.c Wed Feb 16 15:42:06 2000
+++ linux/fs/partitions/sun.c Sat Oct 28 22:54:04 2000
@@ -19,7 +19,8 @@
#include "check.h"
#include "sun.h"

-int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+static int
+sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
{
int i, csum;
unsigned short *ush;
@@ -87,3 +88,5 @@
return 1;
}

+#define check_partition sun_partition
+#include "partition_module.h"
diff --new-file -u -r linux-2.4.0-test10-pre6/fs/partitions/ultrix.c linux/fs/partitions/ultrix.c
--- linux-2.4.0-test10-pre6/fs/partitions/ultrix.c Sun Jul 9 22:21:41 2000
+++ linux/fs/partitions/ultrix.c Sat Oct 28 22:54:04 2000
@@ -14,8 +14,9 @@

#include "check.h"

-int ultrix_partition(struct gendisk *hd, kdev_t dev,
- unsigned long first_sector, int first_part_minor)
+static int
+ultrix_partition(struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector, int first_part_minor)
{
int i;
struct buffer_head *bh;
@@ -58,3 +59,6 @@
return 0;
}
}
+
+#define check_partition ultrix_partition
+#include "partition_module.h"