diff options
-rw-r--r-- | drivers/mtd/mtd_blkdevs.c | 52 |
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) | |||
176 | static int blktrans_open(struct block_device *bdev, fmode_t mode) | 176 | static 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); | ||
198 | unlock: | 198 | unlock: |
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: | |||
205 | static int blktrans_release(struct gendisk *disk, fmode_t mode) | 205 | static 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 | } | ||
223 | unlock: | 226 | unlock: |
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; |
412 | error4: | 412 | error4: |
413 | module_put(tr->owner); | ||
414 | __put_mtd_device(new->mtd); | ||
415 | blk_cleanup_queue(new->rq); | 413 | blk_cleanup_queue(new->rq); |
416 | error3: | 414 | error3: |
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); |