aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-01-12 05:26:42 -0500
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-02-01 08:16:36 -0500
commit0bf1c4399afee6a2031b0ee943a4c016e53f727c (patch)
treec5d7a62b2c965e65a42f17f6206c28f3c4e57a81 /drivers/mtd/ubi
parentf9b0080e10e0ce3b8acbe91ae6a50da4f2ed7339 (diff)
UBI: fix attaching error path
In the error path of 'ubi_attach_mtd_dev()' we have a tricky situation: we have to release things differently depending on at which point the failure happening. Namely, if @ubi->dev is not initialized, we have to free everything ourselves. But if it was, we should not free the @ubi object, because it will be freed in the 'dev_release()' function. And we did not get this situation right. This patch introduces additional argument to the 'uif_init()' function. On exit, this argument indicates whether the final 'free(ubi)' will happen in 'dev_release()' or not. So the caller always knows how to properly release the resources. Impact: all memory is now correctly released when UBI fails to attach an MTD device. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r--drivers/mtd/ubi/build.c63
1 files changed, 30 insertions, 33 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 99ff57d3ac68..bc45ef9af17d 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -365,11 +365,13 @@ static void dev_release(struct device *dev)
365/** 365/**
366 * ubi_sysfs_init - initialize sysfs for an UBI device. 366 * ubi_sysfs_init - initialize sysfs for an UBI device.
367 * @ubi: UBI device description object 367 * @ubi: UBI device description object
368 * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
369 * taken
368 * 370 *
369 * This function returns zero in case of success and a negative error code in 371 * This function returns zero in case of success and a negative error code in
370 * case of failure. 372 * case of failure.
371 */ 373 */
372static int ubi_sysfs_init(struct ubi_device *ubi) 374static int ubi_sysfs_init(struct ubi_device *ubi, int *ref)
373{ 375{
374 int err; 376 int err;
375 377
@@ -381,6 +383,7 @@ static int ubi_sysfs_init(struct ubi_device *ubi)
381 if (err) 383 if (err)
382 return err; 384 return err;
383 385
386 *ref = 1;
384 err = device_create_file(&ubi->dev, &dev_eraseblock_size); 387 err = device_create_file(&ubi->dev, &dev_eraseblock_size);
385 if (err) 388 if (err)
386 return err; 389 return err;
@@ -436,7 +439,7 @@ static void ubi_sysfs_close(struct ubi_device *ubi)
436} 439}
437 440
438/** 441/**
439 * kill_volumes - destroy all volumes. 442 * kill_volumes - destroy all user volumes.
440 * @ubi: UBI device description object 443 * @ubi: UBI device description object
441 */ 444 */
442static void kill_volumes(struct ubi_device *ubi) 445static void kill_volumes(struct ubi_device *ubi)
@@ -449,36 +452,29 @@ static void kill_volumes(struct ubi_device *ubi)
449} 452}
450 453
451/** 454/**
452 * free_user_volumes - free all user volumes.
453 * @ubi: UBI device description object
454 *
455 * Normally the volumes are freed at the release function of the volume device
456 * objects. However, on error paths the volumes have to be freed before the
457 * device objects have been initialized.
458 */
459static void free_user_volumes(struct ubi_device *ubi)
460{
461 int i;
462
463 for (i = 0; i < ubi->vtbl_slots; i++)
464 if (ubi->volumes[i]) {
465 kfree(ubi->volumes[i]->eba_tbl);
466 kfree(ubi->volumes[i]);
467 }
468}
469
470/**
471 * uif_init - initialize user interfaces for an UBI device. 455 * uif_init - initialize user interfaces for an UBI device.
472 * @ubi: UBI device description object 456 * @ubi: UBI device description object
457 * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
458 * taken, otherwise set to %0
459 *
460 * This function initializes various user interfaces for an UBI device. If the
461 * initialization fails at an early stage, this function frees all the
462 * resources it allocated, returns an error, and @ref is set to %0. However,
463 * if the initialization fails after the UBI device was registered in the
464 * driver core subsystem, this function takes a reference to @ubi->dev, because
465 * otherwise the release function ('dev_release()') would free whole @ubi
466 * object. The @ref argument is set to %1 in this case. The caller has to put
467 * this reference.
473 * 468 *
474 * This function returns zero in case of success and a negative error code in 469 * This function returns zero in case of success and a negative error code in
475 * case of failure. Note, this function destroys all volumes if it fails. 470 * case of failure.
476 */ 471 */
477static int uif_init(struct ubi_device *ubi) 472static int uif_init(struct ubi_device *ubi, int *ref)
478{ 473{
479 int i, err; 474 int i, err;
480 dev_t dev; 475 dev_t dev;
481 476
477 *ref = 0;
482 sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); 478 sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
483 479
484 /* 480 /*
@@ -506,7 +502,7 @@ static int uif_init(struct ubi_device *ubi)
506 goto out_unreg; 502 goto out_unreg;
507 } 503 }
508 504
509 err = ubi_sysfs_init(ubi); 505 err = ubi_sysfs_init(ubi, ref);
510 if (err) 506 if (err)
511 goto out_sysfs; 507 goto out_sysfs;
512 508
@@ -524,6 +520,8 @@ static int uif_init(struct ubi_device *ubi)
524out_volumes: 520out_volumes:
525 kill_volumes(ubi); 521 kill_volumes(ubi);
526out_sysfs: 522out_sysfs:
523 if (*ref)
524 get_device(&ubi->dev);
527 ubi_sysfs_close(ubi); 525 ubi_sysfs_close(ubi);
528 cdev_del(&ubi->cdev); 526 cdev_del(&ubi->cdev);
529out_unreg: 527out_unreg:
@@ -877,7 +875,7 @@ static int ubi_reboot_notifier(struct notifier_block *n, unsigned long state,
877int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) 875int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
878{ 876{
879 struct ubi_device *ubi; 877 struct ubi_device *ubi;
880 int i, err, do_free = 1; 878 int i, err, ref = 0;
881 879
882 /* 880 /*
883 * Check if we already have the same MTD device attached. 881 * Check if we already have the same MTD device attached.
@@ -977,9 +975,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
977 goto out_detach; 975 goto out_detach;
978 } 976 }
979 977
980 err = uif_init(ubi); 978 err = uif_init(ubi, &ref);
981 if (err) 979 if (err)
982 goto out_nofree; 980 goto out_detach;
983 981
984 ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); 982 ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
985 if (IS_ERR(ubi->bgt_thread)) { 983 if (IS_ERR(ubi->bgt_thread)) {
@@ -1027,12 +1025,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
1027 1025
1028out_uif: 1026out_uif:
1029 uif_close(ubi); 1027 uif_close(ubi);
1030out_nofree:
1031 do_free = 0;
1032out_detach: 1028out_detach:
1033 ubi_wl_close(ubi); 1029 ubi_wl_close(ubi);
1034 if (do_free)
1035 free_user_volumes(ubi);
1036 free_internal_volumes(ubi); 1030 free_internal_volumes(ubi);
1037 vfree(ubi->vtbl); 1031 vfree(ubi->vtbl);
1038out_free: 1032out_free:
@@ -1041,7 +1035,10 @@ out_free:
1041#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID 1035#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
1042 vfree(ubi->dbg_peb_buf); 1036 vfree(ubi->dbg_peb_buf);
1043#endif 1037#endif
1044 kfree(ubi); 1038 if (ref)
1039 put_device(&ubi->dev);
1040 else
1041 kfree(ubi);
1045 return err; 1042 return err;
1046} 1043}
1047 1044
@@ -1098,7 +1095,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
1098 1095
1099 /* 1096 /*
1100 * Get a reference to the device in order to prevent 'dev_release()' 1097 * Get a reference to the device in order to prevent 'dev_release()'
1101 * from freeing @ubi object. 1098 * from freeing the @ubi object.
1102 */ 1099 */
1103 get_device(&ubi->dev); 1100 get_device(&ubi->dev);
1104 1101