bitkeeper revision 1.82 (3e562a3eivWgqJ6O9wH-OFGq-YzJ5w)

.del-msdos.c~f31e5a4d337da875:
  Delete: xenolinux-2.4.16-sparse/fs/partitions/msdos.c
.del-check.c~ebcaa3de1bfb8ad8:
  Delete: xenolinux-2.4.16-sparse/fs/partitions/check.c
This commit is contained in:
kaf24@labyrinth.cl.cam.ac.uk committed 2003-02-21 13:31:42 +00:00
1 parent b772c635b9
commit 04c216516f
3 files changed
-1087

No files matched your search

-2
View File
@@ -329,8 +329,6 @@
3ddb79bcJfHdwrPsjqgI33_OsGdVCg xenolinux-2.4.16-sparse/drivers/block/rd.c
3ddb79bcpVu-IbnqwQqpRqsEbLpsuw xenolinux-2.4.16-sparse/drivers/char/tty_io.c
3e15d5273gfR2fbcYe05kqBSAvCX_w xenolinux-2.4.16-sparse/fs/exec.c
3e4a8cb7kqfJTMeOpPcYxqxv7N18DA xenolinux-2.4.16-sparse/fs/partitions/check.c
3e4a8cb7p079Xxly4uNcouacMSjJLw xenolinux-2.4.16-sparse/fs/partitions/msdos.c
3ddb79b8VFtfWSCrXKPN2K21zd_vtw xenolinux-2.4.16-sparse/include/asm-xeno/a.out.h
3ddb79b8Zzi13p3OAPV25QgiC3THAQ xenolinux-2.4.16-sparse/include/asm-xeno/apic.h
3ddb79baZDlsdV_m6C5CXnWMl15p1g xenolinux-2.4.16-sparse/include/asm-xeno/apicdef.h
@@ -1,443 +0,0 @@
/*
* Code extracted from drivers/block/genhd.c
* Copyright (C) 1991-1998 Linus Torvalds
* Re-organised Feb 1998 Russell King
*
* We now have independent partition support from the
* block drivers, which allows all the partition code to
* be grouped in one location, and it to be mostly self
* contained.
*
* Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
*/
#include <linux/config.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/blk.h>
#include <linux/init.h>
#include <linux/raid/md.h>
#include "check.h"
#include "acorn.h"
#include "amiga.h"
#include "atari.h"
#include "ldm.h"
#include "mac.h"
#include "msdos.h"
#include "osf.h"
#include "sgi.h"
#include "sun.h"
#include "ibm.h"
#include "ultrix.h"
extern int *blk_size[];
#define CHECK_DEBUG 0
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) = {
#ifdef CONFIG_ACORN_PARTITION
acorn_partition,
#endif
#ifdef CONFIG_LDM_PARTITION
ldm_partition, /* this must come before msdos */
#endif
#ifdef CONFIG_MSDOS_PARTITION
msdos_partition,
#endif
#ifdef CONFIG_OSF_PARTITION
osf_partition,
#endif
#ifdef CONFIG_SUN_PARTITION
sun_partition,
#endif
#ifdef CONFIG_AMIGA_PARTITION
amiga_partition,
#endif
#ifdef CONFIG_ATARI_PARTITION
atari_partition,
#endif
#ifdef CONFIG_MAC_PARTITION
mac_partition,
#endif
#ifdef CONFIG_SGI_PARTITION
sgi_partition,
#endif
#ifdef CONFIG_ULTRIX_PARTITION
ultrix_partition,
#endif
#ifdef CONFIG_IBM_PARTITION
ibm_partition,
#endif
NULL
};
/*
* This is ucking fugly but its probably the best thing for 2.4.x
* Take it as a clear reminder than we should put the device name
* generation in the object kdev_t points to in 2.5.
*/
#ifdef CONFIG_ARCH_S390
int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
EXPORT_SYMBOL(genhd_dasd_name);
#endif
/*
* 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).
*/
char *disk_name (struct gendisk *hd, int minor, char *buf)
{
const char *maj = hd->major_name;
unsigned int unit = (minor >> hd->minor_shift);
unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
if ((unit < hd->nr_real) && hd->part[minor].de) {
int pos;
pos = devfs_generate_path (hd->part[minor].de, buf, 64);
if (pos >= 0)
return buf + pos;
}
#ifdef CONFIG_ARCH_S390
if (genhd_dasd_name
&& genhd_dasd_name (buf, unit, part, hd) == 0)
return buf;
#endif
/*
* IDE devices use multiple major numbers, but the drives
* are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
* This requires special handling here.
*/
switch (hd->major) {
case IDE9_MAJOR:
unit += 2;
case IDE8_MAJOR:
unit += 2;
case IDE7_MAJOR:
unit += 2;
case IDE6_MAJOR:
unit += 2;
case IDE5_MAJOR:
unit += 2;
case IDE4_MAJOR:
unit += 2;
case IDE3_MAJOR:
unit += 2;
case IDE2_MAJOR:
unit += 2;
case IDE1_MAJOR:
unit += 2;
case IDE0_MAJOR:
maj = "hd";
break;
case MD_MAJOR:
sprintf(buf, "%s%d", maj, unit);
return buf;
}
if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
if (unit+'a' > 'z') {
unit -= 26;
sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
if (part)
sprintf(buf + 4, "%d", part);
return buf;
}
}
if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
if (part == 0)
sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
else
sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
return buf;
}
if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
int ctlr = hd->major - COMPAQ_CISS_MAJOR;
if (part == 0)
sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
else
sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
return buf;
}
if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
int ctlr = hd->major - DAC960_MAJOR;
if (part == 0)
sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
else
sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
return buf;
}
if (hd->major == ATARAID_MAJOR) {
int disk = minor >> hd->minor_shift;
int part = minor & (( 1 << hd->minor_shift) - 1);
if (part == 0)
sprintf(buf, "%s/d%d", maj, disk);
else
sprintf(buf, "%s/d%dp%d", maj, disk, part);
return buf;
}
if (part)
sprintf(buf, "%s%c%d", maj, unit+'a', part);
else
sprintf(buf, "%s%c", maj, unit+'a');
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
}
static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
{
devfs_handle_t de = NULL;
static int first_time = 1;
unsigned long first_sector;
struct block_device *bdev;
char buf[64];
int i;
if (CHECK_DEBUG) printk (KERN_ALERT "check.c::check_partition\n");
if (first_time)
printk(KERN_INFO "Partition check:\n");
first_time = 0;
first_sector = hd->part[MINOR(dev)].start_sect;
/*
* This is a kludge to allow the partition check to be
* skipped for specific drives (e.g. IDE CD-ROM drives)
*/
if ((int)first_sector == -1) {
hd->part[MINOR(dev)].start_sect = 0;
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)
printk(KERN_INFO " /dev/%s:", buf + i);
else
printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
bdev = bdget(kdev_t_to_nr(dev));
bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
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)
printk(" unable to read partition table\n");
goto setup_devfs;
}
}
printk(" unknown partition table\n");
setup_devfs:
invalidate_bdev(bdev, 1);
truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
bdput(bdev);
i = first_part_minor - 1;
devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
}
#ifdef CONFIG_DEVFS_FS
static void devfs_register_partition (struct gendisk *dev, int minor, int part)
{
int devnum = minor >> dev->minor_shift;
devfs_handle_t dir;
unsigned int devfs_flags = DEVFS_FL_DEFAULT;
char devname[16];
if (dev->part[minor + part].de) return;
dir = devfs_get_parent (dev->part[minor].de);
if (!dir) return;
if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
devfs_flags |= DEVFS_FL_REMOVABLE;
sprintf (devname, "part%d", part);
dev->part[minor + part].de =
devfs_register (dir, devname, devfs_flags,
dev->major, minor + part,
S_IFBLK | S_IRUSR | S_IWUSR,
dev->fops, NULL);
}
static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
static void devfs_register_disc (struct gendisk *dev, int minor)
{
int pos = 0;
int devnum = minor >> dev->minor_shift;
devfs_handle_t dir, slave;
unsigned int devfs_flags = DEVFS_FL_DEFAULT;
char dirname[64], symlink[16];
static devfs_handle_t devfs_handle;
if (dev->part[minor].de) return;
if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
devfs_flags |= DEVFS_FL_REMOVABLE;
if (dev->de_arr) {
dir = dev->de_arr[devnum];
if (!dir) /* Aware driver wants to block disc management */
return;
pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
if (pos < 0) return;
strncpy (dirname + pos, "../", 3);
}
else {
/* Unaware driver: construct "real" directory */
sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
dir = devfs_mk_dir (NULL, dirname + 3, NULL);
}
if (!devfs_handle)
devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
sprintf (symlink, "disc%d", dev->part[minor].number);
devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
dirname + pos, &slave, NULL);
dev->part[minor].de =
devfs_register (dir, "disc", devfs_flags, dev->major, minor,
S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
devfs_auto_unregister (dev->part[minor].de, slave);
if (!dev->de_arr)
devfs_auto_unregister (slave, dir);
}
#endif /* CONFIG_DEVFS_FS */
void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
{
#ifdef CONFIG_DEVFS_FS
int part;
if (!unregister)
devfs_register_disc (dev, minor);
for (part = 1; part < dev->max_p; part++) {
if ( unregister || (dev->part[part + minor].nr_sects < 1) ) {
devfs_unregister (dev->part[part + minor].de);
dev->part[part + minor].de = NULL;
continue;
}
devfs_register_partition (dev, minor, part);
}
if (unregister) {
devfs_unregister (dev->part[minor].de);
dev->part[minor].de = NULL;
devfs_dealloc_unique_number (&disc_numspace,
dev->part[minor].number);
}
#endif /* CONFIG_DEVFS_FS */
}
/*
* This function will re-read the partition tables for a given device,
* and set things back up again. There are some important caveats,
* however. You must ensure that no one is using the device, and no one
* can start using the device while this function is being executed.
*
* Much of the cleanup from the old partition tables should have already been
* done
*/
void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
struct block_device_operations *ops, long size)
{
if (CHECK_DEBUG)
{
if (gdev != NULL)
printk (KERN_ALERT
"check.c::register_disk gdev:%p dev:%d min:%u ops:%p sz:%ld\n",
gdev, dev, minors, ops, size);
}
if (!gdev)
return;
grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
}
void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
{
int i;
int first_minor = drive << dev->minor_shift;
int end_minor = first_minor + dev->max_p;
if (CHECK_DEBUG) printk (KERN_ALERT "check.c::grok_partitions\n");
if(!dev->sizes)
blk_size[dev->major] = NULL;
dev->part[first_minor].nr_sects = size;
/* No such device or no minors to use for partitions */
if (!size || minors == 1)
return;
if (dev->sizes) {
dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
for (i = first_minor + 1; i < end_minor; i++)
dev->sizes[i] = 0;
}
blk_size[dev->major] = dev->sizes;
check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
/*
* We need to set the sizes array before we will be able to access
* any of the partitions on this device.
*/
if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
for (i = first_minor; i < end_minor; i++)
dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
}
}
unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
{
struct address_space *mapping = bdev->bd_inode->i_mapping;
int sect = PAGE_CACHE_SIZE / 512;
struct page *page;
page = read_cache_page(mapping, n/sect,
(filler_t *)mapping->a_ops->readpage, NULL);
if (!IS_ERR(page)) {
wait_on_page(page);
if (!Page_Uptodate(page))
goto fail;
if (PageError(page))
goto fail;
p->v = page;
return (unsigned char *)page_address(page) + 512 * (n % sect);
fail:
page_cache_release(page);
}
p->v = NULL;
return NULL;
}
@@ -1,642 +0,0 @@
/*
* fs/partitions/msdos.c
*
* Code extracted from drivers/block/genhd.c
* Copyright (C) 1991-1998 Linus Torvalds
*
* Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
* in the early extended-partition checks and added DM partitions
*
* Support for DiskManager v6.0x added by Mark Lord,
* with information provided by OnTrack. This now works for linux fdisk
* and LILO, as well as loadlin and bootln. Note that disks other than
* /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
*
* More flexible handling of extended partitions - aeb, 950831
*
* Check partition table on IDE disks for common CHS translations
*
* Re-organised Feb 1998 Russell King
*/
#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>
#ifdef CONFIG_BLK_DEV_IDE
#include <linux/ide.h> /* IDE xlate */
#endif /* CONFIG_BLK_DEV_IDE */
#define MSDOS_DEBUG 0
#include <asm/system.h>
#include "check.h"
#include "msdos.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
* table entries.
*/
#include <asm/unaligned.h>
#define SYS_IND(p) (get_unaligned(&p->sys_ind))
#define NR_SECTS(p) ({ __typeof__(p->nr_sects) __a = \
get_unaligned(&p->nr_sects); \
le32_to_cpu(__a); \
})
#define START_SECT(p) ({ __typeof__(p->start_sect) __a = \
get_unaligned(&p->start_sect); \
le32_to_cpu(__a); \
})
static inline int is_extended_partition(struct partition *p)
{
return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
SYS_IND(p) == LINUX_EXTENDED_PARTITION);
}
/*
* partition_name() formats the short partition name into the supplied
* buffer, and returns a pointer to that buffer.
* Used by several partition types which makes conditional inclusion messy,
* use __attribute__ ((unused)) instead.
*/
static char __attribute__ ((unused))
*partition_name (struct gendisk *hd, int minor, char *buf)
{
#ifdef CONFIG_DEVFS_FS
sprintf(buf, "p%d", (minor & ((1 << hd->minor_shift) - 1)));
return buf;
#else
return disk_name(hd, minor, buf);
#endif
}
#define MSDOS_LABEL_MAGIC1 0x55
#define MSDOS_LABEL_MAGIC2 0xAA
static inline int
msdos_magic_present(unsigned char *p)
{
return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
}
/*
* 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
* is the real data partition (with a start relative to the partition
* table start). The second is a pointer to the next logical partition
* (with a start relative to the entire extended partition).
* We do not create a Linux partition for the partition tables, but
* 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)
{
struct partition *p;
Sector sect;
unsigned char *data;
unsigned long first_sector, this_sector, this_size;
int mask = (1 << hd->minor_shift) - 1;
int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 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_size = first_size;
while (1) {
if (++loopct > 100)
return;
if ((*current_minor & mask) == 0)
return;
data = read_dev_sector(bdev, this_sector, &sect);
if (!data)
return;
if (!msdos_magic_present(data + 510))
goto done;
p = (struct partition *) (data + 0x1be);
/*
* Usually, the first entry is the real data partition,
* the 2nd entry is the next extended partition, or empty,
* and the 3rd and 4th entries are unused.
* However, DRDOS sometimes has the extended partition as
* the first entry (when the data partition is empty),
* and OS/2 seems to use all four entries.
*/
/*
* First process the data partition(s)
*/
for (i=0; i<4; i++, p++) {
unsigned long offs, size, next;
if (!NR_SECTS(p) || is_extended_partition(p))
continue;
/* Check the 3rd and 4th entries -
these sometimes contain random garbage */
offs = START_SECT(p)*sector_size;
size = NR_SECTS(p)*sector_size;
next = this_sector + offs;
if (i >= 2) {
if (offs + size > this_size)
continue;
if (next < first_sector)
continue;
if (next + size > first_sector + first_size)
continue;
}
add_gd_partition(hd, *current_minor, next, size);
#if CONFIG_BLK_DEV_MD
if (SYS_IND(p) == LINUX_RAID_PARTITION) {
md_autodetect_dev(MKDEV(hd->major,*current_minor));
}
#endif
(*current_minor)++;
loopct = 0;
if ((*current_minor & mask) == 0)
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
* 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++)
if (NR_SECTS(p) && is_extended_partition(p))
break;
if (i == 4)
goto done; /* nothing left to do */
this_sector = first_sector + START_SECT(p) * sector_size;
this_size = NR_SECTS(p) * sector_size;
minor = *current_minor;
put_dev_sector(sect);
}
done:
put_dev_sector(sect);
}
/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
indicates linux swap. Be careful before believing this is Solaris. */
static void
solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
{
#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)
return;
if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
put_dev_sector(sect);
return;
}
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));
put_dev_sector(sect);
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)
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,
le32_to_cpu(s->s_start)+offset,
le32_to_cpu(s->s_size));
(*current_minor)++;
}
put_dev_sector(sect);
printk(" >\n");
#endif
}
#ifdef CONFIG_BSD_DISKLABEL
static void
check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
int minor, int *current_minor)
{
struct hd_struct *lin_p;
/* check relative position of partitions. */
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 <= 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 == 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 <= 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,
le32_to_cpu(bsd_p->p_offset),
le32_to_cpu(bsd_p->p_size));
#endif
break;
}
/* ouch: bsd and linux overlap. Don't even try for that partition */
#ifdef DEBUG_BSD_DISKLABEL
printk("???: %d %ld+%ld,%d+%d",
lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
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, le32_to_cpu(bsd_p->p_offset),
le32_to_cpu(bsd_p->p_size));
(*current_minor)++;
}
/*
* Create devices for BSD partitions listed in a disklabel, under a
* dos-like partition. See extended_partition() for more information.
*/
static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor, char *name, 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)
return;
if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
put_dev_sector(sect);
return;
}
printk(" %s: <%s", partition_name(hd, minor, buf), name);
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) == 0)
break;
if (p->p_fstype == BSD_FS_UNUSED)
continue;
check_and_add_bsd_partition(hd, p, minor, current_minor);
}
put_dev_sector(sect);
printk(" >\n");
}
#endif
static void bsd_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
{
#ifdef CONFIG_BSD_DISKLABEL
do_bsd_partition(hd, bdev, minor, current_minor, "bsd",
BSD_MAXPARTITIONS);
#endif
}
static void netbsd_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
{
#ifdef CONFIG_BSD_DISKLABEL
do_bsd_partition(hd, bdev, minor, current_minor, "netbsd",
BSD_MAXPARTITIONS);
#endif
}
static void openbsd_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
{
#ifdef CONFIG_BSD_DISKLABEL
do_bsd_partition(hd, bdev, minor, current_minor,
"openbsd", OPENBSD_MAXPARTITIONS);
#endif
}
/*
* Create devices for Unixware partitions listed in a disklabel, under a
* dos-like partition. See extended_partition() for more information.
*/
static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
int minor, int *current_minor)
{
#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)
return;
if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
put_dev_sector(sect);
return;
}
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) {
if ((*current_minor & mask) == 0)
break;
if (p->s_label != UNIXWARE_FS_UNUSED) {
add_gd_partition(hd, *current_minor, START_SECT(p),
NR_SECTS(p));
(*current_minor)++;
}
p++;
}
put_dev_sector(sect);
printk(" >\n");
#endif
}
/*
* 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, struct block_device *bdev,
int minor, int *current_minor)
{
#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)
return;
p = (struct partition *)(data + 0x1be);
/* The first sector of a Minix partition can have either
* a secondary MBR describing its subpartitions, or
* the normal boot sector. */
if (msdos_magic_present (data + 510) &&
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");
}
put_dev_sector(sect);
#endif /* CONFIG_MINIX_SUBPARTITION */
}
static struct {
unsigned char id;
void (*parse)(struct gendisk *, struct block_device *, int, 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},
{0, NULL},
};
/*
* Look for various forms of IDE disk geometry translation
*/
static int handle_ide_mess(struct block_device *bdev)
{
#ifdef CONFIG_BLK_DEV_IDE
Sector sect;
unsigned char *data;
kdev_t dev = to_kdev_t(bdev->bd_dev);
unsigned int sig;
int heads = 0;
struct partition *p;
int i;
if (MSDOS_DEBUG)
printk (KERN_ALERT "handle_ide_mess ------------\n");
/*
* The i386 partition handling programs very often
* make partitions end on cylinder boundaries.
* There is no need to do so, and Linux fdisk doesnt always
* do this, and Windows NT on Alpha doesnt do this either,
* but still, this helps to guess #heads.
*/
data = read_dev_sector(bdev, 0, &sect);
if (!data)
return -1;
if (!msdos_magic_present(data + 510)) {
put_dev_sector(sect);
return 0;
}
sig = le16_to_cpu(*(unsigned short *)(data + 2));
p = (struct partition *) (data + 0x1be);
for (i = 0; i < 4; i++) {
struct partition *q = &p[i];
if (NR_SECTS(q)) {
if ((q->sector & 63) == 1 &&
(q->end_sector & 63) == 63)
heads = q->end_head + 1;
break;
}
}
if (SYS_IND(p) == EZD_PARTITION) {
/*
* Accesses to sector 0 must go to sector 1 instead.
*/
if (ide_xlate_1024(dev, -1, heads, " [EZD]"))
goto reread;
} else if (SYS_IND(p) == DM6_PARTITION) {
/*
* Everything on the disk is offset by 63 sectors,
* including a "new" MBR with its own partition table.
*/
if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]"))
goto reread;
} else if (sig <= 0x1ae &&
data[sig] == 0xAA && data[sig+1] == 0x55 &&
(data[sig+2] & 1)) {
/* DM6 signature in MBR, courtesy of OnTrack */
(void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
} else if (SYS_IND(p) == DM6_AUX1PARTITION ||
SYS_IND(p) == DM6_AUX3PARTITION) {
/*
* DM6 on other than the first (boot) drive
*/
(void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
} else {
(void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
}
put_dev_sector(sect);
if (MSDOS_DEBUG)
printk (KERN_ALERT "handle_ide_mess -------- %d\n", heads);
return 1;
reread:
put_dev_sector(sect);
/* Flush the cache */
invalidate_bdev(bdev, 1);
truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
#endif /* CONFIG_BLK_DEV_IDE */
return 1;
}
int msdos_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor)
{
int i, minor = first_part_minor;
Sector sect;
struct partition *p;
unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
int current_minor = first_part_minor;
int err;
if (MSDOS_DEBUG) printk (KERN_ALERT "msdos.c::msdos_partition\n");
err = handle_ide_mess(bdev);
if (err <= 0)
return err;
data = read_dev_sector(bdev, 0, &sect);
if (!data)
return -1;
if (!msdos_magic_present(data + 510)) {
put_dev_sector(sect);
return 0;
}
p = (struct partition *) (data + 0x1be);
/*
* Look for partitions in two passes:
* First find the primary and DOS-type extended partitions.
* 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))
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(MKDEV(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);
printk(" >");
}
}
/*
* Check for old-style Disk Manager partition table
*/
if (msdos_magic_present(data + 0xfc)) {
p = (struct partition *) (0x1be + data);
for (i = 4 ; i < 16 ; i++, current_minor++) {
p--;
if ((current_minor & mask) == 0)
break;
if (!(START_SECT(p) && NR_SECTS(p)))
continue;
add_gd_partition(hd, current_minor, 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++) {
unsigned char id = SYS_IND(p);
int n;
if (!NR_SECTS(p))
continue;
for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
;
if (subtypes[n].parse)
subtypes[n].parse(hd, bdev, minor, &current_minor);
}
put_dev_sector(sect);
return 1;
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.