linux/block/partitions/check.c
<<
>>
Prefs
   1/*
   2 *  fs/partitions/check.c
   3 *
   4 *  Code extracted from drivers/block/genhd.c
   5 *  Copyright (C) 1991-1998  Linus Torvalds
   6 *  Re-organised Feb 1998 Russell King
   7 *
   8 *  We now have independent partition support from the
   9 *  block drivers, which allows all the partition code to
  10 *  be grouped in one location, and it to be mostly self
  11 *  contained.
  12 *
  13 *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
  14 */
  15
  16#include <linux/slab.h>
  17#include <linux/vmalloc.h>
  18#include <linux/ctype.h>
  19#include <linux/genhd.h>
  20
  21#include "check.h"
  22
  23#include "acorn.h"
  24#include "amiga.h"
  25#include "atari.h"
  26#include "ldm.h"
  27#include "mac.h"
  28#include "msdos.h"
  29#include "osf.h"
  30#include "sgi.h"
  31#include "sun.h"
  32#include "ibm.h"
  33#include "ultrix.h"
  34#include "efi.h"
  35#include "karma.h"
  36#include "sysv68.h"
  37
  38int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
  39
  40static int (*check_part[])(struct parsed_partitions *) = {
  41        /*
  42         * Probe partition formats with tables at disk address 0
  43         * that also have an ADFS boot block at 0xdc0.
  44         */
  45#ifdef CONFIG_ACORN_PARTITION_ICS
  46        adfspart_check_ICS,
  47#endif
  48#ifdef CONFIG_ACORN_PARTITION_POWERTEC
  49        adfspart_check_POWERTEC,
  50#endif
  51#ifdef CONFIG_ACORN_PARTITION_EESOX
  52        adfspart_check_EESOX,
  53#endif
  54
  55        /*
  56         * Now move on to formats that only have partition info at
  57         * disk address 0xdc0.  Since these may also have stale
  58         * PC/BIOS partition tables, they need to come before
  59         * the msdos entry.
  60         */
  61#ifdef CONFIG_ACORN_PARTITION_CUMANA
  62        adfspart_check_CUMANA,
  63#endif
  64#ifdef CONFIG_ACORN_PARTITION_ADFS
  65        adfspart_check_ADFS,
  66#endif
  67
  68#ifdef CONFIG_EFI_PARTITION
  69        efi_partition,          /* this must come before msdos */
  70#endif
  71#ifdef CONFIG_SGI_PARTITION
  72        sgi_partition,
  73#endif
  74#ifdef CONFIG_LDM_PARTITION
  75        ldm_partition,          /* this must come before msdos */
  76#endif
  77#ifdef CONFIG_MSDOS_PARTITION
  78        msdos_partition,
  79#endif
  80#ifdef CONFIG_OSF_PARTITION
  81        osf_partition,
  82#endif
  83#ifdef CONFIG_SUN_PARTITION
  84        sun_partition,
  85#endif
  86#ifdef CONFIG_AMIGA_PARTITION
  87        amiga_partition,
  88#endif
  89#ifdef CONFIG_ATARI_PARTITION
  90        atari_partition,
  91#endif
  92#ifdef CONFIG_MAC_PARTITION
  93        mac_partition,
  94#endif
  95#ifdef CONFIG_ULTRIX_PARTITION
  96        ultrix_partition,
  97#endif
  98#ifdef CONFIG_IBM_PARTITION
  99        ibm_partition,
 100#endif
 101#ifdef CONFIG_KARMA_PARTITION
 102        karma_partition,
 103#endif
 104#ifdef CONFIG_SYSV68_PARTITION
 105        sysv68_partition,
 106#endif
 107        NULL
 108};
 109
 110static struct parsed_partitions *allocate_partitions(struct gendisk *hd)
 111{
 112        struct parsed_partitions *state;
 113        int nr;
 114
 115        state = kzalloc(sizeof(*state), GFP_KERNEL);
 116        if (!state)
 117                return NULL;
 118
 119        nr = disk_max_parts(hd);
 120        state->parts = vzalloc(nr * sizeof(state->parts[0]));
 121        if (!state->parts) {
 122                kfree(state);
 123                return NULL;
 124        }
 125
 126        state->limit = nr;
 127
 128        return state;
 129}
 130
 131void free_partitions(struct parsed_partitions *state)
 132{
 133        vfree(state->parts);
 134        kfree(state);
 135}
 136
 137struct parsed_partitions *
 138check_partition(struct gendisk *hd, struct block_device *bdev)
 139{
 140        struct parsed_partitions *state;
 141        int i, res, err;
 142
 143        state = allocate_partitions(hd);
 144        if (!state)
 145                return NULL;
 146        state->pp_buf = (char *)__get_free_page(GFP_KERNEL);
 147        if (!state->pp_buf) {
 148                free_partitions(state);
 149                return NULL;
 150        }
 151        state->pp_buf[0] = '\0';
 152
 153        state->bdev = bdev;
 154        disk_name(hd, 0, state->name);
 155        snprintf(state->pp_buf, PAGE_SIZE, " %s:", state->name);
 156        if (isdigit(state->name[strlen(state->name)-1]))
 157                sprintf(state->name, "p");
 158
 159        i = res = err = 0;
 160        while (!res && check_part[i]) {
 161                memset(state->parts, 0, state->limit * sizeof(state->parts[0]));
 162                res = check_part[i++](state);
 163                if (res < 0) {
 164                        /* We have hit an I/O error which we don't report now.
 165                        * But record it, and let the others do their job.
 166                        */
 167                        err = res;
 168                        res = 0;
 169                }
 170
 171        }
 172        if (res > 0) {
 173                printk(KERN_INFO "%s", state->pp_buf);
 174
 175                free_page((unsigned long)state->pp_buf);
 176                return state;
 177        }
 178        if (state->access_beyond_eod)
 179                err = -ENOSPC;
 180        if (err)
 181        /* The partition is unrecognized. So report I/O errors if there were any */
 182                res = err;
 183        if (!res)
 184                strlcat(state->pp_buf, " unknown partition table\n", PAGE_SIZE);
 185        else if (warn_no_part)
 186                strlcat(state->pp_buf, " unable to read partition table\n", PAGE_SIZE);
 187
 188        printk(KERN_INFO "%s", state->pp_buf);
 189
 190        free_page((unsigned long)state->pp_buf);
 191        free_partitions(state);
 192        return ERR_PTR(res);
 193}
 194