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)
* since if there are any non-ADFS partitions on the disk, this won't work!
* Hence, I want to get rid of this...
*/
void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads,
unsigned long discsize, unsigned int secsize)
void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
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) {
mfm_info[drive].sectors = secsptrack;
......@@ -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);
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
* lucky you can pick apart your disc to find out what is going on -
......
......@@ -10,33 +10,14 @@
* Scan ADFS partitions on hard disk drives.
*/
#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 "check.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 *
adfs_partition(struct gendisk *hd, char *name, char *data,
unsigned long first_sector, int minor)
adfs_partition(struct parsed_partitions *state, char *name, char *data,
unsigned long first_sector, int slot)
{
struct adfs_discrecord *dr;
unsigned int nr_sects;
......@@ -54,14 +35,14 @@ adfs_partition(struct gendisk *hd, char *name, char *data,
if (name)
printk(" [%s]", name);
add_gd_partition(hd, minor, first_sector, nr_sects);
put_partition(state, slot, first_sector, nr_sects);
return dr;
}
#ifdef CONFIG_ACORN_PARTITION_RISCIX
static int
riscix_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sect, int minor, unsigned long nr_sects)
riscix_partition(struct parsed_partitions *state, struct block_device *bdev,
unsigned long first_sect, int slot, unsigned long nr_sects)
{
Sector sect;
struct riscix_record *rr;
......@@ -79,11 +60,11 @@ riscix_partition(struct gendisk *hd, struct block_device *bdev,
printk(" <");
add_gd_partition(hd, minor++, first_sect, size);
put_partition(state, slot++, first_sect, size);
for (part = 0; part < 8; part++) {
if (rr->part[part].one &&
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].length));
printk("(%s)", rr->part[part].name);
......@@ -92,26 +73,25 @@ riscix_partition(struct gendisk *hd, struct block_device *bdev,
printk(" >\n");
} else {
add_gd_partition(hd, minor++, first_sect, nr_sects);
put_partition(state, slot++, first_sect, nr_sects);
}
put_dev_sector(sect);
return minor;
return slot;
}
#endif
static int
linux_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sect, int minor, unsigned long nr_sects)
linux_partition(struct parsed_partitions *state, struct block_device *bdev,
unsigned long first_sect, int slot, unsigned long nr_sects)
{
Sector sect;
struct linux_part *linuxp;
unsigned int mask = (1 << hd->minor_shift) - 1;
unsigned long size = nr_sects > 2 ? 2 : nr_sects;
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);
if (!linuxp)
......@@ -120,9 +100,9 @@ linux_partition(struct gendisk *hd, struct block_device *bdev,
printk(" <");
while (linuxp->magic == cpu_to_le32(LINUX_NATIVE_MAGIC) ||
linuxp->magic == cpu_to_le32(LINUX_SWAP_MAGIC)) {
if (!(minor & mask))
if (slot == state->limit)
break;
add_gd_partition(hd, minor++, first_sect +
put_partition(state, slot++, first_sect +
le32_to_cpu(linuxp->start_sect),
le32_to_cpu(linuxp->nr_sects));
linuxp ++;
......@@ -130,19 +110,20 @@ linux_partition(struct gendisk *hd, struct block_device *bdev,
printk(" >");
put_dev_sector(sect);
return minor;
return slot;
}
#ifdef CONFIG_ACORN_PARTITION_CUMANA
static int
adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
adfspart_check_CUMANA(struct parsed_partitions *state, struct block_device *bdev)
{
unsigned int start_blk = 0, mask = (1 << hd->minor_shift) - 1;
unsigned long first_sector = 0;
unsigned int start_blk = 0;
Sector sect;
unsigned char *data;
char *name = "CUMANA/ADFS";
int first = 1;
int slot = 1;
/*
* Try Cumana style partitions - sector 3 contains ADFS boot block
......@@ -165,10 +146,10 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
if (!data)
return -1;
if (!(minor & mask))
if (slot == state->limit)
break;
dr = adfs_partition(hd, name, data, first_sector, minor++);
dr = adfs_partition(state, name, data, first_sector, slot++);
if (!dr)
break;
......@@ -193,19 +174,19 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
#ifdef CONFIG_ACORN_PARTITION_RISCIX
case PARTITION_RISCIX_SCSI:
/* RISCiX - we don't know how to find the next one. */
minor = riscix_partition(hd, bdev, first_sector,
minor, nr_sects);
slot = riscix_partition(state, bdev, first_sector,
slot, nr_sects);
break;
#endif
case PARTITION_LINUX:
minor = linux_partition(hd, bdev, first_sector,
minor, nr_sects);
slot = linux_partition(state, bdev, first_sector,
slot, nr_sects);
break;
}
put_dev_sector(sect);
if (minor == -1)
return minor;
if (slot == -1)
return -1;
} while (1);
put_dev_sector(sect);
return first ? 0 : 1;
......@@ -218,8 +199,6 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
*
* Params : hd - pointer to gendisk structure to store partition info.
* 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.
*
......@@ -228,20 +207,20 @@ adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
* hda2 = non-ADFS partition.
*/
static int
adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
adfspart_check_ADFS(struct parsed_partitions *state, struct block_device *bdev)
{
unsigned long start_sect, nr_sects, sectscyl, heads;
Sector sect;
unsigned char *data;
struct adfs_discrecord *dr;
unsigned char id;
int slot = 1;
data = read_dev_sector(bdev, 6, &sect);
if (!data)
return -1;
dr = adfs_partition(hd, "ADFS", data, first_sector, minor++);
dr = adfs_partition(state, "ADFS", data, 0, slot++);
if (!dr) {
put_dev_sector(sect);
return 0;
......@@ -253,9 +232,15 @@ adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
id = data[0x1fc] & 15;
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);
truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
}
#endif
/*
* Work out start of non-adfs partition.
......@@ -263,20 +248,18 @@ adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
nr_sects = (bdev->bd_inode->i_size >> 9) - start_sect;
if (start_sect) {
first_sector += start_sect;
switch (id) {
#ifdef CONFIG_ACORN_PARTITION_RISCIX
case PARTITION_RISCIX_SCSI:
case PARTITION_RISCIX_MFM:
minor = riscix_partition(hd, bdev, first_sector,
minor, nr_sects);
slot = riscix_partition(state, bdev, start_sect,
slot, nr_sects);
break;
#endif
case PARTITION_LINUX:
minor = linux_partition(hd, bdev, first_sector,
minor, nr_sects);
slot = linux_partition(state, bdev, start_sect,
slot, nr_sects);
break;
}
}
......@@ -304,8 +287,6 @@ static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long bloc
* Purpose: allocate ICS partitions.
* Params : hd - pointer to gendisk structure to store partition info.
* 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.
* Alloc : hda = whole drive
* hda1 = ADFS partition 0 on first drive.
......@@ -313,13 +294,13 @@ static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long bloc
* ..etc..
*/
static int
adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
adfspart_check_ICS(struct parsed_partitions *state, struct block_device *bdev)
{
Sector sect;
unsigned char *data;
unsigned long sum;
unsigned int i, mask = (1 << hd->minor_shift) - 1;
unsigned int i;
int slot;
struct ics_part *p;
/*
......@@ -343,16 +324,13 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
printk(" [ICS]");
for (p = (struct ics_part *)data; p->size; p++) {
unsigned long start;
long size;
for (slot = 1, p = (struct ics_part *)data; p->size; p++) {
u32 start = le32_to_cpu(p->start);
u32 size = le32_to_cpu(p->size);
if ((minor & mask) == 0)
if (slot == state->limit)
break;
start = le32_to_cpu(p->start);
size = le32_to_cpu(p->size);
if (size < 0) {
size = -size;
......@@ -366,10 +344,8 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
}
}
if (size) {
add_gd_partition(hd, minor, first_sector + start, size);
minor++;
}
if (size)
put_partition(state, slot++, start, size);
}
put_dev_sector(sect);
......@@ -381,8 +357,6 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
* Purpose: allocate ICS partitions.
* Params : hd - pointer to gendisk structure to store partition info.
* 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.
* Alloc : hda = whole drive
* hda1 = ADFS partition 0 on first drive.
......@@ -391,13 +365,13 @@ adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
*/
#ifdef CONFIG_ACORN_PARTITION_POWERTEC
static int
adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
adfspart_check_POWERTEC(struct parsed_partitions *state, struct block_device *bdev)
{
Sector sect;
unsigned char *data;
struct ptec_partition *p;
unsigned char checksum;
int slot = 1;
int i;
data = read_dev_sector(bdev, 0, &sect);
......@@ -415,16 +389,11 @@ adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
printk(" [POWERTEC]");
for (i = 0, p = (struct ptec_partition *)data; i < 12; i++, p++) {
unsigned long start;
unsigned long size;
start = le32_to_cpu(p->start);
size = le32_to_cpu(p->size);
u32 start = le32_to_cpu(p->start);
u32 size = le32_to_cpu(p->size);
if (size)
add_gd_partition(hd, minor, first_sector + start,
size);
minor++;
put_partition(state, slot++, start, size);
}
put_dev_sector(sect);
......@@ -432,7 +401,7 @@ adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
}
#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
adfspart_check_ICS,
#endif
......@@ -454,18 +423,15 @@ static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, i
*
* Params : hd - pointer to gendisk structure
* 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.
*/
int acorn_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sect, int first_minor)
int acorn_partition(struct parsed_partitions *state, struct block_device *bdev)
{
int 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 > 0)
printk("\n");
......
......@@ -50,6 +50,4 @@ struct ptec_partition {
};
int acorn_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sect, int first_minor);
int acorn_partition(struct parsed_partitions *state, struct block_device *bdev);
......@@ -7,14 +7,7 @@
* 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/byteorder.h>
#include <linux/types.h>
#include <linux/affs_hardblocks.h>
#include "check.h"
......@@ -31,14 +24,14 @@ checksum_block(u32 *m, int size)
}
int
amiga_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor)
amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
{
Sector sect;
unsigned char *data;
struct RigidDiskBlock *rdb;
struct PartitionBlock *pb;
int start_sect, nr_sects, blk, part, res = 0;
int slot = 1;
for (blk = 0; ; blk++, put_dev_sector(sect)) {
if (blk == RDB_ALLOCATION_LIMIT)
......@@ -100,8 +93,7 @@ amiga_partition(struct gendisk *hd, struct block_device *bdev,
start_sect = be32_to_cpu(pb->pb_Environment[9]) *
be32_to_cpu(pb->pb_Environment[3]) *
be32_to_cpu(pb->pb_Environment[5]);
add_gd_partition(hd,first_part_minor,start_sect,nr_sects);
first_part_minor++;
put_partition(state,slot++,start_sect,nr_sects);
res = 1;
}
printk("\n");
......
......@@ -2,7 +2,5 @@
* fs/partitions/amiga.h
*/
int
amiga_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
int amiga_partition(struct parsed_partitions *state, struct block_device *bdev);
......@@ -7,17 +7,7 @@
* 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 <asm/byteorder.h>
#include <asm/system.h>
#include "check.h"
#include "atari.h"
......@@ -40,15 +30,14 @@ static inline int OK_id(char *s)
memcmp (s, "RAW", 3) == 0 ;
}
int atari_partition (struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
int atari_partition(struct parsed_partitions *state, struct block_device *bdev)
{
int m_lim = minor + (1 << hd->minor_shift);
Sector sect;
struct rootsector *rs;
struct partition_info *pi;
u32 extensect;
u32 hd_size;
int slot;
#ifdef ICD_PARTS
int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
#endif
......@@ -58,7 +47,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
return -1;
/* 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) &&
!VALID_PARTITION(&rs->part[1], hd_size) &&
!VALID_PARTITION(&rs->part[2], hd_size) &&
......@@ -74,7 +63,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
pi = &rs->part[0];
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;
Sector sect2;
ulong partsect;
......@@ -84,7 +73,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
/* active partition */
if (memcmp (pi->id, "XGM", 3) != 0) {
/* 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));
continue;
}
......@@ -109,7 +98,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
break;
}
add_gd_partition(hd, minor,
put_partition(state, slot,
partsect + be32_to_cpu(xrs->part[0].st),
be32_to_cpu(xrs->part[0].siz));
......@@ -126,8 +115,7 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
partsect = be32_to_cpu(xrs->part[1].st) + extensect;
put_dev_sector(sect2);
minor++;
if (minor >= m_lim) {
if (++slot == state->limit) {
printk( "\nMaximum number of partitions reached!\n" );
break;
}
......@@ -140,12 +128,12 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
/* sanity check: no ICD format if first partition invalid */
if (OK_id(pi->id)) {
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 */
if (!((pi->flg & 1) && OK_id(pi->id)))
continue;
part_fmt = 2;
add_gd_partition (hd, minor,
put_partition (state, slot,
be32_to_cpu(pi->st),
be32_to_cpu(pi->siz));
}
......@@ -159,4 +147,3 @@ int atari_partition (struct gendisk *hd, struct block_device *bdev,
return 1;
}
......@@ -31,6 +31,4 @@ struct rootsector
u16 checksum; /* checksum for bootable disks */
} __attribute__((__packed__));
int atari_partition (struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
int atari_partition(struct parsed_partitions *state, struct block_device *bdev);
......@@ -34,10 +34,13 @@
#include "ultrix.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*/
static int (*check_part[])(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sect, int first_minor) = {
static int (*check_part[])(struct parsed_partitions *, struct block_device *) = {
#ifdef CONFIG_ACORN_PARTITION
acorn_partition,
#endif
......@@ -199,28 +202,6 @@ char *disk_name (struct gendisk *hd, int minor, char *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 */
static ssize_t partition_device_kdev_read(struct device *driverfs_dev,
char *page, size_t count, loff_t off)
......@@ -351,12 +332,13 @@ void driverfs_remove_partitions(struct gendisk *hd, int minor)
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;
unsigned long first_sector;
struct block_device *bdev;
char buf[64];
struct parsed_partitions *state;
int i;
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
hd->part[minor(dev)].start_sect = 0;
return;
}
if (first_sector != 0)
BUG();
state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL);
if (!state)
return;
if (hd->de_arr)
de = hd->de_arr[minor(dev) >> hd->minor_shift];
i = devfs_generate_path (de, buf, sizeof buf);
if (i >= 0)
if (i >= 0) {
printk(KERN_INFO " /dev/%s:", buf + i);
else
printk(KERN_INFO " %s:", disk_name(hd, minor(dev), buf));
sprintf(state->name, "p");
} 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->bd_contains = bdev;
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
bdev->bd_block_size = bsize;
bdev->bd_inode->i_blkbits = blksize_bits(bsize);
}
state->limit = 1<<hd->minor_shift;
for (i = 0; check_part[i]; i++) {
int res;
res = check_part[i](hd, bdev, first_sector, first_part_minor);
if (res) {
if (res < 0 && warn_no_part)
int res, j;
memset(&state->parts, 0, sizeof(state->parts));
res = check_part[i](state, bdev);
if (!res)
continue;
if (res < 0) {
if (warn_no_part)
printk(" unable to read partition table\n");
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");
......@@ -410,15 +420,14 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor
invalidate_bdev(bdev, 1);
truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
bdput(bdev);
i = first_part_minor - 1;
/* Setup driverfs tree */
if (hd->sizes)
driverfs_create_partitions(hd, i);
driverfs_create_partitions(hd, minor(dev));
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
......@@ -564,7 +573,7 @@ void grok_partitions(kdev_t dev, long size)
if (!size)
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
......@@ -632,28 +641,3 @@ int wipe_partitions(kdev_t dev)
}
return 0;
}
/*
* Make sure that a proposed subpartition is strictly contained inside
* the parent partition. If all is well, call add_gd_partition().
*/
int
check_and_add_subpartition(struct gendisk *hd, int super_minor, int minor,
int sub_start, int sub_size)
{
int start = hd->part[super_minor].start_sect;
int size = hd->part[super_minor].nr_sects;
if (start == sub_start && size == sub_size) {
/* full parent partition, we have it already */
return 0;
}
if (start <= sub_start && start+size >= sub_start+sub_size) {
add_gd_partition(hd, minor, sub_start, sub_size);
return 1;
}
printk("bad subpartition - ignored\n");
return 0;
}
......@@ -5,12 +5,28 @@
* add_gd_partition adds a partitions details to the devices partition
* description.
*/
void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
/*
* check_and_add_subpartition does the same for subpartitions
*/
int check_and_add_subpartition(struct gendisk *hd, int super_minor,
int minor, int sub_start, int sub_size);
enum { MAX_PART = 256 };
struct parsed_partitions {
char name[40];
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;
......@@ -87,26 +87,10 @@
*
************************************************************/
#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 <asm/system.h>
#include <asm/byteorder.h>
#include "check.h"
#include "efi.h"
#if CONFIG_BLK_DEV_MD
extern void md_autodetect_dev(kdev_t dev);
#endif
/* Handle printing of 64-bit values */
/* Borrowed from /usr/include/inttypes.h */
# if BITS_PER_LONG == 64
......@@ -184,7 +168,6 @@ is_pmbr_valid(legacy_mbr *mbr)
/**
* last_lba(): return number of last logical block of device
* @hd: gendisk with partition list
* @bdev: block device
*
* Description: Returns last LBA value on success, 0 on error.
......@@ -193,16 +176,13 @@ is_pmbr_valid(legacy_mbr *mbr)
* physical sectors available on the disk.
*/
static u64
last_lba(struct gendisk *hd, struct block_device *bdev)
last_lba(struct block_device *bdev)
{
if (!hd || !hd->part || !bdev)
return 0;
return hd->part[minor(to_kdev_t(bdev->bd_dev))].nr_sects - 1;
return (bdev->bd_inode->i_size >> 9) - 1;
}
/**
* read_lba(): Read bytes from disk, starting at given LBA
* @hd
* @bdev
* @lba
* @buffer
......@@ -212,39 +192,26 @@ last_lba(struct gendisk *hd, struct block_device *bdev)
* Returns number of bytes read on success, 0 on error.
*/
static size_t
read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba,
u8 * buffer, size_t count)
read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count)
{
size_t totalreadcount = 0;
size_t totalreadcount = 0, bytesread = 0;
unsigned long blocksize;
int i;
Sector sect;
unsigned char *data = NULL;
if (!hd || !bdev || !buffer || !count)
if (!bdev || !buffer)
return 0;
blocksize = bdev_hardsect_size(bdev);
if (!blocksize)
blocksize = 512;
for (i = 0; count > 0; i++) {
data = read_dev_sector(bdev, lba, &sect);
while (count) {
int copied = 512;
Sector sect;
unsigned char *data = read_dev_sector(bdev, lba++, &sect);
if (!data)
return totalreadcount;
bytesread =
PAGE_CACHE_SIZE - (data -
(unsigned char *) page_address(sect.v));
bytesread = min(bytesread, count);
memcpy(buffer, data, bytesread);
break;
if (copied > count)
copied = count;
memcpy(buffer, data, copied);
put_dev_sector(sect);
buffer += bytesread;
totalreadcount += bytesread;
count -= bytesread;
lba += (bytesread / blocksize);
buffer += copied;
totalreadcount +=copied;
count -= copied;
}
return totalreadcount;
}
......@@ -252,7 +219,6 @@ read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba,
/**
* alloc_read_gpt_entries(): reads partition entries from disk
* @hd
* @bdev
* @gpt - GPT header
*
......@@ -261,12 +227,11 @@ read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba,
* Notes: remember to free pte when you're done!
*/
static gpt_entry *
alloc_read_gpt_entries(struct gendisk *hd,
struct block_device *bdev, gpt_header *gpt)
alloc_read_gpt_entries(struct block_device *bdev, gpt_header *gpt)
{
size_t count;
gpt_entry *pte;
if (!hd || !bdev || !gpt)
if (!bdev || !gpt)
return NULL;
count = le32_to_cpu(gpt->num_partition_entries) *
......@@ -278,7 +243,7 @@ alloc_read_gpt_entries(struct gendisk *hd,
return NULL;
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,
count) < count) {
kfree(pte);
......@@ -290,7 +255,6 @@ alloc_read_gpt_entries(struct gendisk *hd,
/**
* alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
* @hd
* @bdev
* @lba is the Logical Block Address of the partition table
*
......@@ -299,10 +263,10 @@ alloc_read_gpt_entries(struct gendisk *hd,
* Note: remember to free gpt when finished with it.
*/
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;
if (!hd || !bdev)
if (!bdev)
return NULL;
gpt = kmalloc(sizeof (gpt_header), GFP_KERNEL);
......@@ -310,7 +274,7 @@ alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba)
return NULL;
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)) {
kfree(gpt);
gpt=NULL;
......@@ -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
* @hd
* @bdev
* @lba is the logical block address of the GPT header to test
* @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)
* If valid, returns pointers to newly allocated GPT header and PTEs.
*/
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)
{
u32 crc, origcrc;
if (!hd || !bdev || !gpt || !ptes)
if (!bdev || !gpt || !ptes)
return 0;
if (!(*gpt = alloc_read_gpt_header(hd, bdev, lba)))
if (!(*gpt = alloc_read_gpt_header(bdev, lba)))
return 0;
/* Check the GUID Partition Table signature */
......@@ -377,7 +340,7 @@ is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba,
return 0;
}
if (!(*ptes = alloc_read_gpt_entries(hd, bdev, *gpt))) {
if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt))) {
kfree(*gpt);
*gpt = NULL;
return 0;
......@@ -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
* @hd
* @bdev
* @gpt is a GPT header 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)
* or the Alternate GPT header and PTEs valid, and the PMBR valid.
*/
static int
find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
gpt_header **gpt, gpt_entry **ptes)
find_valid_gpt(struct block_device *bdev, gpt_header **gpt, gpt_entry **ptes)
{
int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
gpt_header *pgpt = NULL, *agpt = NULL;
gpt_entry *pptes = NULL, *aptes = NULL;
legacy_mbr *legacymbr = NULL;
u64 lastlba;
if (!hd || !bdev || !gpt || !ptes)
if (!bdev || !gpt || !ptes)
return 0;
lastlba = last_lba(hd, bdev);
good_pgpt = is_gpt_valid(hd, bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
lastlba = last_lba(bdev);
good_pgpt = is_gpt_valid(bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
&pgpt, &pptes);
if (good_pgpt) {
good_agpt = is_gpt_valid(hd, bdev,
good_agpt = is_gpt_valid(bdev,
le64_to_cpu(pgpt->alternate_lba),
&agpt, &aptes);
if (!good_agpt) {
good_agpt = is_gpt_valid(hd, bdev, lastlba,
good_agpt = is_gpt_valid(bdev, lastlba,
&agpt, &aptes);
}
}
else {
good_agpt = is_gpt_valid(hd, bdev, lastlba,
good_agpt = is_gpt_valid(bdev, lastlba,
&agpt, &aptes);
}
......@@ -549,7 +510,7 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
if (legacymbr) {
memset(legacymbr, 0, sizeof (*legacymbr));
read_lba(hd, bdev, 0, (u8 *) legacymbr,
read_lba(bdev, 0, (u8 *) legacymbr,
sizeof (*legacymbr));
good_pmbr = is_pmbr_valid(legacymbr);
kfree(legacymbr);
......@@ -616,12 +577,16 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
}
/**
* add_gpt_partitions(struct gendisk *hd, struct block_device *bdev,
* @hd
* efi_partition(struct parsed_partitions *state, struct block_device *bdev)
* @state
* @bdev
*
* Description: Create devices for each entry in the GUID Partition Table
* Entries.
* 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.
*
* We do not create a Linux partition for GPT, but
* only for the actual data partitions.
......@@ -631,106 +596,41 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
* 1 if successful
*
*/
static int
add_gpt_partitions(struct gendisk *hd, struct block_device *bdev, int nextminor)
int
efi_partition(struct parsed_partitions *state, struct block_device *bdev)
{
gpt_header *gpt = NULL;
gpt_entry *ptes = NULL;
u32 i;
int max_p;
if (!hd || !bdev)
return -1;
if (!find_valid_gpt(hd, bdev, &gpt, &ptes) || !gpt || !ptes) {
if (gpt) {
if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) {
kfree(gpt);
gpt = NULL;
}
if (ptes) {
kfree(ptes);
ptes = NULL;
}
return 0;
}
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 < max_p; i++) {
for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
if (!efi_guidcmp(ptes[i].partition_type_guid, NULL_GUID))
continue;
add_gd_partition(hd, nextminor+i,
le64_to_cpu(ptes[i].starting_lba),
put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba),
(le64_to_cpu(ptes[i].ending_lba) -
le64_to_cpu(ptes[i].starting_lba) +
1));
/* If there's this is a RAID volume, tell md */
#if CONFIG_BLK_DEV_MD
if (!efi_guidcmp(ptes[i].partition_type_guid,
PARTITION_LINUX_RAID_GUID)) {
md_autodetect_dev(mk_kdev(hd->major,
nextminor));
}
#endif
PARTITION_LINUX_RAID_GUID))
state->parts[i+1].flags = 1;
}
kfree(ptes);
ptes=NULL;
kfree(gpt);
gpt=NULL;
printk("\n");
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.
* Emacs will notice this stuff at the end of the file and automatically
......
......@@ -112,9 +112,7 @@ typedef struct _legacy_mbr {
} __attribute__ ((packed)) legacy_mbr;
/* Functions */
extern int
efi_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
extern int efi_partition(struct parsed_partitions *state, struct block_device *bdev);
#endif
......
......@@ -88,8 +88,7 @@ ibm_ioctl_unopened(struct block_device *bdev, unsigned cmd, unsigned long arg)
/*
*/
int
ibm_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor)
ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
{
int blocksize, offset, size;
dasd_information_t *info;
......@@ -100,9 +99,6 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
unsigned char *data;
Sector sect;
if ( first_sector != 0 )
BUG();
if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
goto out_noinfo;
if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
......@@ -155,9 +151,7 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
offset = (info->label_block + 1);
size = bdev->bd_inode->i_size >> 9;
}
// add_gd_partition(hd, first_part_minor - 1, 0, size);
add_gd_partition(hd, first_part_minor,
offset*(blocksize >> 9),
put_partition(state, 1, offset*(blocksize >> 9),
size-offset*(blocksize >> 9));
} else if (strncmp(type, "VOL1", 4) == 0) {
/*
......@@ -194,9 +188,9 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
size = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
offset + geo->sectors;
if (counter >= (1 << hd->minor_shift))
if (counter >= state->limit)
break;
add_gd_partition(hd, first_part_minor + counter,
put_partition(state, counter + 1,
offset * (blocksize >> 9),
size * (blocksize >> 9));
counter++;
......@@ -212,9 +206,7 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
printk("(nonl)/%8s:", name);
offset = (info->label_block + 1);
size = (bdev->bd_inode->i_size >> 9);
// add_gd_partition(hd, first_part_minor - 1, 0, size);
add_gd_partition(hd, first_part_minor,
offset*(blocksize >> 9),
put_partition(state, 1, 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 @@
*
* 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 "check.h"
#include "ldm.h"
......@@ -57,7 +51,6 @@ static void ldm_debug(const char *f, ...);
#endif /* !CONFIG_LDM_DEBUG */
/* Necessary forward declarations. */
static int create_partition(struct gendisk *, int, int, int);
static int parse_privhead(const u8 *, struct privhead *);
static u64 get_vnum(const u8 *, 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)
/**
* add_partition_to_list - insert partition into a partition list
* @pl: sorted list of partitions
* @hd: gendisk structure to which the data partition belongs
* @disk_minor: minor number of the disk device
* @disk_size: number of sectors on the disk device
* @start: first sector within the disk 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)
*
* TODO: Add sanity check for overlapping partitions. (AIA)
*/
static int add_partition_to_list(struct list_head *pl, const struct gendisk *hd,
const int disk_minor, const unsigned long start,
static int add_partition_to_list(struct list_head *pl,
const unsigned long disk_size,
const unsigned long start,
const unsigned long size)
{
struct ldm_part *lp, *lptmp;
struct list_head *tmp;
if (!hd->part)
return -1;
if ((start < 1) || ((start + size) > hd->part[disk_minor].nr_sects)) {
if (start < 1 || start + size > disk_size) {
printk(LDM_CRIT "LDM partition exceeds physical disk. "
"Skipping.\n");
return -1;
......@@ -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
* @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
* @dev: partition device holding the LDM database
* @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,
*
* Return 1 on success and -1 on error.
*/
static int create_data_partitions(struct gendisk *hd,
const unsigned long first_sector, int first_part_minor,
struct block_device *bdev, const struct vmdb *vm,
static int create_data_partitions(struct parsed_partitions *state,
int slot, struct block_device *bdev, const struct vmdb *vm,
const struct privhead *ph, const struct ldmdisk *dk,
unsigned long base)
{
......@@ -249,7 +238,7 @@ static int create_data_partitions(struct gendisk *hd,
int vblk;
int vsize; /* VBLK size. */
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);
if (!vb)
......@@ -268,11 +257,6 @@ static int create_data_partitions(struct gendisk *hd,
if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize >
ph->config_size * 512)
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++) {
data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, &sect);
if (!data)
......@@ -292,8 +276,9 @@ static int create_data_partitions(struct gendisk *hd,
if (dk->obj_id != vb->disk_id)
continue;
/* Ignore invalid partition errors. */
if (add_partition_to_list(&pl, hd, disk_minor,
first_sector + vb->start_sector +
if (add_partition_to_list(&pl,
bdev->bd_inode->i_size>>9,
vb->start_sector +
ph->logical_disk_start,
vb->num_sectors) < -1)
goto brelse_out;
......@@ -306,7 +291,7 @@ static int create_data_partitions(struct gendisk *hd,
printk(" <");
list_for_each(tmp, &pl) {
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");
if (!list_empty(&pl)) {
......@@ -819,42 +804,6 @@ static int validate_privheads(struct block_device *bdev,
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
* @buffer: LDM database privhead structure loaded from the device
......@@ -901,19 +850,16 @@ static int parse_privhead(const u8 *buffer, struct privhead *ph)
}
/**
* create_db_partition - create a dedicated partition for our database
* @hd: gendisk structure in which to create partition
* find_db_partition - find our database
* @dev: device of which to create partition
* @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.
*
* 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,
const unsigned long first_sector, const int first_part_minor,
struct privhead *ph)
static int find_db_partition(struct block_device *bdev, struct privhead *ph)
{
Sector sect;
unsigned char *data;
......@@ -930,10 +876,15 @@ static int create_db_partition(struct gendisk *hd, struct block_device *bdev,
return 0;
}
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);
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;
}
......@@ -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
* @hd: gendisk structure in which to return the handled disk
* @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:
*
......@@ -1010,8 +959,7 @@ static int validate_partition_table(struct block_device *bdev)
* 0 if @dev is not a dynamic disk,
* -1 if an error occured.
*/
int ldm_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor)
int ldm_partition(struct parsed_partitions *state, struct block_device *bdev)
{
struct privhead *ph = NULL;
struct tocblock *toc = NULL;
......@@ -1020,8 +968,6 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long db_first;
int err;
if (!hd)
return 0;
/* Check the partition table. */
err = validate_partition_table(bdev);
if (err != 1)
......@@ -1029,10 +975,11 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev,
if (!(ph = (struct privhead*)kmalloc(sizeof(*ph), GFP_KERNEL)))
goto no_mem;
/* 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)
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. */
err = validate_privheads(bdev, ph, db_first);
if (err != 1)
......@@ -1056,8 +1003,8 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev,
if (err != 1)
goto out;
/* Finally, create the data partition devices. */
err = create_data_partitions(hd, first_sector, first_part_minor +
LDM_FIRST_PART_OFFSET, bdev, vm, ph, dk, db_first);
err = create_data_partitions(state, 1 + LDM_FIRST_PART_OFFSET,
bdev, vm, ph, dk, db_first);
if (err == 1)
ldm_debug("Parsed LDM database successfully.\n");
out:
......@@ -1071,4 +1018,3 @@ int ldm_partition(struct gendisk *hd, struct block_device *bdev,
err = -1;
goto out;
}
......@@ -150,8 +150,7 @@ struct ldm_part {
unsigned long size;
};
int ldm_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
int ldm_partition(struct parsed_partitions *state, struct block_device *bdev);
#endif /* _FS_PT_LDM_H_ */
......@@ -7,16 +7,7 @@
*/
#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 <asm/system.h>
#include "check.h"
#include "mac.h"
......@@ -36,9 +27,9 @@ static inline void mac_fix_string(char *stg, int len)
stg[i] = 0;
}
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)
{
int slot = 1;
Sector sect;
unsigned char *data;
int blk, blocks_in_map;
......@@ -79,8 +70,8 @@ int mac_partition(struct gendisk *hd, struct block_device *bdev,
part = (struct mac_partition *) (data + pos%512);
if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
break;
add_gd_partition(hd, first_part_minor,
fsec + be32_to_cpu(part->start_block) * (secsize/512),
put_partition(state, slot,
be32_to_cpu(part->start_block) * (secsize/512),
be32_to_cpu(part->block_count) * (secsize/512));
#ifdef CONFIG_ALL_PPC
......@@ -126,7 +117,7 @@ int mac_partition(struct gendisk *hd, struct block_device *bdev,
}
#endif /* CONFIG_ALL_PPC */
++first_part_minor;
++slot;
}
#ifdef CONFIG_ALL_PPC
if (found_root_goodness)
......@@ -138,4 +129,3 @@ int mac_partition(struct gendisk *hd, struct block_device *bdev,
printk("\n");
return 1;
}
......@@ -41,4 +41,4 @@ struct mac_driver_desc {
/* ... 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 @@
*/
#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() */
#ifdef CONFIG_BLK_DEV_IDE
......@@ -38,16 +32,10 @@ EXPORT_SYMBOL(ide_xlate_1024_hook);
#define ide_xlate_1024 ide_xlate_1024_hook
#endif
#include <asm/system.h>
#include "check.h"
#include "msdos.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
* frequently the case with the nr_sects and start_sect partition
......@@ -73,23 +61,6 @@ static inline int is_extended_partition(struct partition *p)
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_MAGIC2 0xAA
......@@ -110,26 +81,26 @@ msdos_magic_present(unsigned char *p)
* only for the actual data partitions.
*/
static void extended_partition(struct gendisk *hd, struct block_device *bdev,
int minor, unsigned long first_size, int *current_minor)
static void
parse_extended(struct parsed_partitions *state, struct block_device *bdev,
u32 first_sector, u32 first_size)
{
struct partition *p;
Sector sect;
unsigned char *data;
unsigned long first_sector, this_sector, this_size;
int mask = (1 << hd->minor_shift) - 1;
u32 this_sector, this_size;
int sector_size = bdev_hardsect_size(bdev) / 512;
int loopct = 0; /* number of links followed
without finding a data partition */
int i;
this_sector = first_sector = hd->part[minor].start_sect;
this_sector = first_sector;
this_size = first_size;
while (1) {
if (++loopct > 100)
return;
if ((*current_minor & mask) == 0)
if (state->next == state->limit)
return;
data = read_dev_sector(bdev, this_sector, &sect);
if (!data)
......@@ -153,7 +124,7 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev,
* First process the data partition(s)
*/
for (i=0; i<4; i++, p++) {
unsigned long offs, size, next;
u32 offs, size, next;
if (!NR_SECTS(p) || is_extended_partition(p))
continue;
......@@ -171,27 +142,19 @@ static void extended_partition(struct gendisk *hd, struct block_device *bdev,
continue;
}
add_gd_partition(hd, *current_minor, next, size);
#if CONFIG_BLK_DEV_MD
if (SYS_IND(p) == LINUX_RAID_PARTITION) {
md_autodetect_dev(mk_kdev(hd->major,*current_minor));
}
#endif
(*current_minor)++;
put_partition(state, state->next, next, size);
if (SYS_IND(p) == LINUX_RAID_PARTITION)
state->parts[state->next].flags = 1;
loopct = 0;
if ((*current_minor & mask) == 0)
if (++state->next == state->limit)
goto done;
}
/*
* Next, process the (first) extended partition, if present.
* (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.)
* 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;
for (i=0; i<4; i++, p++)
......@@ -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_size = NR_SECTS(p) * sector_size;
minor = *current_minor;
put_dev_sector(sect);
}
done:
......@@ -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. */
static void
solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{
#ifdef CONFIG_SOLARIS_X86_PARTITION
long offset = hd->part[minor].start_sect;
Sector sect;
struct solaris_x86_vtoc *v;
struct solaris_x86_slice *s;
int mask = (1 << hd->minor_shift) - 1;
int i;
char buf[40];
v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
if (!v)
......@@ -233,29 +190,23 @@ solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
put_dev_sector(sect);
return;
}
printk(" %s: <solaris:", partition_name(hd, minor, buf));
printk(" %s%d: <solaris:", state->name, origin);
if (le32_to_cpu(v->v_version) != 1) {
printk(" cannot handle version %d vtoc>\n",
le32_to_cpu(v->v_version));
put_dev_sector(sect);
return;
}
for (i=0; i<SOLARIS_X86_NUMSLICE; i++) {
if ((*current_minor & mask) == 0)
break;
s = &v->v_slice[i];
for (i=0; i<SOLARIS_X86_NUMSLICE && state->next<state->limit; i++) {
struct solaris_x86_slice *s = &v->v_slice[i];
if (s->s_size == 0)
continue;
printk(" [s%d]", i);
/* solaris partitions are relative to current MS-DOS
* one but add_gd_partition starts relative to sector
* zero of the disk. Therefore, must add the offset
* of the current partition */
add_gd_partition(hd, *current_minor,
* one; must add the offset of the current partition */
put_partition(state, state->next++,
le32_to_cpu(s->s_start)+offset,
le32_to_cpu(s->s_size));
(*current_minor)++;
}
put_dev_sector(sect);
printk(" >\n");
......@@ -265,17 +216,16 @@ solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
#ifdef CONFIG_BSD_DISKLABEL
/*
* 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,
int minor, int *current_minor, char *name, int max_partitions)
static void
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;
struct bsd_disklabel *l;
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);
if (!l)
......@@ -284,69 +234,75 @@ static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
put_dev_sector(sect);
return;
}
printk(" %s: <%s:", partition_name(hd, minor, buf), name);
printk(" %s%d: <%s:", state->name, origin, flavour);
if (le16_to_cpu(l->d_npartitions) < max_partitions)
max_partitions = le16_to_cpu(l->d_npartitions);
for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
int bsd_start, bsd_size;
u32 bsd_start, bsd_size;
if ((*current_minor & mask) == 0)
if (state->next == state->limit)
break;
if (p->p_fstype == BSD_FS_UNUSED)
continue;
bsd_start = le32_to_cpu(p->p_offset);
bsd_size = le32_to_cpu(p->p_size);
if (check_and_add_subpartition(hd, minor, *current_minor,
bsd_start, bsd_size))
(*current_minor)++;
if (offset == bsd_start && size == bsd_size)
/* full parent partition, we have it already */
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);
printk(" >\n");
}
#endif
static void bsd_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
static void
parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{
#ifdef CONFIG_BSD_DISKLABEL
do_bsd_partition(hd, bdev, minor, current_minor, "bsd",
BSD_MAXPARTITIONS);
parse_bsd(state, bdev, offset, size, origin,
"bsd", BSD_MAXPARTITIONS);
#endif
}
static void netbsd_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
static void
parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{
#ifdef CONFIG_BSD_DISKLABEL
do_bsd_partition(hd, bdev, minor, current_minor, "netbsd",
BSD_MAXPARTITIONS);
parse_bsd(state, bdev, offset, size, origin,
"netbsd", BSD_MAXPARTITIONS);
#endif
}
static void openbsd_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
static void
parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{
#ifdef CONFIG_BSD_DISKLABEL
do_bsd_partition(hd, bdev, minor, current_minor,
parse_bsd(state, bdev, offset, size, origin,
"openbsd", OPENBSD_MAXPARTITIONS);
#endif
}
/*
* 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,
int minor, int *current_minor)
static void
parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{
#ifdef CONFIG_UNIXWARE_DISKLABEL
long offset = hd->part[minor].start_sect;
Sector sect;
struct unixware_disklabel *l;
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);
if (!l)
......@@ -356,18 +312,16 @@ static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
put_dev_sector(sect);
return;
}
printk(" %s: <unixware:", partition_name(hd, minor, buf));
printk(" %s%d: <unixware:", state->name, origin);
p = &l->vtoc.v_slice[1];
/* I omit the 0th slice as it is the same as whole disk. */
while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
if ((*current_minor & mask) == 0)
if (state->next == state->limit)
break;
if (p->s_label != UNIXWARE_FS_UNUSED) {
add_gd_partition(hd, *current_minor, START_SECT(p),
NR_SECTS(p));
(*current_minor)++;
}
if (p->s_label != UNIXWARE_FS_UNUSED)
put_partition(state, state->next++,
START_SECT(p), NR_SECTS(p));
p++;
}
put_dev_sector(sect);
......@@ -380,17 +334,15 @@ static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
* Anand Krishnamurthy <anandk@wiproge.med.ge.com>
* Rajeev V. Pillai <rajeevvp@yahoo.com>
*/
static void minix_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
static void
parse_minix(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin)
{
#ifdef CONFIG_MINIX_SUBPARTITION
long offset = hd->part[minor].start_sect;
Sector sect;
unsigned char *data;
struct partition *p;
int mask = (1 << hd->minor_shift) - 1;
int i;
char buf[40];
data = read_dev_sector(bdev, offset, &sect);
if (!data)
......@@ -404,16 +356,14 @@ static void minix_partition(struct gendisk *hd, struct block_device *bdev,
if (msdos_magic_present (data + 510) &&
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++) {
if ((*current_minor & mask) == 0)
if (state->next == state->limit)
break;
/* add each partition in use */
if (SYS_IND(p) == MINIX_PARTITION) {
add_gd_partition(hd, *current_minor,
if (SYS_IND(p) == MINIX_PARTITION)
put_partition(state, state->next++,
START_SECT(p), NR_SECTS(p));
(*current_minor)++;
}
}
printk(" >\n");
}
......@@ -423,14 +373,15 @@ static void minix_partition(struct gendisk *hd, struct block_device *bdev,
static struct {
unsigned char id;
void (*parse)(struct gendisk *, struct block_device *, int, int *);
void (*parse)(struct parsed_partitions *, struct block_device *,
u32, u32, int);
} subtypes[] = {
{BSD_PARTITION, bsd_partition},
{NETBSD_PARTITION, netbsd_partition},
{OPENBSD_PARTITION, openbsd_partition},
{MINIX_PARTITION, minix_partition},
{UNIXWARE_PARTITION, unixware_partition},
{SOLARIS_X86_PARTITION, solaris_x86_partition},
{BSD_PARTITION, parse_freebsd},
{NETBSD_PARTITION, parse_netbsd},
{OPENBSD_PARTITION, parse_openbsd},
{MINIX_PARTITION, parse_minix},
{UNIXWARE_PARTITION, parse_unixware},
{SOLARIS_X86_PARTITION, parse_solaris_x86},
{0, NULL},
};
/*
......@@ -515,16 +466,13 @@ static int handle_ide_mess(struct block_device *bdev)
return 1;
}
int msdos_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor)
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
{
int i, minor = first_part_minor;
int sector_size = bdev_hardsect_size(bdev) / 512;
Sector sect;
struct partition *p;
unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
int sector_size = bdev_hardsect_size(bdev) / 512;
int current_minor = first_part_minor;
struct partition *p;
int slot;
int err;
err = handle_ide_mess(bdev);
......@@ -539,7 +487,7 @@ int msdos_partition(struct gendisk *hd, struct block_device *bdev,
}
p = (struct partition *) (data + 0x1be);
#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 (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
put_dev_sector(sect);
......@@ -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.
*/
current_minor += 4;
for (i=1 ; i<=4 ; minor++,i++,p++) {
if (!NR_SECTS(p))
state->next = 5;
for (slot = 1 ; slot <= 4 ; slot++, p++) {
u32 start = START_SECT(p)*sector_size;
u32 size = NR_SECTS(p)*sector_size;
if (!size)
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)) {
unsigned long size = hd->part[minor].nr_sects;
printk(" <");
/* prevent someone doing mkfs or mkswap on an
extended partition, but leave room for LILO */
if (size > 2)
hd->part[minor].nr_sects = 2;
extended_partition(hd, bdev, minor, size, &current_minor);
put_partition(state, slot, start, size == 1 ? 1 : 2);
printk(" <");
parse_extended(state, bdev, start, size);
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,
*/
if (msdos_magic_present(data + 0xfc)) {
p = (struct partition *) (0x1be + data);
for (i = 4 ; i < 16 ; i++, current_minor++) {
for (slot = 4 ; slot < 16 ; slot++, state->next++) {
p--;
if ((current_minor & mask) == 0)
if (state->next == state->limit)
break;
if (!(START_SECT(p) && NR_SECTS(p)))
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");
/* second pass - output for each on a separate line */
minor -= 4;
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);
int n;
......@@ -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++)
;
if (subtypes[n].parse)
subtypes[n].parse(hd, bdev, minor, &current_minor);
if (!subtypes[n].parse)
continue;
subtypes[n].parse(state, bdev, START_SECT(p)*sector_size,
NR_SECTS(p)*sector_size, n);
}
put_dev_sector(sect);
return 1;
......
......@@ -4,6 +4,5 @@
#define MSDOS_LABEL_MAGIC 0xAA55
int msdos_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev);
......@@ -7,23 +7,15 @@
* 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 "osf.h"
int osf_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int current_minor)
int osf_partition(struct parsed_partitions *state, struct block_device *bdev)
{
int i;
int slot = 1;
Sector sect;
unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
struct disklabel {
u32 d_magic;
u16 d_type,d_subtype;
......@@ -72,16 +64,14 @@ int osf_partition(struct gendisk *hd, struct block_device *bdev,
return 0;
}
for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
if ((current_minor & mask) == 0)
if (slot == state->limit)
break;
if (le32_to_cpu(partition->p_size))
add_gd_partition(hd, current_minor,
first_sector+le32_to_cpu(partition->p_offset),
put_partition(state, slot++,
le32_to_cpu(partition->p_offset),
le32_to_cpu(partition->p_size));
current_minor++;
}
printk("\n");
put_dev_sector(sect);
return 1;
}
......@@ -4,6 +4,4 @@
#define DISKLABELMAGIC (0x82564557UL)
int osf_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int current_minor);
int osf_partition(struct parsed_partitions *state, struct block_device *bdev);
......@@ -4,22 +4,13 @@
* 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 "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 slot = 1;
unsigned int *ui, start, blocks, cs;
Sector sect;
struct sgi_disklabel {
......@@ -73,10 +64,8 @@ int sgi_partition(struct gendisk *hd, struct block_device *bdev, unsigned long f
for(i = 0; i < 16; i++, p++) {
blocks = be32_to_cpu(p->num_blocks);
start = be32_to_cpu(p->first_block);
if(!blocks)
continue;
add_gd_partition(hd, current_minor, start, blocks);
current_minor++;
if (blocks)
put_partition(state, slot++, start, blocks);
}
printk("\n");
put_dev_sector(sect);
......
......@@ -2,8 +2,7 @@
* fs/partitions/sgi.h
*/
extern int sgi_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
extern int sgi_partition(struct parsed_partitions *state, struct block_device *bdev);
#define SGI_LABEL_MAGIC 0x0be5a941
......@@ -7,21 +7,13 @@
* 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 "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 slot = 1;
unsigned short *ush;
Sector sect;
struct sun_disklabel {
......@@ -74,11 +66,10 @@ int sun_partition(struct gendisk *hd, struct block_device *bdev, unsigned long f
unsigned long st_sector;
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);
if (num_sectors)
add_gd_partition(hd, first_part_minor, st_sector, num_sectors);
first_part_minor++;
put_partition(state, slot++, st_sector, num_sectors);
}
printk("\n");
put_dev_sector(sect);
......
......@@ -4,6 +4,4 @@
#define SUN_LABEL_MAGIC 0xDABE
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);
......@@ -6,16 +6,9 @@
* 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"
int ultrix_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor)
int ultrix_partition(struct parsed_partitions *state, struct block_device *bdev)
{
int i;
Sector sect;
......@@ -39,9 +32,9 @@ int ultrix_partition(struct gendisk *hd, struct block_device *bdev,
label = (struct ultrix_disklabel *)(data + 512 - sizeof(*label));
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)
add_gd_partition(hd, first_part_minor,
put_partition(state, i+1,
label->pt_part[i].pi_blkoff,
label->pt_part[i].pi_nblocks);
put_dev_sector(sect);
......
......@@ -2,6 +2,4 @@
* fs/partitions/ultrix.h
*/
int ultrix_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
int ultrix_partition(struct parsed_partitions *state, struct block_device *bdev);
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