diff options
author | David Woodhouse <dwmw2@infradead.org> | 2008-02-03 06:07:40 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2008-02-03 06:07:40 -0500 |
commit | 6208e77e7fa9e69f399fddc55b1cf9527fbde599 (patch) | |
tree | f69fd4ed2e5101a442f14d6657b26e6e92fe72e5 /drivers/mtd | |
parent | 5eb91034f3d825f43b3c8ace7b69f94752b7deda (diff) | |
parent | 6dc4a8717fadd47103b5015cc678c75afda43ae0 (diff) |
Merge git://git.infradead.org/~dedekind/ubi-2.6
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/ubi/build.c | 103 | ||||
-rw-r--r-- | drivers/mtd/ubi/cdev.c | 82 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 40 | ||||
-rw-r--r-- | drivers/mtd/ubi/kapi.c | 10 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.c | 10 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 55 | ||||
-rw-r--r-- | drivers/mtd/ubi/upd.c | 176 | ||||
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 14 | ||||
-rw-r--r-- | drivers/mtd/ubi/vtbl.c | 23 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 1 |
10 files changed, 350 insertions, 164 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 8f1f9feb2d60..6ac81e35355c 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -66,9 +66,6 @@ static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES]; | |||
66 | /* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */ | 66 | /* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */ |
67 | struct class *ubi_class; | 67 | struct class *ubi_class; |
68 | 68 | ||
69 | /* Slab cache for lock-tree entries */ | ||
70 | struct kmem_cache *ubi_ltree_slab; | ||
71 | |||
72 | /* Slab cache for wear-leveling entries */ | 69 | /* Slab cache for wear-leveling entries */ |
73 | struct kmem_cache *ubi_wl_entry_slab; | 70 | struct kmem_cache *ubi_wl_entry_slab; |
74 | 71 | ||
@@ -369,9 +366,6 @@ static int uif_init(struct ubi_device *ubi) | |||
369 | int i, err; | 366 | int i, err; |
370 | dev_t dev; | 367 | dev_t dev; |
371 | 368 | ||
372 | mutex_init(&ubi->volumes_mutex); | ||
373 | spin_lock_init(&ubi->volumes_lock); | ||
374 | |||
375 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); | 369 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); |
376 | 370 | ||
377 | /* | 371 | /* |
@@ -568,7 +562,7 @@ static int io_init(struct ubi_device *ubi) | |||
568 | } | 562 | } |
569 | 563 | ||
570 | /* Similar for the data offset */ | 564 | /* Similar for the data offset */ |
571 | ubi->leb_start = ubi->vid_hdr_offset + ubi->vid_hdr_alsize; | 565 | ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE; |
572 | ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); | 566 | ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); |
573 | 567 | ||
574 | dbg_msg("vid_hdr_offset %d", ubi->vid_hdr_offset); | 568 | dbg_msg("vid_hdr_offset %d", ubi->vid_hdr_offset); |
@@ -627,6 +621,58 @@ static int io_init(struct ubi_device *ubi) | |||
627 | } | 621 | } |
628 | 622 | ||
629 | /** | 623 | /** |
624 | * autoresize - re-size the volume which has the "auto-resize" flag set. | ||
625 | * @ubi: UBI device description object | ||
626 | * @vol_id: ID of the volume to re-size | ||
627 | * | ||
628 | * This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in | ||
629 | * the volume table to the largest possible size. See comments in ubi-header.h | ||
630 | * for more description of the flag. Returns zero in case of success and a | ||
631 | * negative error code in case of failure. | ||
632 | */ | ||
633 | static int autoresize(struct ubi_device *ubi, int vol_id) | ||
634 | { | ||
635 | struct ubi_volume_desc desc; | ||
636 | struct ubi_volume *vol = ubi->volumes[vol_id]; | ||
637 | int err, old_reserved_pebs = vol->reserved_pebs; | ||
638 | |||
639 | /* | ||
640 | * Clear the auto-resize flag in the volume in-memory copy of the | ||
641 | * volume table, and 'ubi_resize_volume()' will propogate this change | ||
642 | * to the flash. | ||
643 | */ | ||
644 | ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG; | ||
645 | |||
646 | if (ubi->avail_pebs == 0) { | ||
647 | struct ubi_vtbl_record vtbl_rec; | ||
648 | |||
649 | /* | ||
650 | * No avalilable PEBs to re-size the volume, clear the flag on | ||
651 | * flash and exit. | ||
652 | */ | ||
653 | memcpy(&vtbl_rec, &ubi->vtbl[vol_id], | ||
654 | sizeof(struct ubi_vtbl_record)); | ||
655 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); | ||
656 | if (err) | ||
657 | ubi_err("cannot clean auto-resize flag for volume %d", | ||
658 | vol_id); | ||
659 | } else { | ||
660 | desc.vol = vol; | ||
661 | err = ubi_resize_volume(&desc, | ||
662 | old_reserved_pebs + ubi->avail_pebs); | ||
663 | if (err) | ||
664 | ubi_err("cannot auto-resize volume %d", vol_id); | ||
665 | } | ||
666 | |||
667 | if (err) | ||
668 | return err; | ||
669 | |||
670 | ubi_msg("volume %d (\"%s\") re-sized from %d to %d LEBs", vol_id, | ||
671 | vol->name, old_reserved_pebs, vol->reserved_pebs); | ||
672 | return 0; | ||
673 | } | ||
674 | |||
675 | /** | ||
630 | * ubi_attach_mtd_dev - attach an MTD device. | 676 | * ubi_attach_mtd_dev - attach an MTD device. |
631 | * @mtd_dev: MTD device description object | 677 | * @mtd_dev: MTD device description object |
632 | * @ubi_num: number to assign to the new UBI device | 678 | * @ubi_num: number to assign to the new UBI device |
@@ -702,6 +748,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
702 | ubi->mtd = mtd; | 748 | ubi->mtd = mtd; |
703 | ubi->ubi_num = ubi_num; | 749 | ubi->ubi_num = ubi_num; |
704 | ubi->vid_hdr_offset = vid_hdr_offset; | 750 | ubi->vid_hdr_offset = vid_hdr_offset; |
751 | ubi->autoresize_vol_id = -1; | ||
752 | |||
753 | mutex_init(&ubi->buf_mutex); | ||
754 | mutex_init(&ubi->ckvol_mutex); | ||
755 | mutex_init(&ubi->volumes_mutex); | ||
756 | spin_lock_init(&ubi->volumes_lock); | ||
705 | 757 | ||
706 | dbg_msg("attaching mtd%d to ubi%d: VID header offset %d", | 758 | dbg_msg("attaching mtd%d to ubi%d: VID header offset %d", |
707 | mtd->index, ubi_num, vid_hdr_offset); | 759 | mtd->index, ubi_num, vid_hdr_offset); |
@@ -710,8 +762,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
710 | if (err) | 762 | if (err) |
711 | goto out_free; | 763 | goto out_free; |
712 | 764 | ||
713 | mutex_init(&ubi->buf_mutex); | ||
714 | mutex_init(&ubi->ckvol_mutex); | ||
715 | ubi->peb_buf1 = vmalloc(ubi->peb_size); | 765 | ubi->peb_buf1 = vmalloc(ubi->peb_size); |
716 | if (!ubi->peb_buf1) | 766 | if (!ubi->peb_buf1) |
717 | goto out_free; | 767 | goto out_free; |
@@ -733,6 +783,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
733 | goto out_free; | 783 | goto out_free; |
734 | } | 784 | } |
735 | 785 | ||
786 | if (ubi->autoresize_vol_id != -1) { | ||
787 | err = autoresize(ubi, ubi->autoresize_vol_id); | ||
788 | if (err) | ||
789 | goto out_detach; | ||
790 | } | ||
791 | |||
736 | err = uif_init(ubi); | 792 | err = uif_init(ubi); |
737 | if (err) | 793 | if (err) |
738 | goto out_detach; | 794 | goto out_detach; |
@@ -858,20 +914,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) | |||
858 | } | 914 | } |
859 | 915 | ||
860 | /** | 916 | /** |
861 | * ltree_entry_ctor - lock tree entries slab cache constructor. | ||
862 | * @obj: the lock-tree entry to construct | ||
863 | * @cache: the lock tree entry slab cache | ||
864 | * @flags: constructor flags | ||
865 | */ | ||
866 | static void ltree_entry_ctor(struct kmem_cache *cache, void *obj) | ||
867 | { | ||
868 | struct ubi_ltree_entry *le = obj; | ||
869 | |||
870 | le->users = 0; | ||
871 | init_rwsem(&le->mutex); | ||
872 | } | ||
873 | |||
874 | /** | ||
875 | * find_mtd_device - open an MTD device by its name or number. | 917 | * find_mtd_device - open an MTD device by its name or number. |
876 | * @mtd_dev: name or number of the device | 918 | * @mtd_dev: name or number of the device |
877 | * | 919 | * |
@@ -933,17 +975,11 @@ static int __init ubi_init(void) | |||
933 | goto out_version; | 975 | goto out_version; |
934 | } | 976 | } |
935 | 977 | ||
936 | ubi_ltree_slab = kmem_cache_create("ubi_ltree_slab", | ||
937 | sizeof(struct ubi_ltree_entry), 0, | ||
938 | 0, <ree_entry_ctor); | ||
939 | if (!ubi_ltree_slab) | ||
940 | goto out_dev_unreg; | ||
941 | |||
942 | ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", | 978 | ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", |
943 | sizeof(struct ubi_wl_entry), | 979 | sizeof(struct ubi_wl_entry), |
944 | 0, 0, NULL); | 980 | 0, 0, NULL); |
945 | if (!ubi_wl_entry_slab) | 981 | if (!ubi_wl_entry_slab) |
946 | goto out_ltree; | 982 | goto out_dev_unreg; |
947 | 983 | ||
948 | /* Attach MTD devices */ | 984 | /* Attach MTD devices */ |
949 | for (i = 0; i < mtd_devs; i++) { | 985 | for (i = 0; i < mtd_devs; i++) { |
@@ -980,8 +1016,6 @@ out_detach: | |||
980 | mutex_unlock(&ubi_devices_mutex); | 1016 | mutex_unlock(&ubi_devices_mutex); |
981 | } | 1017 | } |
982 | kmem_cache_destroy(ubi_wl_entry_slab); | 1018 | kmem_cache_destroy(ubi_wl_entry_slab); |
983 | out_ltree: | ||
984 | kmem_cache_destroy(ubi_ltree_slab); | ||
985 | out_dev_unreg: | 1019 | out_dev_unreg: |
986 | misc_deregister(&ubi_ctrl_cdev); | 1020 | misc_deregister(&ubi_ctrl_cdev); |
987 | out_version: | 1021 | out_version: |
@@ -1005,7 +1039,6 @@ static void __exit ubi_exit(void) | |||
1005 | mutex_unlock(&ubi_devices_mutex); | 1039 | mutex_unlock(&ubi_devices_mutex); |
1006 | } | 1040 | } |
1007 | kmem_cache_destroy(ubi_wl_entry_slab); | 1041 | kmem_cache_destroy(ubi_wl_entry_slab); |
1008 | kmem_cache_destroy(ubi_ltree_slab); | ||
1009 | misc_deregister(&ubi_ctrl_cdev); | 1042 | misc_deregister(&ubi_ctrl_cdev); |
1010 | class_remove_file(ubi_class, &ubi_version); | 1043 | class_remove_file(ubi_class, &ubi_version); |
1011 | class_destroy(ubi_class); | 1044 | class_destroy(ubi_class); |
@@ -1066,7 +1099,7 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp) | |||
1066 | struct mtd_dev_param *p; | 1099 | struct mtd_dev_param *p; |
1067 | char buf[MTD_PARAM_LEN_MAX]; | 1100 | char buf[MTD_PARAM_LEN_MAX]; |
1068 | char *pbuf = &buf[0]; | 1101 | char *pbuf = &buf[0]; |
1069 | char *tokens[3] = {NULL, NULL, NULL}; | 1102 | char *tokens[2] = {NULL, NULL}; |
1070 | 1103 | ||
1071 | if (!val) | 1104 | if (!val) |
1072 | return -EINVAL; | 1105 | return -EINVAL; |
@@ -1096,7 +1129,7 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp) | |||
1096 | if (buf[len - 1] == '\n') | 1129 | if (buf[len - 1] == '\n') |
1097 | buf[len - 1] = '\0'; | 1130 | buf[len - 1] = '\0'; |
1098 | 1131 | ||
1099 | for (i = 0; i < 3; i++) | 1132 | for (i = 0; i < 2; i++) |
1100 | tokens[i] = strsep(&pbuf, ","); | 1133 | tokens[i] = strsep(&pbuf, ","); |
1101 | 1134 | ||
1102 | if (pbuf) { | 1135 | if (pbuf) { |
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 5ec13dc4705b..9d6aae5449b6 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c | |||
@@ -132,8 +132,15 @@ static int vol_cdev_release(struct inode *inode, struct file *file) | |||
132 | if (vol->updating) { | 132 | if (vol->updating) { |
133 | ubi_warn("update of volume %d not finished, volume is damaged", | 133 | ubi_warn("update of volume %d not finished, volume is damaged", |
134 | vol->vol_id); | 134 | vol->vol_id); |
135 | ubi_assert(!vol->changing_leb); | ||
135 | vol->updating = 0; | 136 | vol->updating = 0; |
136 | vfree(vol->upd_buf); | 137 | vfree(vol->upd_buf); |
138 | } else if (vol->changing_leb) { | ||
139 | dbg_msg("only %lld of %lld bytes received for atomic LEB change" | ||
140 | " for volume %d:%d, cancel", vol->upd_received, | ||
141 | vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id); | ||
142 | vol->changing_leb = 0; | ||
143 | vfree(vol->upd_buf); | ||
137 | } | 144 | } |
138 | 145 | ||
139 | ubi_close_volume(desc); | 146 | ubi_close_volume(desc); |
@@ -184,13 +191,13 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, | |||
184 | struct ubi_volume_desc *desc = file->private_data; | 191 | struct ubi_volume_desc *desc = file->private_data; |
185 | struct ubi_volume *vol = desc->vol; | 192 | struct ubi_volume *vol = desc->vol; |
186 | struct ubi_device *ubi = vol->ubi; | 193 | struct ubi_device *ubi = vol->ubi; |
187 | int err, lnum, off, len, vol_id = desc->vol->vol_id, tbuf_size; | 194 | int err, lnum, off, len, tbuf_size; |
188 | size_t count_save = count; | 195 | size_t count_save = count; |
189 | void *tbuf; | 196 | void *tbuf; |
190 | uint64_t tmp; | 197 | uint64_t tmp; |
191 | 198 | ||
192 | dbg_msg("read %zd bytes from offset %lld of volume %d", | 199 | dbg_msg("read %zd bytes from offset %lld of volume %d", |
193 | count, *offp, vol_id); | 200 | count, *offp, vol->vol_id); |
194 | 201 | ||
195 | if (vol->updating) { | 202 | if (vol->updating) { |
196 | dbg_err("updating"); | 203 | dbg_err("updating"); |
@@ -204,7 +211,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, | |||
204 | return 0; | 211 | return 0; |
205 | 212 | ||
206 | if (vol->corrupted) | 213 | if (vol->corrupted) |
207 | dbg_msg("read from corrupted volume %d", vol_id); | 214 | dbg_msg("read from corrupted volume %d", vol->vol_id); |
208 | 215 | ||
209 | if (*offp + count > vol->used_bytes) | 216 | if (*offp + count > vol->used_bytes) |
210 | count_save = count = vol->used_bytes - *offp; | 217 | count_save = count = vol->used_bytes - *offp; |
@@ -274,7 +281,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | |||
274 | uint64_t tmp; | 281 | uint64_t tmp; |
275 | 282 | ||
276 | dbg_msg("requested: write %zd bytes to offset %lld of volume %u", | 283 | dbg_msg("requested: write %zd bytes to offset %lld of volume %u", |
277 | count, *offp, desc->vol->vol_id); | 284 | count, *offp, vol->vol_id); |
278 | 285 | ||
279 | if (vol->vol_type == UBI_STATIC_VOLUME) | 286 | if (vol->vol_type == UBI_STATIC_VOLUME) |
280 | return -EROFS; | 287 | return -EROFS; |
@@ -351,23 +358,32 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf, | |||
351 | struct ubi_volume *vol = desc->vol; | 358 | struct ubi_volume *vol = desc->vol; |
352 | struct ubi_device *ubi = vol->ubi; | 359 | struct ubi_device *ubi = vol->ubi; |
353 | 360 | ||
354 | if (!vol->updating) | 361 | if (!vol->updating && !vol->changing_leb) |
355 | return vol_cdev_direct_write(file, buf, count, offp); | 362 | return vol_cdev_direct_write(file, buf, count, offp); |
356 | 363 | ||
357 | err = ubi_more_update_data(ubi, vol->vol_id, buf, count); | 364 | if (vol->updating) |
365 | err = ubi_more_update_data(ubi, vol, buf, count); | ||
366 | else | ||
367 | err = ubi_more_leb_change_data(ubi, vol, buf, count); | ||
368 | |||
358 | if (err < 0) { | 369 | if (err < 0) { |
359 | ubi_err("cannot write %zd bytes of update data, error %d", | 370 | ubi_err("cannot accept more %zd bytes of data, error %d", |
360 | count, err); | 371 | count, err); |
361 | return err; | 372 | return err; |
362 | } | 373 | } |
363 | 374 | ||
364 | if (err) { | 375 | if (err) { |
365 | /* | 376 | /* |
366 | * Update is finished, @err contains number of actually written | 377 | * The operation is finished, @err contains number of actually |
367 | * bytes now. | 378 | * written bytes. |
368 | */ | 379 | */ |
369 | count = err; | 380 | count = err; |
370 | 381 | ||
382 | if (vol->changing_leb) { | ||
383 | revoke_exclusive(desc, UBI_READWRITE); | ||
384 | return count; | ||
385 | } | ||
386 | |||
371 | err = ubi_check_volume(ubi, vol->vol_id); | 387 | err = ubi_check_volume(ubi, vol->vol_id); |
372 | if (err < 0) | 388 | if (err < 0) |
373 | return err; | 389 | return err; |
@@ -382,7 +398,6 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf, | |||
382 | revoke_exclusive(desc, UBI_READWRITE); | 398 | revoke_exclusive(desc, UBI_READWRITE); |
383 | } | 399 | } |
384 | 400 | ||
385 | *offp += count; | ||
386 | return count; | 401 | return count; |
387 | } | 402 | } |
388 | 403 | ||
@@ -427,11 +442,46 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file, | |||
427 | if (err < 0) | 442 | if (err < 0) |
428 | break; | 443 | break; |
429 | 444 | ||
430 | err = ubi_start_update(ubi, vol->vol_id, bytes); | 445 | err = ubi_start_update(ubi, vol, bytes); |
431 | if (bytes == 0) | 446 | if (bytes == 0) |
432 | revoke_exclusive(desc, UBI_READWRITE); | 447 | revoke_exclusive(desc, UBI_READWRITE); |
448 | break; | ||
449 | } | ||
450 | |||
451 | /* Atomic logical eraseblock change command */ | ||
452 | case UBI_IOCEBCH: | ||
453 | { | ||
454 | struct ubi_leb_change_req req; | ||
455 | |||
456 | err = copy_from_user(&req, argp, | ||
457 | sizeof(struct ubi_leb_change_req)); | ||
458 | if (err) { | ||
459 | err = -EFAULT; | ||
460 | break; | ||
461 | } | ||
462 | |||
463 | if (desc->mode == UBI_READONLY || | ||
464 | vol->vol_type == UBI_STATIC_VOLUME) { | ||
465 | err = -EROFS; | ||
466 | break; | ||
467 | } | ||
468 | |||
469 | /* Validate the request */ | ||
470 | err = -EINVAL; | ||
471 | if (req.lnum < 0 || req.lnum >= vol->reserved_pebs || | ||
472 | req.bytes < 0 || req.lnum >= vol->usable_leb_size) | ||
473 | break; | ||
474 | if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM && | ||
475 | req.dtype != UBI_UNKNOWN) | ||
476 | break; | ||
477 | |||
478 | err = get_exclusive(desc); | ||
479 | if (err < 0) | ||
480 | break; | ||
433 | 481 | ||
434 | file->f_pos = 0; | 482 | err = ubi_start_leb_change(ubi, vol, &req); |
483 | if (req.bytes == 0) | ||
484 | revoke_exclusive(desc, UBI_READWRITE); | ||
435 | break; | 485 | break; |
436 | } | 486 | } |
437 | 487 | ||
@@ -447,7 +497,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file, | |||
447 | break; | 497 | break; |
448 | } | 498 | } |
449 | 499 | ||
450 | if (desc->mode == UBI_READONLY) { | 500 | if (desc->mode == UBI_READONLY || |
501 | vol->vol_type == UBI_STATIC_VOLUME) { | ||
451 | err = -EROFS; | 502 | err = -EROFS; |
452 | break; | 503 | break; |
453 | } | 504 | } |
@@ -457,11 +508,6 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file, | |||
457 | break; | 508 | break; |
458 | } | 509 | } |
459 | 510 | ||
460 | if (vol->vol_type != UBI_DYNAMIC_VOLUME) { | ||
461 | err = -EROFS; | ||
462 | break; | ||
463 | } | ||
464 | |||
465 | dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); | 511 | dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); |
466 | err = ubi_eba_unmap_leb(ubi, vol, lnum); | 512 | err = ubi_eba_unmap_leb(ubi, vol, lnum); |
467 | if (err) | 513 | if (err) |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 85297cde4ac5..7ce91ca742b1 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -78,7 +78,7 @@ static unsigned long long next_sqnum(struct ubi_device *ubi) | |||
78 | */ | 78 | */ |
79 | static int ubi_get_compat(const struct ubi_device *ubi, int vol_id) | 79 | static int ubi_get_compat(const struct ubi_device *ubi, int vol_id) |
80 | { | 80 | { |
81 | if (vol_id == UBI_LAYOUT_VOL_ID) | 81 | if (vol_id == UBI_LAYOUT_VOLUME_ID) |
82 | return UBI_LAYOUT_VOLUME_COMPAT; | 82 | return UBI_LAYOUT_VOLUME_COMPAT; |
83 | return 0; | 83 | return 0; |
84 | } | 84 | } |
@@ -137,10 +137,12 @@ static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi, | |||
137 | { | 137 | { |
138 | struct ubi_ltree_entry *le, *le1, *le_free; | 138 | struct ubi_ltree_entry *le, *le1, *le_free; |
139 | 139 | ||
140 | le = kmem_cache_alloc(ubi_ltree_slab, GFP_NOFS); | 140 | le = kmalloc(sizeof(struct ubi_ltree_entry), GFP_NOFS); |
141 | if (!le) | 141 | if (!le) |
142 | return ERR_PTR(-ENOMEM); | 142 | return ERR_PTR(-ENOMEM); |
143 | 143 | ||
144 | le->users = 0; | ||
145 | init_rwsem(&le->mutex); | ||
144 | le->vol_id = vol_id; | 146 | le->vol_id = vol_id; |
145 | le->lnum = lnum; | 147 | le->lnum = lnum; |
146 | 148 | ||
@@ -188,7 +190,7 @@ static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi, | |||
188 | spin_unlock(&ubi->ltree_lock); | 190 | spin_unlock(&ubi->ltree_lock); |
189 | 191 | ||
190 | if (le_free) | 192 | if (le_free) |
191 | kmem_cache_free(ubi_ltree_slab, le_free); | 193 | kfree(le_free); |
192 | 194 | ||
193 | return le; | 195 | return le; |
194 | } | 196 | } |
@@ -236,7 +238,7 @@ static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum) | |||
236 | 238 | ||
237 | up_read(&le->mutex); | 239 | up_read(&le->mutex); |
238 | if (free) | 240 | if (free) |
239 | kmem_cache_free(ubi_ltree_slab, le); | 241 | kfree(le); |
240 | } | 242 | } |
241 | 243 | ||
242 | /** | 244 | /** |
@@ -292,7 +294,7 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) | |||
292 | free = 0; | 294 | free = 0; |
293 | spin_unlock(&ubi->ltree_lock); | 295 | spin_unlock(&ubi->ltree_lock); |
294 | if (free) | 296 | if (free) |
295 | kmem_cache_free(ubi_ltree_slab, le); | 297 | kfree(le); |
296 | 298 | ||
297 | return 1; | 299 | return 1; |
298 | } | 300 | } |
@@ -321,7 +323,7 @@ static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) | |||
321 | 323 | ||
322 | up_write(&le->mutex); | 324 | up_write(&le->mutex); |
323 | if (free) | 325 | if (free) |
324 | kmem_cache_free(ubi_ltree_slab, le); | 326 | kfree(le); |
325 | } | 327 | } |
326 | 328 | ||
327 | /** | 329 | /** |
@@ -339,9 +341,6 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, | |||
339 | { | 341 | { |
340 | int err, pnum, vol_id = vol->vol_id; | 342 | int err, pnum, vol_id = vol->vol_id; |
341 | 343 | ||
342 | ubi_assert(ubi->ref_count > 0); | ||
343 | ubi_assert(vol->ref_count > 0); | ||
344 | |||
345 | if (ubi->ro_mode) | 344 | if (ubi->ro_mode) |
346 | return -EROFS; | 345 | return -EROFS; |
347 | 346 | ||
@@ -390,9 +389,6 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
390 | struct ubi_vid_hdr *vid_hdr; | 389 | struct ubi_vid_hdr *vid_hdr; |
391 | uint32_t uninitialized_var(crc); | 390 | uint32_t uninitialized_var(crc); |
392 | 391 | ||
393 | ubi_assert(ubi->ref_count > 0); | ||
394 | ubi_assert(vol->ref_count > 0); | ||
395 | |||
396 | err = leb_read_lock(ubi, vol_id, lnum); | 392 | err = leb_read_lock(ubi, vol_id, lnum); |
397 | if (err) | 393 | if (err) |
398 | return err; | 394 | return err; |
@@ -616,9 +612,6 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
616 | int err, pnum, tries = 0, vol_id = vol->vol_id; | 612 | int err, pnum, tries = 0, vol_id = vol->vol_id; |
617 | struct ubi_vid_hdr *vid_hdr; | 613 | struct ubi_vid_hdr *vid_hdr; |
618 | 614 | ||
619 | ubi_assert(ubi->ref_count > 0); | ||
620 | ubi_assert(vol->ref_count > 0); | ||
621 | |||
622 | if (ubi->ro_mode) | 615 | if (ubi->ro_mode) |
623 | return -EROFS; | 616 | return -EROFS; |
624 | 617 | ||
@@ -752,9 +745,6 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, | |||
752 | struct ubi_vid_hdr *vid_hdr; | 745 | struct ubi_vid_hdr *vid_hdr; |
753 | uint32_t crc; | 746 | uint32_t crc; |
754 | 747 | ||
755 | ubi_assert(ubi->ref_count > 0); | ||
756 | ubi_assert(vol->ref_count > 0); | ||
757 | |||
758 | if (ubi->ro_mode) | 748 | if (ubi->ro_mode) |
759 | return -EROFS; | 749 | return -EROFS; |
760 | 750 | ||
@@ -869,12 +859,20 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, | |||
869 | struct ubi_vid_hdr *vid_hdr; | 859 | struct ubi_vid_hdr *vid_hdr; |
870 | uint32_t crc; | 860 | uint32_t crc; |
871 | 861 | ||
872 | ubi_assert(ubi->ref_count > 0); | ||
873 | ubi_assert(vol->ref_count > 0); | ||
874 | |||
875 | if (ubi->ro_mode) | 862 | if (ubi->ro_mode) |
876 | return -EROFS; | 863 | return -EROFS; |
877 | 864 | ||
865 | if (len == 0) { | ||
866 | /* | ||
867 | * Special case when data length is zero. In this case the LEB | ||
868 | * has to be unmapped and mapped somewhere else. | ||
869 | */ | ||
870 | err = ubi_eba_unmap_leb(ubi, vol, lnum); | ||
871 | if (err) | ||
872 | return err; | ||
873 | return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype); | ||
874 | } | ||
875 | |||
878 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); | 876 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); |
879 | if (!vid_hdr) | 877 | if (!vid_hdr) |
880 | return -ENOMEM; | 878 | return -ENOMEM; |
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 146957c3380d..a70d58823f8d 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c | |||
@@ -480,9 +480,9 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum) | |||
480 | { | 480 | { |
481 | struct ubi_volume *vol = desc->vol; | 481 | struct ubi_volume *vol = desc->vol; |
482 | struct ubi_device *ubi = vol->ubi; | 482 | struct ubi_device *ubi = vol->ubi; |
483 | int err, vol_id = vol->vol_id; | 483 | int err; |
484 | 484 | ||
485 | dbg_msg("erase LEB %d:%d", vol_id, lnum); | 485 | dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); |
486 | 486 | ||
487 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) | 487 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) |
488 | return -EROFS; | 488 | return -EROFS; |
@@ -541,9 +541,8 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum) | |||
541 | { | 541 | { |
542 | struct ubi_volume *vol = desc->vol; | 542 | struct ubi_volume *vol = desc->vol; |
543 | struct ubi_device *ubi = vol->ubi; | 543 | struct ubi_device *ubi = vol->ubi; |
544 | int vol_id = vol->vol_id; | ||
545 | 544 | ||
546 | dbg_msg("unmap LEB %d:%d", vol_id, lnum); | 545 | dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum); |
547 | 546 | ||
548 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) | 547 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) |
549 | return -EROFS; | 548 | return -EROFS; |
@@ -579,9 +578,8 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) | |||
579 | { | 578 | { |
580 | struct ubi_volume *vol = desc->vol; | 579 | struct ubi_volume *vol = desc->vol; |
581 | struct ubi_device *ubi = vol->ubi; | 580 | struct ubi_device *ubi = vol->ubi; |
582 | int vol_id = vol->vol_id; | ||
583 | 581 | ||
584 | dbg_msg("unmap LEB %d:%d", vol_id, lnum); | 582 | dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum); |
585 | 583 | ||
586 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) | 584 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) |
587 | return -EROFS; | 585 | return -EROFS; |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index c57e8eff9866..05aa3e7daba1 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
@@ -286,9 +286,14 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, | |||
286 | * FIXME: but this is anyway obsolete and will be removed at | 286 | * FIXME: but this is anyway obsolete and will be removed at |
287 | * some point. | 287 | * some point. |
288 | */ | 288 | */ |
289 | |||
290 | dbg_bld("using old crappy leb_ver stuff"); | 289 | dbg_bld("using old crappy leb_ver stuff"); |
291 | 290 | ||
291 | if (v1 == v2) { | ||
292 | ubi_err("PEB %d and PEB %d have the same version %lld", | ||
293 | seb->pnum, pnum, v1); | ||
294 | return -EINVAL; | ||
295 | } | ||
296 | |||
292 | abs = v1 - v2; | 297 | abs = v1 - v2; |
293 | if (abs < 0) | 298 | if (abs < 0) |
294 | abs = -abs; | 299 | abs = -abs; |
@@ -390,7 +395,6 @@ out_free_buf: | |||
390 | vfree(buf); | 395 | vfree(buf); |
391 | out_free_vidh: | 396 | out_free_vidh: |
392 | ubi_free_vid_hdr(ubi, vh); | 397 | ubi_free_vid_hdr(ubi, vh); |
393 | ubi_assert(err < 0); | ||
394 | return err; | 398 | return err; |
395 | } | 399 | } |
396 | 400 | ||
@@ -854,7 +858,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum | |||
854 | } | 858 | } |
855 | 859 | ||
856 | vol_id = be32_to_cpu(vidh->vol_id); | 860 | vol_id = be32_to_cpu(vidh->vol_id); |
857 | if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOL_ID) { | 861 | if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) { |
858 | int lnum = be32_to_cpu(vidh->lnum); | 862 | int lnum = be32_to_cpu(vidh->lnum); |
859 | 863 | ||
860 | /* Unsupported internal volume */ | 864 | /* Unsupported internal volume */ |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index ef22f922f580..457710615261 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -144,7 +144,6 @@ struct ubi_volume_desc; | |||
144 | * @readers: number of users holding this volume in read-only mode | 144 | * @readers: number of users holding this volume in read-only mode |
145 | * @writers: number of users holding this volume in read-write mode | 145 | * @writers: number of users holding this volume in read-write mode |
146 | * @exclusive: whether somebody holds this volume in exclusive mode | 146 | * @exclusive: whether somebody holds this volume in exclusive mode |
147 | * @checked: if this static volume was checked | ||
148 | * | 147 | * |
149 | * @reserved_pebs: how many physical eraseblocks are reserved for this volume | 148 | * @reserved_pebs: how many physical eraseblocks are reserved for this volume |
150 | * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) | 149 | * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) |
@@ -152,21 +151,30 @@ struct ubi_volume_desc; | |||
152 | * @used_ebs: how many logical eraseblocks in this volume contain data | 151 | * @used_ebs: how many logical eraseblocks in this volume contain data |
153 | * @last_eb_bytes: how many bytes are stored in the last logical eraseblock | 152 | * @last_eb_bytes: how many bytes are stored in the last logical eraseblock |
154 | * @used_bytes: how many bytes of data this volume contains | 153 | * @used_bytes: how many bytes of data this volume contains |
155 | * @upd_marker: non-zero if the update marker is set for this volume | ||
156 | * @corrupted: non-zero if the volume is corrupted (static volumes only) | ||
157 | * @alignment: volume alignment | 154 | * @alignment: volume alignment |
158 | * @data_pad: how many bytes are not used at the end of physical eraseblocks to | 155 | * @data_pad: how many bytes are not used at the end of physical eraseblocks to |
159 | * satisfy the requested alignment | 156 | * satisfy the requested alignment |
160 | * @name_len: volume name length | 157 | * @name_len: volume name length |
161 | * @name: volume name | 158 | * @name: volume name |
162 | * | 159 | * |
163 | * @updating: whether the volume is being updated | ||
164 | * @upd_ebs: how many eraseblocks are expected to be updated | 160 | * @upd_ebs: how many eraseblocks are expected to be updated |
165 | * @upd_bytes: how many bytes are expected to be received | 161 | * @ch_lnum: LEB number which is being changing by the atomic LEB change |
166 | * @upd_received: how many update bytes were already received | 162 | * operation |
167 | * @upd_buf: update buffer which is used to collect update data | 163 | * @ch_dtype: data persistency type which is being changing by the atomic LEB |
164 | * change operation | ||
165 | * @upd_bytes: how many bytes are expected to be received for volume update or | ||
166 | * atomic LEB change | ||
167 | * @upd_received: how many bytes were already received for volume update or | ||
168 | * atomic LEB change | ||
169 | * @upd_buf: update buffer which is used to collect update data or data for | ||
170 | * atomic LEB change | ||
168 | * | 171 | * |
169 | * @eba_tbl: EBA table of this volume (LEB->PEB mapping) | 172 | * @eba_tbl: EBA table of this volume (LEB->PEB mapping) |
173 | * @checked: %1 if this static volume was checked | ||
174 | * @corrupted: %1 if the volume is corrupted (static volumes only) | ||
175 | * @upd_marker: %1 if the update marker is set for this volume | ||
176 | * @updating: %1 if the volume is being updated | ||
177 | * @changing_leb: %1 if the atomic LEB change ioctl command is in progress | ||
170 | * | 178 | * |
171 | * @gluebi_desc: gluebi UBI volume descriptor | 179 | * @gluebi_desc: gluebi UBI volume descriptor |
172 | * @gluebi_refcount: reference count of the gluebi MTD device | 180 | * @gluebi_refcount: reference count of the gluebi MTD device |
@@ -189,7 +197,6 @@ struct ubi_volume { | |||
189 | int readers; | 197 | int readers; |
190 | int writers; | 198 | int writers; |
191 | int exclusive; | 199 | int exclusive; |
192 | int checked; | ||
193 | 200 | ||
194 | int reserved_pebs; | 201 | int reserved_pebs; |
195 | int vol_type; | 202 | int vol_type; |
@@ -197,23 +204,31 @@ struct ubi_volume { | |||
197 | int used_ebs; | 204 | int used_ebs; |
198 | int last_eb_bytes; | 205 | int last_eb_bytes; |
199 | long long used_bytes; | 206 | long long used_bytes; |
200 | int upd_marker; | ||
201 | int corrupted; | ||
202 | int alignment; | 207 | int alignment; |
203 | int data_pad; | 208 | int data_pad; |
204 | int name_len; | 209 | int name_len; |
205 | char name[UBI_VOL_NAME_MAX+1]; | 210 | char name[UBI_VOL_NAME_MAX+1]; |
206 | 211 | ||
207 | int updating; | ||
208 | int upd_ebs; | 212 | int upd_ebs; |
213 | int ch_lnum; | ||
214 | int ch_dtype; | ||
209 | long long upd_bytes; | 215 | long long upd_bytes; |
210 | long long upd_received; | 216 | long long upd_received; |
211 | void *upd_buf; | 217 | void *upd_buf; |
212 | 218 | ||
213 | int *eba_tbl; | 219 | int *eba_tbl; |
220 | int checked:1; | ||
221 | int corrupted:1; | ||
222 | int upd_marker:1; | ||
223 | int updating:1; | ||
224 | int changing_leb:1; | ||
214 | 225 | ||
215 | #ifdef CONFIG_MTD_UBI_GLUEBI | 226 | #ifdef CONFIG_MTD_UBI_GLUEBI |
216 | /* Gluebi-related stuff may be compiled out */ | 227 | /* |
228 | * Gluebi-related stuff may be compiled out. | ||
229 | * TODO: this should not be built into UBI but should be a separate | ||
230 | * ubimtd driver which works on top of UBI and emulates MTD devices. | ||
231 | */ | ||
217 | struct ubi_volume_desc *gluebi_desc; | 232 | struct ubi_volume_desc *gluebi_desc; |
218 | int gluebi_refcount; | 233 | int gluebi_refcount; |
219 | struct mtd_info gluebi_mtd; | 234 | struct mtd_info gluebi_mtd; |
@@ -250,9 +265,11 @@ struct ubi_wl_entry; | |||
250 | * @rsvd_pebs: count of reserved physical eraseblocks | 265 | * @rsvd_pebs: count of reserved physical eraseblocks |
251 | * @avail_pebs: count of available physical eraseblocks | 266 | * @avail_pebs: count of available physical eraseblocks |
252 | * @beb_rsvd_pebs: how many physical eraseblocks are reserved for bad PEB | 267 | * @beb_rsvd_pebs: how many physical eraseblocks are reserved for bad PEB |
253 | * handling | 268 | * handling |
254 | * @beb_rsvd_level: normal level of PEBs reserved for bad PEB handling | 269 | * @beb_rsvd_level: normal level of PEBs reserved for bad PEB handling |
255 | * | 270 | * |
271 | * @autoresize_vol_id: ID of the volume which has to be auto-resized at the end | ||
272 | * of UBI ititializetion | ||
256 | * @vtbl_slots: how many slots are available in the volume table | 273 | * @vtbl_slots: how many slots are available in the volume table |
257 | * @vtbl_size: size of the volume table in bytes | 274 | * @vtbl_size: size of the volume table in bytes |
258 | * @vtbl: in-RAM volume table copy | 275 | * @vtbl: in-RAM volume table copy |
@@ -333,12 +350,14 @@ struct ubi_device { | |||
333 | int beb_rsvd_pebs; | 350 | int beb_rsvd_pebs; |
334 | int beb_rsvd_level; | 351 | int beb_rsvd_level; |
335 | 352 | ||
353 | int autoresize_vol_id; | ||
336 | int vtbl_slots; | 354 | int vtbl_slots; |
337 | int vtbl_size; | 355 | int vtbl_size; |
338 | struct ubi_vtbl_record *vtbl; | 356 | struct ubi_vtbl_record *vtbl; |
339 | struct mutex volumes_mutex; | 357 | struct mutex volumes_mutex; |
340 | 358 | ||
341 | int max_ec; | 359 | int max_ec; |
360 | /* TODO: mean_ec is not updated run-time, fix */ | ||
342 | int mean_ec; | 361 | int mean_ec; |
343 | 362 | ||
344 | /* EBA unit's stuff */ | 363 | /* EBA unit's stuff */ |
@@ -399,7 +418,6 @@ struct ubi_device { | |||
399 | #endif | 418 | #endif |
400 | }; | 419 | }; |
401 | 420 | ||
402 | extern struct kmem_cache *ubi_ltree_slab; | ||
403 | extern struct kmem_cache *ubi_wl_entry_slab; | 421 | extern struct kmem_cache *ubi_wl_entry_slab; |
404 | extern struct file_operations ubi_ctrl_cdev_operations; | 422 | extern struct file_operations ubi_ctrl_cdev_operations; |
405 | extern struct file_operations ubi_cdev_operations; | 423 | extern struct file_operations ubi_cdev_operations; |
@@ -420,9 +438,14 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol); | |||
420 | void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol); | 438 | void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol); |
421 | 439 | ||
422 | /* upd.c */ | 440 | /* upd.c */ |
423 | int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes); | 441 | int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, |
424 | int ubi_more_update_data(struct ubi_device *ubi, int vol_id, | 442 | long long bytes); |
443 | int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, | ||
425 | const void __user *buf, int count); | 444 | const void __user *buf, int count); |
445 | int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, | ||
446 | const struct ubi_leb_change_req *req); | ||
447 | int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, | ||
448 | const void __user *buf, int count); | ||
426 | 449 | ||
427 | /* misc.c */ | 450 | /* misc.c */ |
428 | int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length); | 451 | int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length); |
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index e32b04d2e048..ddaa1a56cc69 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c | |||
@@ -22,7 +22,8 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * This file contains implementation of the volume update functionality. | 25 | * This file contains implementation of the volume update and atomic LEB change |
26 | * functionality. | ||
26 | * | 27 | * |
27 | * The update operation is based on the per-volume update marker which is | 28 | * The update operation is based on the per-volume update marker which is |
28 | * stored in the volume table. The update marker is set before the update | 29 | * stored in the volume table. The update marker is set before the update |
@@ -45,30 +46,30 @@ | |||
45 | /** | 46 | /** |
46 | * set_update_marker - set update marker. | 47 | * set_update_marker - set update marker. |
47 | * @ubi: UBI device description object | 48 | * @ubi: UBI device description object |
48 | * @vol_id: volume ID | 49 | * @vol: volume description object |
49 | * | 50 | * |
50 | * This function sets the update marker flag for volume @vol_id. Returns zero | 51 | * This function sets the update marker flag for volume @vol. Returns zero |
51 | * in case of success and a negative error code in case of failure. | 52 | * in case of success and a negative error code in case of failure. |
52 | */ | 53 | */ |
53 | static int set_update_marker(struct ubi_device *ubi, int vol_id) | 54 | static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol) |
54 | { | 55 | { |
55 | int err; | 56 | int err; |
56 | struct ubi_vtbl_record vtbl_rec; | 57 | struct ubi_vtbl_record vtbl_rec; |
57 | struct ubi_volume *vol = ubi->volumes[vol_id]; | ||
58 | 58 | ||
59 | dbg_msg("set update marker for volume %d", vol_id); | 59 | dbg_msg("set update marker for volume %d", vol->vol_id); |
60 | 60 | ||
61 | if (vol->upd_marker) { | 61 | if (vol->upd_marker) { |
62 | ubi_assert(ubi->vtbl[vol_id].upd_marker); | 62 | ubi_assert(ubi->vtbl[vol->vol_id].upd_marker); |
63 | dbg_msg("already set"); | 63 | dbg_msg("already set"); |
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | 66 | ||
67 | memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); | 67 | memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], |
68 | sizeof(struct ubi_vtbl_record)); | ||
68 | vtbl_rec.upd_marker = 1; | 69 | vtbl_rec.upd_marker = 1; |
69 | 70 | ||
70 | mutex_lock(&ubi->volumes_mutex); | 71 | mutex_lock(&ubi->volumes_mutex); |
71 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); | 72 | err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec); |
72 | mutex_unlock(&ubi->volumes_mutex); | 73 | mutex_unlock(&ubi->volumes_mutex); |
73 | vol->upd_marker = 1; | 74 | vol->upd_marker = 1; |
74 | return err; | 75 | return err; |
@@ -77,23 +78,24 @@ static int set_update_marker(struct ubi_device *ubi, int vol_id) | |||
77 | /** | 78 | /** |
78 | * clear_update_marker - clear update marker. | 79 | * clear_update_marker - clear update marker. |
79 | * @ubi: UBI device description object | 80 | * @ubi: UBI device description object |
80 | * @vol_id: volume ID | 81 | * @vol: volume description object |
81 | * @bytes: new data size in bytes | 82 | * @bytes: new data size in bytes |
82 | * | 83 | * |
83 | * This function clears the update marker for volume @vol_id, sets new volume | 84 | * This function clears the update marker for volume @vol, sets new volume |
84 | * data size and clears the "corrupted" flag (static volumes only). Returns | 85 | * data size and clears the "corrupted" flag (static volumes only). Returns |
85 | * zero in case of success and a negative error code in case of failure. | 86 | * zero in case of success and a negative error code in case of failure. |
86 | */ | 87 | */ |
87 | static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long bytes) | 88 | static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol, |
89 | long long bytes) | ||
88 | { | 90 | { |
89 | int err; | 91 | int err; |
90 | uint64_t tmp; | 92 | uint64_t tmp; |
91 | struct ubi_vtbl_record vtbl_rec; | 93 | struct ubi_vtbl_record vtbl_rec; |
92 | struct ubi_volume *vol = ubi->volumes[vol_id]; | ||
93 | 94 | ||
94 | dbg_msg("clear update marker for volume %d", vol_id); | 95 | dbg_msg("clear update marker for volume %d", vol->vol_id); |
95 | 96 | ||
96 | memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); | 97 | memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], |
98 | sizeof(struct ubi_vtbl_record)); | ||
97 | ubi_assert(vol->upd_marker && vtbl_rec.upd_marker); | 99 | ubi_assert(vol->upd_marker && vtbl_rec.upd_marker); |
98 | vtbl_rec.upd_marker = 0; | 100 | vtbl_rec.upd_marker = 0; |
99 | 101 | ||
@@ -109,7 +111,7 @@ static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long byt | |||
109 | } | 111 | } |
110 | 112 | ||
111 | mutex_lock(&ubi->volumes_mutex); | 113 | mutex_lock(&ubi->volumes_mutex); |
112 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); | 114 | err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec); |
113 | mutex_unlock(&ubi->volumes_mutex); | 115 | mutex_unlock(&ubi->volumes_mutex); |
114 | vol->upd_marker = 0; | 116 | vol->upd_marker = 0; |
115 | return err; | 117 | return err; |
@@ -118,23 +120,24 @@ static int clear_update_marker(struct ubi_device *ubi, int vol_id, long long byt | |||
118 | /** | 120 | /** |
119 | * ubi_start_update - start volume update. | 121 | * ubi_start_update - start volume update. |
120 | * @ubi: UBI device description object | 122 | * @ubi: UBI device description object |
121 | * @vol_id: volume ID | 123 | * @vol: volume description object |
122 | * @bytes: update bytes | 124 | * @bytes: update bytes |
123 | * | 125 | * |
124 | * This function starts volume update operation. If @bytes is zero, the volume | 126 | * This function starts volume update operation. If @bytes is zero, the volume |
125 | * is just wiped out. Returns zero in case of success and a negative error code | 127 | * is just wiped out. Returns zero in case of success and a negative error code |
126 | * in case of failure. | 128 | * in case of failure. |
127 | */ | 129 | */ |
128 | int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes) | 130 | int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, |
131 | long long bytes) | ||
129 | { | 132 | { |
130 | int i, err; | 133 | int i, err; |
131 | uint64_t tmp; | 134 | uint64_t tmp; |
132 | struct ubi_volume *vol = ubi->volumes[vol_id]; | ||
133 | 135 | ||
134 | dbg_msg("start update of volume %d, %llu bytes", vol_id, bytes); | 136 | dbg_msg("start update of volume %d, %llu bytes", vol->vol_id, bytes); |
137 | ubi_assert(!vol->updating && !vol->changing_leb); | ||
135 | vol->updating = 1; | 138 | vol->updating = 1; |
136 | 139 | ||
137 | err = set_update_marker(ubi, vol_id); | 140 | err = set_update_marker(ubi, vol); |
138 | if (err) | 141 | if (err) |
139 | return err; | 142 | return err; |
140 | 143 | ||
@@ -146,7 +149,7 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes) | |||
146 | } | 149 | } |
147 | 150 | ||
148 | if (bytes == 0) { | 151 | if (bytes == 0) { |
149 | err = clear_update_marker(ubi, vol_id, 0); | 152 | err = clear_update_marker(ubi, vol, 0); |
150 | if (err) | 153 | if (err) |
151 | return err; | 154 | return err; |
152 | err = ubi_wl_flush(ubi); | 155 | err = ubi_wl_flush(ubi); |
@@ -167,9 +170,42 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes) | |||
167 | } | 170 | } |
168 | 171 | ||
169 | /** | 172 | /** |
173 | * ubi_start_leb_change - start atomic LEB change. | ||
174 | * @ubi: UBI device description object | ||
175 | * @vol: volume description object | ||
176 | * @req: operation request | ||
177 | * | ||
178 | * This function starts atomic LEB change operation. Returns zero in case of | ||
179 | * success and a negative error code in case of failure. | ||
180 | */ | ||
181 | int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, | ||
182 | const struct ubi_leb_change_req *req) | ||
183 | { | ||
184 | ubi_assert(!vol->updating && !vol->changing_leb); | ||
185 | |||
186 | dbg_msg("start changing LEB %d:%d, %u bytes", | ||
187 | vol->vol_id, req->lnum, req->bytes); | ||
188 | if (req->bytes == 0) | ||
189 | return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0, | ||
190 | req->dtype); | ||
191 | |||
192 | vol->upd_bytes = req->bytes; | ||
193 | vol->upd_received = 0; | ||
194 | vol->changing_leb = 1; | ||
195 | vol->ch_lnum = req->lnum; | ||
196 | vol->ch_dtype = req->dtype; | ||
197 | |||
198 | vol->upd_buf = vmalloc(req->bytes); | ||
199 | if (!vol->upd_buf) | ||
200 | return -ENOMEM; | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | /** | ||
170 | * write_leb - write update data. | 206 | * write_leb - write update data. |
171 | * @ubi: UBI device description object | 207 | * @ubi: UBI device description object |
172 | * @vol_id: volume ID | 208 | * @vol: volume description object |
173 | * @lnum: logical eraseblock number | 209 | * @lnum: logical eraseblock number |
174 | * @buf: data to write | 210 | * @buf: data to write |
175 | * @len: data size | 211 | * @len: data size |
@@ -195,25 +231,22 @@ int ubi_start_update(struct ubi_device *ubi, int vol_id, long long bytes) | |||
195 | * This function returns zero in case of success and a negative error code in | 231 | * This function returns zero in case of success and a negative error code in |
196 | * case of failure. | 232 | * case of failure. |
197 | */ | 233 | */ |
198 | static int write_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf, | 234 | static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, |
199 | int len, int used_ebs) | 235 | void *buf, int len, int used_ebs) |
200 | { | 236 | { |
201 | int err, l; | 237 | int err; |
202 | struct ubi_volume *vol = ubi->volumes[vol_id]; | ||
203 | 238 | ||
204 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { | 239 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
205 | l = ALIGN(len, ubi->min_io_size); | 240 | len = ALIGN(len, ubi->min_io_size); |
206 | memset(buf + len, 0xFF, l - len); | 241 | memset(buf + len, 0xFF, len - len); |
207 | 242 | ||
208 | l = ubi_calc_data_len(ubi, buf, l); | 243 | len = ubi_calc_data_len(ubi, buf, len); |
209 | if (l == 0) { | 244 | if (len == 0) { |
210 | dbg_msg("all %d bytes contain 0xFF - skip", len); | 245 | dbg_msg("all %d bytes contain 0xFF - skip", len); |
211 | return 0; | 246 | return 0; |
212 | } | 247 | } |
213 | if (len != l) | ||
214 | dbg_msg("skip last %d bytes (0xFF)", len - l); | ||
215 | 248 | ||
216 | err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, l, UBI_UNKNOWN); | 249 | err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, UBI_UNKNOWN); |
217 | } else { | 250 | } else { |
218 | /* | 251 | /* |
219 | * When writing static volume, and this is the last logical | 252 | * When writing static volume, and this is the last logical |
@@ -239,16 +272,15 @@ static int write_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf, | |||
239 | * @count: how much bytes to write | 272 | * @count: how much bytes to write |
240 | * | 273 | * |
241 | * This function writes more data to the volume which is being updated. It may | 274 | * This function writes more data to the volume which is being updated. It may |
242 | * be called arbitrary number of times until all of the update data arrive. | 275 | * be called arbitrary number of times until all the update data arriveis. This |
243 | * This function returns %0 in case of success, number of bytes written during | 276 | * function returns %0 in case of success, number of bytes written during the |
244 | * the last call if the whole volume update was successfully finished, and a | 277 | * last call if the whole volume update has been successfully finished, and a |
245 | * negative error code in case of failure. | 278 | * negative error code in case of failure. |
246 | */ | 279 | */ |
247 | int ubi_more_update_data(struct ubi_device *ubi, int vol_id, | 280 | int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, |
248 | const void __user *buf, int count) | 281 | const void __user *buf, int count) |
249 | { | 282 | { |
250 | uint64_t tmp; | 283 | uint64_t tmp; |
251 | struct ubi_volume *vol = ubi->volumes[vol_id]; | ||
252 | int lnum, offs, err = 0, len, to_write = count; | 284 | int lnum, offs, err = 0, len, to_write = count; |
253 | 285 | ||
254 | dbg_msg("write %d of %lld bytes, %lld already passed", | 286 | dbg_msg("write %d of %lld bytes, %lld already passed", |
@@ -293,8 +325,8 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id, | |||
293 | * is the last chunk, it's time to flush the buffer. | 325 | * is the last chunk, it's time to flush the buffer. |
294 | */ | 326 | */ |
295 | ubi_assert(flush_len <= vol->usable_leb_size); | 327 | ubi_assert(flush_len <= vol->usable_leb_size); |
296 | err = write_leb(ubi, vol_id, lnum, vol->upd_buf, | 328 | err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len, |
297 | flush_len, vol->upd_ebs); | 329 | vol->upd_ebs); |
298 | if (err) | 330 | if (err) |
299 | return err; | 331 | return err; |
300 | } | 332 | } |
@@ -321,8 +353,8 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id, | |||
321 | 353 | ||
322 | if (len == vol->usable_leb_size || | 354 | if (len == vol->usable_leb_size || |
323 | vol->upd_received + len == vol->upd_bytes) { | 355 | vol->upd_received + len == vol->upd_bytes) { |
324 | err = write_leb(ubi, vol_id, lnum, vol->upd_buf, len, | 356 | err = write_leb(ubi, vol, lnum, vol->upd_buf, |
325 | vol->upd_ebs); | 357 | len, vol->upd_ebs); |
326 | if (err) | 358 | if (err) |
327 | break; | 359 | break; |
328 | } | 360 | } |
@@ -336,16 +368,70 @@ int ubi_more_update_data(struct ubi_device *ubi, int vol_id, | |||
336 | ubi_assert(vol->upd_received <= vol->upd_bytes); | 368 | ubi_assert(vol->upd_received <= vol->upd_bytes); |
337 | if (vol->upd_received == vol->upd_bytes) { | 369 | if (vol->upd_received == vol->upd_bytes) { |
338 | /* The update is finished, clear the update marker */ | 370 | /* The update is finished, clear the update marker */ |
339 | err = clear_update_marker(ubi, vol_id, vol->upd_bytes); | 371 | err = clear_update_marker(ubi, vol, vol->upd_bytes); |
340 | if (err) | 372 | if (err) |
341 | return err; | 373 | return err; |
342 | err = ubi_wl_flush(ubi); | 374 | err = ubi_wl_flush(ubi); |
343 | if (err == 0) { | 375 | if (err == 0) { |
376 | vol->updating = 0; | ||
344 | err = to_write; | 377 | err = to_write; |
345 | vfree(vol->upd_buf); | 378 | vfree(vol->upd_buf); |
346 | vol->updating = 0; | ||
347 | } | 379 | } |
348 | } | 380 | } |
349 | 381 | ||
350 | return err; | 382 | return err; |
351 | } | 383 | } |
384 | |||
385 | /** | ||
386 | * ubi_more_leb_change_data - accept more data for atomic LEB change. | ||
387 | * @vol: volume description object | ||
388 | * @buf: write data (user-space memory buffer) | ||
389 | * @count: how much bytes to write | ||
390 | * | ||
391 | * This function accepts more data to the volume which is being under the | ||
392 | * "atomic LEB change" operation. It may be called arbitrary number of times | ||
393 | * until all data arrives. This function returns %0 in case of success, number | ||
394 | * of bytes written during the last call if the whole "atomic LEB change" | ||
395 | * operation has been successfully finished, and a negative error code in case | ||
396 | * of failure. | ||
397 | */ | ||
398 | int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, | ||
399 | const void __user *buf, int count) | ||
400 | { | ||
401 | int err; | ||
402 | |||
403 | dbg_msg("write %d of %lld bytes, %lld already passed", | ||
404 | count, vol->upd_bytes, vol->upd_received); | ||
405 | |||
406 | if (ubi->ro_mode) | ||
407 | return -EROFS; | ||
408 | |||
409 | if (vol->upd_received + count > vol->upd_bytes) | ||
410 | count = vol->upd_bytes - vol->upd_received; | ||
411 | |||
412 | err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count); | ||
413 | if (err) | ||
414 | return -EFAULT; | ||
415 | |||
416 | vol->upd_received += count; | ||
417 | |||
418 | if (vol->upd_received == vol->upd_bytes) { | ||
419 | int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size); | ||
420 | |||
421 | memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes); | ||
422 | len = ubi_calc_data_len(ubi, vol->upd_buf, len); | ||
423 | err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum, | ||
424 | vol->upd_buf, len, UBI_UNKNOWN); | ||
425 | if (err) | ||
426 | return err; | ||
427 | } | ||
428 | |||
429 | ubi_assert(vol->upd_received <= vol->upd_bytes); | ||
430 | if (vol->upd_received == vol->upd_bytes) { | ||
431 | vol->changing_leb = 0; | ||
432 | err = count; | ||
433 | vfree(vol->upd_buf); | ||
434 | } | ||
435 | |||
436 | return err; | ||
437 | } | ||
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 177227e1f80d..a3ca2257e601 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
@@ -497,8 +497,6 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
497 | 497 | ||
498 | dbg_msg("re-size volume %d to from %d to %d PEBs", | 498 | dbg_msg("re-size volume %d to from %d to %d PEBs", |
499 | vol_id, vol->reserved_pebs, reserved_pebs); | 499 | vol_id, vol->reserved_pebs, reserved_pebs); |
500 | ubi_assert(desc->mode == UBI_EXCLUSIVE); | ||
501 | ubi_assert(vol == ubi->volumes[vol_id]); | ||
502 | 500 | ||
503 | if (vol->vol_type == UBI_STATIC_VOLUME && | 501 | if (vol->vol_type == UBI_STATIC_VOLUME && |
504 | reserved_pebs < vol->used_ebs) { | 502 | reserved_pebs < vol->used_ebs) { |
@@ -526,7 +524,6 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
526 | } | 524 | } |
527 | spin_unlock(&ubi->volumes_lock); | 525 | spin_unlock(&ubi->volumes_lock); |
528 | 526 | ||
529 | |||
530 | /* Reserve physical eraseblocks */ | 527 | /* Reserve physical eraseblocks */ |
531 | pebs = reserved_pebs - vol->reserved_pebs; | 528 | pebs = reserved_pebs - vol->reserved_pebs; |
532 | if (pebs > 0) { | 529 | if (pebs > 0) { |
@@ -746,11 +743,6 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
746 | goto fail; | 743 | goto fail; |
747 | } | 744 | } |
748 | 745 | ||
749 | if (vol->upd_marker != 0 && vol->upd_marker != 1) { | ||
750 | ubi_err("bad upd_marker"); | ||
751 | goto fail; | ||
752 | } | ||
753 | |||
754 | if (vol->upd_marker && vol->corrupted) { | 746 | if (vol->upd_marker && vol->corrupted) { |
755 | dbg_err("update marker and corrupted simultaneously"); | 747 | dbg_err("update marker and corrupted simultaneously"); |
756 | goto fail; | 748 | goto fail; |
@@ -785,7 +777,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
785 | 777 | ||
786 | n = (long long)vol->used_ebs * vol->usable_leb_size; | 778 | n = (long long)vol->used_ebs * vol->usable_leb_size; |
787 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { | 779 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
788 | if (vol->corrupted != 0) { | 780 | if (vol->corrupted) { |
789 | ubi_err("corrupted dynamic volume"); | 781 | ubi_err("corrupted dynamic volume"); |
790 | goto fail; | 782 | goto fail; |
791 | } | 783 | } |
@@ -802,10 +794,6 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
802 | goto fail; | 794 | goto fail; |
803 | } | 795 | } |
804 | } else { | 796 | } else { |
805 | if (vol->corrupted != 0 && vol->corrupted != 1) { | ||
806 | ubi_err("bad corrupted"); | ||
807 | goto fail; | ||
808 | } | ||
809 | if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) { | 797 | if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) { |
810 | ubi_err("bad used_ebs"); | 798 | ubi_err("bad used_ebs"); |
811 | goto fail; | 799 | goto fail; |
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 7a1a8a1da610..56fc3fbce838 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
@@ -89,7 +89,7 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, | |||
89 | struct ubi_volume *layout_vol; | 89 | struct ubi_volume *layout_vol; |
90 | 90 | ||
91 | ubi_assert(idx >= 0 && idx < ubi->vtbl_slots); | 91 | ubi_assert(idx >= 0 && idx < ubi->vtbl_slots); |
92 | layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOL_ID)]; | 92 | layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)]; |
93 | 93 | ||
94 | if (!vtbl_rec) | 94 | if (!vtbl_rec) |
95 | vtbl_rec = &empty_vtbl_record; | 95 | vtbl_rec = &empty_vtbl_record; |
@@ -111,7 +111,7 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, | |||
111 | } | 111 | } |
112 | 112 | ||
113 | paranoid_vtbl_check(ubi); | 113 | paranoid_vtbl_check(ubi); |
114 | return ubi_wl_flush(ubi); | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | /** | 117 | /** |
@@ -269,7 +269,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
269 | * this volume table copy was found during scanning. It has to be wiped | 269 | * this volume table copy was found during scanning. It has to be wiped |
270 | * out. | 270 | * out. |
271 | */ | 271 | */ |
272 | sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOL_ID); | 272 | sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID); |
273 | if (sv) | 273 | if (sv) |
274 | old_seb = ubi_scan_find_seb(sv, copy); | 274 | old_seb = ubi_scan_find_seb(sv, copy); |
275 | 275 | ||
@@ -281,7 +281,7 @@ retry: | |||
281 | } | 281 | } |
282 | 282 | ||
283 | vid_hdr->vol_type = UBI_VID_DYNAMIC; | 283 | vid_hdr->vol_type = UBI_VID_DYNAMIC; |
284 | vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOL_ID); | 284 | vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOLUME_ID); |
285 | vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT; | 285 | vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT; |
286 | vid_hdr->data_size = vid_hdr->used_ebs = | 286 | vid_hdr->data_size = vid_hdr->used_ebs = |
287 | vid_hdr->data_pad = cpu_to_be32(0); | 287 | vid_hdr->data_pad = cpu_to_be32(0); |
@@ -514,6 +514,17 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
514 | vol->name[vol->name_len] = '\0'; | 514 | vol->name[vol->name_len] = '\0'; |
515 | vol->vol_id = i; | 515 | vol->vol_id = i; |
516 | 516 | ||
517 | if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) { | ||
518 | /* Auto re-size flag may be set only for one volume */ | ||
519 | if (ubi->autoresize_vol_id != -1) { | ||
520 | ubi_err("more then one auto-resize volume (%d " | ||
521 | "and %d)", ubi->autoresize_vol_id, i); | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | |||
525 | ubi->autoresize_vol_id = i; | ||
526 | } | ||
527 | |||
517 | ubi_assert(!ubi->volumes[i]); | 528 | ubi_assert(!ubi->volumes[i]); |
518 | ubi->volumes[i] = vol; | 529 | ubi->volumes[i] = vol; |
519 | ubi->vol_count += 1; | 530 | ubi->vol_count += 1; |
@@ -579,7 +590,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
579 | vol->last_eb_bytes = vol->reserved_pebs; | 590 | vol->last_eb_bytes = vol->reserved_pebs; |
580 | vol->used_bytes = | 591 | vol->used_bytes = |
581 | (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad); | 592 | (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad); |
582 | vol->vol_id = UBI_LAYOUT_VOL_ID; | 593 | vol->vol_id = UBI_LAYOUT_VOLUME_ID; |
583 | vol->ref_count = 1; | 594 | vol->ref_count = 1; |
584 | 595 | ||
585 | ubi_assert(!ubi->volumes[i]); | 596 | ubi_assert(!ubi->volumes[i]); |
@@ -732,7 +743,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) | |||
732 | ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE; | 743 | ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE; |
733 | ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size); | 744 | ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size); |
734 | 745 | ||
735 | sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOL_ID); | 746 | sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID); |
736 | if (!sv) { | 747 | if (!sv) { |
737 | /* | 748 | /* |
738 | * No logical eraseblocks belonging to the layout volume were | 749 | * No logical eraseblocks belonging to the layout volume were |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 0d44ad95ab84..a471a491f0ab 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
@@ -1303,7 +1303,6 @@ int ubi_wl_flush(struct ubi_device *ubi) | |||
1303 | * Make sure all the works which have been done in parallel are | 1303 | * Make sure all the works which have been done in parallel are |
1304 | * finished. | 1304 | * finished. |
1305 | */ | 1305 | */ |
1306 | ubi_assert(ubi->ref_count > 0); | ||
1307 | down_write(&ubi->work_sem); | 1306 | down_write(&ubi->work_sem); |
1308 | up_write(&ubi->work_sem); | 1307 | up_write(&ubi->work_sem); |
1309 | 1308 | ||