Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: part: Create the master device node when partitioned

For many use cases, it helps to have a device node for the entire
MTD device as well as device nodes for the individual partitions.
For example, this allows querying the entire device's properties.
A common idiom is to create an additional partition which spans
over the whole device.

This patch makes a config option, CONFIG_MTD_PARTITIONED_MASTER,
which makes the master partition present even when the device is
partitioned. This isn't turned on by default since it presents
a backwards-incompatible device numbering.

The patch also makes the parent of a partition device be the master,
if the config flag is set, now that the master is a full device.

Signed-off-by: Dan Ehrenberg <dehrenberg@chromium.org>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>

authored by

Dan Ehrenberg and committed by
Brian Norris
727dc612 9cd5196e

+62 -21
+13
drivers/mtd/Kconfig
··· 309 309 The driver provides wear leveling by storing erase counter into the 310 310 OOB. 311 311 312 + config MTD_PARTITIONED_MASTER 313 + bool "Retain master device when partitioned" 314 + default n 315 + depends on MTD 316 + help 317 + For historical reasons, by default, either a master is present or 318 + several partitions are present, but not both. The concern was that 319 + data listed in multiple partitions was dangerous; however, SCSI does 320 + this and it is frequently useful for applications. This config option 321 + leaves the master in even if the device is partitioned. It also makes 322 + the parent of the partition device be the master device, rather than 323 + what lies behind the master. 324 + 312 325 source "drivers/mtd/chips/Kconfig" 313 326 314 327 source "drivers/mtd/maps/Kconfig"
+36 -16
drivers/mtd/mtdcore.c
··· 38 38 #include <linux/gfp.h> 39 39 #include <linux/slab.h> 40 40 #include <linux/reboot.h> 41 + #include <linux/kconfig.h> 41 42 42 43 #include <linux/mtd/mtd.h> 43 44 #include <linux/mtd/partitions.h> ··· 502 501 return ret; 503 502 } 504 503 504 + static int mtd_add_device_partitions(struct mtd_info *mtd, 505 + struct mtd_partition *real_parts, 506 + int nbparts) 507 + { 508 + int ret; 509 + 510 + if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { 511 + ret = add_mtd_device(mtd); 512 + if (ret == 1) 513 + return -ENODEV; 514 + } 515 + 516 + if (nbparts > 0) { 517 + ret = add_mtd_partitions(mtd, real_parts, nbparts); 518 + if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) 519 + del_mtd_device(mtd); 520 + return ret; 521 + } 522 + 523 + return 0; 524 + } 525 + 526 + 505 527 /** 506 528 * mtd_device_parse_register - parse partitions and register an MTD device. 507 529 * ··· 547 523 * found this functions tries to fallback to information specified in 548 524 * @parts/@nr_parts. 549 525 * * If any partitioning info was found, this function registers the found 550 - * partitions. 526 + * partitions. If the MTD_PARTITIONED_MASTER option is set, then the device 527 + * as a whole is registered first. 551 528 * * If no partitions were found this function just registers the MTD device 552 529 * @mtd and exits. 553 530 * ··· 559 534 const struct mtd_partition *parts, 560 535 int nr_parts) 561 536 { 562 - int err; 563 - struct mtd_partition *real_parts; 537 + int ret; 538 + struct mtd_partition *real_parts = NULL; 564 539 565 - err = parse_mtd_partitions(mtd, types, &real_parts, parser_data); 566 - if (err <= 0 && nr_parts && parts) { 540 + ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data); 541 + if (ret <= 0 && nr_parts && parts) { 567 542 real_parts = kmemdup(parts, sizeof(*parts) * nr_parts, 568 543 GFP_KERNEL); 569 544 if (!real_parts) 570 - err = -ENOMEM; 545 + ret = -ENOMEM; 571 546 else 572 - err = nr_parts; 547 + ret = nr_parts; 573 548 } 574 549 575 - if (err > 0) { 576 - err = add_mtd_partitions(mtd, real_parts, err); 577 - kfree(real_parts); 578 - } else if (err == 0) { 579 - err = add_mtd_device(mtd); 580 - if (err == 1) 581 - err = -ENODEV; 582 - } 550 + if (ret >= 0) 551 + ret = mtd_add_device_partitions(mtd, real_parts, ret); 583 552 584 553 /* 585 554 * FIXME: some drivers unfortunately call this function more than once. ··· 588 569 register_reboot_notifier(&mtd->reboot_notifier); 589 570 } 590 571 591 - return err; 572 + kfree(real_parts); 573 + return ret; 592 574 } 593 575 EXPORT_SYMBOL_GPL(mtd_device_parse_register); 594 576
+13 -5
drivers/mtd/mtdpart.c
··· 30 30 #include <linux/mtd/mtd.h> 31 31 #include <linux/mtd/partitions.h> 32 32 #include <linux/err.h> 33 + #include <linux/kconfig.h> 33 34 34 35 #include "mtdcore.h" 35 36 ··· 380 379 slave->mtd.name = name; 381 380 slave->mtd.owner = master->owner; 382 381 383 - /* NOTE: we don't arrange MTDs as a tree; it'd be error-prone 384 - * to have the same data be in two different partitions. 382 + /* NOTE: Historically, we didn't arrange MTDs as a tree out of 383 + * concern for showing the same data in multiple partitions. 384 + * However, it is very useful to have the master node present, 385 + * so the MTD_PARTITIONED_MASTER option allows that. The master 386 + * will have device nodes etc only if this is set, so make the 387 + * parent conditional on that option. Note, this is a way to 388 + * distinguish between the master and the partition in sysfs. 385 389 */ 386 - slave->mtd.dev.parent = master->dev.parent; 390 + slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ? 391 + &master->dev : 392 + master->dev.parent; 387 393 388 394 slave->mtd._read = part_read; 389 395 slave->mtd._write = part_write; ··· 639 631 * and registers slave MTD objects which are bound to the master according to 640 632 * the partition definitions. 641 633 * 642 - * We don't register the master, or expect the caller to have done so, 643 - * for reasons of data integrity. 634 + * For historical reasons, this function's caller only registers the master 635 + * if the MTD_PARTITIONED_MASTER config option is set. 644 636 */ 645 637 646 638 int add_mtd_partitions(struct mtd_info *master,