]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] BSD partition handling
authorAndries E. Brouwer <andries.brouwer@cwi.nl>
Tue, 5 Mar 2002 07:18:18 +0000 (23:18 -0800)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Tue, 5 Mar 2002 07:18:18 +0000 (23:18 -0800)
I see that this is fixed now in 2.2 and 2.4, but 2.5 still has broken
BSD partition handling.  Here a fix.

Andries

fs/partitions/check.c
fs/partitions/check.h
fs/partitions/msdos.c

index 14b26548eb15671c93ec29376a791448ff28c592..48c25baf58f46b5f1e0f4b628c239f3e1fdc54bd 100644 (file)
@@ -480,3 +480,28 @@ int wipe_partitions(kdev_t dev)
 
        return 0;
 }
+
+/*
+ * Make sure that a proposed subpartition is strictly contained inside
+ * the parent partition.  If all is well, call add_gd_partition().
+ */
+int
+check_and_add_subpartition(struct gendisk *hd, int super_minor, int minor,
+                          int sub_start, int sub_size)
+{
+       int start = hd->part[super_minor].start_sect;
+       int size = hd->part[super_minor].nr_sects;
+
+       if (start == sub_start && size == sub_size) {
+               /* full parent partition, we have it already */
+               return 0;
+       }
+
+       if (start <= sub_start && start+size >= sub_start+sub_size) {
+               add_gd_partition(hd, minor, sub_start, sub_size);
+               return 1;
+       }
+
+       printk("bad subpartition - ignored\n");
+       return 0;
+}
index 3f8c810c0bda9d10f76c2f293603f8c7810ee90d..17818bd6401fdfd56dceb6609885595b37eaed92 100644 (file)
@@ -7,4 +7,10 @@
  */
 void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
 
+/*
+ * check_and_add_subpartition does the same for subpartitions
+ */
+int check_and_add_subpartition(struct gendisk *hd, int super_minor,
+                              int minor, int sub_start, int sub_size);
+
 extern int warn_no_part;
index fdf9a82713a91774ec802eecea49d85f88ada954..43c6ab1e7ce7f80b81015c1b6043c929d897ce4d 100644 (file)
@@ -261,50 +261,6 @@ solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
 }
 
 #ifdef CONFIG_BSD_DISKLABEL
-static void
-check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
-       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 <= le32_to_cpu(bsd_p->p_offset) ||
-                   lin_p->start_sect >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size))
-                       continue;       
-                       /* equal -> no need to add */
-               if (lin_p->start_sect == le32_to_cpu(bsd_p->p_offset) && 
-                       lin_p->nr_sects == le32_to_cpu(bsd_p->p_size)) 
-                       return;
-                       /* bsd living within dos partition */
-               if (lin_p->start_sect <= le32_to_cpu(bsd_p->p_offset) && lin_p->start_sect 
-                       + lin_p->nr_sects >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(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, 
-                               le32_to_cpu(bsd_p->p_offset),
-                               le32_to_cpu(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,
-                       le32_to_cpu(bsd_p->p_offset), le32_to_cpu(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, le32_to_cpu(bsd_p->p_offset),
-                        le32_to_cpu(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.
@@ -326,16 +282,22 @@ static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
                put_dev_sector(sect);
                return;
        }
-       printk(" %s: <%s", partition_name(hd, minor, buf), name);
+       printk(" %s: <%s:", partition_name(hd, minor, buf), name);
 
        if (le16_to_cpu(l->d_npartitions) < max_partitions)
                max_partitions = le16_to_cpu(l->d_npartitions);
-       for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
+       for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
+               int bsd_start, bsd_size;
+
                if ((*current_minor & mask) == 0)
                        break;
                if (p->p_fstype == BSD_FS_UNUSED) 
                        continue;
-               check_and_add_bsd_partition(hd, p, minor, current_minor);
+               bsd_start = le32_to_cpu(p->p_offset);
+               bsd_size = le32_to_cpu(p->p_size);
+               if (check_and_add_subpartition(hd, minor, *current_minor,
+                                              bsd_start, bsd_size))
+                       (*current_minor)++;
        }
        put_dev_sector(sect);
        printk(" >\n");