mtd/drivers/mtd mtd_blkdevs.c,1.11,1.12
David Woodhouse
dwmw2 at infradead.org
Tue May 20 21:01:02 EDT 2003
Update of /home/cvs/mtd/drivers/mtd
In directory phoenix.infradead.org:/tmp/cvs-serv20708/drivers/mtd
Modified Files:
mtd_blkdevs.c
Log Message:
clean up open, release and ioctl to avoid lookups and locking
Index: mtd_blkdevs.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/mtd_blkdevs.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- mtd_blkdevs.c 20 May 2003 22:29:08 -0000 1.11
+++ mtd_blkdevs.c 21 May 2003 01:00:59 -0000 1.12
@@ -27,44 +27,14 @@
extern struct semaphore mtd_table_mutex;
extern struct mtd_info *mtd_table[];
-static struct request_queue mtd_blktrans_queue;
-static spinlock_t mtd_blktrans_queue_lock;
-
struct mtd_blkcore_priv {
struct completion thread_dead;
int exiting;
wait_queue_head_t thread_wq;
+ struct request_queue rq;
+ spinlock_t queue_lock;
};
-static inline struct mtd_blktrans_dev *tr_get_dev(struct mtd_blktrans_ops *tr,
- int devnum)
-{
- struct list_head *this;
- struct mtd_blktrans_dev *d;
-
- list_for_each(this, &tr->devs) {
- d = list_entry(this, struct mtd_blktrans_dev, list);
-
- if (d->devnum == devnum)
- return d;
- }
- return NULL;
-}
-
-static inline struct mtd_blktrans_ops *get_tr(int major)
-{
- struct list_head *this;
- struct mtd_blktrans_ops *t;
-
- list_for_each(this, &blktrans_majors) {
- t = list_entry(this, struct mtd_blktrans_ops, list);
-
- if (t->major == major)
- return t;
- }
- return NULL;
-}
-
static int do_blktrans_request(struct mtd_blktrans_ops *tr,
struct mtd_blktrans_dev *dev,
struct request *req)
@@ -107,7 +77,7 @@
static int mtd_blktrans_thread(void *arg)
{
struct mtd_blktrans_ops *tr = arg;
- struct request_queue *rq = &mtd_blktrans_queue;
+ struct request_queue *rq = &tr->blkcore_priv->rq;
/* we might get involved when memory gets low, so use PF_MEMALLOC */
current->flags |= PF_MEMALLOC;
@@ -170,61 +140,32 @@
int blktrans_open(struct inode *i, struct file *f)
{
- struct mtd_blktrans_ops *tr = NULL;
- struct mtd_blktrans_dev *dev = NULL;
- int major_nr = major(i->i_rdev);
- int minor_nr = minor(i->i_rdev);
- int devnum;
+ struct mtd_blktrans_dev *dev;
+ struct mtd_blktrans_ops *tr;
int ret = -ENODEV;
-#if 0 /* Do we still have to do this in 2.5? Hopefully not since I don't
- see how */
- if (is_read_only(i->i_rdev) && (f->f_mode & FMODE_WRITE))
- return -EROFS;
-#endif
-
- down(&mtd_table_mutex);
-
- tr = get_tr(major_nr);
+ dev = i->i_bdev->bd_disk->private_data;
+ tr = dev->tr;
- if (!tr)
- goto out;
-
- devnum = minor_nr >> tr->part_bits;
-
- dev = tr_get_dev(tr, devnum);
-
- if (!dev)
- goto out;
-
-#if 0 /* Does it prevent us from opening a partition which doesn't exist */
- if (!tr->blkcore_priv->part_table[minor_nr].nr_sects) {
- ret = -ENODEV;
- goto out;
- }
-#endif
if (!try_module_get(dev->mtd->owner))
goto out;
if (!try_module_get(tr->owner))
goto out_tr;
+ /* FIXME: Locking. A hot pluggable device can go away
+ (del_mtd_device can be called for it) without its module
+ being unloaded. */
dev->mtd->usecount++;
- dev->usecount++;
- tr->usecount++;
ret = 0;
if (tr->open && (ret = tr->open(dev, i, f))) {
- tr->usecount--;
- dev->usecount--;
dev->mtd->usecount--;
module_put(dev->mtd->owner);
out_tr:
module_put(tr->owner);
}
out:
- up(&mtd_table_mutex);
-
return ret;
}
@@ -233,36 +174,18 @@
struct mtd_blktrans_dev *dev;
struct mtd_blktrans_ops *tr;
int ret = 0;
- int devnum;
- down(&mtd_table_mutex);
-
- tr = get_tr(major(i->i_rdev));
- if (!tr) {
- up(&mtd_table_mutex);
- return -ENODEV;
- }
-
- devnum = minor(i->i_rdev) >> tr->part_bits;
- dev = tr_get_dev(tr, devnum);
-
- if (!dev) {
- up(&mtd_table_mutex);
- return -ENODEV;
- }
+ dev = i->i_bdev->bd_disk->private_data;
+ tr = dev->tr;
if (tr->release)
ret = tr->release(dev, i, f);
if (!ret) {
- tr->usecount--;
- dev->usecount--;
dev->mtd->usecount--;
module_put(dev->mtd->owner);
module_put(tr->owner);
}
-
- up(&mtd_table_mutex);
return ret;
}
@@ -273,24 +196,10 @@
{
struct mtd_blktrans_dev *dev;
struct mtd_blktrans_ops *tr;
- int devnum;
int ret = -ENOTTY;
- down(&mtd_table_mutex);
-
- tr = get_tr(major(inode->i_rdev));
- if (!tr) {
- up(&mtd_table_mutex);
- return -ENODEV;
- }
-
- devnum = minor(inode->i_rdev) >> tr->part_bits;
- dev = tr_get_dev(tr, devnum);
-
- up(&mtd_table_mutex);
-
- if (!dev)
- return -ENODEV;
+ dev = inode->i_bdev->bd_disk->private_data;
+ tr = dev->tr;
if (tr->ioctl)
ret = tr->ioctl(dev, inode, file, cmd, arg);
@@ -351,8 +260,6 @@
init_MUTEX(&new->sem);
list_add_tail(&new->list, &tr->devs);
added:
- new->usecount = 0;
-
if (!tr->writesect)
new->readonly = 1;
@@ -373,7 +280,7 @@
set_capacity(gd, new->size);
gd->private_data = new;
new->blkcore_priv = gd;
- gd->queue = &mtd_blktrans_queue;
+ gd->queue = &tr->blkcore_priv->rq;
if (new->readonly)
set_disk_ro(gd, 1);
@@ -390,9 +297,6 @@
BUG();
}
- if (old->usecount)
- return -EBUSY;
-
list_del(&old->list);
del_gendisk(old->blkcore_priv);
@@ -424,6 +328,8 @@
if (mtd->type == MTD_ABSENT)
return;
+ printk("%s:%s %d: count %d\n", __FILE__, __func__, __LINE__, atomic_read(&mtd_table_mutex.count));
+
list_for_each(this, &blktrans_majors) {
struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
@@ -447,35 +353,47 @@
if (!blktrans_notifier.list.next)
register_mtd_user(&blktrans_notifier);
+ tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
+ if (!tr->blkcore_priv)
+ return -ENOMEM;
+
+ memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv));
+
down(&mtd_table_mutex);
ret = register_blkdev(tr->major, tr->name);
if (ret) {
printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
tr->name, tr->major, ret);
+ kfree(tr->blkcore_priv);
up(&mtd_table_mutex);
return ret;
}
- blk_init_queue(&mtd_blktrans_queue, mtd_blktrans_request,
- &mtd_blktrans_queue_lock);
-
+ spin_lock_init(&tr->blkcore_priv->queue_lock);
init_completion(&tr->blkcore_priv->thread_dead);
init_waitqueue_head(&tr->blkcore_priv->thread_wq);
+ blk_init_queue(&tr->blkcore_priv->rq, mtd_blktrans_request,
+ &tr->blkcore_priv->queue_lock);
+ tr->blkcore_priv->rq.queuedata = tr;
+
ret = kernel_thread(mtd_blktrans_thread, tr,
CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
if (ret < 0) {
- blk_cleanup_queue(&mtd_blktrans_queue);
+ blk_cleanup_queue(&tr->blkcore_priv->rq);
unregister_blkdev(tr->major, tr->name);
+ kfree(tr->blkcore_priv);
+ up(&mtd_table_mutex);
return ret;
- }
+ }
devfs_mk_dir(tr->name);
- tr->usecount = 0;
INIT_LIST_HEAD(&tr->devs);
list_add(&tr->list, &blktrans_majors);
+ printk("%s:%s %d: count %d\n", __FILE__, __func__, __LINE__, atomic_read(&mtd_table_mutex.count));
+
for (i=0; i<MAX_MTD_DEVICES; i++) {
if (mtd_table[i] && mtd_table[i]->type != MTD_ABSENT)
tr->add_mtd(tr, mtd_table[i]);
@@ -492,12 +410,6 @@
down(&mtd_table_mutex);
- if (tr->usecount) {
- up(&mtd_table_mutex);
- return -EBUSY;
- }
-
-
/* Clean up the kernel thread */
tr->blkcore_priv->exiting = 1;
wake_up(&tr->blkcore_priv->thread_wq);
@@ -512,11 +424,13 @@
}
devfs_remove(tr->name);
- blk_cleanup_queue(&mtd_blktrans_queue);
+ blk_cleanup_queue(&tr->blkcore_priv->rq);
unregister_blkdev(tr->major, tr->name);
up(&mtd_table_mutex);
+ kfree(tr->blkcore_priv);
+
if (!list_empty(&tr->devs))
BUG();
return 0;
@@ -531,6 +445,11 @@
}
module_exit(mtd_blktrans_exit);
+
+EXPORT_SYMBOL_GPL(register_mtd_blktrans);
+EXPORT_SYMBOL_GPL(deregister_mtd_blktrans);
+EXPORT_SYMBOL_GPL(add_mtd_blktrans_dev);
+EXPORT_SYMBOL_GPL(del_mtd_blktrans_dev);
MODULE_AUTHOR("David Woodhouse <dwmw2 at infradead.org>");
MODULE_LICENSE("GPL");
More information about the linux-mtd-cvs
mailing list