Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.14.15.
  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(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}