aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/build.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-01-16 08:44:24 -0500
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-01-25 09:41:24 -0500
commit4ccf8cffa963c7b5bdc6d455ea9417084ee49aa8 (patch)
treea7281874dc9298b3d7eca2d1e4cb22c326625382 /drivers/mtd/ubi/build.c
parent896c0c06aa30147630e9a75949b6ae2014c841fc (diff)
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 <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi/build.c')
-rw-r--r--drivers/mtd/ubi/build.c69
1 files changed, 64 insertions, 5 deletions
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)
366 int i, err; 366 int i, err;
367 dev_t dev; 367 dev_t dev;
368 368
369 mutex_init(&ubi->volumes_mutex);
370 spin_lock_init(&ubi->volumes_lock);
371
372 sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); 369 sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
373 370
374 /* 371 /*
@@ -624,6 +621,58 @@ static int io_init(struct ubi_device *ubi)
624} 621}
625 622
626/** 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 */
633static 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/**
627 * ubi_attach_mtd_dev - attach an MTD device. 676 * ubi_attach_mtd_dev - attach an MTD device.
628 * @mtd_dev: MTD device description object 677 * @mtd_dev: MTD device description object
629 * @ubi_num: number to assign to the new UBI device 678 * @ubi_num: number to assign to the new UBI device
@@ -699,6 +748,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
699 ubi->mtd = mtd; 748 ubi->mtd = mtd;
700 ubi->ubi_num = ubi_num; 749 ubi->ubi_num = ubi_num;
701 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);
702 757
703 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",
704 mtd->index, ubi_num, vid_hdr_offset); 759 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)
707 if (err) 762 if (err)
708 goto out_free; 763 goto out_free;
709 764
710 mutex_init(&ubi->buf_mutex);
711 mutex_init(&ubi->ckvol_mutex);
712 ubi->peb_buf1 = vmalloc(ubi->peb_size); 765 ubi->peb_buf1 = vmalloc(ubi->peb_size);
713 if (!ubi->peb_buf1) 766 if (!ubi->peb_buf1)
714 goto out_free; 767 goto out_free;
@@ -730,6 +783,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
730 goto out_free; 783 goto out_free;
731 } 784 }
732 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
733 err = uif_init(ubi); 792 err = uif_init(ubi);
734 if (err) 793 if (err)
735 goto out_detach; 794 goto out_detach;