check.c 16.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 *  fs/partitions/check.c
 *
 *  Code extracted from drivers/block/genhd.c
 *  Copyright (C) 1991-1998  Linus Torvalds
 *  Re-organised Feb 1998 Russell King
 *
 *  We now have independent partition support from the
 *  block drivers, which allows all the partition code to
 *  be grouped in one location, and it to be mostly self
 *  contained.
 *
 *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kmod.h>
#include <linux/ctype.h>
21
#include <linux/genhd.h>
22
#include <linux/blktrace_api.h>
L
Linus Torvalds 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

#include "check.h"

#include "acorn.h"
#include "amiga.h"
#include "atari.h"
#include "ldm.h"
#include "mac.h"
#include "msdos.h"
#include "osf.h"
#include "sgi.h"
#include "sun.h"
#include "ibm.h"
#include "ultrix.h"
#include "efi.h"
38
#include "karma.h"
39
#include "sysv68.h"
L
Linus Torvalds 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

#ifdef CONFIG_BLK_DEV_MD
extern void md_autodetect_dev(dev_t dev);
#endif

int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/

static int (*check_part[])(struct parsed_partitions *, struct block_device *) = {
	/*
	 * Probe partition formats with tables at disk address 0
	 * that also have an ADFS boot block at 0xdc0.
	 */
#ifdef CONFIG_ACORN_PARTITION_ICS
	adfspart_check_ICS,
#endif
#ifdef CONFIG_ACORN_PARTITION_POWERTEC
	adfspart_check_POWERTEC,
#endif
#ifdef CONFIG_ACORN_PARTITION_EESOX
	adfspart_check_EESOX,
#endif

	/*
	 * Now move on to formats that only have partition info at
	 * disk address 0xdc0.  Since these may also have stale
	 * PC/BIOS partition tables, they need to come before
	 * the msdos entry.
	 */
#ifdef CONFIG_ACORN_PARTITION_CUMANA
	adfspart_check_CUMANA,
#endif
#ifdef CONFIG_ACORN_PARTITION_ADFS
	adfspart_check_ADFS,
#endif

#ifdef CONFIG_EFI_PARTITION
	efi_partition,		/* this must come before msdos */
#endif
#ifdef CONFIG_SGI_PARTITION
	sgi_partition,
#endif
#ifdef CONFIG_LDM_PARTITION
	ldm_partition,		/* this must come before msdos */
#endif
#ifdef CONFIG_MSDOS_PARTITION
	msdos_partition,
#endif
#ifdef CONFIG_OSF_PARTITION
	osf_partition,
#endif
#ifdef CONFIG_SUN_PARTITION
	sun_partition,
#endif
#ifdef CONFIG_AMIGA_PARTITION
	amiga_partition,
#endif
#ifdef CONFIG_ATARI_PARTITION
	atari_partition,
#endif
#ifdef CONFIG_MAC_PARTITION
	mac_partition,
#endif
#ifdef CONFIG_ULTRIX_PARTITION
	ultrix_partition,
#endif
#ifdef CONFIG_IBM_PARTITION
	ibm_partition,
107 108 109
#endif
#ifdef CONFIG_KARMA_PARTITION
	karma_partition,
110 111 112
#endif
#ifdef CONFIG_SYSV68_PARTITION
	sysv68_partition,
L
Linus Torvalds 已提交
113 114 115 116 117 118 119 120 121 122 123
#endif
	NULL
};
 
/*
 * disk_name() is used by partition check code and the genhd driver.
 * It formats the devicename of the indicated disk into
 * the supplied buffer (of size at least 32), and returns
 * a pointer to that same buffer (for convenience).
 */

124
char *disk_name(struct gendisk *hd, int partno, char *buf)
L
Linus Torvalds 已提交
125
{
126
	if (!partno)
L
Linus Torvalds 已提交
127 128
		snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name);
	else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1]))
129
		snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, partno);
L
Linus Torvalds 已提交
130
	else
131
		snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, partno);
L
Linus Torvalds 已提交
132 133 134 135 136 137

	return buf;
}

const char *bdevname(struct block_device *bdev, char *buf)
{
T
Tejun Heo 已提交
138
	return disk_name(bdev->bd_disk, bdev->bd_part->partno, buf);
L
Linus Torvalds 已提交
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
}

EXPORT_SYMBOL(bdevname);

/*
 * There's very little reason to use this, you should really
 * have a struct block_device just about everywhere and use
 * bdevname() instead.
 */
const char *__bdevname(dev_t dev, char *buffer)
{
	scnprintf(buffer, BDEVNAME_SIZE, "unknown-block(%u,%u)",
				MAJOR(dev), MINOR(dev));
	return buffer;
}

EXPORT_SYMBOL(__bdevname);

static struct parsed_partitions *
check_partition(struct gendisk *hd, struct block_device *bdev)
{
	struct parsed_partitions *state;
S
Suzuki K P 已提交
161
	int i, res, err;
L
Linus Torvalds 已提交
162 163 164 165 166

	state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL);
	if (!state)
		return NULL;

167 168 169
	disk_name(hd, 0, state->name);
	printk(KERN_INFO " %s:", state->name);
	if (isdigit(state->name[strlen(state->name)-1]))
L
Linus Torvalds 已提交
170
		sprintf(state->name, "p");
171

T
Tejun Heo 已提交
172
	state->limit = disk_max_parts(hd);
S
Suzuki K P 已提交
173
	i = res = err = 0;
L
Linus Torvalds 已提交
174 175 176
	while (!res && check_part[i]) {
		memset(&state->parts, 0, sizeof(state->parts));
		res = check_part[i++](state, bdev);
S
Suzuki K P 已提交
177 178 179 180 181 182 183 184
		if (res < 0) {
			/* We have hit an I/O error which we don't report now.
		 	* But record it, and let the others do their job.
		 	*/
			err = res;
			res = 0;
		}

L
Linus Torvalds 已提交
185 186 187
	}
	if (res > 0)
		return state;
188
	if (err)
S
Suzuki K P 已提交
189 190
	/* The partition is unrecognized. So report I/O errors if there were any */
		res = err;
L
Linus Torvalds 已提交
191 192 193 194 195
	if (!res)
		printk(" unknown partition table\n");
	else if (warn_no_part)
		printk(" unable to read partition table\n");
	kfree(state);
196
	return ERR_PTR(res);
L
Linus Torvalds 已提交
197 198
}

199 200 201 202 203 204 205 206
static ssize_t part_partition_show(struct device *dev,
				   struct device_attribute *attr, char *buf)
{
	struct hd_struct *p = dev_to_part(dev);

	return sprintf(buf, "%d\n", p->partno);
}

207 208
static ssize_t part_start_show(struct device *dev,
			       struct device_attribute *attr, char *buf)
L
Linus Torvalds 已提交
209
{
210
	struct hd_struct *p = dev_to_part(dev);
211

212
	return sprintf(buf, "%llu\n",(unsigned long long)p->start_sect);
L
Linus Torvalds 已提交
213 214
}

T
Tejun Heo 已提交
215 216
ssize_t part_size_show(struct device *dev,
		       struct device_attribute *attr, char *buf)
217
{
218 219
	struct hd_struct *p = dev_to_part(dev);
	return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
220
}
221

222 223 224 225 226 227 228
ssize_t part_alignment_offset_show(struct device *dev,
				   struct device_attribute *attr, char *buf)
{
	struct hd_struct *p = dev_to_part(dev);
	return sprintf(buf, "%llu\n", (unsigned long long)p->alignment_offset);
}

229 230 231 232 233 234 235
ssize_t part_discard_alignment_show(struct device *dev,
				   struct device_attribute *attr, char *buf)
{
	struct hd_struct *p = dev_to_part(dev);
	return sprintf(buf, "%u\n", p->discard_alignment);
}

T
Tejun Heo 已提交
236 237
ssize_t part_stat_show(struct device *dev,
		       struct device_attribute *attr, char *buf)
L
Linus Torvalds 已提交
238
{
239
	struct hd_struct *p = dev_to_part(dev);
T
Tejun Heo 已提交
240
	int cpu;
241

T
Tejun Heo 已提交
242
	cpu = part_stat_lock();
T
Tejun Heo 已提交
243
	part_round_stats(cpu, p);
T
Tejun Heo 已提交
244
	part_stat_unlock();
245 246 247 248 249 250 251 252 253 254 255 256 257
	return sprintf(buf,
		"%8lu %8lu %8llu %8u "
		"%8lu %8lu %8llu %8u "
		"%8u %8u %8u"
		"\n",
		part_stat_read(p, ios[READ]),
		part_stat_read(p, merges[READ]),
		(unsigned long long)part_stat_read(p, sectors[READ]),
		jiffies_to_msecs(part_stat_read(p, ticks[READ])),
		part_stat_read(p, ios[WRITE]),
		part_stat_read(p, merges[WRITE]),
		(unsigned long long)part_stat_read(p, sectors[WRITE]),
		jiffies_to_msecs(part_stat_read(p, ticks[WRITE])),
258
		part_in_flight(p),
259 260
		jiffies_to_msecs(part_stat_read(p, io_ticks)),
		jiffies_to_msecs(part_stat_read(p, time_in_queue)));
L
Linus Torvalds 已提交
261 262
}

263 264 265 266 267 268 269 270
ssize_t part_inflight_show(struct device *dev,
			struct device_attribute *attr, char *buf)
{
	struct hd_struct *p = dev_to_part(dev);

	return sprintf(buf, "%8u %8u\n", p->in_flight[0], p->in_flight[1]);
}

271
#ifdef CONFIG_FAIL_MAKE_REQUEST
272 273
ssize_t part_fail_show(struct device *dev,
		       struct device_attribute *attr, char *buf)
274 275
{
	struct hd_struct *p = dev_to_part(dev);
276

277 278 279
	return sprintf(buf, "%d\n", p->make_it_fail);
}

280 281 282
ssize_t part_fail_store(struct device *dev,
			struct device_attribute *attr,
			const char *buf, size_t count)
283
{
284
	struct hd_struct *p = dev_to_part(dev);
285 286 287 288 289 290 291
	int i;

	if (count > 0 && sscanf(buf, "%d", &i) > 0)
		p->make_it_fail = (i == 0) ? 0 : 1;

	return count;
}
292
#endif
293

294
static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL);
295 296
static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
297
static DEVICE_ATTR(alignment_offset, S_IRUGO, part_alignment_offset_show, NULL);
298 299
static DEVICE_ATTR(discard_alignment, S_IRUGO, part_discard_alignment_show,
		   NULL);
300
static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL);
301
static DEVICE_ATTR(inflight, S_IRUGO, part_inflight_show, NULL);
302 303 304
#ifdef CONFIG_FAIL_MAKE_REQUEST
static struct device_attribute dev_attr_fail =
	__ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
305 306
#endif

307
static struct attribute *part_attrs[] = {
308
	&dev_attr_partition.attr,
309 310
	&dev_attr_start.attr,
	&dev_attr_size.attr,
311
	&dev_attr_alignment_offset.attr,
312
	&dev_attr_discard_alignment.attr,
313
	&dev_attr_stat.attr,
314
	&dev_attr_inflight.attr,
315
#ifdef CONFIG_FAIL_MAKE_REQUEST
316
	&dev_attr_fail.attr,
317
#endif
318
	NULL
L
Linus Torvalds 已提交
319 320
};

321 322 323
static struct attribute_group part_attr_group = {
	.attrs = part_attrs,
};
L
Linus Torvalds 已提交
324

325
static const struct attribute_group *part_attr_groups[] = {
326
	&part_attr_group,
327 328 329
#ifdef CONFIG_BLK_DEV_IO_TRACE
	&blk_trace_attr_group,
#endif
330 331 332 333
	NULL
};

static void part_release(struct device *dev)
L
Linus Torvalds 已提交
334
{
335
	struct hd_struct *p = dev_to_part(dev);
336
	free_part_stats(p);
L
Linus Torvalds 已提交
337 338 339
	kfree(p);
}

340 341 342
struct device_type part_type = {
	.name		= "partition",
	.groups		= part_attr_groups,
L
Linus Torvalds 已提交
343 344 345
	.release	= part_release,
};

346 347 348 349 350 351 352
static void delete_partition_rcu_cb(struct rcu_head *head)
{
	struct hd_struct *part = container_of(head, struct hd_struct, rcu_head);

	part->start_sect = 0;
	part->nr_sects = 0;
	part_stat_set_all(part, 0);
353
	put_device(part_to_dev(part));
354 355
}

356
void delete_partition(struct gendisk *disk, int partno)
L
Linus Torvalds 已提交
357
{
T
Tejun Heo 已提交
358
	struct disk_part_tbl *ptbl = disk->part_tbl;
359
	struct hd_struct *part;
360

T
Tejun Heo 已提交
361 362 363 364
	if (partno >= ptbl->len)
		return;

	part = ptbl->part[partno];
365
	if (!part)
L
Linus Torvalds 已提交
366
		return;
367

T
Tejun Heo 已提交
368
	blk_free_devt(part_devt(part));
T
Tejun Heo 已提交
369
	rcu_assign_pointer(ptbl->part[partno], NULL);
N
Neil Brown 已提交
370
	rcu_assign_pointer(ptbl->last_lookup, NULL);
371
	kobject_put(part->holder_dir);
372
	device_del(part_to_dev(part));
373 374

	call_rcu(&part->rcu_head, delete_partition_rcu_cb);
L
Linus Torvalds 已提交
375 376
}

377 378 379 380 381 382 383 384
static ssize_t whole_disk_show(struct device *dev,
			       struct device_attribute *attr, char *buf)
{
	return 0;
}
static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH,
		   whole_disk_show, NULL);

385 386
struct hd_struct *add_partition(struct gendisk *disk, int partno,
				sector_t start, sector_t len, int flags)
L
Linus Torvalds 已提交
387 388
{
	struct hd_struct *p;
T
Tejun Heo 已提交
389
	dev_t devt = MKDEV(0, 0);
390 391
	struct device *ddev = disk_to_dev(disk);
	struct device *pdev;
T
Tejun Heo 已提交
392
	struct disk_part_tbl *ptbl;
393
	const char *dname;
394
	int err;
L
Linus Torvalds 已提交
395

T
Tejun Heo 已提交
396 397
	err = disk_expand_part_tbl(disk, partno);
	if (err)
398
		return ERR_PTR(err);
T
Tejun Heo 已提交
399 400 401
	ptbl = disk->part_tbl;

	if (ptbl->part[partno])
402
		return ERR_PTR(-EBUSY);
403

404
	p = kzalloc(sizeof(*p), GFP_KERNEL);
L
Linus Torvalds 已提交
405
	if (!p)
406
		return ERR_PTR(-EBUSY);
407

408
	if (!init_part_stats(p)) {
409
		err = -ENOMEM;
410
		goto out_free;
411
	}
412 413
	pdev = part_to_dev(p);

L
Linus Torvalds 已提交
414
	p->start_sect = start;
415
	p->alignment_offset = queue_sector_alignment_offset(disk->queue, start);
416 417
	p->discard_alignment = queue_sector_discard_alignment(disk->queue,
							      start);
L
Linus Torvalds 已提交
418
	p->nr_sects = len;
419
	p->partno = partno;
T
Tejun Heo 已提交
420
	p->policy = get_disk_ro(disk);
L
Linus Torvalds 已提交
421

422 423
	dname = dev_name(ddev);
	if (isdigit(dname[strlen(dname) - 1]))
424
		dev_set_name(pdev, "%sp%d", dname, partno);
L
Linus Torvalds 已提交
425
	else
426
		dev_set_name(pdev, "%s%d", dname, partno);
427

428 429 430 431
	device_initialize(pdev);
	pdev->class = &block_class;
	pdev->type = &part_type;
	pdev->parent = ddev;
432

T
Tejun Heo 已提交
433 434
	err = blk_alloc_devt(p, &devt);
	if (err)
T
Tejun Heo 已提交
435
		goto out_free_stats;
436
	pdev->devt = devt;
T
Tejun Heo 已提交
437

438
	/* delay uevent until 'holders' subdir is created */
439
	dev_set_uevent_suppress(pdev, 1);
440
	err = device_add(pdev);
441
	if (err)
442 443 444
		goto out_put;

	err = -ENOMEM;
445
	p->holder_dir = kobject_create_and_add("holders", &pdev->kobj);
446 447 448
	if (!p->holder_dir)
		goto out_del;

449
	dev_set_uevent_suppress(pdev, 0);
450
	if (flags & ADDPART_FLAG_WHOLEDISK) {
451
		err = device_create_file(pdev, &dev_attr_whole_disk);
452
		if (err)
453
			goto out_del;
454
	}
L
Linus Torvalds 已提交
455

456
	/* everything is up and running, commence */
457
	INIT_RCU_HEAD(&p->rcu_head);
T
Tejun Heo 已提交
458
	rcu_assign_pointer(ptbl->part[partno], p);
459

460
	/* suppress uevent if the disk supresses it */
461
	if (!dev_get_uevent_suppress(ddev))
462
		kobject_uevent(&pdev->kobj, KOBJ_ADD);
463

464
	return p;
465

T
Tejun Heo 已提交
466 467
out_free_stats:
	free_part_stats(p);
468 469
out_free:
	kfree(p);
470
	return ERR_PTR(err);
471 472
out_del:
	kobject_put(p->holder_dir);
473
	device_del(pdev);
474
out_put:
475
	put_device(pdev);
T
Tejun Heo 已提交
476
	blk_free_devt(devt);
477
	return ERR_PTR(err);
L
Linus Torvalds 已提交
478 479 480 481 482
}

/* Not exported, helper to add_disk(). */
void register_disk(struct gendisk *disk)
{
483
	struct device *ddev = disk_to_dev(disk);
L
Linus Torvalds 已提交
484
	struct block_device *bdev;
485 486
	struct disk_part_iter piter;
	struct hd_struct *part;
L
Linus Torvalds 已提交
487 488
	int err;

489
	ddev->parent = disk->driverfs_dev;
490

491
	dev_set_name(ddev, disk->disk_name);
492 493

	/* delay uevents, until we scanned partition table */
494
	dev_set_uevent_suppress(ddev, 1);
495

496
	if (device_add(ddev))
L
Linus Torvalds 已提交
497
		return;
498
#ifndef CONFIG_SYSFS_DEPRECATED
499 500
	err = sysfs_create_link(block_depr, &ddev->kobj,
				kobject_name(&ddev->kobj));
501
	if (err) {
502
		device_del(ddev);
503 504
		return;
	}
505
#endif
506 507
	disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
	disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
L
Linus Torvalds 已提交
508 509

	/* No minors to use for partitions */
T
Tejun Heo 已提交
510
	if (!disk_partitionable(disk))
511
		goto exit;
L
Linus Torvalds 已提交
512 513 514

	/* No such device (e.g., media were just removed) */
	if (!get_capacity(disk))
515
		goto exit;
L
Linus Torvalds 已提交
516 517 518

	bdev = bdget_disk(disk, 0);
	if (!bdev)
519
		goto exit;
L
Linus Torvalds 已提交
520 521

	bdev->bd_invalidated = 1;
522
	err = blkdev_get(bdev, FMODE_READ);
523 524
	if (err < 0)
		goto exit;
A
Al Viro 已提交
525
	blkdev_put(bdev, FMODE_READ);
526 527

exit:
528
	/* announce disk after possible partitions are created */
529
	dev_set_uevent_suppress(ddev, 0);
530
	kobject_uevent(&ddev->kobj, KOBJ_ADD);
531 532

	/* announce possible partitions */
533 534
	disk_part_iter_init(&piter, disk, 0);
	while ((part = disk_part_iter_next(&piter)))
535
		kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD);
536
	disk_part_iter_exit(&piter);
L
Linus Torvalds 已提交
537 538 539 540
}

int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
{
541 542
	struct disk_part_iter piter;
	struct hd_struct *part;
L
Linus Torvalds 已提交
543
	struct parsed_partitions *state;
T
Tejun Heo 已提交
544
	int p, highest, res;
L
Linus Torvalds 已提交
545 546 547 548 549 550

	if (bdev->bd_part_count)
		return -EBUSY;
	res = invalidate_partition(disk, 0);
	if (res)
		return res;
551 552 553 554 555 556

	disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY);
	while ((part = disk_part_iter_next(&piter)))
		delete_partition(disk, part->partno);
	disk_part_iter_exit(&piter);

L
Linus Torvalds 已提交
557 558
	if (disk->fops->revalidate_disk)
		disk->fops->revalidate_disk(disk);
559 560
	check_disk_size_change(disk, bdev);
	bdev->bd_invalidated = 0;
L
Linus Torvalds 已提交
561 562
	if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
		return 0;
563
	if (IS_ERR(state))	/* I/O error reading the partition table */
564
		return -EIO;
565 566

	/* tell userspace that the media / partition table may have changed */
567
	kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
568

T
Tejun Heo 已提交
569 570 571 572 573 574 575 576 577 578 579
	/* Detect the highest partition number and preallocate
	 * disk->part_tbl.  This is an optimization and not strictly
	 * necessary.
	 */
	for (p = 1, highest = 0; p < state->limit; p++)
		if (state->parts[p].size)
			highest = p;

	disk_expand_part_tbl(disk, highest);

	/* add partitions */
L
Linus Torvalds 已提交
580
	for (p = 1; p < state->limit; p++) {
581 582 583
		sector_t size, from;
try_scan:
		size = state->parts[p].size;
L
Linus Torvalds 已提交
584 585
		if (!size)
			continue;
586 587

		from = state->parts[p].from;
588 589 590 591 592 593
		if (from >= get_capacity(disk)) {
			printk(KERN_WARNING
			       "%s: p%d ignored, start %llu is behind the end of the disk\n",
			       disk->disk_name, p, (unsigned long long) from);
			continue;
		}
594

595
		if (from + size > get_capacity(disk)) {
596
			const struct block_device_operations *bdops = disk->fops;
597 598
			unsigned long long capacity;

599
			printk(KERN_WARNING
600
			       "%s: p%d size %llu exceeds device capacity, ",
601
			       disk->disk_name, p, (unsigned long long) size);
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623

			if (bdops->set_capacity &&
			    (disk->flags & GENHD_FL_NATIVE_CAPACITY) == 0) {
				printk(KERN_CONT "enabling native capacity\n");
				capacity = bdops->set_capacity(disk, ~0ULL);
				disk->flags |= GENHD_FL_NATIVE_CAPACITY;
				if (capacity > get_capacity(disk)) {
					set_capacity(disk, capacity);
					check_disk_size_change(disk, bdev);
					bdev->bd_invalidated = 0;
				}
				goto try_scan;
			} else {
				/*
				 * we can not ignore partitions of broken tables
				 * created by for example camera firmware, but
				 * we limit them to the end of the disk to avoid
				 * creating invalid block devices
				 */
				printk(KERN_CONT "limited to end of disk\n");
				size = get_capacity(disk) - from;
			}
624
		}
625 626 627 628 629
		part = add_partition(disk, p, from, size,
				     state->parts[p].flags);
		if (IS_ERR(part)) {
			printk(KERN_ERR " %s: p%d could not be added: %ld\n",
			       disk->disk_name, p, -PTR_ERR(part));
630
			continue;
631
		}
L
Linus Torvalds 已提交
632
#ifdef CONFIG_BLK_DEV_MD
633
		if (state->parts[p].flags & ADDPART_FLAG_RAID)
T
Tejun Heo 已提交
634
			md_autodetect_dev(part_to_dev(part)->devt);
L
Linus Torvalds 已提交
635 636 637 638 639 640 641 642 643 644 645
#endif
	}
	kfree(state);
	return 0;
}

unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
{
	struct address_space *mapping = bdev->bd_inode->i_mapping;
	struct page *page;

646 647
	page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)),
				 NULL);
L
Linus Torvalds 已提交
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
	if (!IS_ERR(page)) {
		if (PageError(page))
			goto fail;
		p->v = page;
		return (unsigned char *)page_address(page) +  ((n & ((1 << (PAGE_CACHE_SHIFT - 9)) - 1)) << 9);
fail:
		page_cache_release(page);
	}
	p->v = NULL;
	return NULL;
}

EXPORT_SYMBOL(read_dev_sector);

void del_gendisk(struct gendisk *disk)
{
664 665
	struct disk_part_iter piter;
	struct hd_struct *part;
L
Linus Torvalds 已提交
666 667

	/* invalidate stuff */
668 669 670 671 672
	disk_part_iter_init(&piter, disk,
			     DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE);
	while ((part = disk_part_iter_next(&piter))) {
		invalidate_partition(disk, part->partno);
		delete_partition(disk, part->partno);
L
Linus Torvalds 已提交
673
	}
674 675
	disk_part_iter_exit(&piter);

L
Linus Torvalds 已提交
676
	invalidate_partition(disk, 0);
677
	blk_free_devt(disk_to_dev(disk)->devt);
678
	set_capacity(disk, 0);
L
Linus Torvalds 已提交
679 680
	disk->flags &= ~GENHD_FL_UP;
	unlink_gendisk(disk);
T
Tejun Heo 已提交
681 682
	part_stat_set_all(&disk->part0, 0);
	disk->part0.stamp = 0;
L
Linus Torvalds 已提交
683

684
	kobject_put(disk->part0.holder_dir);
685
	kobject_put(disk->slave_dir);
686 687
	disk->driverfs_dev = NULL;
#ifndef CONFIG_SYSFS_DEPRECATED
688
	sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
689
#endif
690
	device_del(disk_to_dev(disk));
L
Linus Torvalds 已提交
691
}