Messages in this thread Patch in this message | | | Date | Fri, 14 Jan 2000 23:44:38 +0100 (MET) | From | Andries.Brouwer@cwi ... | Subject | [PATCH] partition handling |
| |
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/
| |