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