aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-17 08:42:57 -0500
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-26 12:15:16 -0500
commitd05c77a816974c09f8c7e8f48e5b9f7b59dafdf3 (patch)
tree6263ef3ad76c654e9d2635e5145f15c2b517edeb /drivers
parentdb6e5770ef0ab351a403ac26e1ab1309e58f15d7 (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')
-rw-r--r--drivers/mtd/ubi/eba.c10
-rw-r--r--drivers/mtd/ubi/kapi.c4
-rw-r--r--drivers/mtd/ubi/ubi.h22
-rw-r--r--drivers/mtd/ubi/vmt.c88
-rw-r--r--drivers/mtd/ubi/vtbl.c2
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}
270EXPORT_SYMBOL_GPL(ubi_close_volume); 272EXPORT_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 */
320struct ubi_device { 320struct 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 */
70static ssize_t vol_attribute_show(struct device *dev, 69static 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
354out_sysfs: 362out_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;
377out_unlock: 384out_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);
450out: 464 mutex_unlock(&ubi->volumes_mutex);
465 return 0;
466
467out_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;
471out_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 */
584int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) 615int 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;