Commit a22f8253 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] partition parsing cleanup

struct gendisk and partition parsers divorced; all these parsers (IBM style,
disklabel, etc.) just fill the structure they get from check_partitions().

Actual setting the things up (filling hd_struct arrays, telling RAID that
we had found partitions worth a look, etc.) is taken into check_partitions()
and done only when we are done with parsing.  Parsers don't know (or care)
what majors/minors they are dealing with; that knowledge also went to
check_partitions().
parent d6d4f980
...@@ -1254,10 +1254,11 @@ void mfm_setup(char *str, int *ints) ...@@ -1254,10 +1254,11 @@ void mfm_setup(char *str, int *ints)
* since if there are any non-ADFS partitions on the disk, this won't work! * since if there are any non-ADFS partitions on the disk, this won't work!
* Hence, I want to get rid of this... * Hence, I want to get rid of this...
*/ */
void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads, void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
unsigned long discsize, unsigned int secsize) unsigned char heads, unsigned int secsize)
{ {
int drive = minor(dev) >> 6; int drive = MINOR(bdev->bd_dev) >> 6;
unsigned long disksize = bdev->bd_inode->i_size;
if (mfm_info[drive].cylinders == 1) { if (mfm_info[drive].cylinders == 1) {
mfm_info[drive].sectors = secsptrack; mfm_info[drive].sectors = secsptrack;
...@@ -1265,7 +1266,7 @@ void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads, ...@@ -1265,7 +1266,7 @@ void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads,
mfm_info[drive].cylinders = discsize / (secsptrack * heads * secsize); mfm_info[drive].cylinders = discsize / (secsptrack * heads * secsize);
if ((heads < 1) || (mfm_info[drive].cylinders > 1024)) { if ((heads < 1) || (mfm_info[drive].cylinders > 1024)) {
printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + (dev >> 6)); printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + drive);
/* These values are fairly arbitary, but are there so that if your /* These values are fairly arbitary, but are there so that if your
* lucky you can pick apart your disc to find out what is going on - * lucky you can pick apart your disc to find out what is going on -
......
...@@ -10,33 +10,14 @@ ...@@ -10,33 +10,14 @@
* Scan ADFS partitions on hard disk drives. * Scan ADFS partitions on hard disk drives.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/genhd.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include "check.h" #include "check.h"
#include "acorn.h" #include "acorn.h"
static void
adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads)
{
#ifdef CONFIG_BLK_DEV_MFM
extern void xd_set_geometry(kdev_t dev, unsigned char, unsigned char,
unsigned long, unsigned int);
if (major(dev) == MFM_ACORN_MAJOR) {
unsigned long totalblocks = hd->part[MINOR(dev)].nr_sects;
xd_set_geometry(dev, secspertrack, heads, totalblocks, 1);
}
#endif
}
static struct adfs_discrecord * static struct adfs_discrecord *
adfs_partition(struct gendisk *hd, char *name, char *data, adfs_partition(struct parsed_partitions *state, char *name, char *data,
unsigned long first_sector, int minor) unsigned long first_sector, int slot)
{ {
struct adfs_discrecord *dr; struct adfs_discrecord *dr;
unsigned int nr_sects; unsigned int nr_sects;
...@@ -54,14 +35,14 @@ adfs_partition(struct gendisk *hd, char *name, char *data, ...@@ -54,14 +35,14 @@ adfs_partition(struct gendisk *hd, char *name, char *data,
if (name) if (name)
printk(" [%s]", name); printk(" [%s]", name);
add_gd_partition(hd, minor, first_sector, nr_sects); put_partition(state, slot, first_sector, nr_sects);
return dr; return dr;
} }
#ifdef CONFIG_ACORN_PARTITION_RISCIX #ifdef CONFIG_ACORN_PARTITION_RISCIX
static int static int
riscix_partition(struct gendisk *hd, struct block_device *bdev, riscix_partition(struct parsed_partitions *state, struct block_device *bdev,
unsigned long first_sect, int minor, unsigned long nr_sects) unsigned long first_sect, int slot, unsigned long nr_sects)
{ {
Sector sect; Sector sect;
struct riscix_record *rr; struct riscix_record *rr;
...@@ -79,11 +60,11 @@ riscix_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -79,11 +60,11 @@ riscix_partition(struct gendisk *hd, struct block_device *bdev,
printk(" <"); printk(" <");
add_gd_partition(hd, minor++, first_sect, size); put_partition(state, slot++, first_sect, size);
for (part = 0; part < 8; part++) { for (part = 0; part < 8; part++) {
if (rr->part[part].one && if (rr->part[part].one &&
memcmp(rr->part[part].name, "All\0", 4)) { memcmp(rr->part[part].name, "All\0", 4)) {
add_gd_partition(hd, minor++, put_partition(state, slot++,
le32_to_cpu(rr->part[part].start), le32_to_cpu(rr->part[part].start),
le32_to_cpu(rr->part[part].length)); le32_to_cpu(rr->part[part].length));
printk("(%s)", rr->part[part].name); printk("(%s)", rr->part[part].name);
...@@ -92,26 +73,25 @@ riscix_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -92,26 +73,25 @@ riscix_partition(struct gendisk *hd, struct block_device *bdev,
printk(" >\n"); printk(" >\n");
} else { } else {
add_gd_partition(hd, minor++, first_sect, nr_sects); put_partition(state, slot++, first_sect, nr_sects);
} }
put_dev_sector(sect); put_dev_sector(sect);
return minor; return slot;
} }
#endif #endif
static int static int
linux_partition(struct gendisk *hd, struct block_device *bdev, linux_partition(struct parsed_partitions *state, struct block_device *bdev,
unsigned long first_sect, int minor, unsigned long nr_sects) unsigned long first_sect, int slot, unsigned long nr_sects)
{ {
Sector sect; Sector sect;
struct linux_part *linuxp; struct linux_part *linuxp;
unsigned int mask = (1 << hd->minor_shift) - 1;
unsigned long size = nr_sects > 2 ? 2 : nr_sects; unsigned long size = nr_sects > 2 ? 2 : nr_sects;
printk(" [Linux]"); printk(" [Linux]");
add_gd_partition(hd, minor++, first_sect, size); put_partition(state, slot++, first_sect, size);
linuxp = (struct linux_part *)read_dev_sector(bdev, first_sect, &sect); linuxp = (struct linux_part *)read_dev_sector(bdev, first_sect, &sect);
if (!linuxp) if (!linuxp)
...@@ -120,9 +100,9 @@ linux_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -120,9 +100,9 @@ linux_partition(struct gendisk *hd, struct block_device *bdev,
printk(" <"); printk(" <");
while (linuxp->magic == cpu_to_le32(LINUX_NATIVE_MAGIC) || while (linuxp->magic == cpu_to_le32(LINUX_NATIVE_MAGIC) ||
linuxp->magic == cpu_to_le32(LINUX_SWAP_MAGIC)) { linuxp->magic == cpu_to_le32(LINUX_SWAP_MAGIC)) {
if (!(minor & mask)) if (slot == state->limit)
break; break;
add_gd_partition(hd, minor++, first_sect + put_partition(state, slot++, first_sect +
le32_to_cpu(linuxp->start_sect), le32_to_cpu(linuxp->start_sect),
le32_to_cpu(linuxp->nr_sects)); le32_to_cpu(linuxp->nr_sects));
linuxp ++; linuxp ++;
...@@ -130,19 +110,20 @@ linux_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -130,19 +110,20 @@ linux_partition(struct gendisk *hd, struct block_device *bdev,
printk(" >"); printk(" >");
put_dev_sector(sect); put_dev_sector(sect);
return minor; return slot;
} }
#ifdef CONFIG_ACORN_PARTITION_CUMANA #ifdef CONFIG_ACORN_PARTITION_CUMANA
static int static int
adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev, adfspart_check_CUMANA(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int minor)
{ {
unsigned int start_blk = 0, mask = (1 << hd->minor_shift) - 1; unsigned long first_sector = 0;
unsigned int start_blk = 0;
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
char *name = "CUMANA/ADFS"; char *name = "CUMANA/ADFS";
int first = 1; int first = 1;
int slot = 1;
/* /*
* Try Cumana style partitions - sector 3 contains ADFS boot block * Try Cumana style partitions - sector 3 contains ADFS boot block
...@@ -165,10 +146,10 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev, ...@@ -165,10 +146,10 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
if (!data) if (!data)
return -1; return -1;
if (!(minor & mask)) if (slot == state->limit)
break; break;
dr = adfs_partition(hd, name, data, first_sector, minor++); dr = adfs_partition(state, name, data, first_sector, slot++);
if (!dr) if (!dr)
break; break;
...@@ -193,19 +174,19 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev, ...@@ -193,19 +174,19 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
#ifdef CONFIG_ACORN_PARTITION_RISCIX #ifdef CONFIG_ACORN_PARTITION_RISCIX
case PARTITION_RISCIX_SCSI: case PARTITION_RISCIX_SCSI:
/* RISCiX - we don't know how to find the next one. */ /* RISCiX - we don't know how to find the next one. */
minor = riscix_partition(hd, bdev, first_sector, slot = riscix_partition(state, bdev, first_sector,
minor, nr_sects); slot, nr_sects);
break; break;
#endif #endif
case PARTITION_LINUX: case PARTITION_LINUX:
minor = linux_partition(hd, bdev, first_sector, slot = linux_partition(state, bdev, first_sector,
minor, nr_sects); slot, nr_sects);
break; break;
} }
put_dev_sector(sect); put_dev_sector(sect);
if (minor == -1) if (slot == -1)
return minor; return -1;
} while (1); } while (1);
put_dev_sector(sect); put_dev_sector(sect);
return first ? 0 : 1; return first ? 0 : 1;
...@@ -218,8 +199,6 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev, ...@@ -218,8 +199,6 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
* *
* Params : hd - pointer to gendisk structure to store partition info. * Params : hd - pointer to gendisk structure to store partition info.
* dev - device number to access. * dev - device number to access.
* first_sector- first readable sector on the device.
* minor - first available minor on device.
* *
* Returns: -1 on error, 0 for no ADFS boot sector, 1 for ok. * Returns: -1 on error, 0 for no ADFS boot sector, 1 for ok.
* *
...@@ -228,20 +207,20 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev, ...@@ -228,20 +207,20 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
* hda2 = non-ADFS partition. * hda2 = non-ADFS partition.
*/ */
static int static int
adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev, adfspart_check_ADFS(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int minor)
{ {
unsigned long start_sect, nr_sects, sectscyl, heads; unsigned long start_sect, nr_sects, sectscyl, heads;
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
struct adfs_discrecord *dr; struct adfs_discrecord *dr;
unsigned char id; unsigned char id;
int slot = 1;
data = read_dev_sector(bdev, 6, &sect); data = read_dev_sector(bdev, 6, &sect);
if (!data) if (!data)
return -1; return -1;
dr = adfs_partition(hd, "ADFS", data, first_sector, minor++); dr = adfs_partition(state, "ADFS", data, 0, slot++);
if (!dr) { if (!dr) {
put_dev_sector(sect); put_dev_sector(sect);
return 0; return 0;
...@@ -253,9 +232,15 @@ adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev, ...@@ -253,9 +232,15 @@ adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
id = data[0x1fc] & 15; id = data[0x1fc] & 15;
put_dev_sector(sect); put_dev_sector(sect);
adfspart_setgeometry(to_kdev_t(bdev->bd_dev), dr->secspertrack, heads); #ifdef CONFIG_BLK_DEV_MFM
if (MAJOR(bdev->bd_dev) == MFM_ACORN_MAJOR) {
extern void xd_set_geometry(struct block_device *,
unsigned char, unsigned char, unsigned int);
xd_set_geometry(bdev, dr->secspertrack, heads, 1);
invalidate_bdev(bdev, 1); invalidate_bdev(bdev, 1);
truncate_inode_pages(bdev->bd_inode->i_mapping, 0); truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
}
#endif
/* /*
* Work out start of non-adfs partition. * Work out start of non-adfs partition.
...@@ -263,20 +248,18 @@ adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev, ...@@ -263,20 +248,18 @@ adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
nr_sects = (bdev->bd_inode->i_size >> 9) - start_sect; nr_sects = (bdev->bd_inode->i_size >> 9) - start_sect;
if (start_sect) { if (start_sect) {
first_sector += start_sect;
switch (id) { switch (id) {
#ifdef CONFIG_ACORN_PARTITION_RISCIX #ifdef CONFIG_ACORN_PARTITION_RISCIX
case PARTITION_RISCIX_SCSI: case PARTITION_RISCIX_SCSI:
case PARTITION_RISCIX_MFM: case PARTITION_RISCIX_MFM:
minor = riscix_partition(hd, bdev, first_sector, slot = riscix_partition(state, bdev, start_sect,
minor, nr_sects); slot, nr_sects);
break; break;
#endif #endif
case PARTITION_LINUX: case PARTITION_LINUX:
minor = linux_partition(hd, bdev, first_sector, slot = linux_partition(state, bdev, start_sect,
minor, nr_sects); slot, nr_sects);
break; break;
} }
} }
...@@ -304,8 +287,6 @@ static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long bloc ...@@ -304,8 +287,6 @@ static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long bloc
* Purpose: allocate ICS partitions. * Purpose: allocate ICS partitions.
* Params : hd - pointer to gendisk structure to store partition info. * Params : hd - pointer to gendisk structure to store partition info.
* dev - device number to access. * dev - device number to access.
* first_sector- first readable sector on the device.
* minor - first available minor on device.
* Returns: -1 on error, 0 for no ICS table, 1 for partitions ok. * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok.
* Alloc : hda = whole drive * Alloc : hda = whole drive
* hda1 = ADFS partition 0 on first drive. * hda1 = ADFS partition 0 on first drive.
...@@ -313,13 +294,13 @@ static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long bloc ...@@ -313,13 +294,13 @@ static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long bloc
* ..etc.. * ..etc..
*/ */
static int static int
adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev, adfspart_check_ICS(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int minor)
{ {
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
unsigned long sum; unsigned long sum;
unsigned int i, mask = (1 << hd->minor_shift) - 1; unsigned int i;
int slot;
struct ics_part *p; struct ics_part *p;
/* /*
...@@ -343,16 +324,13 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev, ...@@ -343,16 +324,13 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
printk(" [ICS]"); printk(" [ICS]");
for (p = (struct ics_part *)data; p->size; p++) { for (slot = 1, p = (struct ics_part *)data; p->size; p++) {
unsigned long start; u32 start = le32_to_cpu(p->start);
long size; u32 size = le32_to_cpu(p->size);
if ((minor & mask) == 0) if (slot == state->limit)
break; break;
start = le32_to_cpu(p->start);
size = le32_to_cpu(p->size);
if (size < 0) { if (size < 0) {
size = -size; size = -size;
...@@ -366,10 +344,8 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev, ...@@ -366,10 +344,8 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
} }
} }
if (size) { if (size)
add_gd_partition(hd, minor, first_sector + start, size); put_partition(state, slot++, start, size);
minor++;
}
} }
put_dev_sector(sect); put_dev_sector(sect);
...@@ -381,8 +357,6 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev, ...@@ -381,8 +357,6 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
* Purpose: allocate ICS partitions. * Purpose: allocate ICS partitions.
* Params : hd - pointer to gendisk structure to store partition info. * Params : hd - pointer to gendisk structure to store partition info.
* dev - device number to access. * dev - device number to access.
* first_sector- first readable sector on the device.
* minor - first available minor on device.
* Returns: -1 on error, 0 for no ICS table, 1 for partitions ok. * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok.
* Alloc : hda = whole drive * Alloc : hda = whole drive
* hda1 = ADFS partition 0 on first drive. * hda1 = ADFS partition 0 on first drive.
...@@ -391,13 +365,13 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev, ...@@ -391,13 +365,13 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
*/ */
#ifdef CONFIG_ACORN_PARTITION_POWERTEC #ifdef CONFIG_ACORN_PARTITION_POWERTEC
static int static int
adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev, adfspart_check_POWERTEC(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int minor)
{ {
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
struct ptec_partition *p; struct ptec_partition *p;
unsigned char checksum; unsigned char checksum;
int slot = 1;
int i; int i;
data = read_dev_sector(bdev, 0, &sect); data = read_dev_sector(bdev, 0, &sect);
...@@ -415,16 +389,11 @@ adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev, ...@@ -415,16 +389,11 @@ adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
printk(" [POWERTEC]"); printk(" [POWERTEC]");
for (i = 0, p = (struct ptec_partition *)data; i < 12; i++, p++) { for (i = 0, p = (struct ptec_partition *)data; i < 12; i++, p++) {
unsigned long start; u32 start = le32_to_cpu(p->start);
unsigned long size; u32 size = le32_to_cpu(p->size);
start = le32_to_cpu(p->start);
size = le32_to_cpu(p->size);
if (size) if (size)
add_gd_partition(hd, minor, first_sector + start, put_partition(state, slot++, start, size);
size);
minor++;
} }
put_dev_sector(sect); put_dev_sector(sect);
...@@ -432,7 +401,7 @@ adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev, ...@@ -432,7 +401,7 @@ adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
} }
#endif #endif
static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, int) = { static int (*partfn[])(struct parsed_partitions *, struct block_device *) = {
#ifdef CONFIG_ACORN_PARTITION_ICS #ifdef CONFIG_ACORN_PARTITION_ICS
adfspart_check_ICS, adfspart_check_ICS,
#endif #endif
...@@ -454,18 +423,15 @@ static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, i ...@@ -454,18 +423,15 @@ static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, i
* *
* Params : hd - pointer to gendisk structure * Params : hd - pointer to gendisk structure
* dev - device number to access * dev - device number to access
* first_sect - first available sector on the disk.
* first_minor - first available minor on this device.
* *
* Returns: -1 on error, 0 if not ADFS format, 1 if ok. * Returns: -1 on error, 0 if not ADFS format, 1 if ok.
*/ */
int acorn_partition(struct gendisk *hd, struct block_device *bdev, int acorn_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sect, int first_minor)
{ {
int i; int i;
for (i = 0; partfn[i]; i++) { for (i = 0; partfn[i]; i++) {
int r = partfn[i](hd, bdev, first_sect, first_minor); int r = partfn[i](state, bdev);
if (r) { if (r) {
if (r > 0) if (r > 0)
printk("\n"); printk("\n");
......
...@@ -50,6 +50,4 @@ struct ptec_partition { ...@@ -50,6 +50,4 @@ struct ptec_partition {
}; };
int acorn_partition(struct gendisk *hd, struct block_device *bdev, int acorn_partition(struct parsed_partitions *state, struct block_device *bdev);
unsigned long first_sect, int first_minor);
...@@ -7,14 +7,7 @@ ...@@ -7,14 +7,7 @@
* Re-organised Feb 1998 Russell King * Re-organised Feb 1998 Russell King
*/ */
#include <linux/fs.h> #include <linux/types.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/blk.h>
#include <asm/byteorder.h>
#include <linux/affs_hardblocks.h> #include <linux/affs_hardblocks.h>
#include "check.h" #include "check.h"
...@@ -31,14 +24,14 @@ checksum_block(u32 *m, int size) ...@@ -31,14 +24,14 @@ checksum_block(u32 *m, int size)
} }
int int
amiga_partition(struct gendisk *hd, struct block_device *bdev, amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int first_part_minor)
{ {
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
struct RigidDiskBlock *rdb; struct RigidDiskBlock *rdb;
struct PartitionBlock *pb; struct PartitionBlock *pb;
int start_sect, nr_sects, blk, part, res = 0; int start_sect, nr_sects, blk, part, res = 0;
int slot = 1;
for (blk = 0; ; blk++, put_dev_sector(sect)) { for (blk = 0; ; blk++, put_dev_sector(sect)) {
if (blk == RDB_ALLOCATION_LIMIT) if (blk == RDB_ALLOCATION_LIMIT)
...@@ -100,8 +93,7 @@ amiga_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -100,8 +93,7 @@ amiga_partition(struct gendisk *hd, struct block_device *bdev,
start_sect = be32_to_cpu(pb->pb_Environment[9]) * start_sect = be32_to_cpu(pb->pb_Environment[9]) *
be32_to_cpu(pb->pb_Environment[3]) * be32_to_cpu(pb->pb_Environment[3]) *
be32_to_cpu(pb->pb_Environment[5]); be32_to_cpu(pb->pb_Environment[5]);
add_gd_partition(hd,first_part_minor,start_sect,nr_sects); put_partition(state,slot++,start_sect,nr_sects);
first_part_minor++;
res = 1; res = 1;
} }
printk("\n"); printk("\n");
......
...@@ -2,7 +2,5 @@ ...@@ -2,7 +2,5 @@
* fs/partitions/amiga.h * fs/partitions/amiga.h
*/ */
int int amiga_partition(struct parsed_partitions *state, struct block_device *bdev);
amiga_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
...@@ -7,17 +7,7 @@ ...@@ -7,17 +7,7 @@
* Re-organised Feb 1998 Russell King * Re-organised Feb 1998 Russell King
*/ */
#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/ctype.h> #include <linux/ctype.h>
#include <asm/byteorder.h>
#include <asm/system.h>
#include "check.h" #include "check.h"
#include "atari.h" #include "atari.h"
...@@ -40,15 +30,14 @@ static inline int OK_id(char *s) ...@@ -40,15 +30,14 @@ static inline int OK_id(char *s)
memcmp (s, "RAW", 3) == 0 ; memcmp (s, "RAW", 3) == 0 ;
} }
int atari_partition (struct gendisk *hd, struct block_device *bdev, int atari_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int minor)
{ {
int m_lim = minor + (1 << hd->minor_shift);
Sector sect; Sector sect;
struct rootsector *rs; struct rootsector *rs;
struct partition_info *pi; struct partition_info *pi;
u32 extensect; u32 extensect;
u32 hd_size; u32 hd_size;
int slot;
#ifdef ICD_PARTS #ifdef ICD_PARTS
int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */ int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
#endif #endif
...@@ -58,7 +47,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev, ...@@ -58,7 +47,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
return -1; return -1;
/* Verify this is an Atari rootsector: */ /* Verify this is an Atari rootsector: */
hd_size = hd->part[minor - 1].nr_sects; hd_size = bdev->bd_inode->i_size >> 9;
if (!VALID_PARTITION(&rs->part[0], hd_size) && if (!VALID_PARTITION(&rs->part[0], hd_size) &&
!VALID_PARTITION(&rs->part[1], hd_size) && !VALID_PARTITION(&rs->part[1], hd_size) &&
!VALID_PARTITION(&rs->part[2], hd_size) && !VALID_PARTITION(&rs->part[2], hd_size) &&
...@@ -74,7 +63,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev, ...@@ -74,7 +63,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
pi = &rs->part[0]; pi = &rs->part[0];
printk (" AHDI"); printk (" AHDI");
for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++) { for (slot = 1; pi < &rs->part[4] && slot < state->limit; slot++, pi++) {
struct rootsector *xrs; struct rootsector *xrs;
Sector sect2; Sector sect2;
ulong partsect; ulong partsect;
...@@ -84,7 +73,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev, ...@@ -84,7 +73,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
/* active partition */ /* active partition */
if (memcmp (pi->id, "XGM", 3) != 0) { if (memcmp (pi->id, "XGM", 3) != 0) {
/* we don't care about other id's */ /* we don't care about other id's */
add_gd_partition (hd, minor, be32_to_cpu(pi->st), put_partition (state, slot, be32_to_cpu(pi->st),
be32_to_cpu(pi->siz)); be32_to_cpu(pi->siz));
continue; continue;
} }
...@@ -109,7 +98,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev, ...@@ -109,7 +98,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
break; break;
} }
add_gd_partition(hd, minor, put_partition(state, slot,
partsect + be32_to_cpu(xrs->part[0].st), partsect + be32_to_cpu(xrs->part[0].st),
be32_to_cpu(xrs->part[0].siz)); be32_to_cpu(xrs->part[0].siz));
...@@ -126,8 +115,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev, ...@@ -126,8 +115,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
partsect = be32_to_cpu(xrs->part[1].st) + extensect; partsect = be32_to_cpu(xrs->part[1].st) + extensect;
put_dev_sector(sect2); put_dev_sector(sect2);
minor++; if (++slot == state->limit) {
if (minor >= m_lim) {
printk( "\nMaximum number of partitions reached!\n" ); printk( "\nMaximum number of partitions reached!\n" );
break; break;
} }
...@@ -140,12 +128,12 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev, ...@@ -140,12 +128,12 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
/* sanity check: no ICD format if first partition invalid */ /* sanity check: no ICD format if first partition invalid */
if (OK_id(pi->id)) { if (OK_id(pi->id)) {
printk(" ICD<"); printk(" ICD<");
for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++) { for (; pi < &rs->icdpart[8] && slot < state->limit; slot++, pi++) {
/* accept only GEM,BGM,RAW,LNX,SWP partitions */ /* accept only GEM,BGM,RAW,LNX,SWP partitions */
if (!((pi->flg & 1) && OK_id(pi->id))) if (!((pi->flg & 1) && OK_id(pi->id)))
continue; continue;
part_fmt = 2; part_fmt = 2;
add_gd_partition (hd, minor, put_partition (state, slot,
be32_to_cpu(pi->st), be32_to_cpu(pi->st),
be32_to_cpu(pi->siz)); be32_to_cpu(pi->siz));
} }
...@@ -159,4 +147,3 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev, ...@@ -159,4 +147,3 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
return 1; return 1;
} }
...@@ -31,6 +31,4 @@ struct rootsector ...@@ -31,6 +31,4 @@ struct rootsector
u16 checksum; /* checksum for bootable disks */ u16 checksum; /* checksum for bootable disks */
} __attribute__((__packed__)); } __attribute__((__packed__));
int atari_partition (struct gendisk *hd, struct block_device *bdev, int atari_partition(struct parsed_partitions *state, struct block_device *bdev);
unsigned long first_sector, int first_part_minor);
...@@ -34,10 +34,13 @@ ...@@ -34,10 +34,13 @@
#include "ultrix.h" #include "ultrix.h"
#include "efi.h" #include "efi.h"
#if CONFIG_BLK_DEV_MD
extern void md_autodetect_dev(kdev_t dev);
#endif
int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/ int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, static int (*check_part[])(struct parsed_partitions *, struct block_device *) = {
unsigned long first_sect, int first_minor) = {
#ifdef CONFIG_ACORN_PARTITION #ifdef CONFIG_ACORN_PARTITION
acorn_partition, acorn_partition,
#endif #endif
...@@ -199,28 +202,6 @@ char *disk_name (struct gendisk *hd, int minor, char *buf) ...@@ -199,28 +202,6 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
return buf; return buf;
} }
/*
* Add a partitions details to the devices partition description.
*/
void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
{
#ifndef CONFIG_DEVFS_FS
char buf[40];
#endif
hd->part[minor].start_sect = start;
hd->part[minor].nr_sects = size;
#ifdef CONFIG_DEVFS_FS
printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
#else
if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
(hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
else
printk(" %s", disk_name(hd, minor, buf));
#endif
}
/* Driverfs file support */ /* Driverfs file support */
static ssize_t partition_device_kdev_read(struct device *driverfs_dev, static ssize_t partition_device_kdev_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off) char *page, size_t count, loff_t off)
...@@ -351,12 +332,13 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor) ...@@ -351,12 +332,13 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor)
return; return;
} }
static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor) static void check_partition(struct gendisk *hd, kdev_t dev)
{ {
devfs_handle_t de = NULL; devfs_handle_t de = NULL;
unsigned long first_sector; unsigned long first_sector;
struct block_device *bdev; struct block_device *bdev;
char buf[64]; char buf[64];
struct parsed_partitions *state;
int i; int i;
first_sector = hd->part[minor(dev)].start_sect; first_sector = hd->part[minor(dev)].start_sect;
...@@ -369,14 +351,26 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor ...@@ -369,14 +351,26 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor
hd->part[minor(dev)].start_sect = 0; hd->part[minor(dev)].start_sect = 0;
return; return;
} }
if (first_sector != 0)
BUG();
state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL);
if (!state)
return;
if (hd->de_arr) if (hd->de_arr)
de = hd->de_arr[minor(dev) >> hd->minor_shift]; de = hd->de_arr[minor(dev) >> hd->minor_shift];
i = devfs_generate_path (de, buf, sizeof buf); i = devfs_generate_path (de, buf, sizeof buf);
if (i >= 0) if (i >= 0) {
printk(KERN_INFO " /dev/%s:", buf + i); printk(KERN_INFO " /dev/%s:", buf + i);
else sprintf(state->name, "p");
printk(KERN_INFO " %s:", disk_name(hd, minor(dev), buf)); } else {
unsigned n = hd->major;
disk_name(hd, minor(dev), state->name);
printk(KERN_INFO " %s:", state->name);
if (n - COMPAQ_SMART2_MAJOR <= 7 || n - COMPAQ_CISS_MAJOR <= 7)
sprintf(state->name, "p");
}
bdev = bdget(kdev_t_to_nr(dev)); bdev = bdget(kdev_t_to_nr(dev));
bdev->bd_contains = bdev; bdev->bd_contains = bdev;
bdev->bd_inode->i_size = (loff_t)hd->part[minor(dev)].nr_sects << 9; bdev->bd_inode->i_size = (loff_t)hd->part[minor(dev)].nr_sects << 9;
...@@ -395,14 +389,30 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor ...@@ -395,14 +389,30 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor
bdev->bd_block_size = bsize; bdev->bd_block_size = bsize;
bdev->bd_inode->i_blkbits = blksize_bits(bsize); bdev->bd_inode->i_blkbits = blksize_bits(bsize);
} }
state->limit = 1<<hd->minor_shift;
for (i = 0; check_part[i]; i++) { for (i = 0; check_part[i]; i++) {
int res; int res, j;
res = check_part[i](hd, bdev, first_sector, first_part_minor); memset(&state->parts, 0, sizeof(state->parts));
if (res) { res = check_part[i](state, bdev);
if (res < 0 && warn_no_part) if (!res)
continue;
if (res < 0) {
if (warn_no_part)
printk(" unable to read partition table\n"); printk(" unable to read partition table\n");
goto setup_devfs; goto setup_devfs;
} }
for (j = 1; j < state->limit; j++) {
hd->part[j + minor(dev)].start_sect =
state->parts[j].from;
hd->part[j + minor(dev)].nr_sects =
state->parts[j].size;
#if CONFIG_BLK_DEV_MD
if (!state->parts[j].flags)
continue;
md_autodetect_dev(mk_kdev(major(dev),minor(dev)+j));
#endif
}
goto setup_devfs;
} }
printk(" unknown partition table\n"); printk(" unknown partition table\n");
...@@ -410,15 +420,14 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor ...@@ -410,15 +420,14 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor
invalidate_bdev(bdev, 1); invalidate_bdev(bdev, 1);
truncate_inode_pages(bdev->bd_inode->i_mapping, 0); truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
bdput(bdev); bdput(bdev);
i = first_part_minor - 1;
/* Setup driverfs tree */ /* Setup driverfs tree */
if (hd->sizes) if (hd->sizes)
driverfs_create_partitions(hd, i); driverfs_create_partitions(hd, minor(dev));
else else
driverfs_remove_partitions(hd, i); driverfs_remove_partitions(hd, minor(dev));
devfs_register_partitions (hd, i, hd->sizes ? 0 : 1); devfs_register_partitions (hd, minor(dev), hd->sizes ? 0 : 1);
} }
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
...@@ -564,7 +573,7 @@ void grok_partitions(kdev_t dev, long size) ...@@ -564,7 +573,7 @@ void grok_partitions(kdev_t dev, long size)
if (!size) if (!size)
return; return;
check_partition(g, mk_kdev(g->major, first_minor), 1 + first_minor); check_partition(g, mk_kdev(g->major, first_minor));
/* /*
* We need to set the sizes array before we will be able to access * We need to set the sizes array before we will be able to access
...@@ -632,28 +641,3 @@ int wipe_partitions(kdev_t dev) ...@@ -632,28 +641,3 @@ int wipe_partitions(kdev_t dev)
} }
return 0; 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;
}
...@@ -5,12 +5,28 @@ ...@@ -5,12 +5,28 @@
* add_gd_partition adds a partitions details to the devices partition * add_gd_partition adds a partitions details to the devices partition
* description. * description.
*/ */
void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
/* enum { MAX_PART = 256 };
* check_and_add_subpartition does the same for subpartitions
*/ struct parsed_partitions {
int check_and_add_subpartition(struct gendisk *hd, int super_minor, char name[40];
int minor, int sub_start, int sub_size); struct {
unsigned long from;
unsigned long size;
int flags;
} parts[MAX_PART];
int next;
int limit;
};
static inline void
put_partition(struct parsed_partitions *p, int n, int from, int size)
{
if (n < p->limit) {
p->parts[n].from = from;
p->parts[n].size = size;
printk(" %s%d", p->name, n);
}
}
extern int warn_no_part; extern int warn_no_part;
...@@ -87,26 +87,10 @@ ...@@ -87,26 +87,10 @@
* *
************************************************************/ ************************************************************/
#include <linux/config.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/blkpg.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <asm/system.h>
#include <asm/byteorder.h>
#include "check.h" #include "check.h"
#include "efi.h" #include "efi.h"
#if CONFIG_BLK_DEV_MD
extern void md_autodetect_dev(kdev_t dev);
#endif
/* Handle printing of 64-bit values */ /* Handle printing of 64-bit values */
/* Borrowed from /usr/include/inttypes.h */ /* Borrowed from /usr/include/inttypes.h */
# if BITS_PER_LONG == 64 # if BITS_PER_LONG == 64
...@@ -184,7 +168,6 @@ is_pmbr_valid(legacy_mbr *mbr) ...@@ -184,7 +168,6 @@ is_pmbr_valid(legacy_mbr *mbr)
/** /**
* last_lba(): return number of last logical block of device * last_lba(): return number of last logical block of device
* @hd: gendisk with partition list
* @bdev: block device * @bdev: block device
* *
* Description: Returns last LBA value on success, 0 on error. * Description: Returns last LBA value on success, 0 on error.
...@@ -193,16 +176,13 @@ is_pmbr_valid(legacy_mbr *mbr) ...@@ -193,16 +176,13 @@ is_pmbr_valid(legacy_mbr *mbr)
* physical sectors available on the disk. * physical sectors available on the disk.
*/ */
static u64 static u64
last_lba(struct gendisk *hd, struct block_device *bdev) last_lba(struct block_device *bdev)
{ {
if (!hd || !hd->part || !bdev) return (bdev->bd_inode->i_size >> 9) - 1;
return 0;
return hd->part[minor(to_kdev_t(bdev->bd_dev))].nr_sects - 1;
} }
/** /**
* read_lba(): Read bytes from disk, starting at given LBA * read_lba(): Read bytes from disk, starting at given LBA
* @hd
* @bdev * @bdev
* @lba * @lba
* @buffer * @buffer
...@@ -212,39 +192,26 @@ last_lba(struct gendisk *hd, struct block_device *bdev) ...@@ -212,39 +192,26 @@ last_lba(struct gendisk *hd, struct block_device *bdev)
* Returns number of bytes read on success, 0 on error. * Returns number of bytes read on success, 0 on error.
*/ */
static size_t static size_t
read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba, read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count)
u8 * buffer, size_t count)
{ {
size_t totalreadcount = 0;
size_t totalreadcount = 0, bytesread = 0; if (!bdev || !buffer)
unsigned long blocksize;
int i;
Sector sect;
unsigned char *data = NULL;
if (!hd || !bdev || !buffer || !count)
return 0; return 0;
blocksize = bdev_hardsect_size(bdev); while (count) {
if (!blocksize) int copied = 512;
blocksize = 512; Sector sect;
unsigned char *data = read_dev_sector(bdev, lba++, &sect);
for (i = 0; count > 0; i++) {
data = read_dev_sector(bdev, lba, &sect);
if (!data) if (!data)
return totalreadcount; break;
if (copied > count)
bytesread = copied = count;
PAGE_CACHE_SIZE - (data - memcpy(buffer, data, copied);
(unsigned char *) page_address(sect.v));
bytesread = min(bytesread, count);
memcpy(buffer, data, bytesread);
put_dev_sector(sect); put_dev_sector(sect);
buffer += copied;
buffer += bytesread; totalreadcount +=copied;
totalreadcount += bytesread; count -= copied;
count -= bytesread;
lba += (bytesread / blocksize);
} }
return totalreadcount; return totalreadcount;
} }
...@@ -252,7 +219,6 @@ read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba, ...@@ -252,7 +219,6 @@ read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba,
/** /**
* alloc_read_gpt_entries(): reads partition entries from disk * alloc_read_gpt_entries(): reads partition entries from disk
* @hd
* @bdev * @bdev
* @gpt - GPT header * @gpt - GPT header
* *
...@@ -261,12 +227,11 @@ read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba, ...@@ -261,12 +227,11 @@ read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba,
* Notes: remember to free pte when you're done! * Notes: remember to free pte when you're done!
*/ */
static gpt_entry * static gpt_entry *
alloc_read_gpt_entries(struct gendisk *hd, alloc_read_gpt_entries(struct block_device *bdev, gpt_header *gpt)
struct block_device *bdev, gpt_header *gpt)
{ {
size_t count; size_t count;
gpt_entry *pte; gpt_entry *pte;
if (!hd || !bdev || !gpt) if (!bdev || !gpt)
return NULL; return NULL;
count = le32_to_cpu(gpt->num_partition_entries) * count = le32_to_cpu(gpt->num_partition_entries) *
...@@ -278,7 +243,7 @@ alloc_read_gpt_entries(struct gendisk *hd, ...@@ -278,7 +243,7 @@ alloc_read_gpt_entries(struct gendisk *hd,
return NULL; return NULL;
memset(pte, 0, count); memset(pte, 0, count);
if (read_lba(hd, bdev, le64_to_cpu(gpt->partition_entry_lba), if (read_lba(bdev, le64_to_cpu(gpt->partition_entry_lba),
(u8 *) pte, (u8 *) pte,
count) < count) { count) < count) {
kfree(pte); kfree(pte);
...@@ -290,7 +255,6 @@ alloc_read_gpt_entries(struct gendisk *hd, ...@@ -290,7 +255,6 @@ alloc_read_gpt_entries(struct gendisk *hd,
/** /**
* alloc_read_gpt_header(): Allocates GPT header, reads into it from disk * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
* @hd
* @bdev * @bdev
* @lba is the Logical Block Address of the partition table * @lba is the Logical Block Address of the partition table
* *
...@@ -299,10 +263,10 @@ alloc_read_gpt_entries(struct gendisk *hd, ...@@ -299,10 +263,10 @@ alloc_read_gpt_entries(struct gendisk *hd,
* Note: remember to free gpt when finished with it. * Note: remember to free gpt when finished with it.
*/ */
static gpt_header * static gpt_header *
alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba) alloc_read_gpt_header(struct block_device *bdev, u64 lba)
{ {
gpt_header *gpt; gpt_header *gpt;
if (!hd || !bdev) if (!bdev)
return NULL; return NULL;
gpt = kmalloc(sizeof (gpt_header), GFP_KERNEL); gpt = kmalloc(sizeof (gpt_header), GFP_KERNEL);
...@@ -310,7 +274,7 @@ alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba) ...@@ -310,7 +274,7 @@ alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba)
return NULL; return NULL;
memset(gpt, 0, sizeof (gpt_header)); memset(gpt, 0, sizeof (gpt_header));
if (read_lba(hd, bdev, lba, (u8 *) gpt, if (read_lba(bdev, lba, (u8 *) gpt,
sizeof (gpt_header)) < sizeof (gpt_header)) { sizeof (gpt_header)) < sizeof (gpt_header)) {
kfree(gpt); kfree(gpt);
gpt=NULL; gpt=NULL;
...@@ -322,7 +286,6 @@ alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba) ...@@ -322,7 +286,6 @@ alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba)
/** /**
* is_gpt_valid() - tests one GPT header and PTEs for validity * is_gpt_valid() - tests one GPT header and PTEs for validity
* @hd
* @bdev * @bdev
* @lba is the logical block address of the GPT header to test * @lba is the logical block address of the GPT header to test
* @gpt is a GPT header ptr, filled on return. * @gpt is a GPT header ptr, filled on return.
...@@ -332,14 +295,14 @@ alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba) ...@@ -332,14 +295,14 @@ alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba)
* If valid, returns pointers to newly allocated GPT header and PTEs. * If valid, returns pointers to newly allocated GPT header and PTEs.
*/ */
static int static int
is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba, is_gpt_valid(struct block_device *bdev, u64 lba,
gpt_header **gpt, gpt_entry **ptes) gpt_header **gpt, gpt_entry **ptes)
{ {
u32 crc, origcrc; u32 crc, origcrc;
if (!hd || !bdev || !gpt || !ptes) if (!bdev || !gpt || !ptes)
return 0; return 0;
if (!(*gpt = alloc_read_gpt_header(hd, bdev, lba))) if (!(*gpt = alloc_read_gpt_header(bdev, lba)))
return 0; return 0;
/* Check the GUID Partition Table signature */ /* Check the GUID Partition Table signature */
...@@ -377,7 +340,7 @@ is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba, ...@@ -377,7 +340,7 @@ is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba,
return 0; return 0;
} }
if (!(*ptes = alloc_read_gpt_entries(hd, bdev, *gpt))) { if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt))) {
kfree(*gpt); kfree(*gpt);
*gpt = NULL; *gpt = NULL;
return 0; return 0;
...@@ -502,7 +465,6 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba) ...@@ -502,7 +465,6 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
/** /**
* find_valid_gpt() - Search disk for valid GPT headers and PTEs * find_valid_gpt() - Search disk for valid GPT headers and PTEs
* @hd
* @bdev * @bdev
* @gpt is a GPT header ptr, filled on return. * @gpt is a GPT header ptr, filled on return.
* @ptes is a PTEs ptr, filled on return. * @ptes is a PTEs ptr, filled on return.
...@@ -512,31 +474,30 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba) ...@@ -512,31 +474,30 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
* or the Alternate GPT header and PTEs valid, and the PMBR valid. * or the Alternate GPT header and PTEs valid, and the PMBR valid.
*/ */
static int static int
find_valid_gpt(struct gendisk *hd, struct block_device *bdev, find_valid_gpt(struct block_device *bdev, gpt_header **gpt, gpt_entry **ptes)
gpt_header **gpt, gpt_entry **ptes)
{ {
int good_pgpt = 0, good_agpt = 0, good_pmbr = 0; int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
gpt_header *pgpt = NULL, *agpt = NULL; gpt_header *pgpt = NULL, *agpt = NULL;
gpt_entry *pptes = NULL, *aptes = NULL; gpt_entry *pptes = NULL, *aptes = NULL;
legacy_mbr *legacymbr = NULL; legacy_mbr *legacymbr = NULL;
u64 lastlba; u64 lastlba;
if (!hd || !bdev || !gpt || !ptes) if (!bdev || !gpt || !ptes)
return 0; return 0;
lastlba = last_lba(hd, bdev); lastlba = last_lba(bdev);
good_pgpt = is_gpt_valid(hd, bdev, GPT_PRIMARY_PARTITION_TABLE_LBA, good_pgpt = is_gpt_valid(bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
&pgpt, &pptes); &pgpt, &pptes);
if (good_pgpt) { if (good_pgpt) {
good_agpt = is_gpt_valid(hd, bdev, good_agpt = is_gpt_valid(bdev,
le64_to_cpu(pgpt->alternate_lba), le64_to_cpu(pgpt->alternate_lba),
&agpt, &aptes); &agpt, &aptes);
if (!good_agpt) { if (!good_agpt) {
good_agpt = is_gpt_valid(hd, bdev, lastlba, good_agpt = is_gpt_valid(bdev, lastlba,
&agpt, &aptes); &agpt, &aptes);
} }
} }
else { else {
good_agpt = is_gpt_valid(hd, bdev, lastlba, good_agpt = is_gpt_valid(bdev, lastlba,
&agpt, &aptes); &agpt, &aptes);
} }
...@@ -549,7 +510,7 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev, ...@@ -549,7 +510,7 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL); legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
if (legacymbr) { if (legacymbr) {
memset(legacymbr, 0, sizeof (*legacymbr)); memset(legacymbr, 0, sizeof (*legacymbr));
read_lba(hd, bdev, 0, (u8 *) legacymbr, read_lba(bdev, 0, (u8 *) legacymbr,
sizeof (*legacymbr)); sizeof (*legacymbr));
good_pmbr = is_pmbr_valid(legacymbr); good_pmbr = is_pmbr_valid(legacymbr);
kfree(legacymbr); kfree(legacymbr);
...@@ -616,12 +577,16 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev, ...@@ -616,12 +577,16 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
} }
/** /**
* add_gpt_partitions(struct gendisk *hd, struct block_device *bdev, * efi_partition(struct parsed_partitions *state, struct block_device *bdev)
* @hd * @state
* @bdev * @bdev
* *
* Description: Create devices for each entry in the GUID Partition Table * Description: called from check.c, if the disk contains GPT
* Entries. * partitions, sets up partition entries in the kernel.
*
* If the first block on the disk is a legacy MBR,
* it will get handled by msdos_partition().
* If it's a Protective MBR, we'll handle it here.
* *
* We do not create a Linux partition for GPT, but * We do not create a Linux partition for GPT, but
* only for the actual data partitions. * only for the actual data partitions.
...@@ -631,106 +596,41 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev, ...@@ -631,106 +596,41 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
* 1 if successful * 1 if successful
* *
*/ */
static int int
add_gpt_partitions(struct gendisk *hd, struct block_device *bdev, int nextminor) efi_partition(struct parsed_partitions *state, struct block_device *bdev)
{ {
gpt_header *gpt = NULL; gpt_header *gpt = NULL;
gpt_entry *ptes = NULL; gpt_entry *ptes = NULL;
u32 i; u32 i;
int max_p;
if (!hd || !bdev) if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) {
return -1;
if (!find_valid_gpt(hd, bdev, &gpt, &ptes) || !gpt || !ptes) {
if (gpt) {
kfree(gpt); kfree(gpt);
gpt = NULL;
}
if (ptes) {
kfree(ptes); kfree(ptes);
ptes = NULL;
}
return 0; return 0;
} }
Dprintk("GUID Partition Table is valid! Yea!\n"); Dprintk("GUID Partition Table is valid! Yea!\n");
max_p = (1 << hd->minor_shift) - 1; for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < max_p; i++) {
if (!efi_guidcmp(ptes[i].partition_type_guid, NULL_GUID)) if (!efi_guidcmp(ptes[i].partition_type_guid, NULL_GUID))
continue; continue;
add_gd_partition(hd, nextminor+i, put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba),
le64_to_cpu(ptes[i].starting_lba),
(le64_to_cpu(ptes[i].ending_lba) - (le64_to_cpu(ptes[i].ending_lba) -
le64_to_cpu(ptes[i].starting_lba) + le64_to_cpu(ptes[i].starting_lba) +
1)); 1));
/* If there's this is a RAID volume, tell md */ /* If there's this is a RAID volume, tell md */
#if CONFIG_BLK_DEV_MD
if (!efi_guidcmp(ptes[i].partition_type_guid, if (!efi_guidcmp(ptes[i].partition_type_guid,
PARTITION_LINUX_RAID_GUID)) { PARTITION_LINUX_RAID_GUID))
md_autodetect_dev(mk_kdev(hd->major, state->parts[i+1].flags = 1;
nextminor));
}
#endif
} }
kfree(ptes); kfree(ptes);
ptes=NULL;
kfree(gpt); kfree(gpt);
gpt=NULL;
printk("\n"); printk("\n");
return 1; return 1;
} }
/**
* efi_partition(): EFI GPT partition handling entry function
* @hd
* @bdev
* @first_sector: unused
* @first_part_minor: minor number assigned to first GPT partition found
*
* Description: called from check.c, if the disk contains GPT
* partitions, sets up partition entries in the kernel.
*
* If the first block on the disk is a legacy MBR,
* it will get handled by msdos_partition().
* If it's a Protective MBR, we'll handle it here.
*
* set_blocksize() calls are necessary to be able to read
* a disk with an odd number of 512-byte sectors, as the
* default BLOCK_SIZE of 1024 bytes won't let that last
* sector be read otherwise.
*
* Returns:
* -1 if unable to read the partition table
* 0 if this isn't our partitoin table
* 1 if successful
*/
int
efi_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor)
{
int hardblocksize = bdev_hardsect_size(bdev);
int orig_blksize_size = block_size(bdev);
int rc = 0;
/* Need to change the block size that the block layer uses */
if (orig_blksize_size != hardblocksize)
set_blocksize(bdev, hardblocksize);
rc = add_gpt_partitions(hd, bdev, first_part_minor);
/* change back */
if (orig_blksize_size != hardblocksize)
set_blocksize(bdev, orig_blksize_size);
return rc;
}
/* /*
* Overrides for Emacs so that we follow Linus's tabbing style. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * Emacs will notice this stuff at the end of the file and automatically
......
...@@ -112,9 +112,7 @@ typedef struct _legacy_mbr { ...@@ -112,9 +112,7 @@ typedef struct _legacy_mbr {
} __attribute__ ((packed)) legacy_mbr; } __attribute__ ((packed)) legacy_mbr;
/* Functions */ /* Functions */
extern int extern int efi_partition(struct parsed_partitions *state, struct block_device *bdev);
efi_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
#endif #endif
......
...@@ -88,8 +88,7 @@ ibm_ioctl_unopened(struct block_device *bdev, unsigned cmd, unsigned long arg) ...@@ -88,8 +88,7 @@ ibm_ioctl_unopened(struct block_device *bdev, unsigned cmd, unsigned long arg)
/* /*
*/ */
int int
ibm_partition(struct gendisk *hd, struct block_device *bdev, ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int first_part_minor)
{ {
int blocksize, offset, size; int blocksize, offset, size;
dasd_information_t *info; dasd_information_t *info;
...@@ -100,9 +99,6 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -100,9 +99,6 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
unsigned char *data; unsigned char *data;
Sector sect; Sector sect;
if ( first_sector != 0 )
BUG();
if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL) if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
goto out_noinfo; goto out_noinfo;
if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL) if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
...@@ -155,9 +151,7 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -155,9 +151,7 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
offset = (info->label_block + 1); offset = (info->label_block + 1);
size = bdev->bd_inode->i_size >> 9; size = bdev->bd_inode->i_size >> 9;
} }
// add_gd_partition(hd, first_part_minor - 1, 0, size); put_partition(state, 1, offset*(blocksize >> 9),
add_gd_partition(hd, first_part_minor,
offset*(blocksize >> 9),
size-offset*(blocksize >> 9)); size-offset*(blocksize >> 9));
} else if (strncmp(type, "VOL1", 4) == 0) { } else if (strncmp(type, "VOL1", 4) == 0) {
/* /*
...@@ -194,9 +188,9 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -194,9 +188,9 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
offset = cchh2blk(&f1.DS1EXT1.llimit, geo); offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - size = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
offset + geo->sectors; offset + geo->sectors;
if (counter >= (1 << hd->minor_shift)) if (counter >= state->limit)
break; break;
add_gd_partition(hd, first_part_minor + counter, put_partition(state, counter + 1,
offset * (blocksize >> 9), offset * (blocksize >> 9),
size * (blocksize >> 9)); size * (blocksize >> 9));
counter++; counter++;
...@@ -212,9 +206,7 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -212,9 +206,7 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
printk("(nonl)/%8s:", name); printk("(nonl)/%8s:", name);
offset = (info->label_block + 1); offset = (info->label_block + 1);
size = (bdev->bd_inode->i_size >> 9); size = (bdev->bd_inode->i_size >> 9);
// add_gd_partition(hd, first_part_minor - 1, 0, size); put_partition(state, 1, offset*(blocksize >> 9),
add_gd_partition(hd, first_part_minor,
offset*(blocksize >> 9),
size-offset*(blocksize >> 9)); size-offset*(blocksize >> 9));
} }
......
int ibm_partition(struct gendisk *, struct block_device *, unsigned long, int); int ibm_partition(struct parsed_partitions *, struct block_device *);
...@@ -23,12 +23,6 @@ ...@@ -23,12 +23,6 @@
* *
* 28/10/2001 - Added sorting of ldm partitions. (AIA) * 28/10/2001 - Added sorting of ldm partitions. (AIA)
*/ */
#include <linux/types.h>
#include <asm/unaligned.h>
#include <asm/byteorder.h>
#include <linux/pagemap.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "check.h" #include "check.h"
#include "ldm.h" #include "ldm.h"
...@@ -57,7 +51,6 @@ static void ldm_debug(const char *f, ...); ...@@ -57,7 +51,6 @@ static void ldm_debug(const char *f, ...);
#endif /* !CONFIG_LDM_DEBUG */ #endif /* !CONFIG_LDM_DEBUG */
/* Necessary forward declarations. */ /* Necessary forward declarations. */
static int create_partition(struct gendisk *, int, int, int);
static int parse_privhead(const u8 *, struct privhead *); static int parse_privhead(const u8 *, struct privhead *);
static u64 get_vnum(const u8 *, int *); static u64 get_vnum(const u8 *, int *);
static int get_vstr(const u8 *, u8 *, const int); static int get_vstr(const u8 *, u8 *, const int);
...@@ -161,8 +154,7 @@ static int parse_vblk(const u8 *buffer, const int buf_size, struct vblk *vb) ...@@ -161,8 +154,7 @@ static int parse_vblk(const u8 *buffer, const int buf_size, struct vblk *vb)
/** /**
* add_partition_to_list - insert partition into a partition list * add_partition_to_list - insert partition into a partition list
* @pl: sorted list of partitions * @pl: sorted list of partitions
* @hd: gendisk structure to which the data partition belongs * @disk_size: number of sectors on the disk device
* @disk_minor: minor number of the disk device
* @start: first sector within the disk device * @start: first sector within the disk device
* @size: number of sectors on the partition device * @size: number of sectors on the partition device
* *
...@@ -174,16 +166,15 @@ static int parse_vblk(const u8 *buffer, const int buf_size, struct vblk *vb) ...@@ -174,16 +166,15 @@ static int parse_vblk(const u8 *buffer, const int buf_size, struct vblk *vb)
* *
* TODO: Add sanity check for overlapping partitions. (AIA) * TODO: Add sanity check for overlapping partitions. (AIA)
*/ */
static int add_partition_to_list(struct list_head *pl, const struct gendisk *hd, static int add_partition_to_list(struct list_head *pl,
const int disk_minor, const unsigned long start, const unsigned long disk_size,
const unsigned long start,
const unsigned long size) const unsigned long size)
{ {
struct ldm_part *lp, *lptmp; struct ldm_part *lp, *lptmp;
struct list_head *tmp; struct list_head *tmp;
if (!hd->part) if (start < 1 || start + size > disk_size) {
return -1;
if ((start < 1) || ((start + size) > hd->part[disk_minor].nr_sects)) {
printk(LDM_CRIT "LDM partition exceeds physical disk. " printk(LDM_CRIT "LDM partition exceeds physical disk. "
"Skipping.\n"); "Skipping.\n");
return -1; return -1;
...@@ -215,7 +206,6 @@ static int add_partition_to_list(struct list_head *pl, const struct gendisk *hd, ...@@ -215,7 +206,6 @@ static int add_partition_to_list(struct list_head *pl, const struct gendisk *hd,
/** /**
* create_data_partitions - create the data partition devices * create_data_partitions - create the data partition devices
* @hd: gendisk structure in which to create the data partitions * @hd: gendisk structure in which to create the data partitions
* @first_sector: first sector within the disk device
* @first_part_minor: first minor number of data partition devices * @first_part_minor: first minor number of data partition devices
* @dev: partition device holding the LDM database * @dev: partition device holding the LDM database
* @vm: in memory vmdb structure of @dev * @vm: in memory vmdb structure of @dev
...@@ -234,9 +224,8 @@ static int add_partition_to_list(struct list_head *pl, const struct gendisk *hd, ...@@ -234,9 +224,8 @@ static int add_partition_to_list(struct list_head *pl, const struct gendisk *hd,
* *
* Return 1 on success and -1 on error. * Return 1 on success and -1 on error.
*/ */
static int create_data_partitions(struct gendisk *hd, static int create_data_partitions(struct parsed_partitions *state,
const unsigned long first_sector, int first_part_minor, int slot, struct block_device *bdev, const struct vmdb *vm,
struct block_device *bdev, const struct vmdb *vm,
const struct privhead *ph, const struct ldmdisk *dk, const struct privhead *ph, const struct ldmdisk *dk,
unsigned long base) unsigned long base)
{ {
...@@ -249,7 +238,7 @@ static int create_data_partitions(struct gendisk *hd, ...@@ -249,7 +238,7 @@ static int create_data_partitions(struct gendisk *hd,
int vblk; int vblk;
int vsize; /* VBLK size. */ int vsize; /* VBLK size. */
int perbuf; /* VBLKs per buffer. */ int perbuf; /* VBLKs per buffer. */
int buffer, lastbuf, lastofs, err, disk_minor; int buffer, lastbuf, lastofs, err;
vb = (struct vblk*)kmalloc(sizeof(struct vblk), GFP_KERNEL); vb = (struct vblk*)kmalloc(sizeof(struct vblk), GFP_KERNEL);
if (!vb) if (!vb)
...@@ -268,11 +257,6 @@ static int create_data_partitions(struct gendisk *hd, ...@@ -268,11 +257,6 @@ static int create_data_partitions(struct gendisk *hd,
if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize > if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize >
ph->config_size * 512) ph->config_size * 512)
goto err_out; goto err_out;
/*
* Get the minor number of the parent device so we can check we don't
* go beyond the end of the device.
*/
disk_minor = (first_part_minor >> hd->minor_shift) << hd->minor_shift;
for (buffer = 0; buffer < lastbuf; buffer++) { for (buffer = 0; buffer < lastbuf; buffer++) {
data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, &sect); data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, &sect);
if (!data) if (!data)
...@@ -292,8 +276,9 @@ static int create_data_partitions(struct gendisk *hd, ...@@ -292,8 +276,9 @@ static int create_data_partitions(struct gendisk *hd,
if (dk->obj_id != vb->disk_id) if (dk->obj_id != vb->disk_id)
continue; continue;
/* Ignore invalid partition errors. */ /* Ignore invalid partition errors. */
if (add_partition_to_list(&pl, hd, disk_minor, if (add_partition_to_list(&pl,
first_sector + vb->start_sector + bdev->bd_inode->i_size>>9,
vb->start_sector +
ph->logical_disk_start, ph->logical_disk_start,
vb->num_sectors) < -1) vb->num_sectors) < -1)
goto brelse_out; goto brelse_out;
...@@ -306,7 +291,7 @@ static int create_data_partitions(struct gendisk *hd, ...@@ -306,7 +291,7 @@ static int create_data_partitions(struct gendisk *hd,
printk(" <"); printk(" <");
list_for_each(tmp, &pl) { list_for_each(tmp, &pl) {
lp = list_entry(tmp, struct ldm_part, part_list); lp = list_entry(tmp, struct ldm_part, part_list);
add_gd_partition(hd, first_part_minor++, lp->start, lp->size); put_partition(state, slot++, lp->start, lp->size);
} }
printk(" >\n"); printk(" >\n");
if (!list_empty(&pl)) { if (!list_empty(&pl)) {
...@@ -819,42 +804,6 @@ static int validate_privheads(struct block_device *bdev, ...@@ -819,42 +804,6 @@ static int validate_privheads(struct block_device *bdev,
goto out; goto out;
} }
/**
* create_partition - validate input and create a kernel partition device
* @hd: gendisk structure in which to create partition
* @minor: minor number for device to create
* @start: starting offset of the partition into the parent device
* @size: size of the partition
*
* This validates the range, then puts an entry into the kernel's partition
* table.
*
* @start and @size are numbers of sectors.
*
* Return 1 on succes and -1 on error.
*/
static int create_partition(struct gendisk *hd, const int minor,
const int start, const int size)
{
int disk_minor;
if (!hd->part)
return -1;
/*
* Get the minor number of the parent device so we can check we don't
* go beyond the end of the device.
*/
disk_minor = (minor >> hd->minor_shift) << hd->minor_shift;
if ((start < 1) || ((start + size) > hd->part[disk_minor].nr_sects)) {
printk(LDM_CRIT "LDM Partition exceeds physical disk. "
"Aborting.\n");
return -1;
}
add_gd_partition(hd, minor, start, size);
ldm_debug("Created partition successfully.\n");
return 1;
}
/** /**
* parse_privhead - parse the LDM database PRIVHEAD structure * parse_privhead - parse the LDM database PRIVHEAD structure
* @buffer: LDM database privhead structure loaded from the device * @buffer: LDM database privhead structure loaded from the device
...@@ -901,19 +850,16 @@ static int parse_privhead(const u8 *buffer, struct privhead *ph) ...@@ -901,19 +850,16 @@ static int parse_privhead(const u8 *buffer, struct privhead *ph)
} }
/** /**
* create_db_partition - create a dedicated partition for our database * find_db_partition - find our database
* @hd: gendisk structure in which to create partition
* @dev: device of which to create partition * @dev: device of which to create partition
* @ph: @dev's LDM database private header * @ph: @dev's LDM database private header
* *
* Find the primary private header, locate the LDM database, then create a * Find the primary private header and the LDM database
* partition to wrap it. * partition to wrap it.
* *
* Return 1 on succes, 0 if device is not a dynamic disk and -1 on error. * Return 1 on succes, 0 if device is not a dynamic disk and -1 on error.
*/ */
static int create_db_partition(struct gendisk *hd, struct block_device *bdev, static int find_db_partition(struct block_device *bdev, struct privhead *ph)
const unsigned long first_sector, const int first_part_minor,
struct privhead *ph)
{ {
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
...@@ -930,10 +876,15 @@ static int create_db_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -930,10 +876,15 @@ static int create_db_partition(struct gendisk *hd, struct block_device *bdev,
return 0; return 0;
} }
err = parse_privhead(data, ph); err = parse_privhead(data, ph);
if (err == 1)
err = create_partition(hd, first_part_minor, first_sector +
ph->config_start, ph->config_size);
put_dev_sector(sect); put_dev_sector(sect);
if (err <= 0)
return err;
if (ph->config_start < 1 ||
ph->config_start + ph->config_size > bdev->bd_inode->i_size >> 9) {
printk(LDM_CRIT "LDM Partition exceeds physical disk. "
"Aborting.\n");
err = -1;
}
return err; return err;
} }
...@@ -990,8 +941,6 @@ static int validate_partition_table(struct block_device *bdev) ...@@ -990,8 +941,6 @@ static int validate_partition_table(struct block_device *bdev)
* ldm_partition - find out whether a device is a dynamic disk and handle it * ldm_partition - find out whether a device is a dynamic disk and handle it
* @hd: gendisk structure in which to return the handled disk * @hd: gendisk structure in which to return the handled disk
* @dev: device we need to look at * @dev: device we need to look at
* @first_sector: first sector within the device
* @first_part_minor: first minor number of partitions for the device
* *
* Description: * Description:
* *
...@@ -1010,8 +959,7 @@ static int validate_partition_table(struct block_device *bdev) ...@@ -1010,8 +959,7 @@ static int validate_partition_table(struct block_device *bdev)
* 0 if @dev is not a dynamic disk, * 0 if @dev is not a dynamic disk,
* -1 if an error occured. * -1 if an error occured.
*/ */
int ldm_partition(struct gendisk *hd, struct block_device *bdev, int ldm_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int first_part_minor)
{ {
struct privhead *ph = NULL; struct privhead *ph = NULL;
struct tocblock *toc = NULL; struct tocblock *toc = NULL;
...@@ -1020,8 +968,6 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -1020,8 +968,6 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long db_first; unsigned long db_first;
int err; int err;
if (!hd)
return 0;
/* Check the partition table. */ /* Check the partition table. */
err = validate_partition_table(bdev); err = validate_partition_table(bdev);
if (err != 1) if (err != 1)
...@@ -1029,10 +975,11 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -1029,10 +975,11 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev,
if (!(ph = (struct privhead*)kmalloc(sizeof(*ph), GFP_KERNEL))) if (!(ph = (struct privhead*)kmalloc(sizeof(*ph), GFP_KERNEL)))
goto no_mem; goto no_mem;
/* Create the LDM database device. */ /* Create the LDM database device. */
err = create_db_partition(hd, bdev, first_sector, first_part_minor, ph); err = find_db_partition(bdev, ph);
if (err != 1) if (err != 1)
goto out; goto out;
db_first = hd->part[first_part_minor].start_sect; db_first = ph->config_start;
put_partition(state, 1, db_first, ph->config_size);
/* Check the backup privheads. */ /* Check the backup privheads. */
err = validate_privheads(bdev, ph, db_first); err = validate_privheads(bdev, ph, db_first);
if (err != 1) if (err != 1)
...@@ -1056,8 +1003,8 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -1056,8 +1003,8 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev,
if (err != 1) if (err != 1)
goto out; goto out;
/* Finally, create the data partition devices. */ /* Finally, create the data partition devices. */
err = create_data_partitions(hd, first_sector, first_part_minor + err = create_data_partitions(state, 1 + LDM_FIRST_PART_OFFSET,
LDM_FIRST_PART_OFFSET, bdev, vm, ph, dk, db_first); bdev, vm, ph, dk, db_first);
if (err == 1) if (err == 1)
ldm_debug("Parsed LDM database successfully.\n"); ldm_debug("Parsed LDM database successfully.\n");
out: out:
...@@ -1071,4 +1018,3 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -1071,4 +1018,3 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev,
err = -1; err = -1;
goto out; goto out;
} }
...@@ -150,8 +150,7 @@ struct ldm_part { ...@@ -150,8 +150,7 @@ struct ldm_part {
unsigned long size; unsigned long size;
}; };
int ldm_partition(struct gendisk *hd, struct block_device *bdev, int ldm_partition(struct parsed_partitions *state, struct block_device *bdev);
unsigned long first_sector, int first_part_minor);
#endif /* _FS_PT_LDM_H_ */ #endif /* _FS_PT_LDM_H_ */
...@@ -7,16 +7,7 @@ ...@@ -7,16 +7,7 @@
*/ */
#include <linux/config.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/ctype.h> #include <linux/ctype.h>
#include <asm/system.h>
#include "check.h" #include "check.h"
#include "mac.h" #include "mac.h"
...@@ -36,9 +27,9 @@ static inline void mac_fix_string(char *stg, int len) ...@@ -36,9 +27,9 @@ static inline void mac_fix_string(char *stg, int len)
stg[i] = 0; stg[i] = 0;
} }
int mac_partition(struct gendisk *hd, struct block_device *bdev, int mac_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned long fsec, int first_part_minor)
{ {
int slot = 1;
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
int blk, blocks_in_map; int blk, blocks_in_map;
...@@ -79,8 +70,8 @@ int mac_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -79,8 +70,8 @@ int mac_partition(struct gendisk *hd, struct block_device *bdev,
part = (struct mac_partition *) (data + pos%512); part = (struct mac_partition *) (data + pos%512);
if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
break; break;
add_gd_partition(hd, first_part_minor, put_partition(state, slot,
fsec + be32_to_cpu(part->start_block) * (secsize/512), be32_to_cpu(part->start_block) * (secsize/512),
be32_to_cpu(part->block_count) * (secsize/512)); be32_to_cpu(part->block_count) * (secsize/512));
#ifdef CONFIG_ALL_PPC #ifdef CONFIG_ALL_PPC
...@@ -126,7 +117,7 @@ int mac_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -126,7 +117,7 @@ int mac_partition(struct gendisk *hd, struct block_device *bdev,
} }
#endif /* CONFIG_ALL_PPC */ #endif /* CONFIG_ALL_PPC */
++first_part_minor; ++slot;
} }
#ifdef CONFIG_ALL_PPC #ifdef CONFIG_ALL_PPC
if (found_root_goodness) if (found_root_goodness)
...@@ -138,4 +129,3 @@ int mac_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -138,4 +129,3 @@ int mac_partition(struct gendisk *hd, struct block_device *bdev,
printk("\n"); printk("\n");
return 1; return 1;
} }
...@@ -41,4 +41,4 @@ struct mac_driver_desc { ...@@ -41,4 +41,4 @@ struct mac_driver_desc {
/* ... more stuff */ /* ... more stuff */
}; };
int mac_partition(struct gendisk *hd, struct block_device *bdev, unsigned long fsec, int first_part_minor); int mac_partition(struct parsed_partitions *state, struct block_device *bdev);
...@@ -20,12 +20,6 @@ ...@@ -20,12 +20,6 @@
*/ */
#include <linux/config.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/buffer_head.h> /* for invalidate_bdev() */ #include <linux/buffer_head.h> /* for invalidate_bdev() */
#ifdef CONFIG_BLK_DEV_IDE #ifdef CONFIG_BLK_DEV_IDE
...@@ -38,16 +32,10 @@ EXPORT_SYMBOL(ide_xlate_1024_hook); ...@@ -38,16 +32,10 @@ EXPORT_SYMBOL(ide_xlate_1024_hook);
#define ide_xlate_1024 ide_xlate_1024_hook #define ide_xlate_1024 ide_xlate_1024_hook
#endif #endif
#include <asm/system.h>
#include "check.h" #include "check.h"
#include "msdos.h" #include "msdos.h"
#include "efi.h" #include "efi.h"
#if CONFIG_BLK_DEV_MD
extern void md_autodetect_dev(kdev_t dev);
#endif
/* /*
* Many architectures don't like unaligned accesses, which is * Many architectures don't like unaligned accesses, which is
* frequently the case with the nr_sects and start_sect partition * frequently the case with the nr_sects and start_sect partition
...@@ -73,23 +61,6 @@ static inline int is_extended_partition(struct partition *p) ...@@ -73,23 +61,6 @@ static inline int is_extended_partition(struct partition *p)
SYS_IND(p) == LINUX_EXTENDED_PARTITION); SYS_IND(p) == LINUX_EXTENDED_PARTITION);
} }
/*
* partition_name() formats the short partition name into the supplied
* buffer, and returns a pointer to that buffer.
* Used by several partition types which makes conditional inclusion messy,
* use __attribute__ ((unused)) instead.
*/
static char __attribute__ ((unused))
*partition_name (struct gendisk *hd, int minor, char *buf)
{
#ifdef CONFIG_DEVFS_FS
sprintf(buf, "p%d", (minor & ((1 << hd->minor_shift) - 1)));
return buf;
#else
return disk_name(hd, minor, buf);
#endif
}
#define MSDOS_LABEL_MAGIC1 0x55 #define MSDOS_LABEL_MAGIC1 0x55
#define MSDOS_LABEL_MAGIC2 0xAA #define MSDOS_LABEL_MAGIC2 0xAA
...@@ -110,26 +81,26 @@ msdos_magic_present(unsigned char *p) ...@@ -110,26 +81,26 @@ msdos_magic_present(unsigned char *p)
* only for the actual data partitions. * only for the actual data partitions.
*/ */
static void extended_partition(struct gendisk *hd, struct block_device *bdev, static void
int minor, unsigned long first_size, int *current_minor) parse_extended(struct parsed_partitions *state, struct block_device *bdev,
u32 first_sector, u32 first_size)
{ {
struct partition *p; struct partition *p;
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
unsigned long first_sector, this_sector, this_size; u32 this_sector, this_size;
int mask = (1 << hd->minor_shift) - 1;
int sector_size = bdev_hardsect_size(bdev) / 512; int sector_size = bdev_hardsect_size(bdev) / 512;
int loopct = 0; /* number of links followed int loopct = 0; /* number of links followed
without finding a data partition */ without finding a data partition */
int i; int i;
this_sector = first_sector = hd->part[minor].start_sect; this_sector = first_sector;
this_size = first_size; this_size = first_size;
while (1) { while (1) {
if (++loopct > 100) if (++loopct > 100)
return; return;
if ((*current_minor & mask) == 0) if (state->next == state->limit)
return; return;
data = read_dev_sector(bdev, this_sector, &sect); data = read_dev_sector(bdev, this_sector, &sect);
if (!data) if (!data)
...@@ -153,7 +124,7 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -153,7 +124,7 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev,
* First process the data partition(s) * First process the data partition(s)
*/ */
for (i=0; i<4; i++, p++) { for (i=0; i<4; i++, p++) {
unsigned long offs, size, next; u32 offs, size, next;
if (!NR_SECTS(p) || is_extended_partition(p)) if (!NR_SECTS(p) || is_extended_partition(p))
continue; continue;
...@@ -171,27 +142,19 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -171,27 +142,19 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev,
continue; continue;
} }
add_gd_partition(hd, *current_minor, next, size); put_partition(state, state->next, next, size);
#if CONFIG_BLK_DEV_MD if (SYS_IND(p) == LINUX_RAID_PARTITION)
if (SYS_IND(p) == LINUX_RAID_PARTITION) { state->parts[state->next].flags = 1;
md_autodetect_dev(mk_kdev(hd->major,*current_minor));
}
#endif
(*current_minor)++;
loopct = 0; loopct = 0;
if ((*current_minor & mask) == 0) if (++state->next == state->limit)
goto done; goto done;
} }
/* /*
* Next, process the (first) extended partition, if present. * Next, process the (first) extended partition, if present.
* (So far, there seems to be no reason to make * (So far, there seems to be no reason to make
* extended_partition() recursive and allow a tree * parse_extended() recursive and allow a tree
* of extended partitions.) * of extended partitions.)
* It should be a link to the next logical partition. * 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; p -= 4;
for (i=0; i<4; i++, p++) for (i=0; i<4; i++, p++)
...@@ -202,7 +165,6 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -202,7 +165,6 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev,
this_sector = first_sector + START_SECT(p) * sector_size; this_sector = first_sector + START_SECT(p) * sector_size;
this_size = NR_SECTS(p) * sector_size; this_size = NR_SECTS(p) * sector_size;
minor = *current_minor;
put_dev_sector(sect); put_dev_sector(sect);
} }
done: done:
...@@ -213,18 +175,13 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -213,18 +175,13 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev,
indicates linux swap. Be careful before believing this is Solaris. */ indicates linux swap. Be careful before believing this is Solaris. */
static void static void
solaris_x86_partition(struct gendisk *hd, struct block_device *bdev, parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
int minor, int *current_minor) u32 offset, u32 size, int origin)
{ {
#ifdef CONFIG_SOLARIS_X86_PARTITION #ifdef CONFIG_SOLARIS_X86_PARTITION
long offset = hd->part[minor].start_sect;
Sector sect; Sector sect;
struct solaris_x86_vtoc *v; struct solaris_x86_vtoc *v;
struct solaris_x86_slice *s;
int mask = (1 << hd->minor_shift) - 1;
int i; int i;
char buf[40];
v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect); v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
if (!v) if (!v)
...@@ -233,29 +190,23 @@ solaris_x86_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -233,29 +190,23 @@ solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
put_dev_sector(sect); put_dev_sector(sect);
return; return;
} }
printk(" %s: <solaris:", partition_name(hd, minor, buf)); printk(" %s%d: <solaris:", state->name, origin);
if (le32_to_cpu(v->v_version) != 1) { if (le32_to_cpu(v->v_version) != 1) {
printk(" cannot handle version %d vtoc>\n", printk(" cannot handle version %d vtoc>\n",
le32_to_cpu(v->v_version)); le32_to_cpu(v->v_version));
put_dev_sector(sect); put_dev_sector(sect);
return; return;
} }
for (i=0; i<SOLARIS_X86_NUMSLICE; i++) { for (i=0; i<SOLARIS_X86_NUMSLICE && state->next<state->limit; i++) {
if ((*current_minor & mask) == 0) struct solaris_x86_slice *s = &v->v_slice[i];
break;
s = &v->v_slice[i];
if (s->s_size == 0) if (s->s_size == 0)
continue; continue;
printk(" [s%d]", i); printk(" [s%d]", i);
/* solaris partitions are relative to current MS-DOS /* solaris partitions are relative to current MS-DOS
* one but add_gd_partition starts relative to sector * one; must add the offset of the current partition */
* zero of the disk. Therefore, must add the offset put_partition(state, state->next++,
* of the current partition */
add_gd_partition(hd, *current_minor,
le32_to_cpu(s->s_start)+offset, le32_to_cpu(s->s_start)+offset,
le32_to_cpu(s->s_size)); le32_to_cpu(s->s_size));
(*current_minor)++;
} }
put_dev_sector(sect); put_dev_sector(sect);
printk(" >\n"); printk(" >\n");
...@@ -265,17 +216,16 @@ solaris_x86_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -265,17 +216,16 @@ solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
#ifdef CONFIG_BSD_DISKLABEL #ifdef CONFIG_BSD_DISKLABEL
/* /*
* Create devices for BSD partitions listed in a disklabel, under a * Create devices for BSD partitions listed in a disklabel, under a
* dos-like partition. See extended_partition() for more information. * dos-like partition. See parse_extended() for more information.
*/ */
static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev, static void
int minor, int *current_minor, char *name, int max_partitions) parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin, char *flavour,
int max_partitions)
{ {
long offset = hd->part[minor].start_sect;
Sector sect; Sector sect;
struct bsd_disklabel *l; struct bsd_disklabel *l;
struct bsd_partition *p; struct bsd_partition *p;
int mask = (1 << hd->minor_shift) - 1;
char buf[40];
l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect); l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect);
if (!l) if (!l)
...@@ -284,69 +234,75 @@ static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -284,69 +234,75 @@ static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
put_dev_sector(sect); put_dev_sector(sect);
return; return;
} }
printk(" %s: <%s:", partition_name(hd, minor, buf), name); printk(" %s%d: <%s:", state->name, origin, flavour);
if (le16_to_cpu(l->d_npartitions) < max_partitions) if (le16_to_cpu(l->d_npartitions) < max_partitions)
max_partitions = le16_to_cpu(l->d_npartitions); 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; u32 bsd_start, bsd_size;
if ((*current_minor & mask) == 0) if (state->next == state->limit)
break; break;
if (p->p_fstype == BSD_FS_UNUSED) if (p->p_fstype == BSD_FS_UNUSED)
continue; continue;
bsd_start = le32_to_cpu(p->p_offset); bsd_start = le32_to_cpu(p->p_offset);
bsd_size = le32_to_cpu(p->p_size); bsd_size = le32_to_cpu(p->p_size);
if (check_and_add_subpartition(hd, minor, *current_minor, if (offset == bsd_start && size == bsd_size)
bsd_start, bsd_size)) /* full parent partition, we have it already */
(*current_minor)++; continue;
if (offset > bsd_start || offset+size < bsd_start+bsd_size) {
printk("bad subpartition - ignored\n");
continue;
}
put_partition(state, state->next++, bsd_start, bsd_size);
} }
put_dev_sector(sect); put_dev_sector(sect);
printk(" >\n"); printk(" >\n");
} }
#endif #endif
static void bsd_partition(struct gendisk *hd, struct block_device *bdev, static void
int minor, int *current_minor) parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{ {
#ifdef CONFIG_BSD_DISKLABEL #ifdef CONFIG_BSD_DISKLABEL
do_bsd_partition(hd, bdev, minor, current_minor, "bsd", parse_bsd(state, bdev, offset, size, origin,
BSD_MAXPARTITIONS); "bsd", BSD_MAXPARTITIONS);
#endif #endif
} }
static void netbsd_partition(struct gendisk *hd, struct block_device *bdev, static void
int minor, int *current_minor) parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{ {
#ifdef CONFIG_BSD_DISKLABEL #ifdef CONFIG_BSD_DISKLABEL
do_bsd_partition(hd, bdev, minor, current_minor, "netbsd", parse_bsd(state, bdev, offset, size, origin,
BSD_MAXPARTITIONS); "netbsd", BSD_MAXPARTITIONS);
#endif #endif
} }
static void openbsd_partition(struct gendisk *hd, struct block_device *bdev, static void
int minor, int *current_minor) parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{ {
#ifdef CONFIG_BSD_DISKLABEL #ifdef CONFIG_BSD_DISKLABEL
do_bsd_partition(hd, bdev, minor, current_minor, parse_bsd(state, bdev, offset, size, origin,
"openbsd", OPENBSD_MAXPARTITIONS); "openbsd", OPENBSD_MAXPARTITIONS);
#endif #endif
} }
/* /*
* Create devices for Unixware partitions listed in a disklabel, under a * Create devices for Unixware partitions listed in a disklabel, under a
* dos-like partition. See extended_partition() for more information. * dos-like partition. See parse_extended() for more information.
*/ */
static void unixware_partition(struct gendisk *hd, struct block_device *bdev, static void
int minor, int *current_minor) parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{ {
#ifdef CONFIG_UNIXWARE_DISKLABEL #ifdef CONFIG_UNIXWARE_DISKLABEL
long offset = hd->part[minor].start_sect;
Sector sect; Sector sect;
struct unixware_disklabel *l; struct unixware_disklabel *l;
struct unixware_slice *p; struct unixware_slice *p;
int mask = (1 << hd->minor_shift) - 1;
char buf[40];
l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, &sect); l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, &sect);
if (!l) if (!l)
...@@ -356,18 +312,16 @@ static void unixware_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -356,18 +312,16 @@ static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
put_dev_sector(sect); put_dev_sector(sect);
return; return;
} }
printk(" %s: <unixware:", partition_name(hd, minor, buf)); printk(" %s%d: <unixware:", state->name, origin);
p = &l->vtoc.v_slice[1]; p = &l->vtoc.v_slice[1];
/* I omit the 0th slice as it is the same as whole disk. */ /* I omit the 0th slice as it is the same as whole disk. */
while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) { while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
if ((*current_minor & mask) == 0) if (state->next == state->limit)
break; break;
if (p->s_label != UNIXWARE_FS_UNUSED) { if (p->s_label != UNIXWARE_FS_UNUSED)
add_gd_partition(hd, *current_minor, START_SECT(p), put_partition(state, state->next++,
NR_SECTS(p)); START_SECT(p), NR_SECTS(p));
(*current_minor)++;
}
p++; p++;
} }
put_dev_sector(sect); put_dev_sector(sect);
...@@ -380,17 +334,15 @@ static void unixware_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -380,17 +334,15 @@ static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
* Anand Krishnamurthy <anandk@wiproge.med.ge.com> * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
* Rajeev V. Pillai <rajeevvp@yahoo.com> * Rajeev V. Pillai <rajeevvp@yahoo.com>
*/ */
static void minix_partition(struct gendisk *hd, struct block_device *bdev, static void
int minor, int *current_minor) parse_minix(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{ {
#ifdef CONFIG_MINIX_SUBPARTITION #ifdef CONFIG_MINIX_SUBPARTITION
long offset = hd->part[minor].start_sect;
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
struct partition *p; struct partition *p;
int mask = (1 << hd->minor_shift) - 1;
int i; int i;
char buf[40];
data = read_dev_sector(bdev, offset, &sect); data = read_dev_sector(bdev, offset, &sect);
if (!data) if (!data)
...@@ -404,16 +356,14 @@ static void minix_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -404,16 +356,14 @@ static void minix_partition(struct gendisk *hd, struct block_device *bdev,
if (msdos_magic_present (data + 510) && if (msdos_magic_present (data + 510) &&
SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */ SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
printk(" %s: <minix:", partition_name(hd, minor, buf)); printk(" %s%d: <minix:", state->name, origin);
for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) { for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
if ((*current_minor & mask) == 0) if (state->next == state->limit)
break; break;
/* add each partition in use */ /* add each partition in use */
if (SYS_IND(p) == MINIX_PARTITION) { if (SYS_IND(p) == MINIX_PARTITION)
add_gd_partition(hd, *current_minor, put_partition(state, state->next++,
START_SECT(p), NR_SECTS(p)); START_SECT(p), NR_SECTS(p));
(*current_minor)++;
}
} }
printk(" >\n"); printk(" >\n");
} }
...@@ -423,14 +373,15 @@ static void minix_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -423,14 +373,15 @@ static void minix_partition(struct gendisk *hd, struct block_device *bdev,
static struct { static struct {
unsigned char id; unsigned char id;
void (*parse)(struct gendisk *, struct block_device *, int, int *); void (*parse)(struct parsed_partitions *, struct block_device *,
u32, u32, int);
} subtypes[] = { } subtypes[] = {
{BSD_PARTITION, bsd_partition}, {BSD_PARTITION, parse_freebsd},
{NETBSD_PARTITION, netbsd_partition}, {NETBSD_PARTITION, parse_netbsd},
{OPENBSD_PARTITION, openbsd_partition}, {OPENBSD_PARTITION, parse_openbsd},
{MINIX_PARTITION, minix_partition}, {MINIX_PARTITION, parse_minix},
{UNIXWARE_PARTITION, unixware_partition}, {UNIXWARE_PARTITION, parse_unixware},
{SOLARIS_X86_PARTITION, solaris_x86_partition}, {SOLARIS_X86_PARTITION, parse_solaris_x86},
{0, NULL}, {0, NULL},
}; };
/* /*
...@@ -515,16 +466,13 @@ static int handle_ide_mess(struct block_device *bdev) ...@@ -515,16 +466,13 @@ static int handle_ide_mess(struct block_device *bdev)
return 1; return 1;
} }
int msdos_partition(struct gendisk *hd, struct block_device *bdev, int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int first_part_minor)
{ {
int i, minor = first_part_minor; int sector_size = bdev_hardsect_size(bdev) / 512;
Sector sect; Sector sect;
struct partition *p;
unsigned char *data; unsigned char *data;
int mask = (1 << hd->minor_shift) - 1; struct partition *p;
int sector_size = bdev_hardsect_size(bdev) / 512; int slot;
int current_minor = first_part_minor;
int err; int err;
err = handle_ide_mess(bdev); err = handle_ide_mess(bdev);
...@@ -539,7 +487,7 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -539,7 +487,7 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev,
} }
p = (struct partition *) (data + 0x1be); p = (struct partition *) (data + 0x1be);
#ifdef CONFIG_EFI_PARTITION #ifdef CONFIG_EFI_PARTITION
for (i=1 ; i<=4 ; i++,p++) { for (slot = 1 ; slot <= 4 ; slot++, p++) {
/* If this is an EFI GPT disk, msdos should ignore it. */ /* If this is an EFI GPT disk, msdos should ignore it. */
if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) { if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
put_dev_sector(sect); put_dev_sector(sect);
...@@ -555,28 +503,24 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -555,28 +503,24 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev,
* On the second pass look inside *BSD, Unixware and Solaris partitions. * On the second pass look inside *BSD, Unixware and Solaris partitions.
*/ */
current_minor += 4; state->next = 5;
for (i=1 ; i<=4 ; minor++,i++,p++) { for (slot = 1 ; slot <= 4 ; slot++, p++) {
if (!NR_SECTS(p)) u32 start = START_SECT(p)*sector_size;
u32 size = NR_SECTS(p)*sector_size;
if (!size)
continue; continue;
add_gd_partition(hd, minor,
first_sector+START_SECT(p)*sector_size,
NR_SECTS(p)*sector_size);
#if CONFIG_BLK_DEV_MD
if (SYS_IND(p) == LINUX_RAID_PARTITION) {
md_autodetect_dev(mk_kdev(hd->major,minor));
}
#endif
if (is_extended_partition(p)) { if (is_extended_partition(p)) {
unsigned long size = hd->part[minor].nr_sects;
printk(" <");
/* prevent someone doing mkfs or mkswap on an /* prevent someone doing mkfs or mkswap on an
extended partition, but leave room for LILO */ extended partition, but leave room for LILO */
if (size > 2) put_partition(state, slot, start, size == 1 ? 1 : 2);
hd->part[minor].nr_sects = 2; printk(" <");
extended_partition(hd, bdev, minor, size, &current_minor); parse_extended(state, bdev, start, size);
printk(" >"); printk(" >");
continue;
} }
put_partition(state, slot, start, size);
if (SYS_IND(p) == LINUX_RAID_PARTITION)
state->parts[slot].flags = 1;
} }
/* /*
...@@ -584,21 +528,21 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -584,21 +528,21 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev,
*/ */
if (msdos_magic_present(data + 0xfc)) { if (msdos_magic_present(data + 0xfc)) {
p = (struct partition *) (0x1be + data); p = (struct partition *) (0x1be + data);
for (i = 4 ; i < 16 ; i++, current_minor++) { for (slot = 4 ; slot < 16 ; slot++, state->next++) {
p--; p--;
if ((current_minor & mask) == 0) if (state->next == state->limit)
break; break;
if (!(START_SECT(p) && NR_SECTS(p))) if (!(START_SECT(p) && NR_SECTS(p)))
continue; continue;
add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p)); put_partition(state, state->next,
START_SECT(p), NR_SECTS(p));
} }
} }
printk("\n"); printk("\n");
/* second pass - output for each on a separate line */ /* second pass - output for each on a separate line */
minor -= 4;
p = (struct partition *) (0x1be + data); p = (struct partition *) (0x1be + data);
for (i=1 ; i<=4 ; minor++,i++,p++) { for (slot = 1 ; slot <= 4 ; slot++, p++) {
unsigned char id = SYS_IND(p); unsigned char id = SYS_IND(p);
int n; int n;
...@@ -608,8 +552,10 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -608,8 +552,10 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev,
for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++) for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
; ;
if (subtypes[n].parse) if (!subtypes[n].parse)
subtypes[n].parse(hd, bdev, minor, &current_minor); continue;
subtypes[n].parse(state, bdev, START_SECT(p)*sector_size,
NR_SECTS(p)*sector_size, n);
} }
put_dev_sector(sect); put_dev_sector(sect);
return 1; return 1;
......
...@@ -4,6 +4,5 @@ ...@@ -4,6 +4,5 @@
#define MSDOS_LABEL_MAGIC 0xAA55 #define MSDOS_LABEL_MAGIC 0xAA55
int msdos_partition(struct gendisk *hd, struct block_device *bdev, int msdos_partition(struct parsed_partitions *state, struct block_device *bdev);
unsigned long first_sector, int first_part_minor);
...@@ -7,23 +7,15 @@ ...@@ -7,23 +7,15 @@
* Re-organised Feb 1998 Russell King * Re-organised Feb 1998 Russell King
*/ */
#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 "check.h" #include "check.h"
#include "osf.h" #include "osf.h"
int osf_partition(struct gendisk *hd, struct block_device *bdev, int osf_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int current_minor)
{ {
int i; int i;
int slot = 1;
Sector sect; Sector sect;
unsigned char *data; unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
struct disklabel { struct disklabel {
u32 d_magic; u32 d_magic;
u16 d_type,d_subtype; u16 d_type,d_subtype;
...@@ -72,16 +64,14 @@ int osf_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -72,16 +64,14 @@ int osf_partition(struct gendisk *hd, struct block_device *bdev,
return 0; return 0;
} }
for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
if ((current_minor & mask) == 0) if (slot == state->limit)
break; break;
if (le32_to_cpu(partition->p_size)) if (le32_to_cpu(partition->p_size))
add_gd_partition(hd, current_minor, put_partition(state, slot++,
first_sector+le32_to_cpu(partition->p_offset), le32_to_cpu(partition->p_offset),
le32_to_cpu(partition->p_size)); le32_to_cpu(partition->p_size));
current_minor++;
} }
printk("\n"); printk("\n");
put_dev_sector(sect); put_dev_sector(sect);
return 1; return 1;
} }
...@@ -4,6 +4,4 @@ ...@@ -4,6 +4,4 @@
#define DISKLABELMAGIC (0x82564557UL) #define DISKLABELMAGIC (0x82564557UL)
int osf_partition(struct gendisk *hd, struct block_device *bdev, int osf_partition(struct parsed_partitions *state, struct block_device *bdev);
unsigned long first_sector, int current_minor);
...@@ -4,22 +4,13 @@ ...@@ -4,22 +4,13 @@
* Code extracted from drivers/block/genhd.c * Code extracted from drivers/block/genhd.c
*/ */
#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/byteorder.h>
#include <asm/system.h>
#include "check.h" #include "check.h"
#include "sgi.h" #include "sgi.h"
int sgi_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int current_minor) int sgi_partition(struct parsed_partitions *state, struct block_device *bdev)
{ {
int i, csum, magic; int i, csum, magic;
int slot = 1;
unsigned int *ui, start, blocks, cs; unsigned int *ui, start, blocks, cs;
Sector sect; Sector sect;
struct sgi_disklabel { struct sgi_disklabel {
...@@ -73,10 +64,8 @@ int sgi_partition(struct gendisk *hd, struct block_device *bdev, unsigned long f ...@@ -73,10 +64,8 @@ int sgi_partition(struct gendisk *hd, struct block_device *bdev, unsigned long f
for(i = 0; i < 16; i++, p++) { for(i = 0; i < 16; i++, p++) {
blocks = be32_to_cpu(p->num_blocks); blocks = be32_to_cpu(p->num_blocks);
start = be32_to_cpu(p->first_block); start = be32_to_cpu(p->first_block);
if(!blocks) if (blocks)
continue; put_partition(state, slot++, start, blocks);
add_gd_partition(hd, current_minor, start, blocks);
current_minor++;
} }
printk("\n"); printk("\n");
put_dev_sector(sect); put_dev_sector(sect);
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
* fs/partitions/sgi.h * fs/partitions/sgi.h
*/ */
extern int sgi_partition(struct gendisk *hd, struct block_device *bdev, extern int sgi_partition(struct parsed_partitions *state, struct block_device *bdev);
unsigned long first_sector, int first_part_minor);
#define SGI_LABEL_MAGIC 0x0be5a941 #define SGI_LABEL_MAGIC 0x0be5a941
...@@ -7,21 +7,13 @@ ...@@ -7,21 +7,13 @@
* Re-organised Feb 1998 Russell King * Re-organised Feb 1998 Russell King
*/ */
#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 "check.h"
#include "sun.h" #include "sun.h"
int sun_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int first_part_minor) int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
{ {
int i, csum; int i, csum;
int slot = 1;
unsigned short *ush; unsigned short *ush;
Sector sect; Sector sect;
struct sun_disklabel { struct sun_disklabel {
...@@ -74,11 +66,10 @@ int sun_partition(struct gendisk *hd, struct block_device *bdev, unsigned long f ...@@ -74,11 +66,10 @@ int sun_partition(struct gendisk *hd, struct block_device *bdev, unsigned long f
unsigned long st_sector; unsigned long st_sector;
int num_sectors; int num_sectors;
st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc; st_sector = be32_to_cpu(p->start_cylinder) * spc;
num_sectors = be32_to_cpu(p->num_sectors); num_sectors = be32_to_cpu(p->num_sectors);
if (num_sectors) if (num_sectors)
add_gd_partition(hd, first_part_minor, st_sector, num_sectors); put_partition(state, slot++, st_sector, num_sectors);
first_part_minor++;
} }
printk("\n"); printk("\n");
put_dev_sector(sect); put_dev_sector(sect);
......
...@@ -4,6 +4,4 @@ ...@@ -4,6 +4,4 @@
#define SUN_LABEL_MAGIC 0xDABE #define SUN_LABEL_MAGIC 0xDABE
int sun_partition(struct gendisk *hd, struct block_device *bdev, int sun_partition(struct parsed_partitions *state, struct block_device *bdev);
unsigned long first_sector, int first_part_minor);
...@@ -6,16 +6,9 @@ ...@@ -6,16 +6,9 @@
* Re-organised Jul 1999 Russell King * Re-organised Jul 1999 Russell King
*/ */
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/blk.h>
#include "check.h" #include "check.h"
int ultrix_partition(struct gendisk *hd, struct block_device *bdev, int ultrix_partition(struct parsed_partitions *state, struct block_device *bdev)
unsigned long first_sector, int first_part_minor)
{ {
int i; int i;
Sector sect; Sector sect;
...@@ -39,9 +32,9 @@ int ultrix_partition(struct gendisk *hd, struct block_device *bdev, ...@@ -39,9 +32,9 @@ int ultrix_partition(struct gendisk *hd, struct block_device *bdev,
label = (struct ultrix_disklabel *)(data + 512 - sizeof(*label)); label = (struct ultrix_disklabel *)(data + 512 - sizeof(*label));
if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) { if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
for (i=0; i<8; i++, first_part_minor++) for (i=0; i<8; i++)
if (label->pt_part[i].pi_nblocks) if (label->pt_part[i].pi_nblocks)
add_gd_partition(hd, first_part_minor, put_partition(state, i+1,
label->pt_part[i].pi_blkoff, label->pt_part[i].pi_blkoff,
label->pt_part[i].pi_nblocks); label->pt_part[i].pi_nblocks);
put_dev_sector(sect); put_dev_sector(sect);
......
...@@ -2,6 +2,4 @@ ...@@ -2,6 +2,4 @@
* fs/partitions/ultrix.h * fs/partitions/ultrix.h
*/ */
int ultrix_partition(struct gendisk *hd, struct block_device *bdev, int ultrix_partition(struct parsed_partitions *state, struct block_device *bdev);
unsigned long first_sector, int first_part_minor);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment