patch-2.3.14 linux/fs/partitions/check.c
Next file: linux/fs/partitions/check.h
Previous file: linux/fs/partitions/atari.h
Back to the patch index
Back to the overall index
- Lines: 325
- Date:
Wed Aug 18 09:38:29 1999
- Orig file:
v2.3.13/linux/fs/partitions/check.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.13/linux/fs/partitions/check.c linux/fs/partitions/check.c
@@ -0,0 +1,324 @@
+/*
+ * 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 "check.h"
+
+#include "acorn.h"
+#include "amiga.h"
+#include "atari.h"
+#include "mac.h"
+#include "msdos.h"
+#include "osf.h"
+#include "sgi.h"
+#include "sun.h"
+
+extern void device_init(void);
+extern void md_setup_drive(void);
+extern int *blk_size[];
+extern void rd_load(void);
+extern void initrd_load(void);
+
+struct gendisk *gendisk_head;
+
+static int (*check_part[])(struct gendisk *hd, kdev_t dev, unsigned long first_sect, int first_minor) = {
+#ifdef CONFIG_ACORN_PARTITION
+ acorn_partition,
+#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
+ NULL
+};
+
+/*
+ * disk_name() is used by genhd.c and blkpg.c.
+ * 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)
+{
+ unsigned int part;
+ const char *maj = hd->major_name;
+ int unit = (minor >> hd->minor_shift) + 'a';
+
+ /*
+ * 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;
+ }
+ part = minor & ((1 << hd->minor_shift) - 1);
+ if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
+ unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
+ if (unit > 'z') {
+ unit -= 'z' + 1;
+ 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;
+ int disk = minor >> hd->minor_shift;
+ int part = minor & (( 1 << hd->minor_shift) - 1);
+ if (part == 0)
+ sprintf(buf, "%s/c%dd%d", maj, ctlr, disk);
+ else
+ sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);
+ return buf;
+ }
+ if (part)
+ sprintf(buf, "%s%c%d", maj, unit, part);
+ else
+ sprintf(buf, "%s%c", maj, unit);
+ return buf;
+}
+
+/*
+ * Add a partitions details to the devices partition description.
+ */
+void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
+{
+ char buf[40];
+ hd->part[minor].start_sect = start;
+ hd->part[minor].nr_sects = size;
+ if (hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7)
+ printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
+ else
+ printk(" %s", disk_name(hd, minor, buf));
+}
+
+int get_hardsect_size(kdev_t dev)
+{
+ if (hardsect_size[MAJOR(dev)] != NULL)
+ return hardsect_size[MAJOR(dev)][MINOR(dev)];
+ else
+ return 512;
+}
+
+unsigned int get_ptable_blocksize(kdev_t dev)
+{
+ int ret = 1024;
+
+ /*
+ * See whether the low-level driver has given us a minumum blocksize.
+ * If so, check to see whether it is larger than the default of 1024.
+ */
+ if (!blksize_size[MAJOR(dev)])
+ return ret;
+
+ /*
+ * Check for certain special power of two sizes that we allow.
+ * With anything larger than 1024, we must force the blocksize up to
+ * the natural blocksize for the device so that we don't have to try
+ * and read partial sectors. Anything smaller should be just fine.
+ */
+
+ switch (blksize_size[MAJOR(dev)][MINOR(dev)]) {
+ case 2048:
+ ret = 2048;
+ break;
+ case 4096:
+ ret = 4096;
+ break;
+ case 8192:
+ ret = 8192;
+ break;
+ case 1024:
+ case 512:
+ case 256:
+ case 0:
+ /*
+ * These are all OK.
+ */
+ break;
+ default:
+ panic("Strange blocksize for partition table\n");
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_PROC_FS
+int get_partition_list(char * page)
+{
+ struct gendisk *p;
+ char buf[40];
+ int n, len;
+
+ len = sprintf(page, "major minor #blocks name\n\n");
+ for (p = gendisk_head; p; p = p->next) {
+ for (n=0; n < (p->nr_real << p->minor_shift); n++) {
+ if (p->part[n].nr_sects && len < PAGE_SIZE - 80) {
+ len += sprintf(page+len,
+ "%4d %4d %10d %s\n",
+ p->major, n, p->sizes[n],
+ disk_name(p, n, buf));
+ }
+ }
+ }
+ return len;
+}
+#endif
+
+void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
+{
+ static int first_time = 1;
+ unsigned long first_sector;
+ char buf[40];
+ int i;
+
+ 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;
+ }
+
+ printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
+ for (i = 0; check_part[i]; i++)
+ if (check_part[i](hd, dev, first_sector, first_part_minor))
+ return;
+
+ printk(" unknown partition table\n");
+}
+
+/*
+ * 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 resetup_one_dev(struct gendisk *dev, int drive)
+{
+ int i;
+ int first_minor = drive << dev->minor_shift;
+ int end_minor = first_minor + dev->max_p;
+
+ blk_size[dev->major] = NULL;
+ 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);
+ blk_size[dev->major] = dev->sizes;
+ }
+}
+
+static inline void setup_dev(struct gendisk *dev)
+{
+ int i, drive;
+ int end_minor = dev->max_nr * dev->max_p;
+
+ blk_size[dev->major] = NULL;
+ for (i = 0; i < end_minor; i++) {
+ dev->part[i].start_sect = 0;
+ dev->part[i].nr_sects = 0;
+ dev->sizes[i] = 0;
+ }
+ dev->init(dev);
+ for (drive = 0 ; drive < dev->nr_real ; drive++)
+ resetup_one_dev(dev, drive);
+}
+
+int __init partition_setup(void)
+{
+ struct gendisk *p;
+
+ device_init();
+
+ for (p = gendisk_head ; p ; p=p->next)
+ setup_dev(p);
+
+#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start && mount_initrd) initrd_load();
+ else
+#endif
+ rd_load();
+#endif
+#ifdef CONFIG_MD_BOOT
+ md_setup_drive();
+#endif
+
+ return 0;
+}
+
+__initcall(partition_setup);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)