Skip to content

Commit 727dc61

Browse files
Dan Ehrenbergcomputersforpeace
authored andcommitted
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 <[email protected]> Signed-off-by: Brian Norris <[email protected]>
1 parent 9cd5196 commit 727dc61

File tree

3 files changed

+62
-21
lines changed

3 files changed

+62
-21
lines changed

drivers/mtd/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,19 @@ config MTD_SWAP
309309
The driver provides wear leveling by storing erase counter into the
310310
OOB.
311311

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+
312325
source "drivers/mtd/chips/Kconfig"
313326

314327
source "drivers/mtd/maps/Kconfig"

drivers/mtd/mtdcore.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <linux/gfp.h>
3939
#include <linux/slab.h>
4040
#include <linux/reboot.h>
41+
#include <linux/kconfig.h>
4142

4243
#include <linux/mtd/mtd.h>
4344
#include <linux/mtd/partitions.h>
@@ -501,6 +502,29 @@ int del_mtd_device(struct mtd_info *mtd)
501502
return ret;
502503
}
503504

505+
static int mtd_add_device_partitions(struct mtd_info *mtd,
506+
struct mtd_partition *real_parts,
507+
int nbparts)
508+
{
509+
int ret;
510+
511+
if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
512+
ret = add_mtd_device(mtd);
513+
if (ret == 1)
514+
return -ENODEV;
515+
}
516+
517+
if (nbparts > 0) {
518+
ret = add_mtd_partitions(mtd, real_parts, nbparts);
519+
if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
520+
del_mtd_device(mtd);
521+
return ret;
522+
}
523+
524+
return 0;
525+
}
526+
527+
504528
/**
505529
* mtd_device_parse_register - parse partitions and register an MTD device.
506530
*
@@ -523,7 +547,8 @@ int del_mtd_device(struct mtd_info *mtd)
523547
* found this functions tries to fallback to information specified in
524548
* @parts/@nr_parts.
525549
* * If any partitioning info was found, this function registers the found
526-
* partitions.
550+
* partitions. If the MTD_PARTITIONED_MASTER option is set, then the device
551+
* as a whole is registered first.
527552
* * If no partitions were found this function just registers the MTD device
528553
* @mtd and exits.
529554
*
@@ -534,27 +559,21 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
534559
const struct mtd_partition *parts,
535560
int nr_parts)
536561
{
537-
int err;
538-
struct mtd_partition *real_parts;
562+
int ret;
563+
struct mtd_partition *real_parts = NULL;
539564

540-
err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
541-
if (err <= 0 && nr_parts && parts) {
565+
ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
566+
if (ret <= 0 && nr_parts && parts) {
542567
real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
543568
GFP_KERNEL);
544569
if (!real_parts)
545-
err = -ENOMEM;
570+
ret = -ENOMEM;
546571
else
547-
err = nr_parts;
572+
ret = nr_parts;
548573
}
549574

550-
if (err > 0) {
551-
err = add_mtd_partitions(mtd, real_parts, err);
552-
kfree(real_parts);
553-
} else if (err == 0) {
554-
err = add_mtd_device(mtd);
555-
if (err == 1)
556-
err = -ENODEV;
557-
}
575+
if (ret >= 0)
576+
ret = mtd_add_device_partitions(mtd, real_parts, ret);
558577

559578
/*
560579
* FIXME: some drivers unfortunately call this function more than once.
@@ -569,7 +588,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
569588
register_reboot_notifier(&mtd->reboot_notifier);
570589
}
571590

572-
return err;
591+
kfree(real_parts);
592+
return ret;
573593
}
574594
EXPORT_SYMBOL_GPL(mtd_device_parse_register);
575595

drivers/mtd/mtdpart.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/mtd/mtd.h>
3131
#include <linux/mtd/partitions.h>
3232
#include <linux/err.h>
33+
#include <linux/kconfig.h>
3334

3435
#include "mtdcore.h"
3536

@@ -379,10 +380,17 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
379380
slave->mtd.name = name;
380381
slave->mtd.owner = master->owner;
381382

382-
/* NOTE: we don't arrange MTDs as a tree; it'd be error-prone
383-
* to have the same data be in two different partitions.
383+
/* NOTE: Historically, we didn't arrange MTDs as a tree out of
384+
* concern for showing the same data in multiple partitions.
385+
* However, it is very useful to have the master node present,
386+
* so the MTD_PARTITIONED_MASTER option allows that. The master
387+
* will have device nodes etc only if this is set, so make the
388+
* parent conditional on that option. Note, this is a way to
389+
* distinguish between the master and the partition in sysfs.
384390
*/
385-
slave->mtd.dev.parent = master->dev.parent;
391+
slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ?
392+
&master->dev :
393+
master->dev.parent;
386394

387395
slave->mtd._read = part_read;
388396
slave->mtd._write = part_write;
@@ -631,8 +639,8 @@ EXPORT_SYMBOL_GPL(mtd_del_partition);
631639
* and registers slave MTD objects which are bound to the master according to
632640
* the partition definitions.
633641
*
634-
* We don't register the master, or expect the caller to have done so,
635-
* for reasons of data integrity.
642+
* For historical reasons, this function's caller only registers the master
643+
* if the MTD_PARTITIONED_MASTER config option is set.
636644
*/
637645

638646
int add_mtd_partitions(struct mtd_info *master,

0 commit comments

Comments
 (0)