X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fmtd%2Fmtd_blkdevs.c;h=c82e09bbc5fd0c31ddf5919db4d645462b984763;hb=bc3966921ff9528ae44a4a108085ab06107c1e7d;hp=9ff007c4962c9f3c58868385729a915ba6b28222;hpb=71a928c0e52cedc43747c64b96a5f74592ab678f;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 9ff007c..c82e09b 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -39,36 +39,42 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, unsigned long block, nsect; char *buf; - block = req->sector << 9 >> tr->blkshift; - nsect = req->current_nr_sectors << 9 >> tr->blkshift; + block = blk_rq_pos(req) << 9 >> tr->blkshift; + nsect = blk_rq_cur_bytes(req) >> tr->blkshift; buf = req->buffer; if (!blk_fs_request(req)) - return 0; + return -EIO; - if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk)) - return 0; + if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > + get_capacity(req->rq_disk)) + return -EIO; + + if (blk_discard_rq(req)) + return tr->discard(dev, block, nsect); switch(rq_data_dir(req)) { case READ: for (; nsect > 0; nsect--, block++, buf += tr->blksize) if (tr->readsect(dev, block, buf)) - return 0; - return 1; + return -EIO; + rq_flush_dcache_pages(req); + return 0; case WRITE: if (!tr->writesect) - return 0; + return -EIO; + rq_flush_dcache_pages(req); for (; nsect > 0; nsect--, block++, buf += tr->blksize) if (tr->writesect(dev, block, buf)) - return 0; - return 1; + return -EIO; + return 0; default: printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); - return 0; + return -EIO; } } @@ -76,19 +82,15 @@ static int mtd_blktrans_thread(void *arg) { struct mtd_blktrans_ops *tr = arg; struct request_queue *rq = tr->blkcore_priv->rq; - - /* we might get involved when memory gets low, so use PF_MEMALLOC */ - current->flags |= PF_MEMALLOC; + struct request *req = NULL; spin_lock_irq(rq->queue_lock); + while (!kthread_should_stop()) { - struct request *req; struct mtd_blktrans_dev *dev; - int res = 0; - - req = elv_next_request(rq); + int res; - if (!req) { + if (!req && !(req = blk_fetch_request(rq))) { set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irq(rq->queue_lock); schedule(); @@ -107,8 +109,13 @@ static int mtd_blktrans_thread(void *arg) spin_lock_irq(rq->queue_lock); - end_request(req, res); + if (!__blk_end_request_cur(req, res)) + req = NULL; } + + if (req) + __blk_end_request_all(req, -EIO); + spin_unlock_irq(rq->queue_lock); return 0; @@ -121,16 +128,13 @@ static void mtd_blktrans_request(struct request_queue *rq) } -static int blktrans_open(struct inode *i, struct file *f) +static int blktrans_open(struct block_device *bdev, fmode_t mode) { - struct mtd_blktrans_dev *dev; - struct mtd_blktrans_ops *tr; + struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; + struct mtd_blktrans_ops *tr = dev->tr; int ret = -ENODEV; - dev = i->i_bdev->bd_disk->private_data; - tr = dev->tr; - - if (!try_module_get(dev->mtd->owner)) + if (!get_mtd_device(NULL, dev->mtd->index)) goto out; if (!try_module_get(tr->owner)) @@ -144,7 +148,7 @@ static int blktrans_open(struct inode *i, struct file *f) ret = 0; if (tr->open && (ret = tr->open(dev))) { dev->mtd->usecount--; - module_put(dev->mtd->owner); + put_mtd_device(dev->mtd); out_tr: module_put(tr->owner); } @@ -152,21 +156,18 @@ static int blktrans_open(struct inode *i, struct file *f) return ret; } -static int blktrans_release(struct inode *i, struct file *f) +static int blktrans_release(struct gendisk *disk, fmode_t mode) { - struct mtd_blktrans_dev *dev; - struct mtd_blktrans_ops *tr; + struct mtd_blktrans_dev *dev = disk->private_data; + struct mtd_blktrans_ops *tr = dev->tr; int ret = 0; - dev = i->i_bdev->bd_disk->private_data; - tr = dev->tr; - if (tr->release) ret = tr->release(dev); if (!ret) { dev->mtd->usecount--; - module_put(dev->mtd->owner); + put_mtd_device(dev->mtd); module_put(tr->owner); } @@ -182,10 +183,10 @@ static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo) return -ENOTTY; } -static int blktrans_ioctl(struct inode *inode, struct file *file, +static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { - struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data; + struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; struct mtd_blktrans_ops *tr = dev->tr; switch (cmd) { @@ -199,11 +200,11 @@ static int blktrans_ioctl(struct inode *inode, struct file *file, } } -static struct block_device_operations mtd_blktrans_ops = { +static const struct block_device_operations mtd_blktrans_ops = { .owner = THIS_MODULE, .open = blktrans_open, .release = blktrans_release, - .ioctl = blktrans_ioctl, + .locked_ioctl = blktrans_ioctl, .getgeo = blktrans_getgeo, }; @@ -280,6 +281,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) gd->private_data = new; new->blkcore_priv = gd; gd->queue = tr->blkcore_priv->rq; + gd->driverfs_dev = &new->mtd->dev; if (new->readonly) set_disk_ro(gd, 1); @@ -366,17 +368,22 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) } tr->blkcore_priv->rq->queuedata = tr; - blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize); + blk_queue_logical_block_size(tr->blkcore_priv->rq, tr->blksize); + if (tr->discard) + queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, + tr->blkcore_priv->rq); + tr->blkshift = ffs(tr->blksize) - 1; tr->blkcore_priv->thread = kthread_run(mtd_blktrans_thread, tr, "%sd", tr->name); if (IS_ERR(tr->blkcore_priv->thread)) { + ret = PTR_ERR(tr->blkcore_priv->thread); blk_cleanup_queue(tr->blkcore_priv->rq); unregister_blkdev(tr->major, tr->name); kfree(tr->blkcore_priv); mutex_unlock(&mtd_table_mutex); - return PTR_ERR(tr->blkcore_priv->thread); + return ret; } INIT_LIST_HEAD(&tr->devs);