[PATCH] partition handling

From: Andries.Brouwer@cwi.nl
Date: Fri Jan 14 2000 - 17:44:38 EST


Last month Piotr Wilkin wrote:

: The problem is, that while kernel 2.0.36 sees all the slices AND
: the logical partitions on both disks, kernel 2.2.13 sees all the slices,
: and all the partitions on the first slice, but it doesn't see partitions
: on the second slice. So, while the partition read on 2.0.36 looks like
: this:
:
: hdb: hdb1 < hdb5 hdb6 hdb7 hdb8 > hdb2 < hdb9 hdb10 >
:
: on 2.2.13 (with compiled FreeBSD disklabel support) it looks like this:
:
: hdb: hdb1 hdb2 < hdb5 hdb6 hdb7 hdb8 >

Tigran Aivazian wrote yesterday or so:

: I am not sure the current algorithm for enumerating 3rd party
: partitions is perfect. It makes it very hard to switch between
: booting kernels with and without support for those partitions.
: E.g. I have 2.2.12 from Red Hat 6.1 that has no support for UnixWare
: and FreeBSD partitions and now use 2.3.40-pre1 with support for those
: two and all my normal (i.e. Linux ext2) partitions get shifted around.
: That;s not good.

Such complaints are familiar, and I have sent the patch below to people
complaining to me. Now that I see Tigran's post, let me submit this
for 2.3.40 or so. I just checked that it compiles on 2.3.39.
It yields

Partition check:
 hda: hda1 < hda5 hda6 > hda4
 hda4: <unixware: hda7 hda8 hda9 hda10 hda11 hda12 hda13 >
 hdb: hdb1 hdb2 hdb3 < hdb5 hdb6 hdb7 >
 hdc: [PTBL] [4441/255/63] hdc1 hdc2 hdc3 hdc4 < hdc5 >
 hdc3: <bsd: hdc6 hdc7 hdc8 hdc9 >

that is, DOS-type partitions are first examined and numbered as
DOS-type partitions, including extended and logical partitions,
and afterwards each is examined for known internal structure.
This way the numbering is a bit more stable, and as a side result
Piotr Wilkin's problem is solved.

Andries

diff -u --recursive --new-file ../linux-2.3.39/linux/fs/partitions/msdos.c ./linux/fs/partitions/msdos.c
--- ../linux-2.3.39/linux/fs/partitions/msdos.c Mon Oct 11 20:49:09 1999
+++ ./linux/fs/partitions/msdos.c Fri Jan 14 22:24:45 2000
@@ -163,25 +163,37 @@
         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
+
+/* james@bpgc.com: 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, kdev_t dev, long offset) {
+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 = bread(dev, 0, get_ptable_blocksize(dev))))
+ 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(" <solaris:");
+ printk(" %s: <solaris:", disk_name(hd, minor, buf));
         if(v->v_version != 1) {
- printk(" cannot handle version %ld vtoc>", v->v_version);
+ printk(" cannot handle version %ld vtoc>\n", v->v_version);
                 brelse(bh);
                 return;
         }
@@ -199,21 +211,21 @@
                 current_minor++;
         }
         brelse(bh);
- printk(" >");
+ printk(" >\n");
 }
 #endif
 
 #ifdef CONFIG_BSD_DISKLABEL
-static void check_and_add_bsd_partition(struct gendisk *hd,
- struct bsd_partition *bsd_p, kdev_t dev)
-{
+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(dev);
- lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) {
+ 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)
+ 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 &&
@@ -244,26 +256,32 @@
         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, kdev_t dev,
- int max_partitions)
-{
+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 = bread(dev,0,get_ptable_blocksize(dev))))
+ 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++) {
@@ -271,12 +289,13 @@
                         break;
 
                 if (p->p_fstype != BSD_FS_UNUSED)
- check_and_add_bsd_partition(hd, p, dev);
+ check_and_add_bsd_partition(hd, p, minor);
         }
 
         /* Use bforget(), as we have changed the disk setup */
         bforget(bh);
 
+ printk(" >\n");
 }
 #endif
 
@@ -285,14 +304,14 @@
  * 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, kdev_t dev)
-{
+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 = bread(dev, 14, get_ptable_blocksize(dev))))
+ 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 ||
@@ -300,7 +319,7 @@
                 brelse(bh);
                 return;
         }
- printk(" <unixware:");
+ 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) {
@@ -308,30 +327,26 @@
                         break;
 
                 if (p->s_label != UNIXWARE_FS_UNUSED) {
- add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
+ 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(" >");
+ printk(" >\n");
 }
 #endif
 
-int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
-{
+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_BSD_DISKLABEL
- /* no bsd disklabel as a default */
- kdev_t bsd_kdev = 0;
- int bsd_maxpart = BSD_MAXPARTITIONS;
-#endif
 #ifdef CONFIG_BLK_DEV_IDE
         int tested_for_xlate = 0;
 
@@ -345,7 +360,7 @@
 #ifdef CONFIG_BLK_DEV_IDE
 check_table:
 #endif
- /* Use bforget(), because we have potentially changed the disk geometry */
+ /* 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;
@@ -410,11 +425,16 @@
         }
 #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);
+ add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size,
+ NR_SECTS(p)*sector_size);
                 if (is_extended_partition(p)) {
                         printk(" <");
                         /*
@@ -432,44 +452,8 @@
                         if (hd->part[minor].nr_sects > 2)
                                 hd->part[minor].nr_sects = 2;
                 }
-#ifdef CONFIG_BSD_DISKLABEL
- /* tag first disklabel for late recognition */
- if (SYS_IND(p) == BSD_PARTITION || SYS_IND(p) == NETBSD_PARTITION) {
- printk("!");
- if (!bsd_kdev)
- bsd_kdev = MKDEV(hd->major, minor);
- } else if (SYS_IND(p) == OPENBSD_PARTITION) {
- printk("!");
- if (!bsd_kdev) {
- bsd_kdev = MKDEV(hd->major, minor);
- bsd_maxpart = OPENBSD_MAXPARTITIONS;
- }
- }
-#endif
-#ifdef CONFIG_UNIXWARE_DISKLABEL
- if (SYS_IND(p) == UNIXWARE_PARTITION)
- unixware_partition(hd, MKDEV(hd->major, minor));
-#endif
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-
- /* james@bpgc.com: Solaris has a nasty indicator: 0x82
- * which also means linux swap. For that reason, all
- * of the prints are done inside the
- * solaris_x86_partition routine */
-
- if(SYS_IND(p) == SOLARIS_X86_PARTITION) {
- solaris_x86_partition(hd, MKDEV(hd->major, minor),
- first_sector+START_SECT(p));
- }
-#endif
- }
-#ifdef CONFIG_BSD_DISKLABEL
- if (bsd_kdev) {
- printk(" <");
- bsd_disklabel_partition(hd, bsd_kdev, bsd_maxpart);
- printk(" >");
         }
-#endif
+
         /*
          * Check for old-style Disk Manager partition table
          */
@@ -485,6 +469,29 @@
                 }
         }
         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 -u --recursive --new-file ../linux-2.3.39/linux/fs/super.c ./linux/fs/super.c
--- ../linux-2.3.39/linux/fs/super.c Thu Jan 13 05:34:56 2000
+++ ./linux/fs/super.c Thu Jan 13 05:38:37 2000
@@ -932,7 +932,6 @@
 /*
  * Alters the mount flags of a mounted file system. Only the mount point
  * is used as a reference - file system type and the device are ignored.
- * FS-specific mount options can't be altered by remounting.
  */
 
 static int do_remount_sb(struct super_block *sb, int flags, char *data)

-
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 : Sat Jan 15 2000 - 21:00:25 EST