diff options
| -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 | ||||
| -rw-r--r-- | include/linux/mtd/ubi.h | 17 | ||||
| -rw-r--r-- | include/mtd/ubi-header.h | 47 | ||||
| -rw-r--r-- | include/mtd/ubi-user.h | 51 |
13 files changed, 441 insertions, 188 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 | ||
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h index c4abe0351225..f71201d0f3e7 100644 --- a/include/linux/mtd/ubi.h +++ b/include/linux/mtd/ubi.h | |||
| @@ -26,23 +26,6 @@ | |||
| 26 | #include <mtd/ubi-user.h> | 26 | #include <mtd/ubi-user.h> |
| 27 | 27 | ||
| 28 | /* | 28 | /* |
| 29 | * UBI data type hint constants. | ||
| 30 | * | ||
| 31 | * UBI_LONGTERM: long-term data | ||
| 32 | * UBI_SHORTTERM: short-term data | ||
| 33 | * UBI_UNKNOWN: data persistence is unknown | ||
| 34 | * | ||
| 35 | * These constants are used when data is written to UBI volumes in order to | ||
| 36 | * help the UBI wear-leveling unit to find more appropriate physical | ||
| 37 | * eraseblocks. | ||
| 38 | */ | ||
| 39 | enum { | ||
| 40 | UBI_LONGTERM = 1, | ||
| 41 | UBI_SHORTTERM, | ||
| 42 | UBI_UNKNOWN | ||
| 43 | }; | ||
| 44 | |||
| 45 | /* | ||
| 46 | * enum ubi_open_mode - UBI volume open mode constants. | 29 | * enum ubi_open_mode - UBI volume open mode constants. |
| 47 | * | 30 | * |
| 48 | * UBI_READONLY: read-only mode | 31 | * UBI_READONLY: read-only mode |
diff --git a/include/mtd/ubi-header.h b/include/mtd/ubi-header.h index 74efa7763479..292f916ea564 100644 --- a/include/mtd/ubi-header.h +++ b/include/mtd/ubi-header.h | |||
| @@ -58,6 +58,43 @@ enum { | |||
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | /* | 60 | /* |
| 61 | * Volume flags used in the volume table record. | ||
| 62 | * | ||
| 63 | * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume | ||
| 64 | * | ||
| 65 | * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume | ||
| 66 | * table. UBI automatically re-sizes the volume which has this flag and makes | ||
| 67 | * the volume to be of largest possible size. This means that if after the | ||
| 68 | * initialization UBI finds out that there are available physical eraseblocks | ||
| 69 | * present on the device, it automatically appends all of them to the volume | ||
| 70 | * (the physical eraseblocks reserved for bad eraseblocks handling and other | ||
| 71 | * reserved physical eraseblocks are not taken). So, if there is a volume with | ||
| 72 | * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical | ||
| 73 | * eraseblocks will be zero after UBI is loaded, because all of them will be | ||
| 74 | * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared | ||
| 75 | * after the volume had been initialized. | ||
| 76 | * | ||
| 77 | * The auto-resize feature is useful for device production purposes. For | ||
| 78 | * example, different NAND flash chips may have different amount of initial bad | ||
| 79 | * eraseblocks, depending of particular chip instance. Manufacturers of NAND | ||
| 80 | * chips usually guarantee that the amount of initial bad eraseblocks does not | ||
| 81 | * exceed certain percent, e.g. 2%. When one creates an UBI image which will be | ||
| 82 | * flashed to the end devices in production, he does not know the exact amount | ||
| 83 | * of good physical eraseblocks the NAND chip on the device will have, but this | ||
| 84 | * number is required to calculate the volume sized and put them to the volume | ||
| 85 | * table of the UBI image. In this case, one of the volumes (e.g., the one | ||
| 86 | * which will store the root file system) is marked as "auto-resizable", and | ||
| 87 | * UBI will adjust its size on the first boot if needed. | ||
| 88 | * | ||
| 89 | * Note, first UBI reserves some amount of physical eraseblocks for bad | ||
| 90 | * eraseblock handling, and then re-sizes the volume, not vice-versa. This | ||
| 91 | * means that the pool of reserved physical eraseblocks will always be present. | ||
| 92 | */ | ||
| 93 | enum { | ||
| 94 | UBI_VTBL_AUTORESIZE_FLG = 0x01, | ||
| 95 | }; | ||
| 96 | |||
| 97 | /* | ||
| 61 | * Compatibility constants used by internal volumes. | 98 | * Compatibility constants used by internal volumes. |
| 62 | * | 99 | * |
| 63 | * @UBI_COMPAT_DELETE: delete this internal volume before anything is written | 100 | * @UBI_COMPAT_DELETE: delete this internal volume before anything is written |
| @@ -262,7 +299,9 @@ struct ubi_vid_hdr { | |||
| 262 | 299 | ||
| 263 | /* The layout volume contains the volume table */ | 300 | /* The layout volume contains the volume table */ |
| 264 | 301 | ||
| 265 | #define UBI_LAYOUT_VOL_ID UBI_INTERNAL_VOL_START | 302 | #define UBI_LAYOUT_VOLUME_ID UBI_INTERNAL_VOL_START |
| 303 | #define UBI_LAYOUT_VOLUME_TYPE UBI_VID_DYNAMIC | ||
| 304 | #define UBI_LAYOUT_VOLUME_ALIGN 1 | ||
| 266 | #define UBI_LAYOUT_VOLUME_EBS 2 | 305 | #define UBI_LAYOUT_VOLUME_EBS 2 |
| 267 | #define UBI_LAYOUT_VOLUME_NAME "layout volume" | 306 | #define UBI_LAYOUT_VOLUME_NAME "layout volume" |
| 268 | #define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT | 307 | #define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT |
| @@ -289,7 +328,8 @@ struct ubi_vid_hdr { | |||
| 289 | * @upd_marker: if volume update was started but not finished | 328 | * @upd_marker: if volume update was started but not finished |
| 290 | * @name_len: volume name length | 329 | * @name_len: volume name length |
| 291 | * @name: the volume name | 330 | * @name: the volume name |
| 292 | * @padding2: reserved, zeroes | 331 | * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG) |
| 332 | * @padding: reserved, zeroes | ||
| 293 | * @crc: a CRC32 checksum of the record | 333 | * @crc: a CRC32 checksum of the record |
| 294 | * | 334 | * |
| 295 | * The volume table records are stored in the volume table, which is stored in | 335 | * The volume table records are stored in the volume table, which is stored in |
| @@ -324,7 +364,8 @@ struct ubi_vtbl_record { | |||
| 324 | __u8 upd_marker; | 364 | __u8 upd_marker; |
| 325 | __be16 name_len; | 365 | __be16 name_len; |
| 326 | __u8 name[UBI_VOL_NAME_MAX+1]; | 366 | __u8 name[UBI_VOL_NAME_MAX+1]; |
| 327 | __u8 padding2[24]; | 367 | __u8 flags; |
| 368 | __u8 padding[23]; | ||
| 328 | __be32 crc; | 369 | __be32 crc; |
| 329 | } __attribute__ ((packed)); | 370 | } __attribute__ ((packed)); |
| 330 | 371 | ||
diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h index 4d184a7f80a8..a7421f130cc0 100644 --- a/include/mtd/ubi-user.h +++ b/include/mtd/ubi-user.h | |||
| @@ -63,7 +63,7 @@ | |||
| 63 | * | 63 | * |
| 64 | * Volume update should be done via the %UBI_IOCVOLUP IOCTL command of the | 64 | * Volume update should be done via the %UBI_IOCVOLUP IOCTL command of the |
| 65 | * corresponding UBI volume character device. A pointer to a 64-bit update | 65 | * corresponding UBI volume character device. A pointer to a 64-bit update |
| 66 | * size should be passed to the IOCTL. After then, UBI expects user to write | 66 | * size should be passed to the IOCTL. After this, UBI expects user to write |
| 67 | * this number of bytes to the volume character device. The update is finished | 67 | * this number of bytes to the volume character device. The update is finished |
| 68 | * when the claimed number of bytes is passed. So, the volume update sequence | 68 | * when the claimed number of bytes is passed. So, the volume update sequence |
| 69 | * is something like: | 69 | * is something like: |
| @@ -72,6 +72,15 @@ | |||
| 72 | * ioctl(fd, UBI_IOCVOLUP, &image_size); | 72 | * ioctl(fd, UBI_IOCVOLUP, &image_size); |
| 73 | * write(fd, buf, image_size); | 73 | * write(fd, buf, image_size); |
| 74 | * close(fd); | 74 | * close(fd); |
| 75 | * | ||
| 76 | * Atomic eraseblock change | ||
| 77 | * ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 78 | * | ||
| 79 | * Atomic eraseblock change operation is done via the %UBI_IOCEBCH IOCTL | ||
| 80 | * command of the corresponding UBI volume character device. A pointer to | ||
| 81 | * &struct ubi_leb_change_req has to be passed to the IOCTL. Then the user is | ||
| 82 | * expected to write the requested amount of bytes. This is similar to the | ||
| 83 | * "volume update" IOCTL. | ||
| 75 | */ | 84 | */ |
| 76 | 85 | ||
| 77 | /* | 86 | /* |
| @@ -113,11 +122,30 @@ | |||
| 113 | #define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t) | 122 | #define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t) |
| 114 | /* An eraseblock erasure command, used for debugging, disabled by default */ | 123 | /* An eraseblock erasure command, used for debugging, disabled by default */ |
| 115 | #define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t) | 124 | #define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t) |
| 125 | /* An atomic eraseblock change command */ | ||
| 126 | #define UBI_IOCEBCH _IOW(UBI_VOL_IOC_MAGIC, 2, int32_t) | ||
| 116 | 127 | ||
| 117 | /* Maximum MTD device name length supported by UBI */ | 128 | /* Maximum MTD device name length supported by UBI */ |
| 118 | #define MAX_UBI_MTD_NAME_LEN 127 | 129 | #define MAX_UBI_MTD_NAME_LEN 127 |
| 119 | 130 | ||
| 120 | /* | 131 | /* |
| 132 | * UBI data type hint constants. | ||
| 133 | * | ||
| 134 | * UBI_LONGTERM: long-term data | ||
| 135 | * UBI_SHORTTERM: short-term data | ||
| 136 | * UBI_UNKNOWN: data persistence is unknown | ||
| 137 | * | ||
| 138 | * These constants are used when data is written to UBI volumes in order to | ||
| 139 | * help the UBI wear-leveling unit to find more appropriate physical | ||
| 140 | * eraseblocks. | ||
| 141 | */ | ||
| 142 | enum { | ||
| 143 | UBI_LONGTERM = 1, | ||
| 144 | UBI_SHORTTERM = 2, | ||
| 145 | UBI_UNKNOWN = 3, | ||
| 146 | }; | ||
| 147 | |||
| 148 | /* | ||
| 121 | * UBI volume type constants. | 149 | * UBI volume type constants. |
| 122 | * | 150 | * |
| 123 | * @UBI_DYNAMIC_VOLUME: dynamic volume | 151 | * @UBI_DYNAMIC_VOLUME: dynamic volume |
| @@ -125,7 +153,7 @@ | |||
| 125 | */ | 153 | */ |
| 126 | enum { | 154 | enum { |
| 127 | UBI_DYNAMIC_VOLUME = 3, | 155 | UBI_DYNAMIC_VOLUME = 3, |
| 128 | UBI_STATIC_VOLUME = 4, | 156 | UBI_STATIC_VOLUME = 4, |
| 129 | }; | 157 | }; |
| 130 | 158 | ||
| 131 | /** | 159 | /** |
| @@ -137,7 +165,7 @@ enum { | |||
| 137 | * | 165 | * |
| 138 | * This data structure is used to specify MTD device UBI has to attach and the | 166 | * This data structure is used to specify MTD device UBI has to attach and the |
| 139 | * parameters it has to use. The number which should be assigned to the new UBI | 167 | * parameters it has to use. The number which should be assigned to the new UBI |
| 140 | * device is passed in @ubi_num. UBI may automatically assing the number if | 168 | * device is passed in @ubi_num. UBI may automatically assign the number if |
| 141 | * @UBI_DEV_NUM_AUTO is passed. In this case, the device number is returned in | 169 | * @UBI_DEV_NUM_AUTO is passed. In this case, the device number is returned in |
| 142 | * @ubi_num. | 170 | * @ubi_num. |
| 143 | * | 171 | * |
| @@ -176,7 +204,7 @@ struct ubi_attach_req { | |||
| 176 | * @padding2: reserved for future, not used, has to be zeroed | 204 | * @padding2: reserved for future, not used, has to be zeroed |
| 177 | * @name: volume name | 205 | * @name: volume name |
| 178 | * | 206 | * |
| 179 | * This structure is used by userspace programs when creating new volumes. The | 207 | * This structure is used by user-space programs when creating new volumes. The |
| 180 | * @used_bytes field is only necessary when creating static volumes. | 208 | * @used_bytes field is only necessary when creating static volumes. |
| 181 | * | 209 | * |
| 182 | * The @alignment field specifies the required alignment of the volume logical | 210 | * The @alignment field specifies the required alignment of the volume logical |
| @@ -222,4 +250,19 @@ struct ubi_rsvol_req { | |||
| 222 | int32_t vol_id; | 250 | int32_t vol_id; |
| 223 | } __attribute__ ((packed)); | 251 | } __attribute__ ((packed)); |
| 224 | 252 | ||
| 253 | /** | ||
| 254 | * struct ubi_leb_change_req - a data structure used in atomic logical | ||
| 255 | * eraseblock change requests. | ||
| 256 | * @lnum: logical eraseblock number to change | ||
| 257 | * @bytes: how many bytes will be written to the logical eraseblock | ||
| 258 | * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN) | ||
| 259 | * @padding: reserved for future, not used, has to be zeroed | ||
| 260 | */ | ||
| 261 | struct ubi_leb_change_req { | ||
| 262 | int32_t lnum; | ||
| 263 | int32_t bytes; | ||
| 264 | uint8_t dtype; | ||
| 265 | uint8_t padding[7]; | ||
| 266 | } __attribute__ ((packed)); | ||
| 267 | |||
| 225 | #endif /* __UBI_USER_H__ */ | 268 | #endif /* __UBI_USER_H__ */ |
