Skip to content

Commit

Permalink
mtd: part: Create the master device node when partitioned
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dan Ehrenberg authored and Brian Norris committed Apr 6, 2015
1 parent 9cd5196 commit 727dc61
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 21 deletions.
13 changes: 13 additions & 0 deletions drivers/mtd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,19 @@ config MTD_SWAP
The driver provides wear leveling by storing erase counter into the
OOB.

config MTD_PARTITIONED_MASTER
bool "Retain master device when partitioned"
default n
depends on MTD
help
For historical reasons, by default, either a master is present or
several partitions are present, but not both. The concern was that
data listed in multiple partitions was dangerous; however, SCSI does
this and it is frequently useful for applications. This config option
leaves the master in even if the device is partitioned. It also makes
the parent of the partition device be the master device, rather than
what lies behind the master.

source "drivers/mtd/chips/Kconfig"

source "drivers/mtd/maps/Kconfig"
Expand Down
52 changes: 36 additions & 16 deletions drivers/mtd/mtdcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/reboot.h>
#include <linux/kconfig.h>

#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
Expand Down Expand Up @@ -501,6 +502,29 @@ int del_mtd_device(struct mtd_info *mtd)
return ret;
}

static int mtd_add_device_partitions(struct mtd_info *mtd,
struct mtd_partition *real_parts,
int nbparts)
{
int ret;

if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
ret = add_mtd_device(mtd);
if (ret == 1)
return -ENODEV;
}

if (nbparts > 0) {
ret = add_mtd_partitions(mtd, real_parts, nbparts);
if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
del_mtd_device(mtd);
return ret;
}

return 0;
}


/**
* mtd_device_parse_register - parse partitions and register an MTD device.
*
Expand All @@ -523,7 +547,8 @@ int del_mtd_device(struct mtd_info *mtd)
* found this functions tries to fallback to information specified in
* @parts/@nr_parts.
* * If any partitioning info was found, this function registers the found
* partitions.
* partitions. If the MTD_PARTITIONED_MASTER option is set, then the device
* as a whole is registered first.
* * If no partitions were found this function just registers the MTD device
* @mtd and exits.
*
Expand All @@ -534,27 +559,21 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
const struct mtd_partition *parts,
int nr_parts)
{
int err;
struct mtd_partition *real_parts;
int ret;
struct mtd_partition *real_parts = NULL;

err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
if (err <= 0 && nr_parts && parts) {
ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
if (ret <= 0 && nr_parts && parts) {
real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
GFP_KERNEL);
if (!real_parts)
err = -ENOMEM;
ret = -ENOMEM;
else
err = nr_parts;
ret = nr_parts;
}

if (err > 0) {
err = add_mtd_partitions(mtd, real_parts, err);
kfree(real_parts);
} else if (err == 0) {
err = add_mtd_device(mtd);
if (err == 1)
err = -ENODEV;
}
if (ret >= 0)
ret = mtd_add_device_partitions(mtd, real_parts, ret);

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

return err;
kfree(real_parts);
return ret;
}
EXPORT_SYMBOL_GPL(mtd_device_parse_register);

Expand Down
18 changes: 13 additions & 5 deletions drivers/mtd/mtdpart.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/err.h>
#include <linux/kconfig.h>

#include "mtdcore.h"

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

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

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

int add_mtd_partitions(struct mtd_info *master,
Expand Down

0 comments on commit 727dc61

Please sign in to comment.