Re: [PATCH] bsd disklabel detection

From: Ion Badulescu (ionut@moisil.cs.columbia.edu)
Date: Sun Mar 26 2000 - 11:56:57 EST


On Thu, 23 Mar 2000 Andries.Brouwer@cwi.nl wrote:

> > Would it be reasonable to switch the two,
>
> Yes, with a comment why.

It turns out that, even though the osf disklabel is identical to the bsd
disklabel, it's placed differently on the disk.

So I pull out the bsd bits from msdos.c into their own file, made both
msdos and osf call them, and added another config option for stand-alone
bsd disklabels.

The resulting patch is attached below.

> [And in case you make a new patch: I do not think
> printk((type == OPENBSD_PARTITION) ? " <openbsd:" :
> + printk((type == BSDI_PARTITION) ? " <bsdi:" :
> will compile.]

Yeah, copy&paste error combine with an untested "obviously
correct" patch. The second patch did compile though.

Thanks,
Ion

-- 
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.
--------------------------------
diff -urNX diff_kernel_excludes linux-2.3-vanilla/Documentation/Configure.help linux-2.3.bad/Documentation/Configure.help
--- linux-2.3-vanilla/Documentation/Configure.help	Fri Mar 24 12:34:58 2000
+++ linux-2.3.bad/Documentation/Configure.help	Sun Mar 26 10:11:20 2000
@@ -10037,6 +10037,21 @@
   Say Y here if you would like to use hard disks under Linux which
   were partitioned on an Alpha machine.
 
+BSD disklabel on entire disk support
+CONFIG_BSD_PARTITION
+
+  Various BSD's can use their own hard disk partition scheme on your
+  PC. It installs a new partition table in BSD disklabel format in the
+  first sector of the hard disk. Saying Y here allows you to read
+  these disklabels and further mount BSD partitions from within
+  Linux if you have also said Y to "UFS file system support", above.
+
+  It is also possible to install the BSD disklabel within one DOS
+  partition. To handle that you should enable 
+  'BSD disklabel within DOS partition support' below.
+
+  If you don't know what all this is about, say N.
+
 Macintosh partition map support
 CONFIG_MAC_PARTITION
   Say Y here if you would like to use hard disks under Linux which
@@ -10047,16 +10062,21 @@
   Say Y here if you would like to use hard disks under Linux which
   were partitioned on an x86 PC (not necessarily by DOS).
 
-BSD disklabel (FreeBSD partition tables) support
+BSD disklabel within DOS partition support
 CONFIG_BSD_DISKLABEL
-  FreeBSD uses its own hard disk partition scheme on your PC. It
+  Various BSD's use their own hard disk partition scheme on your PC. It
   requires only one entry in the primary partition table of your disk
   and manages it similarly to DOS extended partitions, putting in its
   first sector a new partition table in BSD disklabel format. Saying Y
-  here allows you to read these disklabels and further mount FreeBSD
+  here allows you to read these disklabels and further mount BSD
   partitions from within Linux if you have also said Y to "UFS
-  file system support", above. If you don't know what all this is
-  about, say N.
+  file system support", above.
+
+  It is also possible to install BSD such that there is no DOS
+  partition table, only the BSD disklabel. To handle that you should
+  enable 'BSD disklabel on entire disk support' above.
+
+  If you don't know what all this is about, say N.
 
 Sun partition tables support
 CONFIG_SUN_PARTITION
diff -urNX diff_kernel_excludes linux-2.3-vanilla/fs/partitions/Config.in linux-2.3.bad/fs/partitions/Config.in
--- linux-2.3-vanilla/fs/partitions/Config.in	Fri Feb 11 01:02:32 2000
+++ linux-2.3.bad/fs/partitions/Config.in	Sun Mar 26 10:02:42 2000
@@ -14,10 +14,11 @@
    bool '  Alpha OSF partition support' CONFIG_OSF_PARTITION
    bool '  Amiga partition table support' CONFIG_AMIGA_PARTITION
    bool '  Atari partition table support' CONFIG_ATARI_PARTITION
+   bool '  BSD disklabel on entire disk support' CONFIG_BSD_PARTITION
    bool '  Macintosh partition map support' CONFIG_MAC_PARTITION
    bool '  PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
    if [ "$CONFIG_MSDOS_PARTITION" = "y" ]; then
-      bool '    BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
+      bool '    BSD disklabel within DOS partition support' CONFIG_BSD_DISKLABEL
       bool '    Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
       bool '    Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
    fi
diff -urNX diff_kernel_excludes linux-2.3-vanilla/fs/partitions/Makefile linux-2.3.bad/fs/partitions/Makefile
--- linux-2.3-vanilla/fs/partitions/Makefile	Thu Aug 12 15:26:06 1999
+++ linux-2.3.bad/fs/partitions/Makefile	Sun Mar 26 10:03:00 2000
@@ -22,16 +22,23 @@
 O_OBJS += atari.o
 endif
 
+ifeq ($(CONFIG_BSD_DISKLABEL),y)
+O_OBJS += bsd.o
+endif
+
 ifeq ($(CONFIG_MAC_PARTITION),y)
 O_OBJS += mac.o
 endif
 
 ifeq ($(CONFIG_MSDOS_PARTITION),y)
 O_OBJS += msdos.o
+ifeq ($(CONFIG_BSD_DISKLABEL),y)
+O_OBJS += bsd.o
+endif
 endif
 
 ifeq ($(CONFIG_OSF_PARTITION),y)
-O_OBJS += osf.o
+O_OBJS += osf.o bsd.o
 endif
 
 ifeq ($(CONFIG_SGI_PARTITION),y)
diff -urNX diff_kernel_excludes linux-2.3-vanilla/fs/partitions/bsd.c linux-2.3.bad/fs/partitions/bsd.c
--- linux-2.3-vanilla/fs/partitions/bsd.c	Wed Dec 31 19:00:00 1969
+++ linux-2.3.bad/fs/partitions/bsd.c	Sun Mar 26 11:21:01 2000
@@ -0,0 +1,133 @@
+/*
+ *  fs/partitions/bsd.c
+ *
+ *  Code extracted from fs/partitions/msdos.c
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *
+ */
+
+#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 <asm/system.h>
+
+#include "check.h"
+#include "bsd.h"
+#include "osf.h"
+
+/*
+ * 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>
+
+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));
+}
+
+void check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
+				 u_long first_sector, int minor, int current_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, first_sector + bsd_p->p_offset, bsd_p->p_size);
+}
+
+/*
+ * Create devices for BSD partitions listed in a disklabel, under a
+ * dos-like partition. See extended_partition() for more information.
+ *
+ * This function handles OSF partitions as well.
+ */
+int bsd_disklabel_partition(struct gendisk *hd, u_long offset, u_long first_sector,
+			    int minor, int *current_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 0;
+	l = (struct bsd_disklabel *) (bh->b_data + offset);
+	if (l->d_magic != BSD_DISKMAGIC) {
+		brelse(bh);
+		return 0;
+	}
+	if (minor != 0)
+		printk(" %s:", disk_name(hd, minor, buf));
+	printk((type == OPENBSD_PARTITION) ? " <openbsd:" :
+	       (type == BSDI_PARTITION || type == OLDBSDI_PARTITION) ? " <bsdi:" :
+	       (type == NETBSD_PARTITION) ? " <netbsd:" :
+	       (type == OSF_PARTITION) ? " <osf:" : " <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) == 0)
+			break;
+
+		/* osf has p->p_size !=0 -- is that needed as well? */
+		if (p->p_fstype != BSD_FS_UNUSED) {
+			check_and_add_bsd_partition(hd, p, first_sector, minor, *current_minor);
+			(*current_minor)++;
+		}
+
+	}
+
+	/* Use bforget(), as we have changed the disk setup */
+	bforget(bh);
+
+	printk(" >\n");
+	return 1;
+}
+
+#ifdef CONFIG_BSD_PARTITION
+int bsd_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+		  int current_minor)
+{
+	return bsd_disklabel_partition(hd, 512, first_sector, 0, &current_minor, BSD_PARTITION);
+}
+#endif
diff -urNX diff_kernel_excludes linux-2.3-vanilla/fs/partitions/bsd.h linux-2.3.bad/fs/partitions/bsd.h
--- linux-2.3-vanilla/fs/partitions/bsd.h	Wed Dec 31 19:00:00 1969
+++ linux-2.3.bad/fs/partitions/bsd.h	Sun Mar 26 11:08:13 2000
@@ -0,0 +1,9 @@
+/*
+ *  fs/partitions/bsd.h
+ */
+
+int bsd_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
+		  int current_minor);
+
+int bsd_disklabel_partition(struct gendisk *hd, u_long offset, u_long first_sector,
+			    int minor, int *current_minor, int type);
diff -urNX diff_kernel_excludes linux-2.3-vanilla/fs/partitions/check.c linux-2.3.bad/fs/partitions/check.c
--- linux-2.3-vanilla/fs/partitions/check.c	Sat Feb 26 11:25:35 2000
+++ linux-2.3.bad/fs/partitions/check.c	Sun Mar 26 11:51:52 2000
@@ -25,6 +25,7 @@
 #include "acorn.h"
 #include "amiga.h"
 #include "atari.h"
+#include "bsd.h"
 #include "mac.h"
 #include "msdos.h"
 #include "osf.h"
@@ -43,6 +44,14 @@
 static int (*check_part[])(struct gendisk *hd, kdev_t dev, unsigned long first_sect, int first_minor) = {
 #ifdef CONFIG_ACORN_PARTITION
 	acorn_partition,
+#endif
+	/*
+	 * It is important to keep bsd_partition _before_ msdos partition,
+	 * full-disk bsd disklabels also have the msdos 0x55aa signature
+	 * and would confuse msdos_partition rather badly
+	 */
+#ifdef CONFIG_BSD_PARTITION
+	bsd_partition,
 #endif
 #ifdef CONFIG_MSDOS_PARTITION
 	msdos_partition,
diff -urNX diff_kernel_excludes linux-2.3-vanilla/fs/partitions/msdos.c linux-2.3.bad/fs/partitions/msdos.c
--- linux-2.3-vanilla/fs/partitions/msdos.c	Fri Mar 24 12:34:59 2000
+++ linux-2.3.bad/fs/partitions/msdos.c	Sun Mar 26 10:21:51 2000
@@ -35,6 +35,7 @@
 
 #include "check.h"
 #include "msdos.h"
+#include "bsd.h"
 
 static int current_minor;
 
@@ -218,90 +219,6 @@
 }
 #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
@@ -482,8 +399,11 @@
 #ifdef CONFIG_BSD_DISKLABEL
 		if (SYS_IND(p) == BSD_PARTITION ||
 		    SYS_IND(p) == NETBSD_PARTITION ||
+		    SYS_IND(p) == OLDBSDI_PARTITION ||
+		    SYS_IND(p) == BSDI_PARTITION ||
 		    SYS_IND(p) == OPENBSD_PARTITION)
-			bsd_disklabel_partition(hd, minor, SYS_IND(p));
+			bsd_disklabel_partition(hd, 512, first_sector,
+						minor, &current_minor, SYS_IND(p));
 #endif
 #ifdef CONFIG_UNIXWARE_DISKLABEL
 		if (SYS_IND(p) == UNIXWARE_PARTITION)
diff -urNX diff_kernel_excludes linux-2.3-vanilla/fs/partitions/osf.c linux-2.3.bad/fs/partitions/osf.c
--- linux-2.3-vanilla/fs/partitions/osf.c	Wed Feb 16 18:42:06 2000
+++ linux-2.3.bad/fs/partitions/osf.c	Sun Mar 26 11:21:14 2000
@@ -16,71 +16,11 @@
 
 #include "check.h"
 #include "osf.h"
+#include "bsd.h"
 
 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;
-	struct buffer_head *bh;
-	struct disklabel {
-		u32 d_magic;
-		u16 d_type,d_subtype;
-		u8 d_typename[16];
-		u8 d_packname[16];
-		u32 d_secsize;
-		u32 d_nsectors;
-		u32 d_ntracks;
-		u32 d_ncylinders;
-		u32 d_secpercyl;
-		u32 d_secprtunit;
-		u16 d_sparespertrack;
-		u16 d_sparespercyl;
-		u32 d_acylinders;
-		u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
-		u32 d_headswitch, d_trkseek, d_flags;
-		u32 d_drivedata[5];
-		u32 d_spare[5];
-		u32 d_magic2;
-		u16 d_checksum;
-		u16 d_npartitions;
-		u32 d_bbsize, d_sbsize;
-		struct d_partition {
-			u32 p_size;
-			u32 p_offset;
-			u32 p_fsize;
-			u8  p_fstype;
-			u8  p_frag;
-			u16 p_cpg;
-		} d_partitions[8];
-	} * label;
-	struct d_partition * partition;
-
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
-		if (warn_no_part) printk("unable to read partition table\n");
-		return -1;
-	}
-	label = (struct disklabel *) (bh->b_data+64);
-	partition = label->d_partitions;
-	if (label->d_magic != DISKLABELMAGIC) {
-		brelse(bh);
-		return 0;
-	}
-	if (label->d_magic2 != DISKLABELMAGIC) {
-		brelse(bh);
-		return 0;
-	}
-	for (i = 0 ; i < label->d_npartitions; i++, partition++) {
-		if ((current_minor & mask) == 0)
-		        break;
-		if (partition->p_size)
-			add_gd_partition(hd, current_minor,
-				first_sector+partition->p_offset,
-				partition->p_size);
-		current_minor++;
-	}
-	printk("\n");
-	brelse(bh);
-	return 1;
+	return bsd_disklabel_partition(hd, 64, first_sector, 0, &current_minor, OSF_PARTITION);
 }
 
diff -urNX diff_kernel_excludes linux-2.3-vanilla/fs/partitions/osf.h linux-2.3.bad/fs/partitions/osf.h
--- linux-2.3-vanilla/fs/partitions/osf.h	Thu Aug 12 15:26:06 1999
+++ linux-2.3.bad/fs/partitions/osf.h	Sun Mar 26 10:22:37 2000
@@ -2,7 +2,8 @@
  *  fs/partitions/osf.h
  */
 
-#define DISKLABELMAGIC (0x82564557UL)
+/* this is fake, used for pretty-printing */
+#define OSF_PARTITION		0x101   /* OSF disklabel */
 
 int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
 		  int current_minor);
diff -urNX diff_kernel_excludes linux-2.3-vanilla/include/linux/genhd.h linux-2.3.bad/include/linux/genhd.h
--- linux-2.3-vanilla/include/linux/genhd.h	Sat Mar 18 15:11:01 2000
+++ linux-2.3.bad/include/linux/genhd.h	Sun Mar 26 10:45:54 2000
@@ -107,11 +107,13 @@
 /*
  * BSD disklabel support by Yossi Gottlieb <yogo@math.tau.ac.il>
  * updated by Marc Espie <Marc.Espie@openbsd.org>
+ * and by Ion Badulescu <ionut@cs.columbia.edu>
  */
 #define FREEBSD_PARTITION	0xa5    /* FreeBSD Partition ID */
 #define OPENBSD_PARTITION	0xa6    /* OpenBSD Partition ID */
 #define NETBSD_PARTITION	0xa9    /* NetBSD Partition ID */
-#define BSDI_PARTITION		0xb7    /* BSDI Partition ID */
+#define BSDI_PARTITION		0x9f    /* BSDI Partition ID */
+#define OLDBSDI_PARTITION	0xb7    /* Old BSDI Partition ID */
 
 /* Ours is not to wonder why.. */
 #define BSD_PARTITION		FREEBSD_PARTITION

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Mar 31 2000 - 21:00:17 EST