diff options
| -rw-r--r-- | drivers/mtd/ubi/build.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 33205e4c1f5b..a5b19944eca8 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
| @@ -355,15 +355,34 @@ static void kill_volumes(struct ubi_device *ubi) | |||
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | /** | 357 | /** |
| 358 | * free_user_volumes - free all user volumes. | ||
| 359 | * @ubi: UBI device description object | ||
| 360 | * | ||
| 361 | * Normally the volumes are freed at the release function of the volume device | ||
| 362 | * objects. However, on error paths the volumes have to be freed before the | ||
| 363 | * device objects have been initialized. | ||
| 364 | */ | ||
| 365 | static void free_user_volumes(struct ubi_device *ubi) | ||
| 366 | { | ||
| 367 | int i; | ||
| 368 | |||
| 369 | for (i = 0; i < ubi->vtbl_slots; i++) | ||
| 370 | if (ubi->volumes[i]) { | ||
| 371 | kfree(ubi->volumes[i]->eba_tbl); | ||
| 372 | kfree(ubi->volumes[i]); | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | /** | ||
| 358 | * uif_init - initialize user interfaces for an UBI device. | 377 | * uif_init - initialize user interfaces for an UBI device. |
| 359 | * @ubi: UBI device description object | 378 | * @ubi: UBI device description object |
| 360 | * | 379 | * |
| 361 | * This function returns zero in case of success and a negative error code in | 380 | * This function returns zero in case of success and a negative error code in |
| 362 | * case of failure. | 381 | * case of failure. Note, this function destroys all volumes if it failes. |
| 363 | */ | 382 | */ |
| 364 | static int uif_init(struct ubi_device *ubi) | 383 | static int uif_init(struct ubi_device *ubi) |
| 365 | { | 384 | { |
| 366 | int i, err; | 385 | int i, err, do_free = 0; |
| 367 | dev_t dev; | 386 | dev_t dev; |
| 368 | 387 | ||
| 369 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); | 388 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); |
| @@ -410,10 +429,13 @@ static int uif_init(struct ubi_device *ubi) | |||
| 410 | 429 | ||
| 411 | out_volumes: | 430 | out_volumes: |
| 412 | kill_volumes(ubi); | 431 | kill_volumes(ubi); |
| 432 | do_free = 0; | ||
| 413 | out_sysfs: | 433 | out_sysfs: |
| 414 | ubi_sysfs_close(ubi); | 434 | ubi_sysfs_close(ubi); |
| 415 | cdev_del(&ubi->cdev); | 435 | cdev_del(&ubi->cdev); |
| 416 | out_unreg: | 436 | out_unreg: |
| 437 | if (do_free) | ||
| 438 | free_user_volumes(ubi); | ||
| 417 | unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); | 439 | unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); |
| 418 | ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); | 440 | ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); |
| 419 | return err; | 441 | return err; |
| @@ -722,7 +744,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) | |||
| 722 | int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | 744 | int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) |
| 723 | { | 745 | { |
| 724 | struct ubi_device *ubi; | 746 | struct ubi_device *ubi; |
| 725 | int i, err; | 747 | int i, err, do_free = 1; |
| 726 | 748 | ||
| 727 | /* | 749 | /* |
| 728 | * Check if we already have the same MTD device attached. | 750 | * Check if we already have the same MTD device attached. |
| @@ -822,7 +844,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 822 | 844 | ||
| 823 | err = uif_init(ubi); | 845 | err = uif_init(ubi); |
| 824 | if (err) | 846 | if (err) |
| 825 | goto out_detach; | 847 | goto out_nofree; |
| 826 | 848 | ||
| 827 | ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); | 849 | ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); |
| 828 | if (IS_ERR(ubi->bgt_thread)) { | 850 | if (IS_ERR(ubi->bgt_thread)) { |
| @@ -859,8 +881,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 859 | 881 | ||
| 860 | out_uif: | 882 | out_uif: |
| 861 | uif_close(ubi); | 883 | uif_close(ubi); |
| 884 | out_nofree: | ||
| 885 | do_free = 0; | ||
| 862 | out_detach: | 886 | out_detach: |
| 863 | ubi_wl_close(ubi); | 887 | ubi_wl_close(ubi); |
| 888 | if (do_free) | ||
| 889 | free_user_volumes(ubi); | ||
| 864 | free_internal_volumes(ubi); | 890 | free_internal_volumes(ubi); |
| 865 | vfree(ubi->vtbl); | 891 | vfree(ubi->vtbl); |
| 866 | out_free: | 892 | out_free: |
