aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r--drivers/mtd/ubi/build.c34
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 */
365static 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 */
364static int uif_init(struct ubi_device *ubi) 383static 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
411out_volumes: 430out_volumes:
412 kill_volumes(ubi); 431 kill_volumes(ubi);
432 do_free = 0;
413out_sysfs: 433out_sysfs:
414 ubi_sysfs_close(ubi); 434 ubi_sysfs_close(ubi);
415 cdev_del(&ubi->cdev); 435 cdev_del(&ubi->cdev);
416out_unreg: 436out_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)
722int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) 744int 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
860out_uif: 882out_uif:
861 uif_close(ubi); 883 uif_close(ubi);
884out_nofree:
885 do_free = 0;
862out_detach: 886out_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);
866out_free: 892out_free: