/*
- * $Id: mtd_blkdevs.c,v 1.22 2004/07/12 12:35:28 dwmw2 Exp $
+ * $Id: mtd_blkdevs.c,v 1.27 2005/11/07 11:14:20 gleixner Exp $
*
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
*
#include <linux/spinlock.h>
#include <linux/hdreg.h>
#include <linux/init.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
-#include <linux/devfs_fs_kernel.h>
static LIST_HEAD(blktrans_majors);
-extern struct semaphore mtd_table_mutex;
+extern struct mutex mtd_table_mutex;
extern struct mtd_info *mtd_table[];
struct mtd_blkcore_priv {
unsigned long block, nsect;
char *buf;
- block = req->sector;
- nsect = req->current_nr_sectors;
+ block = req->sector << 9 >> tr->blkshift;
+ nsect = req->current_nr_sectors << 9 >> tr->blkshift;
+
buf = req->buffer;
- if (!(req->flags & REQ_CMD))
+ if (!blk_fs_request(req))
return 0;
- if (block + nsect > get_capacity(req->rq_disk))
+ if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk))
return 0;
switch(rq_data_dir(req)) {
case READ:
- for (; nsect > 0; nsect--, block++, buf += 512)
+ for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->readsect(dev, block, buf))
return 0;
return 1;
if (!tr->writesect)
return 0;
- for (; nsect > 0; nsect--, block++, buf += 512)
+ for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->writesect(dev, block, buf))
return 0;
return 1;
default:
- printk(KERN_NOTICE "Unknown request %ld\n", rq_data_dir(req));
+ printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req));
return 0;
}
}
struct request_queue *rq = tr->blkcore_priv->rq;
/* we might get involved when memory gets low, so use PF_MEMALLOC */
- current->flags |= PF_MEMALLOC;
+ current->flags |= PF_MEMALLOC | PF_NOFREEZE;
daemonize("%sd", tr->name);
/* daemonize() doesn't do this for us since some kernel threads
- actually want to deal with signals. We can't just call
+ actually want to deal with signals. We can't just call
exit_sighand() since that'll cause an oops when we finally
do exit. */
spin_lock_irq(¤t->sighand->siglock);
spin_unlock_irq(¤t->sighand->siglock);
spin_lock_irq(rq->queue_lock);
-
+
while (!tr->blkcore_priv->exiting) {
struct request *req;
struct mtd_blktrans_dev *dev;
spin_unlock_irq(rq->queue_lock);
- down(&dev->sem);
+ mutex_lock(&dev->lock);
res = do_blktrans_request(tr, dev, req);
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
spin_lock_irq(rq->queue_lock);
}
-int blktrans_open(struct inode *i, struct file *f)
+static int blktrans_open(struct inode *i, struct file *f)
{
struct mtd_blktrans_dev *dev;
struct mtd_blktrans_ops *tr;
if (!try_module_get(tr->owner))
goto out_tr;
- /* FIXME: Locking. A hot pluggable device can go away
+ /* 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++;
return ret;
}
-int blktrans_release(struct inode *i, struct file *f)
+static int blktrans_release(struct inode *i, struct file *f)
{
struct mtd_blktrans_dev *dev;
struct mtd_blktrans_ops *tr;
return ret;
}
+static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
+
+ if (dev->tr->getgeo)
+ return dev->tr->getgeo(dev, geo);
+ return -ENOTTY;
+}
-static int blktrans_ioctl(struct inode *inode, struct file *file,
+static int blktrans_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data;
return tr->flush(dev);
/* The core code did the work, we had nothing to do. */
return 0;
-
- case HDIO_GETGEO:
- if (tr->getgeo) {
- struct hd_geometry g;
- int ret;
-
- memset(&g, 0, sizeof(g));
- ret = tr->getgeo(dev, &g);
- if (ret)
- return ret;
-
- g.start = get_start_sect(inode->i_bdev);
- if (copy_to_user((void __user *)arg, &g, sizeof(g)))
- return -EFAULT;
- return 0;
- } /* else */
default:
return -ENOTTY;
}
.open = blktrans_open,
.release = blktrans_release,
.ioctl = blktrans_ioctl,
+ .getgeo = blktrans_getgeo,
};
int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
int last_devnum = -1;
struct gendisk *gd;
- if (!down_trylock(&mtd_table_mutex)) {
- up(&mtd_table_mutex);
+ if (!!mutex_trylock(&mtd_table_mutex)) {
+ mutex_unlock(&mtd_table_mutex);
BUG();
}
/* Required number was free */
list_add_tail(&new->list, &d->list);
goto added;
- }
+ }
last_devnum = d->devnum;
}
if (new->devnum == -1)
return -EBUSY;
}
- init_MUTEX(&new->sem);
+ mutex_init(&new->lock);
list_add_tail(&new->list, &tr->devs);
added:
if (!tr->writesect)
gd->major = tr->major;
gd->first_minor = (new->devnum) << tr->part_bits;
gd->fops = &mtd_blktrans_ops;
-
- snprintf(gd->disk_name, sizeof(gd->disk_name),
- "%s%c", tr->name, (tr->part_bits?'a':'0') + new->devnum);
- snprintf(gd->devfs_name, sizeof(gd->devfs_name),
- "%s/%c", tr->name, (tr->part_bits?'a':'0') + new->devnum);
+
+ if (tr->part_bits)
+ if (new->devnum < 26)
+ snprintf(gd->disk_name, sizeof(gd->disk_name),
+ "%s%c", tr->name, 'a' + new->devnum);
+ else
+ snprintf(gd->disk_name, sizeof(gd->disk_name),
+ "%s%c%c", tr->name,
+ 'a' - 1 + new->devnum / 26,
+ 'a' + new->devnum % 26);
+ else
+ snprintf(gd->disk_name, sizeof(gd->disk_name),
+ "%s%d", tr->name, new->devnum);
/* 2.5 has capacity in units of 512 bytes while still
having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */
- set_capacity(gd, (new->size * new->blksize) >> 9);
+ set_capacity(gd, (new->size * tr->blksize) >> 9);
gd->private_data = new;
new->blkcore_priv = gd;
set_disk_ro(gd, 1);
add_disk(gd);
-
+
return 0;
}
int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
{
- if (!down_trylock(&mtd_table_mutex)) {
- up(&mtd_table_mutex);
+ if (!!mutex_trylock(&mtd_table_mutex)) {
+ mutex_unlock(&mtd_table_mutex);
BUG();
}
del_gendisk(old->blkcore_priv);
put_disk(old->blkcore_priv);
-
+
return 0;
}
-void blktrans_notify_remove(struct mtd_info *mtd)
+static void blktrans_notify_remove(struct mtd_info *mtd)
{
struct list_head *this, *this2, *next;
}
}
-void blktrans_notify_add(struct mtd_info *mtd)
+static void blktrans_notify_add(struct mtd_info *mtd)
{
struct list_head *this;
.add = blktrans_notify_add,
.remove = blktrans_notify_remove,
};
-
+
int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
{
int ret, i;
- /* Register the notifier if/when the first device type is
+ /* Register the notifier if/when the first device type is
registered, to prevent the link/init ordering from fucking
us over. */
if (!blktrans_notifier.list.next)
register_mtd_user(&blktrans_notifier);
- tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
+ tr->blkcore_priv = kzalloc(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);
+ mutex_lock(&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);
+ mutex_unlock(&mtd_table_mutex);
return ret;
}
spin_lock_init(&tr->blkcore_priv->queue_lock);
if (!tr->blkcore_priv->rq) {
unregister_blkdev(tr->major, tr->name);
kfree(tr->blkcore_priv);
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return -ENOMEM;
}
tr->blkcore_priv->rq->queuedata = tr;
+ blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize);
+ tr->blkshift = ffs(tr->blksize) - 1;
ret = kernel_thread(mtd_blktrans_thread, tr, CLONE_KERNEL);
if (ret < 0) {
blk_cleanup_queue(tr->blkcore_priv->rq);
unregister_blkdev(tr->major, tr->name);
kfree(tr->blkcore_priv);
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return ret;
- }
-
- devfs_mk_dir(tr->name);
+ }
INIT_LIST_HEAD(&tr->devs);
list_add(&tr->list, &blktrans_majors);
tr->add_mtd(tr, mtd_table[i]);
}
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return 0;
}
{
struct list_head *this, *next;
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
/* Clean up the kernel thread */
tr->blkcore_priv->exiting = 1;
tr->remove_dev(dev);
}
- devfs_remove(tr->name);
blk_cleanup_queue(tr->blkcore_priv->rq);
unregister_blkdev(tr->major, tr->name);
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
kfree(tr->blkcore_priv);
- if (!list_empty(&tr->devs))
- BUG();
+ BUG_ON(!list_empty(&tr->devs));
return 0;
}