From b9a06623d9d0c6dff758d525ceb0d9e2bba8f7d6 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 16 Jan 2008 12:11:54 +0200 Subject: UBI: get rid of ubi_ltree_slab This slab cache is not really needed since the number of objects is low and the constructor does not make much sense because we allocate oblects when doint I/O, which is way slower then allocation. Suggested-by: Arnd Bergmann Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) (limited to 'drivers/mtd/ubi/build.c') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 8f1f9feb2d60..8b4573559dfe 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]; /* Root UBI "class" object (corresponds to '//class/ubi/') */ struct class *ubi_class; -/* Slab cache for lock-tree entries */ -struct kmem_cache *ubi_ltree_slab; - /* Slab cache for wear-leveling entries */ struct kmem_cache *ubi_wl_entry_slab; @@ -857,20 +854,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) return 0; } -/** - * ltree_entry_ctor - lock tree entries slab cache constructor. - * @obj: the lock-tree entry to construct - * @cache: the lock tree entry slab cache - * @flags: constructor flags - */ -static void ltree_entry_ctor(struct kmem_cache *cache, void *obj) -{ - struct ubi_ltree_entry *le = obj; - - le->users = 0; - init_rwsem(&le->mutex); -} - /** * find_mtd_device - open an MTD device by its name or number. * @mtd_dev: name or number of the device @@ -933,17 +916,11 @@ static int __init ubi_init(void) goto out_version; } - ubi_ltree_slab = kmem_cache_create("ubi_ltree_slab", - sizeof(struct ubi_ltree_entry), 0, - 0, <ree_entry_ctor); - if (!ubi_ltree_slab) - goto out_dev_unreg; - ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", sizeof(struct ubi_wl_entry), 0, 0, NULL); if (!ubi_wl_entry_slab) - goto out_ltree; + goto out_dev_unreg; /* Attach MTD devices */ for (i = 0; i < mtd_devs; i++) { @@ -980,8 +957,6 @@ out_detach: mutex_unlock(&ubi_devices_mutex); } kmem_cache_destroy(ubi_wl_entry_slab); -out_ltree: - kmem_cache_destroy(ubi_ltree_slab); out_dev_unreg: misc_deregister(&ubi_ctrl_cdev); out_version: @@ -1005,7 +980,6 @@ static void __exit ubi_exit(void) mutex_unlock(&ubi_devices_mutex); } kmem_cache_destroy(ubi_wl_entry_slab); - kmem_cache_destroy(ubi_ltree_slab); misc_deregister(&ubi_ctrl_cdev); class_remove_file(ubi_class, &ubi_version); class_destroy(ubi_class); -- cgit v1.2.2 From 4ccf8cffa963c7b5bdc6d455ea9417084ee49aa8 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 16 Jan 2008 15:44:24 +0200 Subject: UBI: add auto-resize feature The problem: NAND flashes have different amount of initial bad physical eraseblocks (marked as bad by the manufacturer). For example, for 256MiB Samsung OneNAND flash there might be from 0 to 40 bad initial eraseblocks, which is about 2%. When UBI is used as the base system, one needs to know the exact amount of good physical eraseblocks, because this number is needed to create the UBI image which is put to the devices during production. But this number is not know, which forces us to use the minimum number of good physical eraseblocks. And UBI additionally reserves some percentage of physical eraseblocks for bad block handling (default is 1%), so we have 1-3% of PEBs reserved at the end, depending on the amount of initial bad PEBs. But it is desired to always have 1% (or more, depending on the configuration). Solution: this patch adds an "auto-resize" flag to the volume table. The volume which has the "auto-resize" flag will automatically be re-sized (enlarged) on the first UBI initialization. UBI clears the flag when the volume is re-sized. Only one volume may have the "auto-resize" flag. So, the production UBI image may have one volume with "auto-resize" flag set, and its size is automatically adjusted on the first boot of the device. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 69 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 5 deletions(-) (limited to 'drivers/mtd/ubi/build.c') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 8b4573559dfe..4e761e957de8 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -366,9 +366,6 @@ static int uif_init(struct ubi_device *ubi) int i, err; dev_t dev; - mutex_init(&ubi->volumes_mutex); - spin_lock_init(&ubi->volumes_lock); - sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); /* @@ -623,6 +620,58 @@ static int io_init(struct ubi_device *ubi) return 0; } +/** + * autoresize - re-size the volume which has the "auto-resize" flag set. + * @ubi: UBI device description object + * @vol_id: ID of the volume to re-size + * + * This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in + * the volume table to the largest possible size. See comments in ubi-header.h + * for more description of the flag. Returns zero in case of success and a + * negative error code in case of failure. + */ +static int autoresize(struct ubi_device *ubi, int vol_id) +{ + struct ubi_volume_desc desc; + struct ubi_volume *vol = ubi->volumes[vol_id]; + int err, old_reserved_pebs = vol->reserved_pebs; + + /* + * Clear the auto-resize flag in the volume in-memory copy of the + * volume table, and 'ubi_resize_volume()' will propogate this change + * to the flash. + */ + ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG; + + if (ubi->avail_pebs == 0) { + struct ubi_vtbl_record vtbl_rec; + + /* + * No avalilable PEBs to re-size the volume, clear the flag on + * flash and exit. + */ + memcpy(&vtbl_rec, &ubi->vtbl[vol_id], + sizeof(struct ubi_vtbl_record)); + err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); + if (err) + ubi_err("cannot clean auto-resize flag for volume %d", + vol_id); + } else { + desc.vol = vol; + err = ubi_resize_volume(&desc, + old_reserved_pebs + ubi->avail_pebs); + if (err) + ubi_err("cannot auto-resize volume %d", vol_id); + } + + if (err) + return err; + + ubi_msg("volume %d (\"%s\") re-sized from %d to %d LEBs", vol_id, + vol->name, old_reserved_pebs, vol->reserved_pebs); + return 0; +} + /** * ubi_attach_mtd_dev - attach an MTD device. * @mtd_dev: MTD device description object @@ -699,6 +748,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ubi->mtd = mtd; ubi->ubi_num = ubi_num; ubi->vid_hdr_offset = vid_hdr_offset; + ubi->autoresize_vol_id = -1; + + mutex_init(&ubi->buf_mutex); + mutex_init(&ubi->ckvol_mutex); + mutex_init(&ubi->volumes_mutex); + spin_lock_init(&ubi->volumes_lock); dbg_msg("attaching mtd%d to ubi%d: VID header offset %d", mtd->index, ubi_num, vid_hdr_offset); @@ -707,8 +762,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) if (err) goto out_free; - mutex_init(&ubi->buf_mutex); - mutex_init(&ubi->ckvol_mutex); ubi->peb_buf1 = vmalloc(ubi->peb_size); if (!ubi->peb_buf1) goto out_free; @@ -730,6 +783,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) goto out_free; } + if (ubi->autoresize_vol_id != -1) { + err = autoresize(ubi, ubi->autoresize_vol_id); + if (err) + goto out_detach; + } + err = uif_init(ubi); if (err) goto out_detach; -- cgit v1.2.2 From ddc4939161c502452392b353f9e0dd088239e4c1 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 17 Jan 2008 15:35:57 +0200 Subject: UBI: amend array size Since the data offset parameter was removed, the size of the parameters array is now 2, not 3. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/ubi/build.c') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 4e761e957de8..51bff88342af 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -1099,7 +1099,7 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp) struct mtd_dev_param *p; char buf[MTD_PARAM_LEN_MAX]; char *pbuf = &buf[0]; - char *tokens[3] = {NULL, NULL, NULL}; + char *tokens[2] = {NULL, NULL}; if (!val) return -EINVAL; @@ -1129,7 +1129,7 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp) if (buf[len - 1] == '\n') buf[len - 1] = '\0'; - for (i = 0; i < 3; i++) + for (i = 0; i < 2; i++) tokens[i] = strsep(&pbuf, ","); if (pbuf) { -- cgit v1.2.2 From d536058752274b2fe60135142da550b5355ffa94 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 17 Jan 2008 15:41:14 +0200 Subject: UBI: bugfix: calculate data offset properly Data offset is VID header offset + VID header size aligned to the min. I/O unit size up. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/ubi/build.c') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 51bff88342af..6ac81e35355c 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -562,7 +562,7 @@ static int io_init(struct ubi_device *ubi) } /* Similar for the data offset */ - ubi->leb_start = ubi->vid_hdr_offset + ubi->vid_hdr_alsize; + ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE; ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); dbg_msg("vid_hdr_offset %d", ubi->vid_hdr_offset); -- cgit v1.2.2