mtd/drivers/mtd mtdcore.c,1.34,1.35 mtdpart.c,1.34,1.35

David Woodhouse dwmw2 at infradead.org
Wed May 14 18:27:00 EDT 2003


Update of /home/cvs/mtd/drivers/mtd
In directory phoenix.infradead.org:/tmp/cvs-serv14262/drivers/mtd

Modified Files:
	mtdcore.c mtdpart.c 
Log Message:
fix races in get_mtd_device etc, use set_module_owner everywhere

Index: mtdcore.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/mtdcore.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -r1.34 -r1.35
--- mtdcore.c	24 Jan 2003 23:32:25 -0000	1.34
+++ mtdcore.c	14 May 2003 22:26:27 -0000	1.35
@@ -26,7 +26,7 @@
 
 static DECLARE_MUTEX(mtd_table_mutex);
 static struct mtd_info *mtd_table[MAX_MTD_DEVICES];
-static struct mtd_notifier *mtd_notifiers = NULL;
+static LIST_HEAD(mtd_notifiers);
 
 /**
  *	add_mtd_device - register an MTD device
@@ -44,21 +44,28 @@
 
 	down(&mtd_table_mutex);
 
-	for (i=0; i< MAX_MTD_DEVICES; i++)
-		if (!mtd_table[i])
-		{
-			struct mtd_notifier *not=mtd_notifiers;
+	for (i=0; i < MAX_MTD_DEVICES; i++)
+		if (!mtd_table[i]) {
+			struct list_head *this;
 
 			mtd_table[i] = mtd;
 			mtd->index = i;
+			mtd->usecount = 0;
+
 			DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name);
-			while (not)
-			{
-				(*(not->add))(mtd);
-				not = not->next;
+			/* No need to get a refcount on the module containing
+			   the notifier, since we hold the mtd_table_mutex */
+			list_for_each(this, &mtd_notifiers) {
+				struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
+				not->add(mtd);
 			}
+			
 			up(&mtd_table_mutex);
-			MOD_INC_USE_COUNT;
+			/* We _know_ we aren't being removed, because
+			   our caller is still holding us here. So none
+			   of this try_ nonsense, and no bitching about it
+			   either. :) */
+			__module_get(THIS_MODULE);
 			return 0;
 		}
 	
@@ -78,29 +85,34 @@
 
 int del_mtd_device (struct mtd_info *mtd)
 {
-	struct mtd_notifier *not=mtd_notifiers;
-	int i;
+	int ret;
 	
 	down(&mtd_table_mutex);
 
-	for (i=0; i < MAX_MTD_DEVICES; i++)
-	{
-		if (mtd_table[i] == mtd)
-		{
-			while (not)
-			{
-				(*(not->remove))(mtd);
-				not = not->next;
-			}
-			mtd_table[i] = NULL;
-			up (&mtd_table_mutex);
-			MOD_DEC_USE_COUNT;
-			return 0;
+	if (mtd_table[mtd->index] != mtd) {
+		ret = -ENODEV;
+	} else if (mtd->usecount) {
+		printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", 
+		       mtd->index, mtd->name, mtd->usecount);
+		ret = -EBUSY;
+	} else {
+		struct list_head *this;
+
+		/* No need to get a refcount on the module containing
+		   the notifier, since we hold the mtd_table_mutex */
+		list_for_each(this, &mtd_notifiers) {
+			struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
+			not->remove(mtd);
 		}
+
+		mtd_table[mtd->index] = NULL;
+
+		module_put(THIS_MODULE);
+		ret = 0;
 	}
 
 	up(&mtd_table_mutex);
-	return 1;
+	return ret;
 }
 
 /**
@@ -118,10 +130,9 @@
 
 	down(&mtd_table_mutex);
 
-	new->next = mtd_notifiers;
-	mtd_notifiers = new;
+	list_add(&mtd_notifiers, &new->list);
 
- 	MOD_INC_USE_COUNT;
+ 	__module_get(THIS_MODULE);
 	
 	for (i=0; i< MAX_MTD_DEVICES; i++)
 		if (mtd_table[i])
@@ -142,34 +153,24 @@
 
 int unregister_mtd_user (struct mtd_notifier *old)
 {
-	struct mtd_notifier **prev = &mtd_notifiers;
-	struct mtd_notifier *cur;
 	int i;
 
 	down(&mtd_table_mutex);
 
-	while ((cur = *prev)) {
-		if (cur == old) {
-			*prev = cur->next;
-
-			MOD_DEC_USE_COUNT;
-
-			for (i=0; i< MAX_MTD_DEVICES; i++)
-				if (mtd_table[i])
-					old->remove(mtd_table[i]);
+	module_put(THIS_MODULE);
+
+	for (i=0; i< MAX_MTD_DEVICES; i++)
+		if (mtd_table[i])
+			old->remove(mtd_table[i]);
 			
-			up(&mtd_table_mutex);
-			return 0;
-		}
-		prev = &cur->next;
-	}
+	list_del(&old->list);
 	up(&mtd_table_mutex);
-	return 1;
+	return 0;
 }
 
 
 /**
- *	__get_mtd_device - obtain a validated handle for an MTD device
+ *	___get_mtd_device - obtain a validated handle for an MTD device
  *	@mtd: last known address of the required MTD device
  *	@num: internal device number of the required MTD device
  *
@@ -181,7 +182,7 @@
  *	__get_mtd_device() doesn't - you should generally use get_mtd_device().
  */
 	
-struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num)
+struct mtd_info *___get_mtd_device(struct mtd_info *mtd, int num, int count)
 {
 	struct mtd_info *ret = NULL;
 	int i;
@@ -197,11 +198,28 @@
 		if (mtd && mtd != ret)
 			ret = NULL;
 	}
+	if (count) {
+		if (ret && !try_module_get(ret->owner))
+			ret = NULL;
 	
+		if (ret)
+			ret->usecount++;
+	}
 	up(&mtd_table_mutex);
 	return ret;
 }
 
+void put_mtd_device(struct mtd_info *mtd)
+{
+	int c;
+
+	down(&mtd_table_mutex);
+	c = --mtd->usecount;
+	up(&mtd_table_mutex);
+	BUG_ON(c < 0);
+
+	module_put(mtd->owner);
+}
 
 /* default_mtd_writev - default mtd writev method for MTD devices that
  *			dont implement their own
@@ -265,7 +283,8 @@
 
 EXPORT_SYMBOL(add_mtd_device);
 EXPORT_SYMBOL(del_mtd_device);
-EXPORT_SYMBOL(__get_mtd_device);
+EXPORT_SYMBOL(___get_mtd_device);
+EXPORT_SYMBOL(put_mtd_device);
 EXPORT_SYMBOL(register_mtd_user);
 EXPORT_SYMBOL(unregister_mtd_user);
 EXPORT_SYMBOL(default_mtd_writev);

Index: mtdpart.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/mtdpart.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -r1.34 -r1.35
--- mtdpart.c	18 Feb 2003 20:53:53 -0000	1.34
+++ mtdpart.c	14 May 2003 22:26:27 -0000	1.35
@@ -348,7 +348,7 @@
 
 		slave->mtd.name = parts[i].name;
 		slave->mtd.bank_size = master->bank_size;
-		slave->mtd.module = master->module;
+		slave->mtd.owner = master->owner;
 
 		slave->mtd.read = part_read;
 		slave->mtd.write = part_write;




More information about the linux-mtd-cvs mailing list