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#include "cmdline.h"
  38
  39int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
  40
  41static int (*check_part[])(struct parsed_partitions *) = {
  42        /*
  43         * Probe partition formats with tables at disk address 0
  44         * that also have an ADFS boot block at 0xdc0.
  45         */
  46#ifdef CONFIG_ACORN_PARTITION_ICS
  47        adfspart_check_ICS,
  48#endif
  49#ifdef CONFIG_ACORN_PARTITION_POWERTEC
  50        adfspart_check_POWERTEC,
  51#endif
  52#ifdef CONFIG_ACORN_PARTITION_EESOX
  53        adfspart_check_EESOX,
  54#endif
  55
  56        /*
  57         * Now move on to formats that only have partition info at
  58         * disk address 0xdc0.  Since these may also have stale
  59         * PC/BIOS partition tables, they need to come before
  60         * the msdos entry.
  61         */
  62#ifdef CONFIG_ACORN_PARTITION_CUMANA
  63        adfspart_check_CUMANA,
  64#endif
  65#ifdef CONFIG_ACORN_PARTITION_ADFS
  66        adfspart_check_ADFS,
  67#endif
  68
  69#ifdef CONFIG_CMDLINE_PARTITION
  70        cmdline_partition,
  71#endif
  72#ifdef CONFIG_EFI_PARTITION
  73        efi_partition,          /* this must come before msdos */
  74#endif
  75#ifdef CONFIG_SGI_PARTITION
  76        sgi_partition,
  77#endif
  78#ifdef CONFIG_LDM_PARTITION
  79        ldm_partition,          /* this must come before msdos */
  80#endif
  81#ifdef CONFIG_MSDOS_PARTITION
  82        msdos_partition,
  83#endif
  84#ifdef CONFIG_OSF_PARTITION
  85        osf_partition,
  86#endif
  87#ifdef CONFIG_SUN_PARTITION
  88        sun_partition,
  89#endif
  90#ifdef CONFIG_AMIGA_PARTITION
  91        amiga_partition,
  92#endif
  93#ifdef CONFIG_ATARI_PARTITION
  94        atari_partition,
  95#endif
  96#ifdef CONFIG_MAC_PARTITION
  97        mac_partition,
  98#endif
  99#ifdef CONFIG_ULTRIX_PARTITION
 100        ultrix_partition,
 101#endif
 102#ifdef CONFIG_IBM_PARTITION
 103        ibm_partition,
 104#endif
 105#ifdef CONFIG_KARMA_PARTITION
 106        karma_partition,
 107#endif
 108#ifdef CONFIG_SYSV68_PARTITION
 109        sysv68_partition,
 110#endif
 111        NULL
 112};
 113
 114static struct parsed_partitions *allocate_partitions(struct gendisk *hd)
 115{
 116        struct parsed_partitions *state;
 117        int nr;
 118
 119        state = kzalloc(sizeof(*state), GFP_KERNEL);
 120        if (!state)
 121                return NULL;
 122
 123        nr = disk_max_parts(hd);
 124        state->parts = vzalloc(nr * sizeof(state->parts[0]));
 125        if (!state->parts) {
 126                kfree(state);
 127                return NULL;
 128        }
 129
 130        state->limit = nr;
 131
 132        return state;
 133}
 134
 135void free_partitions(struct parsed_partitions *state)
 136{
 137        vfree(state->parts);
 138        kfree(state);
 139}
 140
 141struct parsed_partitions *
 142check_partition(struct gendisk *hd, struct block_device *bdev)
 143{
 144        struct parsed_partitions *state;
 145        int i, res, err;
 146
 147        state = allocate_partitions(hd);
 148        if (!state)
 149                return NULL;
 150        state->pp_buf = (char *)__get_free_page(GFP_KERNEL);
 151        if (!state->pp_buf) {
 152                free_partitions(state);
 153                return NULL;
 154        }
 155        state->pp_buf[0] = '\0';
 156
 157        state->bdev = bdev;
 158        disk_name(hd, 0, state->name);
 159        snprintf(state->pp_buf, PAGE_SIZE, " %s:", state->name);
 160        if (isdigit(state->name[strlen(state->name)-1]))
 161                sprintf(state->name, "p");
 162
 163        i = res = err = 0;
 164        while (!res && check_part[i]) {
 165                memset(state->parts, 0, state->limit * sizeof(state->parts[0]));
 166                res = check_part[i++](state);
 167                if (res < 0) {
 168                        /* We have hit an I/O error which we don't report now.
 169                        * But record it, and let the others do their job.
 170                        */
 171                        err = res;
 172                        res = 0;
 173                }
 174
 175        }
 176        if (res > 0) {
 177                printk(KERN_INFO "%s", state->pp_buf);
 178
 179                free_page((unsigned long)state->pp_buf);
 180                return state;
 181        }
 182        if (state->access_beyond_eod)
 183                err = -ENOSPC;
 184        if (err)
 185        /* The partition is unrecognized. So report I/O errors if there were any */
 186                res = err;
 187        if (!res)
 188                strlcat(state->pp_buf, " unknown partition table\n", PAGE_SIZE);
 189        else if (warn_no_part)
 190                strlcat(state->pp_buf, " unable to read partition table\n", PAGE_SIZE);
 191
 192        printk(KERN_INFO "%s", state->pp_buf);
 193
 194        free_page((unsigned long)state->pp_buf);
 195        free_partitions(state);
 196        return ERR_PTR(res);
 197}
 198