mtd/drivers/mtd mtd_blkdevs.c,1.5,1.6

David Woodhouse dwmw2 at infradead.org
Sun May 18 14:21:47 EDT 2003


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

Modified Files:
	mtd_blkdevs.c 
Log Message:
fix devs list locking _without_ deadlocking in grok_partitions()


Index: mtd_blkdevs.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/mtd_blkdevs.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- mtd_blkdevs.c	18 May 2003 17:42:12 -0000	1.5
+++ mtd_blkdevs.c	18 May 2003 18:21:44 -0000	1.6
@@ -17,6 +17,7 @@
 #include <linux/blkdev.h>
 #include <linux/blk.h>
 #include <linux/blkpg.h>
+#include <linux/spinlock.h>
 #include <asm/semaphore.h>
 #include <linux/mtd/compatmac.h>
 
@@ -30,6 +31,7 @@
 	int sizes[256];
 	struct hd_struct part_table[256];
 	struct gendisk gd;
+	spinlock_t devs_lock; /* See comment in _request function */
 };
 
 static inline struct mtd_blktrans_dev *tr_get_dev(struct mtd_blktrans_ops *tr,
@@ -126,12 +128,14 @@
 		spin_unlock_irq(&io_request_lock);
 
 		/* FIXME: Where can we store the dev, on which
-		   we already have a refcount anyway? This deadlocks
-		   with grok_partitions called from the registration
+		   we already have a refcount anyway? We need to
+		   lock against concurrent addition/removal of devices,
+		   but if we use the mtd_table_mutex we deadlock when
+		   grok_partitions is called from the registration
 		   callbacks. */
-//		down(&mtd_table_mutex);
+		spin_lock(&tr->blkcore_priv->devs_lock);
 		dev = tr_get_dev(tr, devnum);
-//		up(&mtd_table_mutex);
+		spin_unlock(&tr->blkcore_priv->devs_lock);
 
 		if (!dev) {
 			/* We'd BUG() but it's rude to do so when we know
@@ -355,7 +359,9 @@
 		up(&mtd_table_mutex);
 		BUG();
 	}
-	
+
+	spin_lock(&tr->blkcore_priv->devs_lock);
+
 	list_for_each(this, &tr->devs) {
 		struct mtd_blktrans_dev *d = list_entry(this, struct mtd_blktrans_dev, list);
 		if (new->devnum == -1) {
@@ -368,6 +374,7 @@
 			}
 		} else if (d->devnum == new->devnum) {
 			/* Required number taken */
+			spin_unlock(&tr->blkcore_priv->devs_lock);
 			return -EBUSY;
 		} else if (d->devnum > new->devnum) {
 			/* Required number was free */
@@ -379,12 +386,15 @@
 	if (new->devnum == -1)
 		new->devnum = last_devnum+1;
 
-	if ((new->devnum << tr->part_bits) > 256)
+	if ((new->devnum << tr->part_bits) > 256) {
+		spin_unlock(&tr->blkcore_priv->devs_lock);
 		return -EBUSY;
+	}
 
 	init_MUTEX(&new->sem);
 	list_add_tail(&new->list, &tr->devs);
  added:
+	spin_unlock(&tr->blkcore_priv->devs_lock);
 	new->usecount = 0;
 	tr->blkcore_priv->sizes[new->devnum << tr->part_bits] = new->size;
 	tr->blkcore_priv->gd.nr_real++;
@@ -410,7 +420,9 @@
 	if (old->usecount)
 		return -EBUSY;
 
+	spin_lock(&tr->blkcore_priv->devs_lock);
 	list_del(&old->list);
+	spin_unlock(&tr->blkcore_priv->devs_lock);
 	tr->blkcore_priv->gd.nr_real--;
 	tr->blkcore_priv->sizes[old->devnum << tr->part_bits] = 0;
 
@@ -496,6 +508,8 @@
 	tr->blkcore_priv->gd.max_p = (1<<tr->part_bits) - 1;
 	tr->blkcore_priv->gd.part = tr->blkcore_priv->part_table;
 	tr->blkcore_priv->gd.sizes = tr->blkcore_priv->sizes;
+
+	spin_lock_init(&tr->blkcore_priv->devs_lock);
 
 	add_gendisk(&tr->blkcore_priv->gd);
 




More information about the linux-mtd-cvs mailing list