summaryrefslogtreecommitdiffstats
path: root/fs/partitions
diff options
context:
space:
mode:
Diffstat (limited to 'fs/partitions')
-rw-r--r--fs/partitions/Config.in1
-rw-r--r--fs/partitions/check.c2
-rw-r--r--fs/partitions/ibm.c179
-rw-r--r--fs/partitions/ibm.h2
-rw-r--r--fs/partitions/msdos.c112
-rw-r--r--fs/partitions/osf.c12
6 files changed, 215 insertions, 93 deletions
diff --git a/fs/partitions/Config.in b/fs/partitions/Config.in
index 6fadbd846..2a3f6d8b1 100644
--- a/fs/partitions/Config.in
+++ b/fs/partitions/Config.in
@@ -21,6 +21,7 @@ if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then
bool ' PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
if [ "$CONFIG_MSDOS_PARTITION" = "y" ]; then
bool ' BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
+ bool ' Minix subpartition support' CONFIG_MINIX_SUBPARTITION
bool ' Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
fi
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 53b05e3ef..15568c734 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -76,7 +76,7 @@ static int (*check_part[])(struct gendisk *hd, kdev_t dev, unsigned long first_s
};
/*
- * disk_name() is used by genhd.c and blkpg.c.
+ * disk_name() is used by partition check code and the md driver.
* It formats the devicename of the indicated disk into
* the supplied buffer (of size at least 32), and returns
* a pointer to that same buffer (for convenience).
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c
index 765bbc9f9..be3e7eae7 100644
--- a/fs/partitions/ibm.c
+++ b/fs/partitions/ibm.c
@@ -1,8 +1,12 @@
/*
- * File...........: linux/fs/partitions/ibm.c
+ * File...........: linux/fs/partitions/ibm.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+
+ * History of changes (starts July 2000)
+ * 07/10/00 Fixed detection of CMS formatted disks
+
*/
#include <linux/fs.h>
@@ -11,9 +15,21 @@
#include <linux/major.h>
#include <linux/string.h>
#include <linux/blk.h>
-
+#include <linux/malloc.h>
+#include <linux/hdreg.h>
+#include <linux/ioctl.h>
+#include <linux/version.h>
#include <asm/ebcdic.h>
-#include "../../drivers/s390/block/dasd_types.h"
+#include <asm/uaccess.h>
+#include <asm/dasd.h>
+
+#include "ibm.h"
+#include "check.h"
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+/* We hook in when DASD is a module... */
+int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
+#endif /* LINUX_IS_24 */
typedef enum {
ibm_partition_none = 0,
@@ -25,98 +41,131 @@ typedef enum {
static ibm_partition_t
get_partition_type ( char * type )
{
- static char lnx[5]="LNX1";
- static char vol[5]="VOL1";
- static char cms[5]="CMS1";
- if ( ! strncmp ( lnx, "LNX1",4 ) ) {
- ASCEBC(lnx,4);
- ASCEBC(vol,4);
- ASCEBC(cms,4);
- }
- if ( ! strncmp (type,lnx,4) ||
- ! strncmp (type,"LNX1",4) )
- return ibm_partition_lnx1;
- if ( ! strncmp (type,vol,4) )
- return ibm_partition_vol1;
- if ( ! strncmp (type,cms,4) )
- return ibm_partition_cms1;
- return ibm_partition_none;
+ static char lnx[5]="LNX1";
+ static char vol[5]="VOL1";
+ static char cms[5]="CMS1";
+ if ( ! strncmp ( lnx, "LNX1",4 ) ) {
+ ASCEBC(lnx,4);
+ ASCEBC(vol,4);
+ ASCEBC(cms,4);
+ }
+ if ( ! strncmp (type,lnx,4) ||
+ ! strncmp (type,"LNX1",4) )
+ return ibm_partition_lnx1;
+ if ( ! strncmp (type,vol,4) )
+ return ibm_partition_vol1;
+ if ( ! strncmp (type,cms,4) )
+ return ibm_partition_cms1;
+ return ibm_partition_none;
}
-void
-ibm_partition (struct gendisk *hd, kdev_t dev)
+int
+ibm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int
+first_part_minor)
{
struct buffer_head *bh;
ibm_partition_t partition_type;
- int di = MINOR(dev) >> PARTN_BITS;
char type[5] = {0,};
char name[7] = {0,};
- if ( bh = bread( dev,
- dasd_info[di]->sizes.label_block,
- get_ptable_blocksize(dev) ) ) {
+ struct hd_geometry geo;
+ mm_segment_t old_fs;
+ int blocksize;
+ struct file *filp = NULL;
+ struct inode *inode = NULL;
+ int offset, size;
+
+ blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
+ if ( blocksize <= 0 ) {
+ return 0;
+ }
+ set_blocksize(dev, blocksize); /* OUCH !! */
+
+ /* find out offset of volume label (partn table) */
+ inode = get_empty_inode();
+ inode -> i_rdev = dev;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+ inode -> i_bdev = bdget(kdev_t_to_nr(dev));
+#endif /* KERNEL_VERSION */
+ filp = (struct file *)kmalloc (sizeof(struct file),GFP_KERNEL);
+ if (!filp)
+ return 0;
+ memset(filp,0,sizeof(struct file));
+ filp ->f_mode = 1; /* read only */
+ blkdev_open(inode,filp);
+ old_fs=get_fs();
+ set_fs(KERNEL_DS);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+ inode-> i_bdev -> bd_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
+#else
+ filp->f_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
+#endif /* KERNEL_VERSION */
+ set_fs(old_fs);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
+ blkdev_put(inode->i_bdev,BDEV_FILE);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+ blkdev_close(inode,filp);
+#else
+ blkdev_release(inode);
+#endif /* LINUX_VERSION_CODE */
+
+ size = hd -> sizes[MINOR(dev)]<<1;
+ if ( ( bh = bread( dev, geo.start, blocksize) ) != NULL ) {
strncpy ( type,bh -> b_data, 4);
strncpy ( name,bh -> b_data + 4, 6);
} else {
- return;
+ return 0;
}
if ( (*(char *)bh -> b_data) & 0x80 ) {
EBCASC(name,6);
}
switch ( partition_type = get_partition_type(type) ) {
- case ibm_partition_lnx1:
+ case ibm_partition_lnx1:
+ offset = (geo.start + 1);
printk ( "(LNX1)/%6s:",name);
- add_gd_partition( hd, MINOR(dev) + 1,
- (dasd_info [di]->sizes.label_block + 1) <<
- dasd_info [di]->sizes.s2b_shift,
- (dasd_info [di]->sizes.blocks -
- dasd_info [di]->sizes.label_block - 1) <<
- dasd_info [di]->sizes.s2b_shift );
break;
case ibm_partition_vol1:
+ offset = 0;
+ size = 0;
printk ( "(VOL1)/%6s:",name);
break;
case ibm_partition_cms1:
printk ( "(CMS1)/%6s:",name);
if (* (((long *)bh->b_data) + 13) == 0) {
- /* disk holds a CMS filesystem */
- add_gd_partition( hd, MINOR(dev) + 1,
- (dasd_info [di]->sizes.label_block + 1) <<
- dasd_info [di]->sizes.s2b_shift,
- (dasd_info [di]->sizes.blocks -
- dasd_info [di]->sizes.label_block) <<
- dasd_info [di]->sizes.s2b_shift );
- printk ("(CMS)");
+ /* disk holds a CMS filesystem */
+ offset = (geo.start + 1);
+ printk ("(CMS)");
} else {
- /* disk is reserved minidisk */
- int offset = (*(((long *)bh->b_data) + 13));
- int size = (*(((long *)bh->b_data) + 7)) - 1 -
- (*(((long *)bh->b_data) + 13)) *
- ((*(((long *)bh->b_data) + 3)) >> 9);
- add_gd_partition( hd, MINOR(dev) + 1,
- offset << dasd_info [di]->sizes.s2b_shift,
- size << dasd_info [di]->sizes.s2b_shift );
- printk ("(MDSK)");
+ /* disk is reserved minidisk */
+ // mdisk_setup_data.size[i] =
+ // (label[7] - 1 - label[13]) *
+ // (label[3] >> 9) >> 1;
+ long *label=(long*)bh->b_data;
+ blocksize = label[3];
+ offset = label[13];
+ size = (label[7]-1)*(blocksize>>9);
+ printk ("(MDSK)");
}
break;
case ibm_partition_none:
printk ( "(nonl)/ :");
-/*
- printk ( "%d %d %d ", MINOR(dev) + 1,
- (dasd_info [di]->sizes.label_block + 1) <<
- dasd_info [di]->sizes.s2b_shift,
- (dasd_info [di]->sizes.blocks -
- dasd_info [di]->sizes.label_block - 1) <<
- dasd_info [di]->sizes.s2b_shift );
-*/
- add_gd_partition( hd, MINOR(dev) + 1,
- (dasd_info [di]->sizes.label_block + 1) <<
- dasd_info [di]->sizes.s2b_shift,
- (dasd_info [di]->sizes.blocks -
- dasd_info [di]->sizes.label_block - 1) <<
- dasd_info [di]->sizes.s2b_shift );
+ offset = (geo.start+1);
break;
+ default:
+ offset = 0;
+ size = 0;
+
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+ add_gd_partition( hd, MINOR(dev), 0,size);
+ add_gd_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
+ size-offset*(blocksize>>9));
+#else
+ add_partition( hd, MINOR(dev), 0,size,0);
+ add_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
+ size-offset*(blocksize>>9) ,0 );
+#endif /* LINUX_VERSION */
printk ( "\n" );
bforget(bh);
+ return 1;
}
diff --git a/fs/partitions/ibm.h b/fs/partitions/ibm.h
index 35d01e06c..49ff10bc4 100644
--- a/fs/partitions/ibm.h
+++ b/fs/partitions/ibm.h
@@ -1 +1 @@
-void ibm_partition (struct gendisk *hd, kdev_t dev);
+int ibm_partition(struct gendisk *, kdev_t, unsigned long, int);
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 0d72631c8..952e79b01 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -68,6 +68,23 @@ static inline int is_extended_partition(struct partition *p)
}
/*
+ * 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
+}
+
+/*
* Create devices for each logical partition in an extended partition.
* The logical partitions form a linked list, with each entry being
* a partition table with two entries. The first entry
@@ -194,23 +211,27 @@ solaris_x86_partition(struct gendisk *hd, int minor) {
struct buffer_head *bh;
struct solaris_x86_vtoc *v;
struct solaris_x86_slice *s;
+ int mask = (1 << hd->minor_shift) - 1;
int i;
char buf[40];
if(!(bh = get_partition_table_block(hd, minor, 0)))
return;
v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
- if(v->v_sanity != SOLARIS_X86_VTOC_SANE) {
+ if(le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
brelse(bh);
return;
}
- printk(" %s: <solaris:", disk_name(hd, minor, buf));
- if(v->v_version != 1) {
- printk(" cannot handle version %ld vtoc>\n", v->v_version);
+ printk(" %s: <solaris:", partition_name(hd, minor, buf));
+ if(le32_to_cpu(v->v_version) != 1) {
+ printk(" cannot handle version %d vtoc>\n",
+ le32_to_cpu(v->v_version));
brelse(bh);
return;
}
for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
+ if ((current_minor & mask) == 0)
+ break;
s = &v->v_slice[i];
if (s->s_size == 0)
@@ -220,7 +241,8 @@ solaris_x86_partition(struct gendisk *hd, int minor) {
* 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, s->s_start+offset, s->s_size);
+ add_gd_partition(hd, current_minor, le32_to_cpu(s->s_start)+offset,
+ le32_to_cpu(s->s_size));
current_minor++;
}
brelse(bh);
@@ -237,21 +259,22 @@ check_and_add_bsd_partition(struct gendisk *hd,
for (lin_p = hd->part + 1 + minor;
lin_p - hd->part - minor < current_minor; lin_p++) {
/* no relationship -> try again */
- if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset ||
- lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
+ if (lin_p->start_sect + lin_p->nr_sects <= le32_to_cpu(bsd_p->p_offset) ||
+ lin_p->start_sect >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size))
continue;
/* equal -> no need to add */
- if (lin_p->start_sect == bsd_p->p_offset &&
- lin_p->nr_sects == bsd_p->p_size)
+ if (lin_p->start_sect == le32_to_cpu(bsd_p->p_offset) &&
+ lin_p->nr_sects == le32_to_cpu(bsd_p->p_size))
return;
/* bsd living within dos partition */
- if (lin_p->start_sect <= bsd_p->p_offset && lin_p->start_sect
- + lin_p->nr_sects >= bsd_p->p_offset + bsd_p->p_size) {
+ if (lin_p->start_sect <= le32_to_cpu(bsd_p->p_offset) && lin_p->start_sect
+ + lin_p->nr_sects >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size)) {
#ifdef DEBUG_BSD_DISKLABEL
printk("w: %d %ld+%ld,%d+%d",
lin_p - hd->part,
lin_p->start_sect, lin_p->nr_sects,
- bsd_p->p_offset, bsd_p->p_size);
+ le32_to_cpu(bsd_p->p_offset),
+ le32_to_cpu(bsd_p->p_size));
#endif
break;
}
@@ -259,14 +282,15 @@ check_and_add_bsd_partition(struct gendisk *hd,
#ifdef DEBUG_BSD_DISKLABEL
printk("???: %d %ld+%ld,%d+%d",
lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
- bsd_p->p_offset, bsd_p->p_size);
+ le32_to_cpu(bsd_p->p_offset), le32_to_cpu(bsd_p->p_size));
#endif
printk("???");
return;
} /* if the bsd partition is not currently known to linux, we end
* up here
*/
- add_gd_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size);
+ add_gd_partition(hd, current_minor, le32_to_cpu(bsd_p->p_offset),
+ le32_to_cpu(bsd_p->p_size));
current_minor++;
}
@@ -285,20 +309,20 @@ static void bsd_disklabel_partition(struct gendisk *hd, int minor, int type) {
if (!(bh = get_partition_table_block(hd, minor, 0)))
return;
l = (struct bsd_disklabel *) (bh->b_data+512);
- if (l->d_magic != BSD_DISKMAGIC) {
+ if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
brelse(bh);
return;
}
- printk(" %s:", disk_name(hd, minor, buf));
+ printk(" %s:", partition_name(hd, minor, buf));
printk((type == OPENBSD_PARTITION) ? " <openbsd:" :
(type == NETBSD_PARTITION) ? " <netbsd:" : " <bsd:");
max_partitions = ((type == OPENBSD_PARTITION) ? OPENBSD_MAXPARTITIONS
: BSD_MAXPARTITIONS);
- if (l->d_npartitions < max_partitions)
- max_partitions = l->d_npartitions;
+ 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++) {
- if ((current_minor & mask) >= (4 + hd->max_p))
+ if ((current_minor & mask) == 0)
break;
if (p->p_fstype != BSD_FS_UNUSED)
@@ -332,7 +356,7 @@ static void unixware_partition(struct gendisk *hd, int minor) {
brelse(bh);
return;
}
- printk(" %s: <unixware:", disk_name(hd, minor, buf));
+ printk(" %s: <unixware:", partition_name(hd, minor, buf));
p = &l->vtoc.v_slice[1];
/* I omit the 0th slice as it is the same as whole disk. */
while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
@@ -352,6 +376,49 @@ static void unixware_partition(struct gendisk *hd, int minor) {
}
#endif
+#ifdef CONFIG_MINIX_SUBPARTITION
+/*
+ * Minix 2.0.0/2.0.2 subpartition support.
+ * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
+ * Rajeev V. Pillai <rajeevvp@yahoo.com>
+ */
+static void minix_partition(struct gendisk *hd, int minor)
+{
+ struct buffer_head *bh;
+ struct partition *p;
+ int mask = (1 << hd->minor_shift) - 1;
+ int i;
+ char buf[40];
+
+ if (!(bh = get_partition_table_block(hd, minor, 0)))
+ return;
+ bh->b_state = 0;
+
+ p = (struct partition *)(bh->b_data + 0x1be);
+
+ /* The first sector of a Minix partition can have either
+ * a secondary MBR describing its subpartitions, or
+ * the normal boot sector. */
+ if ((*(__u16 *) (bh->b_data + 510)) != cpu_to_le16(MSDOS_LABEL_MAGIC) &&
+ SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
+
+ printk(" %s: <minix:", partition_name(hd, minor, buf));
+ for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
+ if ((current_minor & mask) == 0)
+ break;
+ /* add each partition in use */
+ if (SYS_IND(p) == MINIX_PARTITION) {
+ add_gd_partition(hd, current_minor,
+ START_SECT(p), NR_SECTS(p));
+ current_minor++;
+ }
+ }
+ printk(" >\n");
+ }
+ brelse(bh);
+}
+#endif /* CONFIG_MINIX_SUBPARTITION */
+
int msdos_partition(struct gendisk *hd, kdev_t dev,
unsigned long first_sector, int first_part_minor) {
int i, minor = current_minor = first_part_minor;
@@ -500,6 +567,11 @@ check_table:
SYS_IND(p) == OPENBSD_PARTITION)
bsd_disklabel_partition(hd, minor, SYS_IND(p));
#endif
+#ifdef CONFIG_MINIX_SUBPARTITION
+ if (SYS_IND(p) == MINIX_PARTITION) {
+ minix_partition(hd, minor);
+ }
+#endif
#ifdef CONFIG_UNIXWARE_DISKLABEL
if (SYS_IND(p) == UNIXWARE_PARTITION)
unixware_partition(hd, minor);
diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c
index 7982302a3..52aae3bbd 100644
--- a/fs/partitions/osf.c
+++ b/fs/partitions/osf.c
@@ -62,21 +62,21 @@ int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
}
label = (struct disklabel *) (bh->b_data+64);
partition = label->d_partitions;
- if (label->d_magic != DISKLABELMAGIC) {
+ if (le32_to_cpu(label->d_magic) != DISKLABELMAGIC) {
brelse(bh);
return 0;
}
- if (label->d_magic2 != DISKLABELMAGIC) {
+ if (le32_to_cpu(label->d_magic2) != DISKLABELMAGIC) {
brelse(bh);
return 0;
}
- for (i = 0 ; i < label->d_npartitions; i++, partition++) {
+ for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
if ((current_minor & mask) == 0)
break;
- if (partition->p_size)
+ if (le32_to_cpu(partition->p_size))
add_gd_partition(hd, current_minor,
- first_sector+partition->p_offset,
- partition->p_size);
+ first_sector+le32_to_cpu(partition->p_offset),
+ le32_to_cpu(partition->p_size));
current_minor++;
}
printk("\n");