diff options
Diffstat (limited to 'fs/partitions')
-rw-r--r-- | fs/partitions/Config.in | 1 | ||||
-rw-r--r-- | fs/partitions/check.c | 2 | ||||
-rw-r--r-- | fs/partitions/ibm.c | 179 | ||||
-rw-r--r-- | fs/partitions/ibm.h | 2 | ||||
-rw-r--r-- | fs/partitions/msdos.c | 112 | ||||
-rw-r--r-- | fs/partitions/osf.c | 12 |
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"); |