Branch data Line data Source code
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 : : 40 : : int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/ 41 : : 42 : : static 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 : : 115 : 3 : static struct parsed_partitions *allocate_partitions(struct gendisk *hd) 116 : : { 117 : : struct parsed_partitions *state; 118 : : int nr; 119 : : 120 : 3 : state = kzalloc(sizeof(*state), GFP_KERNEL); 121 : 3 : if (!state) 122 : : return NULL; 123 : : 124 : : nr = disk_max_parts(hd); 125 : 3 : state->parts = vzalloc(array_size(nr, sizeof(state->parts[0]))); 126 : 3 : if (!state->parts) { 127 : 0 : kfree(state); 128 : 0 : return NULL; 129 : : } 130 : : 131 : 3 : state->limit = nr; 132 : : 133 : 3 : return state; 134 : : } 135 : : 136 : 3 : void free_partitions(struct parsed_partitions *state) 137 : : { 138 : 3 : vfree(state->parts); 139 : 3 : kfree(state); 140 : 3 : } 141 : : 142 : : struct parsed_partitions * 143 : 3 : check_partition(struct gendisk *hd, struct block_device *bdev) 144 : : { 145 : : struct parsed_partitions *state; 146 : : int i, res, err; 147 : : 148 : 3 : state = allocate_partitions(hd); 149 : 3 : if (!state) 150 : : return NULL; 151 : 3 : state->pp_buf = (char *)__get_free_page(GFP_KERNEL); 152 : 3 : if (!state->pp_buf) { 153 : : free_partitions(state); 154 : 0 : return NULL; 155 : : } 156 : 3 : state->pp_buf[0] = '\0'; 157 : : 158 : 3 : state->bdev = bdev; 159 : 3 : disk_name(hd, 0, state->name); 160 : 3 : snprintf(state->pp_buf, PAGE_SIZE, " %s:", state->name); 161 : 3 : if (isdigit(state->name[strlen(state->name)-1])) 162 : 3 : sprintf(state->name, "p"); 163 : : 164 : : i = res = err = 0; 165 : 3 : while (!res && check_part[i]) { 166 : 3 : memset(state->parts, 0, state->limit * sizeof(state->parts[0])); 167 : 3 : res = check_part[i++](state); 168 : 3 : 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 : 3 : if (res > 0) { 178 : 3 : printk(KERN_INFO "%s", state->pp_buf); 179 : : 180 : 3 : free_page((unsigned long)state->pp_buf); 181 : 3 : return state; 182 : : } 183 : 3 : if (state->access_beyond_eod) 184 : : err = -ENOSPC; 185 : 3 : if (err) 186 : : /* The partition is unrecognized. So report I/O errors if there were any */ 187 : : res = err; 188 : 3 : if (res) { 189 : 0 : if (warn_no_part) 190 : 0 : strlcat(state->pp_buf, 191 : : " unable to read partition table\n", PAGE_SIZE); 192 : 0 : printk(KERN_INFO "%s", state->pp_buf); 193 : : } 194 : : 195 : 3 : free_page((unsigned long)state->pp_buf); 196 : : free_partitions(state); 197 : 3 : return ERR_PTR(res); 198 : : }