Patchwork [2/4] mtd: add the possibility to modify partitions in runtime

login
register
mail settings
Submitter Roman Tereshonkov
Date June 18, 2010, 10:08 a.m.
Message ID <1276855711-18570-3-git-send-email-roman.tereshonkov@nokia.com>
Download mbox | patch
Permalink /patch/56162/
State New
Headers show

Comments

Roman Tereshonkov - June 18, 2010, 10:08 a.m.
This includes adding locks, appropriate memory handling and function
to get the master device for given partition.

Signed-off-by: Roman Tereshonkov <roman.tereshonkov@nokia.com>
---
 drivers/mtd/mtdpart.c          |   45 ++++++++++++++++++++++++++++++++++-----
 include/linux/mtd/partitions.h |    2 +
 2 files changed, 41 insertions(+), 6 deletions(-)

Patch

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index b8043a9..595d270 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -21,6 +21,7 @@ 
 
 /* Our partition linked list */
 static LIST_HEAD(mtd_partitions);
+static DEFINE_MUTEX(mtd_partitions_mutex);
 
 /* Our partition node structure */
 struct mtd_part {
@@ -309,21 +310,30 @@  static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
 /*
  * This function unregisters and destroy all slave MTD objects which are
- * attached to the given master MTD object.
+ * attached to the given master MTD object and which are possible to be
+ * deleted (usercount==0).
  */
 
 int del_mtd_partitions(struct mtd_info *master)
 {
 	struct mtd_part *slave, *next;
+	int ret, err = 0;
 
+	mutex_lock(&mtd_partitions_mutex);
 	list_for_each_entry_safe(slave, next, &mtd_partitions, list)
 		if (slave->master == master) {
+			ret = del_mtd_device(&slave->mtd);
+			if (ret < 0) {
+				err = ret;
+				continue;
+			}
 			list_del(&slave->list);
-			del_mtd_device(&slave->mtd);
+			kfree(slave->mtd.name);
 			kfree(slave);
 		}
+	mutex_unlock(&mtd_partitions_mutex);
 
-	return 0;
+	return err;
 }
 EXPORT_SYMBOL(del_mtd_partitions);
 
@@ -332,16 +342,19 @@  static struct mtd_part *add_one_partition(struct mtd_info *master,
 		uint64_t cur_offset)
 {
 	struct mtd_part *slave;
+	char *name;
 
 	/* allocate the partition structure */
 	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
-	if (!slave) {
+	name = kstrdup(part->name, GFP_KERNEL);
+	if (!name || !slave) {
 		printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
 			master->name);
 		del_mtd_partitions(master);
+		kfree(name);
+		kfree(slave);
 		return NULL;
 	}
-	list_add(&slave->list, &mtd_partitions);
 
 	/* set up the MTD object for this partition */
 	slave->mtd.type = master->type;
@@ -352,7 +365,7 @@  static struct mtd_part *add_one_partition(struct mtd_info *master,
 	slave->mtd.oobavail = master->oobavail;
 	slave->mtd.subpage_sft = master->subpage_sft;
 
-	slave->mtd.name = part->name;
+	slave->mtd.name = name;
 	slave->mtd.owner = master->owner;
 	slave->mtd.backing_dev_info = master->backing_dev_info;
 
@@ -497,6 +510,9 @@  static struct mtd_part *add_one_partition(struct mtd_info *master,
 	}
 
 out_register:
+	mutex_lock(&mtd_partitions_mutex);
+	list_add(&slave->list, &mtd_partitions);
+	mutex_unlock(&mtd_partitions_mutex);
 	/* register our partition */
 	add_mtd_device(&slave->mtd);
 
@@ -597,3 +613,20 @@  int parse_mtd_partitions(struct mtd_info *master, const char **types,
 	return ret;
 }
 EXPORT_SYMBOL_GPL(parse_mtd_partitions);
+
+struct mtd_info *part_get_mtd_master(struct mtd_info *mtd)
+{
+	struct mtd_part *part;
+	struct mtd_info *master = NULL;
+
+	mutex_lock(&mtd_partitions_mutex);
+	list_for_each_entry(part, &mtd_partitions, list)
+		if (&part->mtd == mtd) {
+			master = part->master;
+			break;
+		}
+	mutex_unlock(&mtd_partitions_mutex);
+
+	return master;
+}
+EXPORT_SYMBOL(part_get_mtd_master);
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 274b619..942c425 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -89,4 +89,6 @@  static inline int mtd_has_cmdlinepart(void) { return 1; }
 static inline int mtd_has_cmdlinepart(void) { return 0; }
 #endif
 
+struct mtd_info *part_get_mtd_master(struct mtd_info *mtd);
+
 #endif