diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-12-17 08:42:57 -0500 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-12-26 12:15:16 -0500 |
commit | d05c77a816974c09f8c7e8f48e5b9f7b59dafdf3 (patch) | |
tree | 6263ef3ad76c654e9d2635e5145f15c2b517edeb /drivers/mtd | |
parent | db6e5770ef0ab351a403ac26e1ab1309e58f15d7 (diff) |
UBI: introduce volume refcounting
Add ref_count field to UBI volumes and remove weired "vol->removed"
field. This way things are better understandable and we do not have
to do whold show_attr operation under spinlock.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/ubi/eba.c | 10 | ||||
-rw-r--r-- | drivers/mtd/ubi/kapi.c | 4 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 22 | ||||
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 88 | ||||
-rw-r--r-- | drivers/mtd/ubi/vtbl.c | 2 |
5 files changed, 84 insertions, 42 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 2ff34923e51d..84f7dc9fd3ac 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -301,6 +301,8 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, | |||
301 | { | 301 | { |
302 | int err, pnum, vol_id = vol->vol_id; | 302 | int err, pnum, vol_id = vol->vol_id; |
303 | 303 | ||
304 | ubi_assert(vol->ref_count > 0); | ||
305 | |||
304 | if (ubi->ro_mode) | 306 | if (ubi->ro_mode) |
305 | return -EROFS; | 307 | return -EROFS; |
306 | 308 | ||
@@ -349,6 +351,8 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
349 | struct ubi_vid_hdr *vid_hdr; | 351 | struct ubi_vid_hdr *vid_hdr; |
350 | uint32_t uninitialized_var(crc); | 352 | uint32_t uninitialized_var(crc); |
351 | 353 | ||
354 | ubi_assert(vol->ref_count > 0); | ||
355 | |||
352 | err = leb_read_lock(ubi, vol_id, lnum); | 356 | err = leb_read_lock(ubi, vol_id, lnum); |
353 | if (err) | 357 | if (err) |
354 | return err; | 358 | return err; |
@@ -572,6 +576,8 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
572 | int err, pnum, tries = 0, vol_id = vol->vol_id; | 576 | int err, pnum, tries = 0, vol_id = vol->vol_id; |
573 | struct ubi_vid_hdr *vid_hdr; | 577 | struct ubi_vid_hdr *vid_hdr; |
574 | 578 | ||
579 | ubi_assert(vol->ref_count > 0); | ||
580 | |||
575 | if (ubi->ro_mode) | 581 | if (ubi->ro_mode) |
576 | return -EROFS; | 582 | return -EROFS; |
577 | 583 | ||
@@ -705,6 +711,8 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, | |||
705 | struct ubi_vid_hdr *vid_hdr; | 711 | struct ubi_vid_hdr *vid_hdr; |
706 | uint32_t crc; | 712 | uint32_t crc; |
707 | 713 | ||
714 | ubi_assert(vol->ref_count > 0); | ||
715 | |||
708 | if (ubi->ro_mode) | 716 | if (ubi->ro_mode) |
709 | return -EROFS; | 717 | return -EROFS; |
710 | 718 | ||
@@ -819,6 +827,8 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, | |||
819 | struct ubi_vid_hdr *vid_hdr; | 827 | struct ubi_vid_hdr *vid_hdr; |
820 | uint32_t crc; | 828 | uint32_t crc; |
821 | 829 | ||
830 | ubi_assert(vol->ref_count > 0); | ||
831 | |||
822 | if (ubi->ro_mode) | 832 | if (ubi->ro_mode) |
823 | return -EROFS; | 833 | return -EROFS; |
824 | 834 | ||
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 9c283768319f..780c273ff452 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c | |||
@@ -152,6 +152,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode) | |||
152 | break; | 152 | break; |
153 | } | 153 | } |
154 | get_device(&vol->dev); | 154 | get_device(&vol->dev); |
155 | vol->ref_count += 1; | ||
155 | spin_unlock(&ubi->volumes_lock); | 156 | spin_unlock(&ubi->volumes_lock); |
156 | 157 | ||
157 | desc->vol = vol; | 158 | desc->vol = vol; |
@@ -261,10 +262,11 @@ void ubi_close_volume(struct ubi_volume_desc *desc) | |||
261 | case UBI_EXCLUSIVE: | 262 | case UBI_EXCLUSIVE: |
262 | vol->exclusive = 0; | 263 | vol->exclusive = 0; |
263 | } | 264 | } |
265 | vol->ref_count -= 1; | ||
264 | spin_unlock(&vol->ubi->volumes_lock); | 266 | spin_unlock(&vol->ubi->volumes_lock); |
265 | 267 | ||
266 | kfree(desc); | ||
267 | put_device(&vol->dev); | 268 | put_device(&vol->dev); |
269 | kfree(desc); | ||
268 | module_put(THIS_MODULE); | 270 | module_put(THIS_MODULE); |
269 | } | 271 | } |
270 | EXPORT_SYMBOL_GPL(ubi_close_volume); | 272 | EXPORT_SYMBOL_GPL(ubi_close_volume); |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 69cbee3be7a4..f782d5aa849a 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -140,10 +140,10 @@ struct ubi_volume_desc; | |||
140 | * @cdev: character device object to create character device | 140 | * @cdev: character device object to create character device |
141 | * @ubi: reference to the UBI device description object | 141 | * @ubi: reference to the UBI device description object |
142 | * @vol_id: volume ID | 142 | * @vol_id: volume ID |
143 | * @ref_count: volume reference count | ||
143 | * @readers: number of users holding this volume in read-only mode | 144 | * @readers: number of users holding this volume in read-only mode |
144 | * @writers: number of users holding this volume in read-write mode | 145 | * @writers: number of users holding this volume in read-write mode |
145 | * @exclusive: whether somebody holds this volume in exclusive mode | 146 | * @exclusive: whether somebody holds this volume in exclusive mode |
146 | * @removed: if the volume was removed | ||
147 | * @checked: if this static volume was checked | 147 | * @checked: if this static volume was checked |
148 | * | 148 | * |
149 | * @reserved_pebs: how many physical eraseblocks are reserved for this volume | 149 | * @reserved_pebs: how many physical eraseblocks are reserved for this volume |
@@ -156,7 +156,7 @@ struct ubi_volume_desc; | |||
156 | * @corrupted: non-zero if the volume is corrupted (static volumes only) | 156 | * @corrupted: non-zero if the volume is corrupted (static volumes only) |
157 | * @alignment: volume alignment | 157 | * @alignment: volume alignment |
158 | * @data_pad: how many bytes are not used at the end of physical eraseblocks to | 158 | * @data_pad: how many bytes are not used at the end of physical eraseblocks to |
159 | * satisfy the requested alignment | 159 | * satisfy the requested alignment |
160 | * @name_len: volume name length | 160 | * @name_len: volume name length |
161 | * @name: volume name | 161 | * @name: volume name |
162 | * | 162 | * |
@@ -185,10 +185,10 @@ struct ubi_volume { | |||
185 | struct cdev cdev; | 185 | struct cdev cdev; |
186 | struct ubi_device *ubi; | 186 | struct ubi_device *ubi; |
187 | int vol_id; | 187 | int vol_id; |
188 | int ref_count; | ||
188 | int readers; | 189 | int readers; |
189 | int writers; | 190 | int writers; |
190 | int exclusive; | 191 | int exclusive; |
191 | int removed; | ||
192 | int checked; | 192 | int checked; |
193 | 193 | ||
194 | int reserved_pebs; | 194 | int reserved_pebs; |
@@ -242,9 +242,9 @@ struct ubi_wl_entry; | |||
242 | * @vol_count: number of volumes in this UBI device | 242 | * @vol_count: number of volumes in this UBI device |
243 | * @volumes: volumes of this UBI device | 243 | * @volumes: volumes of this UBI device |
244 | * @volumes_lock: protects @volumes, @rsvd_pebs, @avail_pebs, beb_rsvd_pebs, | 244 | * @volumes_lock: protects @volumes, @rsvd_pebs, @avail_pebs, beb_rsvd_pebs, |
245 | * @beb_rsvd_level, @bad_peb_count, @good_peb_count, @vol_count, @vol->readers, | 245 | * @beb_rsvd_level, @bad_peb_count, @good_peb_count, @vol_count, |
246 | * @vol->writers, @vol->exclusive, @vol->removed, @vol->mapping and | 246 | * @vol->readers, @vol->writers, @vol->exclusive, |
247 | * @vol->eba_tbl. | 247 | * @vol->ref_count, @vol->mapping and @vol->eba_tbl. |
248 | * | 248 | * |
249 | * @rsvd_pebs: count of reserved physical eraseblocks | 249 | * @rsvd_pebs: count of reserved physical eraseblocks |
250 | * @avail_pebs: count of available physical eraseblocks | 250 | * @avail_pebs: count of available physical eraseblocks |
@@ -273,11 +273,11 @@ struct ubi_wl_entry; | |||
273 | * @prot.pnum: protection tree indexed by physical eraseblock numbers | 273 | * @prot.pnum: protection tree indexed by physical eraseblock numbers |
274 | * @prot.aec: protection tree indexed by absolute erase counter value | 274 | * @prot.aec: protection tree indexed by absolute erase counter value |
275 | * @wl_lock: protects the @used, @free, @prot, @lookuptbl, @abs_ec, @move_from, | 275 | * @wl_lock: protects the @used, @free, @prot, @lookuptbl, @abs_ec, @move_from, |
276 | * @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works | 276 | * @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works |
277 | * fields | 277 | * fields |
278 | * @wl_scheduled: non-zero if the wear-leveling was scheduled | 278 | * @wl_scheduled: non-zero if the wear-leveling was scheduled |
279 | * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any | 279 | * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any |
280 | * physical eraseblock | 280 | * physical eraseblock |
281 | * @abs_ec: absolute erase counter | 281 | * @abs_ec: absolute erase counter |
282 | * @move_from: physical eraseblock from where the data is being moved | 282 | * @move_from: physical eraseblock from where the data is being moved |
283 | * @move_to: physical eraseblock where the data is being moved to | 283 | * @move_to: physical eraseblock where the data is being moved to |
@@ -308,13 +308,13 @@ struct ubi_wl_entry; | |||
308 | * @hdrs_min_io_size | 308 | * @hdrs_min_io_size |
309 | * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset | 309 | * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset |
310 | * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or | 310 | * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or |
311 | * not | 311 | * not |
312 | * @mtd: MTD device descriptor | 312 | * @mtd: MTD device descriptor |
313 | * | 313 | * |
314 | * @peb_buf1: a buffer of PEB size used for different purposes | 314 | * @peb_buf1: a buffer of PEB size used for different purposes |
315 | * @peb_buf2: another buffer of PEB size used for different purposes | 315 | * @peb_buf2: another buffer of PEB size used for different purposes |
316 | * @buf_mutex: proptects @peb_buf1 and @peb_buf2 | 316 | * @buf_mutex: proptects @peb_buf1 and @peb_buf2 |
317 | * @dbg_peb_buf: buffer of PEB size used for debugging | 317 | * @dbg_peb_buf: buffer of PEB size used for debugging |
318 | * @dbg_buf_mutex: proptects @dbg_peb_buf | 318 | * @dbg_buf_mutex: proptects @dbg_peb_buf |
319 | */ | 319 | */ |
320 | struct ubi_device { | 320 | struct ubi_device { |
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 3d6ac029c177..18ef1e1da496 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
@@ -63,21 +63,24 @@ static struct device_attribute attr_vol_upd_marker = | |||
63 | * B. process 2 removes volume Y; | 63 | * B. process 2 removes volume Y; |
64 | * C. process 1 starts reading the /<sysfs>/class/ubi/ubiX_Y/reserved_ebs file; | 64 | * C. process 1 starts reading the /<sysfs>/class/ubi/ubiX_Y/reserved_ebs file; |
65 | * | 65 | * |
66 | * What we want to do in a situation like that is to return error when the file | 66 | * In this situation, this function will return %-ENODEV because it will find |
67 | * is read. This is done by means of the 'removed' flag and the 'vol_lock' of | 67 | * out that the volume was removed from the @ubi->volumes array. |
68 | * the UBI volume description object. | ||
69 | */ | 68 | */ |
70 | static ssize_t vol_attribute_show(struct device *dev, | 69 | static ssize_t vol_attribute_show(struct device *dev, |
71 | struct device_attribute *attr, char *buf) | 70 | struct device_attribute *attr, char *buf) |
72 | { | 71 | { |
73 | int ret = -ENODEV; | 72 | int ret; |
74 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); | 73 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
74 | struct ubi_device *ubi = vol->ubi; | ||
75 | 75 | ||
76 | spin_lock(&vol->ubi->volumes_lock); | 76 | spin_lock(&ubi->volumes_lock); |
77 | if (vol->removed) { | 77 | if (!ubi->volumes[vol->vol_id]) { |
78 | spin_unlock(&vol->ubi->volumes_lock); | 78 | spin_unlock(&ubi->volumes_lock); |
79 | return ret; | 79 | return -ENODEV; |
80 | } | 80 | } |
81 | /* Take a reference to prevent volume removal */ | ||
82 | vol->ref_count += 1; | ||
83 | spin_unlock(&ubi->volumes_lock); | ||
81 | 84 | ||
82 | if (attr == &attr_vol_reserved_ebs) | 85 | if (attr == &attr_vol_reserved_ebs) |
83 | ret = sprintf(buf, "%d\n", vol->reserved_pebs); | 86 | ret = sprintf(buf, "%d\n", vol->reserved_pebs); |
@@ -102,8 +105,13 @@ static ssize_t vol_attribute_show(struct device *dev, | |||
102 | else if (attr == &attr_vol_upd_marker) | 105 | else if (attr == &attr_vol_upd_marker) |
103 | ret = sprintf(buf, "%d\n", vol->upd_marker); | 106 | ret = sprintf(buf, "%d\n", vol->upd_marker); |
104 | else | 107 | else |
105 | BUG(); | 108 | /* This must be a bug */ |
106 | spin_unlock(&vol->ubi->volumes_lock); | 109 | ret = -EINVAL; |
110 | |||
111 | spin_lock(&ubi->volumes_lock); | ||
112 | vol->ref_count -= 1; | ||
113 | ubi_assert(vol->ref_count >= 0); | ||
114 | spin_unlock(&ubi->volumes_lock); | ||
107 | return ret; | 115 | return ret; |
108 | } | 116 | } |
109 | 117 | ||
@@ -179,7 +187,7 @@ static void volume_sysfs_close(struct ubi_volume *vol) | |||
179 | * @req: volume creation request | 187 | * @req: volume creation request |
180 | * | 188 | * |
181 | * This function creates volume described by @req. If @req->vol_id id | 189 | * This function creates volume described by @req. If @req->vol_id id |
182 | * %UBI_VOL_NUM_AUTO, this function automatically assigne ID to the new volume | 190 | * %UBI_VOL_NUM_AUTO, this function automatically assign ID to the new volume |
183 | * and saves it in @req->vol_id. Returns zero in case of success and a negative | 191 | * and saves it in @req->vol_id. Returns zero in case of success and a negative |
184 | * error code in case of failure. | 192 | * error code in case of failure. |
185 | */ | 193 | */ |
@@ -261,7 +269,6 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
261 | memcpy(vol->name, req->name, vol->name_len + 1); | 269 | memcpy(vol->name, req->name, vol->name_len + 1); |
262 | vol->exclusive = 1; | 270 | vol->exclusive = 1; |
263 | vol->ubi = ubi; | 271 | vol->ubi = ubi; |
264 | ubi->volumes[vol_id] = vol; | ||
265 | spin_unlock(&ubi->volumes_lock); | 272 | spin_unlock(&ubi->volumes_lock); |
266 | 273 | ||
267 | /* | 274 | /* |
@@ -345,6 +352,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
345 | spin_lock(&ubi->volumes_lock); | 352 | spin_lock(&ubi->volumes_lock); |
346 | ubi->vol_count += 1; | 353 | ubi->vol_count += 1; |
347 | vol->exclusive = 0; | 354 | vol->exclusive = 0; |
355 | ubi->volumes[vol_id] = vol; | ||
348 | spin_unlock(&ubi->volumes_lock); | 356 | spin_unlock(&ubi->volumes_lock); |
349 | 357 | ||
350 | paranoid_check_volumes(ubi); | 358 | paranoid_check_volumes(ubi); |
@@ -353,7 +361,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
353 | 361 | ||
354 | out_sysfs: | 362 | out_sysfs: |
355 | /* | 363 | /* |
356 | * We have degistered our device, we should not free the volume* | 364 | * We have registered our device, we should not free the volume* |
357 | * description object in this function in case of an error - it is | 365 | * description object in this function in case of an error - it is |
358 | * freed by the release function. | 366 | * freed by the release function. |
359 | * | 367 | * |
@@ -373,7 +381,6 @@ out_acc: | |||
373 | spin_lock(&ubi->volumes_lock); | 381 | spin_lock(&ubi->volumes_lock); |
374 | ubi->rsvd_pebs -= vol->reserved_pebs; | 382 | ubi->rsvd_pebs -= vol->reserved_pebs; |
375 | ubi->avail_pebs += vol->reserved_pebs; | 383 | ubi->avail_pebs += vol->reserved_pebs; |
376 | ubi->volumes[vol_id] = NULL; | ||
377 | out_unlock: | 384 | out_unlock: |
378 | spin_unlock(&ubi->volumes_lock); | 385 | spin_unlock(&ubi->volumes_lock); |
379 | mutex_unlock(&ubi->volumes_mutex); | 386 | mutex_unlock(&ubi->volumes_mutex); |
@@ -407,25 +414,32 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
407 | return -EROFS; | 414 | return -EROFS; |
408 | 415 | ||
409 | mutex_lock(&ubi->volumes_mutex); | 416 | mutex_lock(&ubi->volumes_mutex); |
417 | spin_lock(&ubi->volumes_lock); | ||
418 | if (vol->ref_count > 1) { | ||
419 | /* | ||
420 | * The volume is busy, probably someone is reading one of its | ||
421 | * sysfs files. | ||
422 | */ | ||
423 | err = -EBUSY; | ||
424 | goto out_unlock; | ||
425 | } | ||
426 | ubi->volumes[vol_id] = NULL; | ||
427 | spin_unlock(&ubi->volumes_lock); | ||
428 | |||
410 | err = ubi_destroy_gluebi(vol); | 429 | err = ubi_destroy_gluebi(vol); |
411 | if (err) | 430 | if (err) |
412 | goto out; | 431 | goto out_err; |
413 | 432 | ||
414 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); | 433 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); |
415 | if (err) | 434 | if (err) |
416 | goto out; | 435 | goto out_err; |
417 | 436 | ||
418 | for (i = 0; i < vol->reserved_pebs; i++) { | 437 | for (i = 0; i < vol->reserved_pebs; i++) { |
419 | err = ubi_eba_unmap_leb(ubi, vol, i); | 438 | err = ubi_eba_unmap_leb(ubi, vol, i); |
420 | if (err) | 439 | if (err) |
421 | goto out; | 440 | goto out_err; |
422 | } | 441 | } |
423 | 442 | ||
424 | spin_lock(&ubi->volumes_lock); | ||
425 | vol->removed = 1; | ||
426 | ubi->volumes[vol_id] = NULL; | ||
427 | spin_unlock(&ubi->volumes_lock); | ||
428 | |||
429 | kfree(vol->eba_tbl); | 443 | kfree(vol->eba_tbl); |
430 | vol->eba_tbl = NULL; | 444 | vol->eba_tbl = NULL; |
431 | cdev_del(&vol->cdev); | 445 | cdev_del(&vol->cdev); |
@@ -447,7 +461,15 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
447 | spin_unlock(&ubi->volumes_lock); | 461 | spin_unlock(&ubi->volumes_lock); |
448 | 462 | ||
449 | paranoid_check_volumes(ubi); | 463 | paranoid_check_volumes(ubi); |
450 | out: | 464 | mutex_unlock(&ubi->volumes_mutex); |
465 | return 0; | ||
466 | |||
467 | out_err: | ||
468 | ubi_err("cannot remove volume %d, error %d", vol_id, err); | ||
469 | spin_lock(&ubi->volumes_lock); | ||
470 | ubi->volumes[vol_id] = vol; | ||
471 | out_unlock: | ||
472 | spin_unlock(&ubi->volumes_lock); | ||
451 | mutex_unlock(&ubi->volumes_mutex); | 473 | mutex_unlock(&ubi->volumes_mutex); |
452 | return err; | 474 | return err; |
453 | } | 475 | } |
@@ -494,8 +516,17 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
494 | for (i = 0; i < reserved_pebs; i++) | 516 | for (i = 0; i < reserved_pebs; i++) |
495 | new_mapping[i] = UBI_LEB_UNMAPPED; | 517 | new_mapping[i] = UBI_LEB_UNMAPPED; |
496 | 518 | ||
497 | /* Reserve physical eraseblocks */ | ||
498 | mutex_lock(&ubi->volumes_mutex); | 519 | mutex_lock(&ubi->volumes_mutex); |
520 | spin_lock(&ubi->volumes_lock); | ||
521 | if (vol->ref_count > 1) { | ||
522 | spin_unlock(&ubi->volumes_lock); | ||
523 | err = -EBUSY; | ||
524 | goto out_free; | ||
525 | } | ||
526 | spin_unlock(&ubi->volumes_lock); | ||
527 | |||
528 | |||
529 | /* Reserve physical eraseblocks */ | ||
499 | pebs = reserved_pebs - vol->reserved_pebs; | 530 | pebs = reserved_pebs - vol->reserved_pebs; |
500 | if (pebs > 0) { | 531 | if (pebs > 0) { |
501 | spin_lock(&ubi->volumes_lock); | 532 | spin_lock(&ubi->volumes_lock); |
@@ -577,8 +608,8 @@ out_free: | |||
577 | * @ubi: UBI device description object | 608 | * @ubi: UBI device description object |
578 | * @vol: volume description object | 609 | * @vol: volume description object |
579 | * | 610 | * |
580 | * This function adds an existin volume and initializes all its data | 611 | * This function adds an existing volume and initializes all its data |
581 | * structures. Returnes zero in case of success and a negative error code in | 612 | * structures. Returns zero in case of success and a negative error code in |
582 | * case of failure. | 613 | * case of failure. |
583 | */ | 614 | */ |
584 | int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) | 615 | int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) |
@@ -588,7 +619,6 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
588 | 619 | ||
589 | dbg_msg("add volume %d", vol_id); | 620 | dbg_msg("add volume %d", vol_id); |
590 | ubi_dbg_dump_vol_info(vol); | 621 | ubi_dbg_dump_vol_info(vol); |
591 | ubi_assert(vol); | ||
592 | 622 | ||
593 | /* Register character device for the volume */ | 623 | /* Register character device for the volume */ |
594 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); | 624 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); |
@@ -645,11 +675,9 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
645 | int err; | 675 | int err; |
646 | 676 | ||
647 | dbg_msg("free volume %d", vol->vol_id); | 677 | dbg_msg("free volume %d", vol->vol_id); |
648 | ubi_assert(vol); | ||
649 | 678 | ||
650 | vol->removed = 1; | ||
651 | err = ubi_destroy_gluebi(vol); | ||
652 | ubi->volumes[vol->vol_id] = NULL; | 679 | ubi->volumes[vol->vol_id] = NULL; |
680 | err = ubi_destroy_gluebi(vol); | ||
653 | cdev_del(&vol->cdev); | 681 | cdev_del(&vol->cdev); |
654 | volume_sysfs_close(vol); | 682 | volume_sysfs_close(vol); |
655 | } | 683 | } |
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 5879fdb3e6d5..a37dc7a213b1 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
@@ -565,6 +565,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
565 | vol->last_eb_bytes = sv->last_data_size; | 565 | vol->last_eb_bytes = sv->last_data_size; |
566 | } | 566 | } |
567 | 567 | ||
568 | /* And add the layout volume */ | ||
568 | vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); | 569 | vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); |
569 | if (!vol) | 570 | if (!vol) |
570 | return -ENOMEM; | 571 | return -ENOMEM; |
@@ -580,6 +581,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
580 | vol->used_bytes = | 581 | vol->used_bytes = |
581 | (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad); | 582 | (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad); |
582 | vol->vol_id = UBI_LAYOUT_VOL_ID; | 583 | vol->vol_id = UBI_LAYOUT_VOL_ID; |
584 | vol->ref_count = 1; | ||
583 | 585 | ||
584 | ubi_assert(!ubi->volumes[i]); | 586 | ubi_assert(!ubi->volumes[i]); |
585 | ubi->volumes[vol_id2idx(ubi, vol->vol_id)] = vol; | 587 | ubi->volumes[vol_id2idx(ubi, vol->vol_id)] = vol; |