diff options
Diffstat (limited to 'drivers/mtd/ubi')
-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: |