diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-12-17 07:02:09 -0500 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-12-26 12:15:15 -0500 |
commit | fc75a1e166268e0c3366c3b30888a024125f6665 (patch) | |
tree | 82dc34795ee9299d6184a31fb87b4e9b8925f6a2 /drivers/mtd/ubi | |
parent | 450f872a8e1763c883c9f723e6937b7ed223e6d3 (diff) |
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')
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 45 |
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) | |||
112 | { | 112 | { |
113 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); | 113 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
114 | 114 | ||
115 | ubi_assert(vol->removed); | ||
116 | kfree(vol); | 115 | kfree(vol); |
117 | } | 116 | } |
118 | 117 | ||
@@ -154,9 +153,7 @@ static int volume_sysfs_init(struct ubi_device *ubi, struct ubi_volume *vol) | |||
154 | if (err) | 153 | if (err) |
155 | return err; | 154 | return err; |
156 | err = device_create_file(&vol->dev, &attr_vol_upd_marker); | 155 | err = device_create_file(&vol->dev, &attr_vol_upd_marker); |
157 | if (err) | 156 | return err; |
158 | return err; | ||
159 | return 0; | ||
160 | } | 157 | } |
161 | 158 | ||
162 | /** | 159 | /** |
@@ -188,7 +185,7 @@ static void volume_sysfs_close(struct ubi_volume *vol) | |||
188 | */ | 185 | */ |
189 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | 186 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) |
190 | { | 187 | { |
191 | int i, err, vol_id = req->vol_id; | 188 | int i, err, vol_id = req->vol_id, dont_free = 0; |
192 | struct ubi_volume *vol; | 189 | struct ubi_volume *vol; |
193 | struct ubi_vtbl_record vtbl_rec; | 190 | struct ubi_vtbl_record vtbl_rec; |
194 | uint64_t bytes; | 191 | uint64_t bytes; |
@@ -317,6 +314,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
317 | vol->dev.parent = &ubi->dev; | 314 | vol->dev.parent = &ubi->dev; |
318 | vol->dev.devt = dev; | 315 | vol->dev.devt = dev; |
319 | vol->dev.class = ubi_class; | 316 | vol->dev.class = ubi_class; |
317 | |||
320 | sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); | 318 | sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); |
321 | err = device_register(&vol->dev); | 319 | err = device_register(&vol->dev); |
322 | if (err) { | 320 | if (err) { |
@@ -353,8 +351,20 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
353 | mutex_unlock(&ubi->volumes_mutex); | 351 | mutex_unlock(&ubi->volumes_mutex); |
354 | return 0; | 352 | return 0; |
355 | 353 | ||
354 | out_sysfs: | ||
355 | /* | ||
356 | * We have degistered our device, we should not free the volume* | ||
357 | * description object in this function in case of an error - it is | ||
358 | * freed by the release function. | ||
359 | * | ||
360 | * Get device reference to prevent the release function from being | ||
361 | * called just after sysfs has been closed. | ||
362 | */ | ||
363 | dont_free = 1; | ||
364 | get_device(&vol->dev); | ||
365 | volume_sysfs_close(vol); | ||
356 | out_gluebi: | 366 | out_gluebi: |
357 | err = ubi_destroy_gluebi(vol); | 367 | ubi_destroy_gluebi(vol); |
358 | out_cdev: | 368 | out_cdev: |
359 | cdev_del(&vol->cdev); | 369 | cdev_del(&vol->cdev); |
360 | out_mapping: | 370 | out_mapping: |
@@ -367,25 +377,10 @@ out_acc: | |||
367 | out_unlock: | 377 | out_unlock: |
368 | spin_unlock(&ubi->volumes_lock); | 378 | spin_unlock(&ubi->volumes_lock); |
369 | mutex_unlock(&ubi->volumes_mutex); | 379 | mutex_unlock(&ubi->volumes_mutex); |
370 | kfree(vol); | 380 | if (dont_free) |
371 | ubi_err("cannot create volume %d, error %d", vol_id, err); | 381 | put_device(&vol->dev); |
372 | return err; | 382 | else |
373 | 383 | kfree(vol); | |
374 | /* | ||
375 | * We are registered, so @vol is destroyed in the release function and | ||
376 | * we have to de-initialize differently. | ||
377 | */ | ||
378 | out_sysfs: | ||
379 | err = ubi_destroy_gluebi(vol); | ||
380 | cdev_del(&vol->cdev); | ||
381 | kfree(vol->eba_tbl); | ||
382 | spin_lock(&ubi->volumes_lock); | ||
383 | ubi->rsvd_pebs -= vol->reserved_pebs; | ||
384 | ubi->avail_pebs += vol->reserved_pebs; | ||
385 | ubi->volumes[vol_id] = NULL; | ||
386 | spin_unlock(&ubi->volumes_lock); | ||
387 | mutex_unlock(&ubi->volumes_mutex); | ||
388 | volume_sysfs_close(vol); | ||
389 | ubi_err("cannot create volume %d, error %d", vol_id, err); | 384 | ubi_err("cannot create volume %d, error %d", vol_id, err); |
390 | return err; | 385 | return err; |
391 | } | 386 | } |