X-Git-Url: http://bbs.cooldavid.org/git/?a=blobdiff_plain;f=drivers%2Fmtd%2Fmtd_blkdevs.c;h=63790e975d204087feee6675a1deb1c68f3c6b1f;hb=6fe4c590313133ebd5dadb769031489ff178ece1;hp=62e68707b07f49a6f07a8f97a7333880f9d7f1db;hpb=7355a5a654ccbbfd2fd11bb1e2389910f786ea92;p=net-next-2.6.git diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 62e68707b07..63790e975d2 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -133,6 +133,10 @@ static int mtd_blktrans_thread(void *arg) if (!req && !(req = blk_fetch_request(rq))) { set_current_state(TASK_INTERRUPTIBLE); + + if (kthread_should_stop()) + set_current_state(TASK_RUNNING); + spin_unlock_irq(rq->queue_lock); schedule(); spin_lock_irq(rq->queue_lock); @@ -176,54 +180,53 @@ static void mtd_blktrans_request(struct request_queue *rq) static int blktrans_open(struct block_device *bdev, fmode_t mode) { struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); - int ret; + int ret = 0; if (!dev) return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ - lock_kernel(); mutex_lock(&dev->lock); - if (!dev->mtd) { - ret = -ENXIO; + if (dev->open++) goto unlock; - } - ret = !dev->open++ && dev->tr->open ? dev->tr->open(dev) : 0; + kref_get(&dev->ref); + __module_get(dev->tr->owner); + + if (dev->mtd) { + ret = dev->tr->open ? dev->tr->open(dev) : 0; + __get_mtd_device(dev->mtd); + } - /* Take another reference on the device so it won't go away till - last release */ - if (!ret) - kref_get(&dev->ref); unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); - unlock_kernel(); return ret; } static int blktrans_release(struct gendisk *disk, fmode_t mode) { struct mtd_blktrans_dev *dev = blktrans_dev_get(disk); - int ret = -ENXIO; + int ret = 0; if (!dev) return ret; - lock_kernel(); mutex_lock(&dev->lock); - /* Release one reference, we sure its not the last one here*/ - kref_put(&dev->ref, blktrans_dev_release); - - if (!dev->mtd) + if (--dev->open) goto unlock; - ret = !--dev->open && dev->tr->release ? dev->tr->release(dev) : 0; + kref_put(&dev->ref, blktrans_dev_release); + module_put(dev->tr->owner); + + if (dev->mtd) { + ret = dev->tr->release ? dev->tr->release(dev) : 0; + __put_mtd_device(dev->mtd); + } unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); - unlock_kernel(); return ret; } @@ -256,7 +259,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, if (!dev) return ret; - lock_kernel(); mutex_lock(&dev->lock); if (!dev->mtd) @@ -271,7 +273,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, } unlock: mutex_unlock(&dev->lock); - unlock_kernel(); blktrans_dev_put(dev); return ret; } @@ -385,9 +386,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) gd->queue = new->rq; - __get_mtd_device(new->mtd); - __module_get(tr->owner); - /* Create processing thread */ /* TODO: workqueue ? */ new->thread = kthread_run(mtd_blktrans_thread, new, @@ -410,8 +408,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) } return 0; error4: - module_put(tr->owner); - __put_mtd_device(new->mtd); blk_cleanup_queue(new->rq); error3: put_disk(new->disk); @@ -448,17 +444,15 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) blk_start_queue(old->rq); spin_unlock_irqrestore(&old->queue_lock, flags); - /* Ask trans driver for release to the mtd device */ + /* If the device is currently open, tell trans driver to close it, + then put mtd device, and don't touch it again */ mutex_lock(&old->lock); - if (old->open && old->tr->release) { - old->tr->release(old); - old->open = 0; + if (old->open) { + if (old->tr->release) + old->tr->release(old); + __put_mtd_device(old->mtd); } - __put_mtd_device(old->mtd); - module_put(old->tr->owner); - - /* At that point, we don't touch the mtd anymore */ old->mtd = NULL; mutex_unlock(&old->lock); @@ -508,13 +502,16 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) mutex_lock(&mtd_table_mutex); ret = register_blkdev(tr->major, tr->name); - if (ret) { + if (ret < 0) { printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", tr->name, tr->major, ret); mutex_unlock(&mtd_table_mutex); return ret; } + if (ret) + tr->major = ret; + tr->blkshift = ffs(tr->blksize) - 1; INIT_LIST_HEAD(&tr->devs);