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