aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/mtd_blkdevs.c52
1 files changed, 24 insertions, 28 deletions
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 62e68707b07f..352831baf785 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -176,7 +176,7 @@ static void mtd_blktrans_request(struct request_queue *rq)
176static int blktrans_open(struct block_device *bdev, fmode_t mode) 176static int blktrans_open(struct block_device *bdev, fmode_t mode)
177{ 177{
178 struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); 178 struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk);
179 int ret; 179 int ret = 0;
180 180
181 if (!dev) 181 if (!dev)
182 return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ 182 return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
@@ -184,17 +184,17 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
184 lock_kernel(); 184 lock_kernel();
185 mutex_lock(&dev->lock); 185 mutex_lock(&dev->lock);
186 186
187 if (!dev->mtd) { 187 if (dev->open++)
188 ret = -ENXIO;
189 goto unlock; 188 goto unlock;
190 }
191 189
192 ret = !dev->open++ && dev->tr->open ? dev->tr->open(dev) : 0; 190 kref_get(&dev->ref);
191 __module_get(dev->tr->owner);
192
193 if (dev->mtd) {
194 ret = dev->tr->open ? dev->tr->open(dev) : 0;
195 __get_mtd_device(dev->mtd);
196 }
193 197
194 /* Take another reference on the device so it won't go away till
195 last release */
196 if (!ret)
197 kref_get(&dev->ref);
198unlock: 198unlock:
199 mutex_unlock(&dev->lock); 199 mutex_unlock(&dev->lock);
200 blktrans_dev_put(dev); 200 blktrans_dev_put(dev);
@@ -205,7 +205,7 @@ unlock:
205static int blktrans_release(struct gendisk *disk, fmode_t mode) 205static int blktrans_release(struct gendisk *disk, fmode_t mode)
206{ 206{
207 struct mtd_blktrans_dev *dev = blktrans_dev_get(disk); 207 struct mtd_blktrans_dev *dev = blktrans_dev_get(disk);
208 int ret = -ENXIO; 208 int ret = 0;
209 209
210 if (!dev) 210 if (!dev)
211 return ret; 211 return ret;
@@ -213,13 +213,16 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
213 lock_kernel(); 213 lock_kernel();
214 mutex_lock(&dev->lock); 214 mutex_lock(&dev->lock);
215 215
216 /* Release one reference, we sure its not the last one here*/ 216 if (--dev->open)
217 kref_put(&dev->ref, blktrans_dev_release);
218
219 if (!dev->mtd)
220 goto unlock; 217 goto unlock;
221 218
222 ret = !--dev->open && dev->tr->release ? dev->tr->release(dev) : 0; 219 kref_put(&dev->ref, blktrans_dev_release);
220 module_put(dev->tr->owner);
221
222 if (dev->mtd) {
223 ret = dev->tr->release ? dev->tr->release(dev) : 0;
224 __put_mtd_device(dev->mtd);
225 }
223unlock: 226unlock:
224 mutex_unlock(&dev->lock); 227 mutex_unlock(&dev->lock);
225 blktrans_dev_put(dev); 228 blktrans_dev_put(dev);
@@ -385,9 +388,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
385 388
386 gd->queue = new->rq; 389 gd->queue = new->rq;
387 390
388 __get_mtd_device(new->mtd);
389 __module_get(tr->owner);
390
391 /* Create processing thread */ 391 /* Create processing thread */
392 /* TODO: workqueue ? */ 392 /* TODO: workqueue ? */
393 new->thread = kthread_run(mtd_blktrans_thread, new, 393 new->thread = kthread_run(mtd_blktrans_thread, new,
@@ -410,8 +410,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
410 } 410 }
411 return 0; 411 return 0;
412error4: 412error4:
413 module_put(tr->owner);
414 __put_mtd_device(new->mtd);
415 blk_cleanup_queue(new->rq); 413 blk_cleanup_queue(new->rq);
416error3: 414error3:
417 put_disk(new->disk); 415 put_disk(new->disk);
@@ -448,17 +446,15 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
448 blk_start_queue(old->rq); 446 blk_start_queue(old->rq);
449 spin_unlock_irqrestore(&old->queue_lock, flags); 447 spin_unlock_irqrestore(&old->queue_lock, flags);
450 448
451 /* Ask trans driver for release to the mtd device */ 449 /* If the device is currently open, tell trans driver to close it,
450 then put mtd device, and don't touch it again */
452 mutex_lock(&old->lock); 451 mutex_lock(&old->lock);
453 if (old->open && old->tr->release) { 452 if (old->open) {
454 old->tr->release(old); 453 if (old->tr->release)
455 old->open = 0; 454 old->tr->release(old);
455 __put_mtd_device(old->mtd);
456 } 456 }
457 457
458 __put_mtd_device(old->mtd);
459 module_put(old->tr->owner);
460
461 /* At that point, we don't touch the mtd anymore */
462 old->mtd = NULL; 458 old->mtd = NULL;
463 459
464 mutex_unlock(&old->lock); 460 mutex_unlock(&old->lock);