diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-06-04 09:48:12 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-07-24 06:32:54 -0400 |
commit | abc5e92262d87f9c5c628492bffc55f81c7dcb80 (patch) | |
tree | ad33229247f99996dd875e68c10dcef9d1d40519 /drivers | |
parent | cadb40ccc16a26a738f1cbc963e35b21edd93e79 (diff) |
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 <ext-adrian.hunter@nokia.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/ubi/build.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 17 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 18 |
4 files changed, 9 insertions, 29 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index ff4425de1527..7b42b4d05b3a 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) | |||
840 | out_uif: | 840 | out_uif: |
841 | uif_close(ubi); | 841 | uif_close(ubi); |
842 | out_detach: | 842 | out_detach: |
843 | ubi_eba_close(ubi); | ||
844 | ubi_wl_close(ubi); | 843 | ubi_wl_close(ubi); |
845 | vfree(ubi->vtbl); | 844 | vfree(ubi->vtbl); |
846 | out_free: | 845 | out_free: |
@@ -903,7 +902,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) | |||
903 | kthread_stop(ubi->bgt_thread); | 902 | kthread_stop(ubi->bgt_thread); |
904 | 903 | ||
905 | uif_close(ubi); | 904 | uif_close(ubi); |
906 | ubi_eba_close(ubi); | ||
907 | ubi_wl_close(ubi); | 905 | ubi_wl_close(ubi); |
908 | vfree(ubi->vtbl); | 906 | vfree(ubi->vtbl); |
909 | put_mtd_device(ubi->mtd); | 907 | put_mtd_device(ubi->mtd); |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 37d778447943..623d25f4855f 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -1233,20 +1233,3 @@ out_free: | |||
1233 | } | 1233 | } |
1234 | return err; | 1234 | return err; |
1235 | } | 1235 | } |
1236 | |||
1237 | /** | ||
1238 | * ubi_eba_close - close EBA unit. | ||
1239 | * @ubi: UBI device description object | ||
1240 | */ | ||
1241 | void ubi_eba_close(const struct ubi_device *ubi) | ||
1242 | { | ||
1243 | int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; | ||
1244 | |||
1245 | dbg_eba("close EBA unit"); | ||
1246 | |||
1247 | for (i = 0; i < num_volumes; i++) { | ||
1248 | if (!ubi->volumes[i]) | ||
1249 | continue; | ||
1250 | kfree(ubi->volumes[i]->eba_tbl); | ||
1251 | } | ||
1252 | } | ||
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 67dcbd11c15c..940f6b7deec3 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, | |||
477 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | 477 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, |
478 | struct ubi_vid_hdr *vid_hdr); | 478 | struct ubi_vid_hdr *vid_hdr); |
479 | int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); | 479 | int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); |
480 | void ubi_eba_close(const struct ubi_device *ubi); | ||
481 | 480 | ||
482 | /* wl.c */ | 481 | /* wl.c */ |
483 | int ubi_wl_get_peb(struct ubi_device *ubi, int dtype); | 482 | 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 7402025ded94..367b04176e0a 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
@@ -127,6 +127,7 @@ static void vol_release(struct device *dev) | |||
127 | { | 127 | { |
128 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); | 128 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
129 | 129 | ||
130 | kfree(vol->eba_tbl); | ||
130 | kfree(vol); | 131 | kfree(vol); |
131 | } | 132 | } |
132 | 133 | ||
@@ -201,7 +202,7 @@ static void volume_sysfs_close(struct ubi_volume *vol) | |||
201 | */ | 202 | */ |
202 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | 203 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) |
203 | { | 204 | { |
204 | int i, err, vol_id = req->vol_id, dont_free = 0; | 205 | int i, err, vol_id = req->vol_id, do_free = 1; |
205 | struct ubi_volume *vol; | 206 | struct ubi_volume *vol; |
206 | struct ubi_vtbl_record vtbl_rec; | 207 | struct ubi_vtbl_record vtbl_rec; |
207 | uint64_t bytes; | 208 | uint64_t bytes; |
@@ -365,14 +366,14 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
365 | 366 | ||
366 | out_sysfs: | 367 | out_sysfs: |
367 | /* | 368 | /* |
368 | * We have registered our device, we should not free the volume* | 369 | * We have registered our device, we should not free the volume |
369 | * description object in this function in case of an error - it is | 370 | * description object in this function in case of an error - it is |
370 | * freed by the release function. | 371 | * freed by the release function. |
371 | * | 372 | * |
372 | * Get device reference to prevent the release function from being | 373 | * Get device reference to prevent the release function from being |
373 | * called just after sysfs has been closed. | 374 | * called just after sysfs has been closed. |
374 | */ | 375 | */ |
375 | dont_free = 1; | 376 | do_free = 0; |
376 | get_device(&vol->dev); | 377 | get_device(&vol->dev); |
377 | volume_sysfs_close(vol); | 378 | volume_sysfs_close(vol); |
378 | out_gluebi: | 379 | out_gluebi: |
@@ -382,17 +383,18 @@ out_gluebi: | |||
382 | out_cdev: | 383 | out_cdev: |
383 | cdev_del(&vol->cdev); | 384 | cdev_del(&vol->cdev); |
384 | out_mapping: | 385 | out_mapping: |
385 | kfree(vol->eba_tbl); | 386 | if (do_free) |
387 | kfree(vol->eba_tbl); | ||
386 | out_acc: | 388 | out_acc: |
387 | spin_lock(&ubi->volumes_lock); | 389 | spin_lock(&ubi->volumes_lock); |
388 | ubi->rsvd_pebs -= vol->reserved_pebs; | 390 | ubi->rsvd_pebs -= vol->reserved_pebs; |
389 | ubi->avail_pebs += vol->reserved_pebs; | 391 | ubi->avail_pebs += vol->reserved_pebs; |
390 | out_unlock: | 392 | out_unlock: |
391 | spin_unlock(&ubi->volumes_lock); | 393 | spin_unlock(&ubi->volumes_lock); |
392 | if (dont_free) | 394 | if (do_free) |
393 | put_device(&vol->dev); | ||
394 | else | ||
395 | kfree(vol); | 395 | kfree(vol); |
396 | else | ||
397 | put_device(&vol->dev); | ||
396 | ubi_err("cannot create volume %d, error %d", vol_id, err); | 398 | ubi_err("cannot create volume %d, error %d", vol_id, err); |
397 | return err; | 399 | return err; |
398 | } | 400 | } |
@@ -445,8 +447,6 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
445 | goto out_err; | 447 | goto out_err; |
446 | } | 448 | } |
447 | 449 | ||
448 | kfree(vol->eba_tbl); | ||
449 | vol->eba_tbl = NULL; | ||
450 | cdev_del(&vol->cdev); | 450 | cdev_del(&vol->cdev); |
451 | volume_sysfs_close(vol); | 451 | volume_sysfs_close(vol); |
452 | 452 | ||