blob: 19ba207ea7d12de48ae0a6182c71df3d188c2b3a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090016#include <linux/slab.h>
Ming Leiac2e5322013-02-27 17:05:19 -080017#include <linux/vmalloc.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/ctype.h>
Jerome Marchand6f2576a2008-02-08 11:04:35 +010019#include <linux/genhd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
21#include "check.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
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"
Bob Copeland0e6e1db2006-01-16 22:14:20 -080035#include "karma.h"
Philippe De Muyter19d0e8c2007-05-08 00:29:15 -070036#include "sysv68.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
Linus Torvalds1da177e2005-04-16 15:20:36 -070038int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
39
Tejun Heo1493bf22010-05-15 20:09:30 +020040static int (*check_part[])(struct parsed_partitions *) = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 /*
42 * Probe partition formats with tables at disk address 0
43 * that also have an ADFS boot block at 0xdc0.
44 */
45#ifdef CONFIG_ACORN_PARTITION_ICS
46 adfspart_check_ICS,
47#endif
48#ifdef CONFIG_ACORN_PARTITION_POWERTEC
49 adfspart_check_POWERTEC,
50#endif
51#ifdef CONFIG_ACORN_PARTITION_EESOX
52 adfspart_check_EESOX,
53#endif
54
55 /*
56 * Now move on to formats that only have partition info at
57 * disk address 0xdc0. Since these may also have stale
58 * PC/BIOS partition tables, they need to come before
59 * the msdos entry.
60 */
61#ifdef CONFIG_ACORN_PARTITION_CUMANA
62 adfspart_check_CUMANA,
63#endif
64#ifdef CONFIG_ACORN_PARTITION_ADFS
65 adfspart_check_ADFS,
66#endif
67
68#ifdef CONFIG_EFI_PARTITION
69 efi_partition, /* this must come before msdos */
70#endif
71#ifdef CONFIG_SGI_PARTITION
72 sgi_partition,
73#endif
74#ifdef CONFIG_LDM_PARTITION
75 ldm_partition, /* this must come before msdos */
76#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070077#ifdef CONFIG_MSDOS_PARTITION
78 msdos_partition,
79#endif
80#ifdef CONFIG_OSF_PARTITION
81 osf_partition,
82#endif
83#ifdef CONFIG_SUN_PARTITION
84 sun_partition,
85#endif
86#ifdef CONFIG_AMIGA_PARTITION
87 amiga_partition,
88#endif
89#ifdef CONFIG_ATARI_PARTITION
90 atari_partition,
91#endif
92#ifdef CONFIG_MAC_PARTITION
93 mac_partition,
94#endif
95#ifdef CONFIG_ULTRIX_PARTITION
96 ultrix_partition,
97#endif
98#ifdef CONFIG_IBM_PARTITION
99 ibm_partition,
100#endif
Bob Copeland0e6e1db2006-01-16 22:14:20 -0800101#ifdef CONFIG_KARMA_PARTITION
102 karma_partition,
103#endif
Philippe De Muyter19d0e8c2007-05-08 00:29:15 -0700104#ifdef CONFIG_SYSV68_PARTITION
105 sysv68_partition,
106#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 NULL
108};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Ming Leiac2e5322013-02-27 17:05:19 -0800110static struct parsed_partitions *allocate_partitions(struct gendisk *hd)
111{
112 struct parsed_partitions *state;
113 int nr;
114
115 state = kzalloc(sizeof(*state), GFP_KERNEL);
116 if (!state)
117 return NULL;
118
119 nr = disk_max_parts(hd);
120 state->parts = vzalloc(nr * sizeof(state->parts[0]));
121 if (!state->parts) {
122 kfree(state);
123 return NULL;
124 }
125
126 state->limit = nr;
127
128 return state;
129}
130
131void free_partitions(struct parsed_partitions *state)
132{
133 vfree(state->parts);
134 kfree(state);
135}
136
Al Viro94ea4152011-09-16 00:45:36 -0400137struct parsed_partitions *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138check_partition(struct gendisk *hd, struct block_device *bdev)
139{
140 struct parsed_partitions *state;
Suzuki K P57881dd2006-12-06 20:35:16 -0800141 int i, res, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Ming Leiac2e5322013-02-27 17:05:19 -0800143 state = allocate_partitions(hd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 if (!state)
145 return NULL;
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700146 state->pp_buf = (char *)__get_free_page(GFP_KERNEL);
147 if (!state->pp_buf) {
Ming Leiac2e5322013-02-27 17:05:19 -0800148 free_partitions(state);
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700149 return NULL;
150 }
151 state->pp_buf[0] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
Tejun Heo1493bf22010-05-15 20:09:30 +0200153 state->bdev = bdev;
Greg Kroah-Hartmana2964182005-06-20 21:15:16 -0700154 disk_name(hd, 0, state->name);
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700155 snprintf(state->pp_buf, PAGE_SIZE, " %s:", state->name);
Greg Kroah-Hartmana2964182005-06-20 21:15:16 -0700156 if (isdigit(state->name[strlen(state->name)-1]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 sprintf(state->name, "p");
Greg Kroah-Hartmana2964182005-06-20 21:15:16 -0700158
Suzuki K P57881dd2006-12-06 20:35:16 -0800159 i = res = err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 while (!res && check_part[i]) {
Ming Leiac2e5322013-02-27 17:05:19 -0800161 memset(state->parts, 0, state->limit * sizeof(state->parts[0]));
Tejun Heo1493bf22010-05-15 20:09:30 +0200162 res = check_part[i++](state);
Suzuki K P57881dd2006-12-06 20:35:16 -0800163 if (res < 0) {
164 /* We have hit an I/O error which we don't report now.
165 * But record it, and let the others do their job.
166 */
167 err = res;
168 res = 0;
169 }
170
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 }
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700172 if (res > 0) {
173 printk(KERN_INFO "%s", state->pp_buf);
174
175 free_page((unsigned long)state->pp_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 return state;
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700177 }
Tejun Heob403a982010-05-15 20:09:31 +0200178 if (state->access_beyond_eod)
179 err = -ENOSPC;
suzuki9bebff62007-03-07 20:41:24 -0800180 if (err)
Suzuki K P57881dd2006-12-06 20:35:16 -0800181 /* The partition is unrecognized. So report I/O errors if there were any */
182 res = err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 if (!res)
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700184 strlcat(state->pp_buf, " unknown partition table\n", PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 else if (warn_no_part)
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700186 strlcat(state->pp_buf, " unable to read partition table\n", PAGE_SIZE);
187
188 printk(KERN_INFO "%s", state->pp_buf);
189
190 free_page((unsigned long)state->pp_buf);
Ming Leiac2e5322013-02-27 17:05:19 -0800191 free_partitions(state);
Suzuki Kp5127d002006-12-06 20:35:14 -0800192 return ERR_PTR(res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193}