• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
39 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
40 
41 static 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 
allocate_partitions(struct gendisk * hd)114 static 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 
free_partitions(struct parsed_partitions * state)135 void free_partitions(struct parsed_partitions *state)
136 {
137 	vfree(state->parts);
138 	kfree(state);
139 }
140 
141 struct parsed_partitions *
check_partition(struct gendisk * hd,struct block_device * bdev)142 check_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