From abc5e92262d87f9c5c628492bffc55f81c7dcb80 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 4 Jun 2008 16:48:12 +0300 Subject: UBI: fix memory leak ubi_free_volume() function sets ubi->volumes[] to NULL, so ubi_eba_close() is useless, it does not free what has to be freed. So zap it and free vol->eba_tbl at the volume release function. Pointed-out-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 2 -- drivers/mtd/ubi/eba.c | 17 ----------------- drivers/mtd/ubi/ubi.h | 1 - drivers/mtd/ubi/vmt.c | 18 +++++++++--------- 4 files changed, 9 insertions(+), 29 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index ff4425de152..7b42b4d05b3 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -840,7 +840,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) out_uif: uif_close(ubi); out_detach: - ubi_eba_close(ubi); ubi_wl_close(ubi); vfree(ubi->vtbl); out_free: @@ -903,7 +902,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) kthread_stop(ubi->bgt_thread); uif_close(ubi); - ubi_eba_close(ubi); ubi_wl_close(ubi); vfree(ubi->vtbl); put_mtd_device(ubi->mtd); diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 37d77844794..623d25f4855 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -1233,20 +1233,3 @@ out_free: } return err; } - -/** - * ubi_eba_close - close EBA unit. - * @ubi: UBI device description object - */ -void ubi_eba_close(const struct ubi_device *ubi) -{ - int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; - - dbg_eba("close EBA unit"); - - for (i = 0; i < num_volumes; i++) { - if (!ubi->volumes[i]) - continue; - kfree(ubi->volumes[i]->eba_tbl); - } -} diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 67dcbd11c15..940f6b7deec 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -477,7 +477,6 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, struct ubi_vid_hdr *vid_hdr); int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); -void ubi_eba_close(const struct ubi_device *ubi); /* wl.c */ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype); diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 7402025ded9..367b04176e0 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -127,6 +127,7 @@ static void vol_release(struct device *dev) { struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); + kfree(vol->eba_tbl); kfree(vol); } @@ -201,7 +202,7 @@ static void volume_sysfs_close(struct ubi_volume *vol) */ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) { - int i, err, vol_id = req->vol_id, dont_free = 0; + int i, err, vol_id = req->vol_id, do_free = 1; struct ubi_volume *vol; struct ubi_vtbl_record vtbl_rec; uint64_t bytes; @@ -365,14 +366,14 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) out_sysfs: /* - * We have registered our device, we should not free the volume* + * We have registered our device, we should not free the volume * description object in this function in case of an error - it is * freed by the release function. * * Get device reference to prevent the release function from being * called just after sysfs has been closed. */ - dont_free = 1; + do_free = 0; get_device(&vol->dev); volume_sysfs_close(vol); out_gluebi: @@ -382,17 +383,18 @@ out_gluebi: out_cdev: cdev_del(&vol->cdev); out_mapping: - kfree(vol->eba_tbl); + if (do_free) + kfree(vol->eba_tbl); out_acc: spin_lock(&ubi->volumes_lock); ubi->rsvd_pebs -= vol->reserved_pebs; ubi->avail_pebs += vol->reserved_pebs; out_unlock: spin_unlock(&ubi->volumes_lock); - if (dont_free) - put_device(&vol->dev); - else + if (do_free) kfree(vol); + else + put_device(&vol->dev); ubi_err("cannot create volume %d, error %d", vol_id, err); return err; } @@ -445,8 +447,6 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) goto out_err; } - kfree(vol->eba_tbl); - vol->eba_tbl = NULL; cdev_del(&vol->cdev); volume_sysfs_close(vol); -- cgit v1.2.3