diff options
Diffstat (limited to 'drivers/mtd/ubi/build.c')
-rw-r--r-- | drivers/mtd/ubi/build.c | 103 |
1 files changed, 68 insertions, 35 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) { |