Commit ac8fc838 authored by Alexander Viro's avatar Alexander Viro Committed by James Bottomley

[PATCH] mtdblock (based on a patch from rmk)

	* switched to private queues
	* set ->queue
parent 836d901c
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/compatmac.h> #include <linux/mtd/compatmac.h>
#include <linux/buffer_head.h>
#define MAJOR_NR MTD_BLOCK_MAJOR #define MAJOR_NR MTD_BLOCK_MAJOR
#define DEVICE_NAME "mtdblock" #define DEVICE_NAME "mtdblock"
...@@ -23,6 +24,10 @@ ...@@ -23,6 +24,10 @@
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
static devfs_handle_t devfs_dir_handle = NULL;
static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES];
#endif
static void mtd_notify_add(struct mtd_info* mtd); static void mtd_notify_add(struct mtd_info* mtd);
static void mtd_notify_remove(struct mtd_info* mtd); static void mtd_notify_remove(struct mtd_info* mtd);
static struct mtd_notifier notifier = { static struct mtd_notifier notifier = {
...@@ -30,9 +35,6 @@ static struct mtd_notifier notifier = { ...@@ -30,9 +35,6 @@ static struct mtd_notifier notifier = {
mtd_notify_remove, mtd_notify_remove,
NULL NULL
}; };
static devfs_handle_t devfs_dir_handle = NULL;
static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES];
#endif
static struct mtdblk_dev { static struct mtdblk_dev {
struct mtd_info *mtd; /* Locked */ struct mtd_info *mtd; /* Locked */
...@@ -42,9 +44,10 @@ static struct mtdblk_dev { ...@@ -42,9 +44,10 @@ static struct mtdblk_dev {
unsigned long cache_offset; unsigned long cache_offset;
unsigned int cache_size; unsigned int cache_size;
enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
struct gendisk *disk;
} *mtdblks[MAX_MTD_DEVICES]; } *mtdblks[MAX_MTD_DEVICES];
static struct gendisk *mtddisk[MAX_MTD_DEVICES];
static spinlock_t mtdblks_lock; static spinlock_t mtdblks_lock;
/* /*
...@@ -295,7 +298,7 @@ static int mtdblock_open(struct inode *inode, struct file *file) ...@@ -295,7 +298,7 @@ static int mtdblock_open(struct inode *inode, struct file *file)
spin_unlock(&mtdblks_lock); spin_unlock(&mtdblks_lock);
mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
disk = alloc_disk(1); disk = mtddisk[dev];
if (!mtdblk || !disk) if (!mtdblk || !disk)
goto Enomem; goto Enomem;
memset(mtdblk, 0, sizeof(*mtdblk)); memset(mtdblk, 0, sizeof(*mtdblk));
...@@ -311,11 +314,6 @@ static int mtdblock_open(struct inode *inode, struct file *file) ...@@ -311,11 +314,6 @@ static int mtdblock_open(struct inode *inode, struct file *file)
if (!mtdblk->cache_data) if (!mtdblk->cache_data)
goto Enomem; goto Enomem;
} }
disk->major = MAJOR_NR;
disk->first_minor = dev;
disk->fops = &mtd_fops;
sprintf(disk->disk_name, "mtd%d", dev);
mtdblk->disk = disk;
/* OK, we've created a new one. Add it to the list. */ /* OK, we've created a new one. Add it to the list. */
...@@ -328,13 +326,10 @@ static int mtdblock_open(struct inode *inode, struct file *file) ...@@ -328,13 +326,10 @@ static int mtdblock_open(struct inode *inode, struct file *file)
put_mtd_device(mtdblk->mtd); put_mtd_device(mtdblk->mtd);
vfree(mtdblk->cache_data); vfree(mtdblk->cache_data);
kfree(mtdblk); kfree(mtdblk);
put_disk(disk);
return 0; return 0;
} }
mtdblks[dev] = mtdblk; mtdblks[dev] = mtdblk;
set_capacity(disk, mtdblk->mtd->size/512);
add_disk(disk);
set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE)); set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE));
spin_unlock(&mtdblks_lock); spin_unlock(&mtdblks_lock);
...@@ -344,7 +339,6 @@ static int mtdblock_open(struct inode *inode, struct file *file) ...@@ -344,7 +339,6 @@ static int mtdblock_open(struct inode *inode, struct file *file)
return 0; return 0;
Enomem: Enomem:
put_mtd_device(mtd); put_mtd_device(mtd);
put_disk(disk);
kfree(mtdblk); kfree(mtdblk);
return -ENOMEM; return -ENOMEM;
} }
...@@ -370,8 +364,6 @@ static release_t mtdblock_release(struct inode *inode, struct file *file) ...@@ -370,8 +364,6 @@ static release_t mtdblock_release(struct inode *inode, struct file *file)
/* It was the last usage. Free the device */ /* It was the last usage. Free the device */
mtdblks[dev] = NULL; mtdblks[dev] = NULL;
spin_unlock(&mtdblks_lock); spin_unlock(&mtdblks_lock);
del_gendisk(mtdblk->disk);
put_disk(mtdblk->disk);
if (mtdblk->mtd->sync) if (mtdblk->mtd->sync)
mtdblk->mtd->sync(mtdblk->mtd); mtdblk->mtd->sync(mtdblk->mtd);
put_mtd_device(mtdblk->mtd); put_mtd_device(mtdblk->mtd);
...@@ -394,18 +386,15 @@ static release_t mtdblock_release(struct inode *inode, struct file *file) ...@@ -394,18 +386,15 @@ static release_t mtdblock_release(struct inode *inode, struct file *file)
* The head of our request queue is considered active so there is no need * The head of our request queue is considered active so there is no need
* to dequeue requests before we are done. * to dequeue requests before we are done.
*/ */
static struct request_queue mtd_queue;
static void handle_mtdblock_request(void) static void handle_mtdblock_request(void)
{ {
struct request *req;
struct mtdblk_dev *mtdblk; struct mtdblk_dev *mtdblk;
unsigned int res; unsigned int res;
for (;;) { while (!blk_queue_empty(&mtd_queue)) {
if (blk_queue_empty(QUEUE)) struct request *req = elv_next_request(&mtd_queue);
return; spin_unlock_irq(mtd_queue.queue_lock);
req = CURRENT;
spin_unlock_irq(QUEUE->queue_lock);
mtdblk = mtdblks[minor(req->rq_dev)]; mtdblk = mtdblks[minor(req->rq_dev)];
res = 0; res = 0;
...@@ -419,7 +408,8 @@ static void handle_mtdblock_request(void) ...@@ -419,7 +408,8 @@ static void handle_mtdblock_request(void)
goto end_req; goto end_req;
// Handle the request // Handle the request
switch (rq_data_dir(CURRENT)) { switch (rq_data_dir(req))
{
int err; int err;
case READ: case READ:
...@@ -449,7 +439,7 @@ static void handle_mtdblock_request(void) ...@@ -449,7 +439,7 @@ static void handle_mtdblock_request(void)
} }
end_req: end_req:
spin_lock_irq(QUEUE->queue_lock); spin_lock_irq(mtd_queue.queue_lock);
if (!end_that_request_first(req, res, req->hard_cur_sectors)) { if (!end_that_request_first(req, res, req->hard_cur_sectors)) {
blkdev_dequeue_request(req); blkdev_dequeue_request(req);
end_that_request_last(req); end_that_request_last(req);
...@@ -479,16 +469,16 @@ int mtdblock_thread(void *dummy) ...@@ -479,16 +469,16 @@ int mtdblock_thread(void *dummy)
while (!leaving) { while (!leaving) {
add_wait_queue(&thr_wq, &wait); add_wait_queue(&thr_wq, &wait);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irq(QUEUE->queue_lock); spin_lock_irq(mtd_queue.queue_lock);
if (blk_queue_empty(QUEUE) || blk_queue_plugged(QUEUE)) { if (blk_queue_empty(&mtd_queue) || blk_queue_plugged(&mtd_queue)) {
spin_unlock_irq(QUEUE->queue_lock); spin_unlock_irq(mtd_queue.queue_lock);
schedule(); schedule();
remove_wait_queue(&thr_wq, &wait); remove_wait_queue(&thr_wq, &wait);
} else { } else {
remove_wait_queue(&thr_wq, &wait); remove_wait_queue(&thr_wq, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
handle_mtdblock_request(); handle_mtdblock_request();
spin_unlock_irq(QUEUE->queue_lock); spin_unlock_irq(mtd_queue.queue_lock);
} }
} }
...@@ -533,28 +523,43 @@ static int mtdblock_ioctl(struct inode * inode, struct file * file, ...@@ -533,28 +523,43 @@ static int mtdblock_ioctl(struct inode * inode, struct file * file,
static struct block_device_operations mtd_fops = static struct block_device_operations mtd_fops =
{ {
owner: THIS_MODULE, .owner = THIS_MODULE,
open: mtdblock_open, .open = mtdblock_open,
release: mtdblock_release, .release = mtdblock_release,
ioctl: mtdblock_ioctl .ioctl = mtdblock_ioctl
}; };
#ifdef CONFIG_DEVFS_FS
/* Notification that a new device has been added. Create the devfs entry for /* Notification that a new device has been added. Create the devfs entry for
* it. */ * it. */
static void mtd_notify_add(struct mtd_info* mtd) static void mtd_notify_add(struct mtd_info* mtd)
{ {
struct gendisk *disk;
char name[8]; char name[8];
if (!mtd || mtd->type == MTD_ABSENT) if (!mtd || mtd->type == MTD_ABSENT)
return; return;
#ifdef CONFIG_DEVFS_FS
sprintf(name, "%d", mtd->index); sprintf(name, "%d", mtd->index);
devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name, devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name,
DEVFS_FL_DEFAULT, MTD_BLOCK_MAJOR, mtd->index, DEVFS_FL_DEFAULT, MTD_BLOCK_MAJOR, mtd->index,
S_IFBLK | S_IRUGO | S_IWUGO, S_IFBLK | S_IRUGO | S_IWUGO,
&mtd_fops, NULL); &mtd_fops, NULL);
#endif
disk = alloc_disk(1);
if (disk) {
disk->major = MAJOR_NR;
disk->first_minor = mtd->index;
disk->fops = &mtd_fops;
sprintf(disk->disk_name, "mtd%d", mtd->index);
mtddisk[mtd->index] = disk;
set_capacity(disk, mtd->size / 512);
disk->queue = &mtd_queue;
add_disk(disk);
}
} }
static void mtd_notify_remove(struct mtd_info* mtd) static void mtd_notify_remove(struct mtd_info* mtd)
...@@ -562,10 +567,17 @@ static void mtd_notify_remove(struct mtd_info* mtd) ...@@ -562,10 +567,17 @@ static void mtd_notify_remove(struct mtd_info* mtd)
if (!mtd || mtd->type == MTD_ABSENT) if (!mtd || mtd->type == MTD_ABSENT)
return; return;
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_rw_handle[mtd->index]); devfs_unregister(devfs_rw_handle[mtd->index]);
}
#endif #endif
if (mtddisk[mtd->index]) {
del_gendisk(mtddisk[mtd->index]);
put_disk(mtddisk[mtd->index]);
mtddisk[mtd->index] = NULL;
}
}
static spinlock_t mtddev_lock = SPIN_LOCK_UNLOCKED; static spinlock_t mtddev_lock = SPIN_LOCK_UNLOCKED;
int __init init_mtdblock(void) int __init init_mtdblock(void)
...@@ -578,11 +590,11 @@ int __init init_mtdblock(void) ...@@ -578,11 +590,11 @@ int __init init_mtdblock(void)
} }
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL); devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
register_mtd_user(&notifier);
#endif #endif
register_mtd_user(&notifier);
init_waitqueue_head(&thr_wq); init_waitqueue_head(&thr_wq);
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request, &mtddev_lock); blk_init_queue(&mtd_queue, &mtdblock_request, &mtddev_lock);
kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND); kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
return 0; return 0;
} }
...@@ -592,12 +604,12 @@ static void __exit cleanup_mtdblock(void) ...@@ -592,12 +604,12 @@ static void __exit cleanup_mtdblock(void)
leaving = 1; leaving = 1;
wake_up(&thr_wq); wake_up(&thr_wq);
down(&thread_sem); down(&thread_sem);
#ifdef CONFIG_DEVFS_FS
unregister_mtd_user(&notifier); unregister_mtd_user(&notifier);
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_dir_handle); devfs_unregister(devfs_dir_handle);
#endif #endif
unregister_blkdev(MAJOR_NR,DEVICE_NAME); unregister_blkdev(MAJOR_NR,DEVICE_NAME);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(&mtd_queue);
} }
module_init(init_mtdblock); module_init(init_mtdblock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment