summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/vmt.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-17 13:02:09 +0100
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-26 18:15:15 +0100
commitfc75a1e166268e0c3366c3b30888a024125f6665 (patch)
tree82dc34795ee9299d6184a31fb87b4e9b8925f6a2 /drivers/mtd/ubi/vmt.c
parentUBI: get device when opening volume (diff)
downloadlinux-fc75a1e166268e0c3366c3b30888a024125f6665.tar.xz
linux-fc75a1e166268e0c3366c3b30888a024125f6665.zip
UBI: fix error path
Error path in volume creation is bogus. First of, it ovverrides the 'err' variable and returns zero to the caller. Second, ubi_assert() in the release function is wrong. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi/vmt.c')
-rw-r--r--drivers/mtd/ubi/vmt.c45
1 files changed, 20 insertions, 25 deletions
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 9dd3689aecd3..3d6ac029c177 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -112,7 +112,6 @@ static void vol_release(struct device *dev)
{
struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
- ubi_assert(vol->removed);
kfree(vol);
}
@@ -154,9 +153,7 @@ static int volume_sysfs_init(struct ubi_device *ubi, struct ubi_volume *vol)
if (err)
return err;
err = device_create_file(&vol->dev, &attr_vol_upd_marker);
- if (err)
- return err;
- return 0;
+ return err;
}
/**
@@ -188,7 +185,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;
+ int i, err, vol_id = req->vol_id, dont_free = 0;
struct ubi_volume *vol;
struct ubi_vtbl_record vtbl_rec;
uint64_t bytes;
@@ -317,6 +314,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
vol->dev.parent = &ubi->dev;
vol->dev.devt = dev;
vol->dev.class = ubi_class;
+
sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id);
err = device_register(&vol->dev);
if (err) {
@@ -353,8 +351,20 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
mutex_unlock(&ubi->volumes_mutex);
return 0;
+out_sysfs:
+ /*
+ * We have degistered 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;
+ get_device(&vol->dev);
+ volume_sysfs_close(vol);
out_gluebi:
- err = ubi_destroy_gluebi(vol);
+ ubi_destroy_gluebi(vol);
out_cdev:
cdev_del(&vol->cdev);
out_mapping:
@@ -367,25 +377,10 @@ out_acc:
out_unlock:
spin_unlock(&ubi->volumes_lock);
mutex_unlock(&ubi->volumes_mutex);
- kfree(vol);
- ubi_err("cannot create volume %d, error %d", vol_id, err);
- return err;
-
- /*
- * We are registered, so @vol is destroyed in the release function and
- * we have to de-initialize differently.
- */
-out_sysfs:
- err = ubi_destroy_gluebi(vol);
- cdev_del(&vol->cdev);
- kfree(vol->eba_tbl);
- spin_lock(&ubi->volumes_lock);
- ubi->rsvd_pebs -= vol->reserved_pebs;
- ubi->avail_pebs += vol->reserved_pebs;
- ubi->volumes[vol_id] = NULL;
- spin_unlock(&ubi->volumes_lock);
- mutex_unlock(&ubi->volumes_mutex);
- volume_sysfs_close(vol);
+ if (dont_free)
+ put_device(&vol->dev);
+ else
+ kfree(vol);
ubi_err("cannot create volume %d, error %d", vol_id, err);
return err;
}