aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/ubi/block.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index b210fdb31c98..b1fc28f63882 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -99,6 +99,8 @@ struct ubiblock {
99 99
100/* Linked list of all ubiblock instances */ 100/* Linked list of all ubiblock instances */
101static LIST_HEAD(ubiblock_devices); 101static LIST_HEAD(ubiblock_devices);
102static DEFINE_IDR(ubiblock_minor_idr);
103/* Protects ubiblock_devices and ubiblock_minor_idr */
102static DEFINE_MUTEX(devices_mutex); 104static DEFINE_MUTEX(devices_mutex);
103static int ubiblock_major; 105static int ubiblock_major;
104 106
@@ -351,8 +353,6 @@ static const struct blk_mq_ops ubiblock_mq_ops = {
351 .init_request = ubiblock_init_request, 353 .init_request = ubiblock_init_request,
352}; 354};
353 355
354static DEFINE_IDR(ubiblock_minor_idr);
355
356int ubiblock_create(struct ubi_volume_info *vi) 356int ubiblock_create(struct ubi_volume_info *vi)
357{ 357{
358 struct ubiblock *dev; 358 struct ubiblock *dev;
@@ -365,14 +365,15 @@ int ubiblock_create(struct ubi_volume_info *vi)
365 /* Check that the volume isn't already handled */ 365 /* Check that the volume isn't already handled */
366 mutex_lock(&devices_mutex); 366 mutex_lock(&devices_mutex);
367 if (find_dev_nolock(vi->ubi_num, vi->vol_id)) { 367 if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
368 mutex_unlock(&devices_mutex); 368 ret = -EEXIST;
369 return -EEXIST; 369 goto out_unlock;
370 } 370 }
371 mutex_unlock(&devices_mutex);
372 371
373 dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL); 372 dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL);
374 if (!dev) 373 if (!dev) {
375 return -ENOMEM; 374 ret = -ENOMEM;
375 goto out_unlock;
376 }
376 377
377 mutex_init(&dev->dev_mutex); 378 mutex_init(&dev->dev_mutex);
378 379
@@ -437,14 +438,13 @@ int ubiblock_create(struct ubi_volume_info *vi)
437 goto out_free_queue; 438 goto out_free_queue;
438 } 439 }
439 440
440 mutex_lock(&devices_mutex);
441 list_add_tail(&dev->list, &ubiblock_devices); 441 list_add_tail(&dev->list, &ubiblock_devices);
442 mutex_unlock(&devices_mutex);
443 442
444 /* Must be the last step: anyone can call file ops from now on */ 443 /* Must be the last step: anyone can call file ops from now on */
445 add_disk(dev->gd); 444 add_disk(dev->gd);
446 dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", 445 dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)",
447 dev->ubi_num, dev->vol_id, vi->name); 446 dev->ubi_num, dev->vol_id, vi->name);
447 mutex_unlock(&devices_mutex);
448 return 0; 448 return 0;
449 449
450out_free_queue: 450out_free_queue:
@@ -457,6 +457,8 @@ out_put_disk:
457 put_disk(dev->gd); 457 put_disk(dev->gd);
458out_free_dev: 458out_free_dev:
459 kfree(dev); 459 kfree(dev);
460out_unlock:
461 mutex_unlock(&devices_mutex);
460 462
461 return ret; 463 return ret;
462} 464}
@@ -478,30 +480,36 @@ static void ubiblock_cleanup(struct ubiblock *dev)
478int ubiblock_remove(struct ubi_volume_info *vi) 480int ubiblock_remove(struct ubi_volume_info *vi)
479{ 481{
480 struct ubiblock *dev; 482 struct ubiblock *dev;
483 int ret;
481 484
482 mutex_lock(&devices_mutex); 485 mutex_lock(&devices_mutex);
483 dev = find_dev_nolock(vi->ubi_num, vi->vol_id); 486 dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
484 if (!dev) { 487 if (!dev) {
485 mutex_unlock(&devices_mutex); 488 ret = -ENODEV;
486 return -ENODEV; 489 goto out_unlock;
487 } 490 }
488 491
489 /* Found a device, let's lock it so we can check if it's busy */ 492 /* Found a device, let's lock it so we can check if it's busy */
490 mutex_lock(&dev->dev_mutex); 493 mutex_lock(&dev->dev_mutex);
491 if (dev->refcnt > 0) { 494 if (dev->refcnt > 0) {
492 mutex_unlock(&dev->dev_mutex); 495 ret = -EBUSY;
493 mutex_unlock(&devices_mutex); 496 goto out_unlock_dev;
494 return -EBUSY;
495 } 497 }
496 498
497 /* Remove from device list */ 499 /* Remove from device list */
498 list_del(&dev->list); 500 list_del(&dev->list);
499 mutex_unlock(&devices_mutex);
500
501 ubiblock_cleanup(dev); 501 ubiblock_cleanup(dev);
502 mutex_unlock(&dev->dev_mutex); 502 mutex_unlock(&dev->dev_mutex);
503 mutex_unlock(&devices_mutex);
504
503 kfree(dev); 505 kfree(dev);
504 return 0; 506 return 0;
507
508out_unlock_dev:
509 mutex_unlock(&dev->dev_mutex);
510out_unlock:
511 mutex_unlock(&devices_mutex);
512 return ret;
505} 513}
506 514
507static int ubiblock_resize(struct ubi_volume_info *vi) 515static int ubiblock_resize(struct ubi_volume_info *vi)
@@ -630,6 +638,7 @@ static void ubiblock_remove_all(void)
630 struct ubiblock *next; 638 struct ubiblock *next;
631 struct ubiblock *dev; 639 struct ubiblock *dev;
632 640
641 mutex_lock(&devices_mutex);
633 list_for_each_entry_safe(dev, next, &ubiblock_devices, list) { 642 list_for_each_entry_safe(dev, next, &ubiblock_devices, list) {
634 /* The module is being forcefully removed */ 643 /* The module is being forcefully removed */
635 WARN_ON(dev->desc); 644 WARN_ON(dev->desc);
@@ -638,6 +647,7 @@ static void ubiblock_remove_all(void)
638 ubiblock_cleanup(dev); 647 ubiblock_cleanup(dev);
639 kfree(dev); 648 kfree(dev);
640 } 649 }
650 mutex_unlock(&devices_mutex);
641} 651}
642 652
643int __init ubiblock_init(void) 653int __init ubiblock_init(void)