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