From 44741cb99d14c37b5081a13f22f6e4a37a8704c6 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 4 Jun 2008 17:58:37 +0300 Subject: [PATCH] --- yaml --- r: 106063 b: refs/heads/master c: 472018f73e7308a7f29b753ee8c742b6f45f103f h: refs/heads/master i: 106061: e80c2061b4a783a9e6400174cacb278a0e78a8e6 106059: a2cb213a05fa7004dd8f90658a6d93611e480879 106055: 13866901d187ffb7eb2f6f4a36e51371b5021f46 106047: 5d4f6e98715730801930b4da3fda7a8ca19579e2 v: v3 --- [refs] | 2 +- trunk/drivers/mtd/ubi/build.c | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/[refs] b/[refs] index cbddc9ca5bd3..fea0f956bca9 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 505d1caa79cd61a70615e9a7eae2eab85e797a83 +refs/heads/master: 472018f73e7308a7f29b753ee8c742b6f45f103f diff --git a/trunk/drivers/mtd/ubi/build.c b/trunk/drivers/mtd/ubi/build.c index 33205e4c1f5b..a5b19944eca8 100644 --- a/trunk/drivers/mtd/ubi/build.c +++ b/trunk/drivers/mtd/ubi/build.c @@ -354,16 +354,35 @@ static void kill_volumes(struct ubi_device *ubi) ubi_free_volume(ubi, ubi->volumes[i]); } +/** + * free_user_volumes - free all user volumes. + * @ubi: UBI device description object + * + * Normally the volumes are freed at the release function of the volume device + * objects. However, on error paths the volumes have to be freed before the + * device objects have been initialized. + */ +static void free_user_volumes(struct ubi_device *ubi) +{ + int i; + + for (i = 0; i < ubi->vtbl_slots; i++) + if (ubi->volumes[i]) { + kfree(ubi->volumes[i]->eba_tbl); + kfree(ubi->volumes[i]); + } +} + /** * uif_init - initialize user interfaces for an UBI device. * @ubi: UBI device description object * * This function returns zero in case of success and a negative error code in - * case of failure. + * case of failure. Note, this function destroys all volumes if it failes. */ static int uif_init(struct ubi_device *ubi) { - int i, err; + int i, err, do_free = 0; dev_t dev; sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); @@ -410,10 +429,13 @@ static int uif_init(struct ubi_device *ubi) out_volumes: kill_volumes(ubi); + do_free = 0; out_sysfs: ubi_sysfs_close(ubi); cdev_del(&ubi->cdev); out_unreg: + if (do_free) + free_user_volumes(ubi); unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); return err; @@ -722,7 +744,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) { struct ubi_device *ubi; - int i, err; + int i, err, do_free = 1; /* * 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) err = uif_init(ubi); if (err) - goto out_detach; + goto out_nofree; ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); 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) out_uif: uif_close(ubi); +out_nofree: + do_free = 0; out_detach: ubi_wl_close(ubi); + if (do_free) + free_user_volumes(ubi); free_internal_volumes(ubi); vfree(ubi->vtbl); out_free: