On Mon, Nov 3, 2008 at 6:01 AM, Magnus Lilja <[EMAIL PROTECTED]> wrote:
> Dear Kyungmin Park,
>
> Some more comments after testing your patches.
>
> 2008/10/28 Kyungmin Park <[EMAIL PROTECTED]>:
>> UBI (Latin: "where?") stands for "Unsorted Block Images". It is a volume 
>> management system for flash devices which manages multiple logical volumes 
>> on a single physical flash device and spreads the I/O load (i.e, 
>> wear-leveling) across the whole flash chip.
>>
>> In a sense, UBI may be compared to the Logical Volume Manager (LVM). Whereas 
>> LVM maps logical sectors to physical sectors, UBI maps logical eraseblocks 
>> to physical eraseblocks. But besides the mapping, UBI implements global 
>> wear-leveling and I/O errors handling.
>>
>> For more details, Please visit the following URL.
>> http://www.linux-mtd.infradead.org/doc/ubi.html
>>
>> Signed-off-by: Kyungmin Park <[EMAIL PROTECTED]>
>> ---
>> diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
>> new file mode 100644
>> index 0000000..b6f8699
>> --- /dev/null
>> +++ b/drivers/mtd/ubi/build.c
>> +static int io_init(struct ubi_device *ubi)
>> +{
>> +       if (ubi->mtd->numeraseregions != 0) {
>> +               /*
>> +                * Some flashes have several erase regions. Different regions
>> +                * may have different eraseblock size and other
>> +                * characteristics. It looks like mostly multi-region flashes
>> +                * have one "main" region and one or more small regions to
>> +                * store boot loader code or boot parameters or whatever. I
>> +                * guess we should just pick the largest region. But this is
>> +                * not implemented.
>> +                */
>> +               ubi_err("multiple regions, not implemented");
>> +               return -EINVAL;
>> +       }
>> +
>> +       if (ubi->vid_hdr_offset < 0)
>> +               return -EINVAL;
>> +
>> +       /*
>> +        * Note, in this implementation we support MTD devices with 
>> 0x7FFFFFFF
>> +        * physical eraseblocks maximum.
>> +        */
>> +
>> +       ubi->peb_size   = ubi->mtd->erasesize;
>> +       ubi->peb_count  = ubi->mtd->size / ubi->mtd->erasesize;
>> +       ubi->flash_size = ubi->mtd->size;
>> +
>> +       if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)
>> +               ubi->bad_allowed = 1;
>> +
>> +       ubi->min_io_size = ubi->mtd->writesize;
>> +       ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
>> +
>> +       /*
>> +        * Make sure minimal I/O unit is power of 2. Note, there is no
>> +        * fundamental reason for this assumption. It is just an optimization
>> +        * which allows us to avoid costly division operations.
>> +        */
>> +       if (!is_power_of_2(ubi->min_io_size)) {
>> +               ubi_err("min. I/O unit (%d) is not power of 2",
>> +                       ubi->min_io_size);
>> +               return -EINVAL;
>> +       }
>> +
>> +       ubi_assert(ubi->hdrs_min_io_size > 0);
>> +       ubi_assert(ubi->hdrs_min_io_size <= ubi->min_io_size);
>> +       ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0);
>> +
>> +       /* Calculate default aligned sizes of EC and VID headers */
>> +       ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
>> +       ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
>> +
>> +       dbg_msg("min_io_size      %d", ubi->min_io_size);
>> +       dbg_msg("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
>> +       dbg_msg("ec_hdr_alsize    %d", ubi->ec_hdr_alsize);
>> +       dbg_msg("vid_hdr_alsize   %d", ubi->vid_hdr_alsize);
>> +
>> +       if (ubi->vid_hdr_offset == 0)
>> +               /* Default offset */
>> +               ubi->vid_hdr_offset = ubi->vid_hdr_aloffset =
>> +                                     ubi->ec_hdr_alsize;
>> +       else {
>> +               ubi->vid_hdr_aloffset = ubi->vid_hdr_offset &
>> +                                               ~(ubi->hdrs_min_io_size - 1);
>> +               ubi->vid_hdr_shift = ubi->vid_hdr_offset -
>> +                                               ubi->vid_hdr_aloffset;
>> +       }
>> +
>> +       /* Similar for the data offset */
>> +       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);
>> +       dbg_msg("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset);
>> +       dbg_msg("vid_hdr_shift    %d", ubi->vid_hdr_shift);
>> +       dbg_msg("leb_start        %d", ubi->leb_start);
>> +
>> +       /* The shift must be aligned to 32-bit boundary */
>> +       if (ubi->vid_hdr_shift % 4) {
>> +               ubi_err("unaligned VID header shift %d",
>> +                       ubi->vid_hdr_shift);
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* Check sanity */
>> +       if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE ||
>> +           ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||
>> +           ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||
>> +           ubi->leb_start & (ubi->min_io_size - 1)) {
>> +               ubi_err("bad VID header (%d) or data offsets (%d)",
>> +                       ubi->vid_hdr_offset, ubi->leb_start);
>> +               return -EINVAL;
>> +       }
>> +
>> +       /*
>> +        * It may happen that EC and VID headers are situated in one minimal
>> +        * I/O unit. In this case we can only accept this UBI image in
>> +        * read-only mode.
>> +        */
>> +       if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) 
>> {
>> +               ubi_warn("EC and VID headers are in the same minimal I/O 
>> unit, "
>> +                        "switch to read-only mode");
>> +               ubi->ro_mode = 1;
>> +       }
>> +
>> +       ubi->leb_size = ubi->peb_size - ubi->leb_start;
>> +
>> +       if (!(ubi->mtd->flags & MTD_WRITEABLE)) {
>> +               ubi_msg("MTD device %d is write-protected, attach in "
>> +                       "read-only mode", ubi->mtd->index);
>> +               ubi->ro_mode = 1;
>> +       }
>> +
>> +       ubi_msg("physical eraseblock size:   %d bytes (%d KiB)",
>> +               ubi->peb_size, ubi->peb_size >> 10);
>> +       ubi_msg("logical eraseblock size:    %d bytes", ubi->leb_size);
>> +       ubi_msg("smallest flash I/O unit:    %d", ubi->min_io_size);
>> +       if (ubi->hdrs_min_io_size != ubi->min_io_size)
>> +               ubi_msg("sub-page size:              %d",
>> +                       ubi->hdrs_min_io_size);
>> +       ubi_msg("VID header offset:          %d (aligned %d)",
>> +               ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
>> +       ubi_msg("data offset:                %d", ubi->leb_start);
>
> I got these messages on my console, my suggestion is that (almost) all
> of the standard info messages are off by default.
>
>> +int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int 
>> vid_hdr_offset)
>> +{
>> +       struct ubi_device *ubi;
>> +       int i, err;
>> +
>> +       /*
>> +        * Check if we already have the same MTD device attached.
>> +        *
>> +        * Note, this function assumes that UBI devices creations and 
>> deletions
>> +        * are serialized, so it does not take the &ubi_devices_lock.
>> +        */
>> +       for (i = 0; i < UBI_MAX_DEVICES; i++) {
>> +               ubi = ubi_devices[i];
>> +               if (ubi && mtd->index == ubi->mtd->index) {
>> +                       dbg_err("mtd%d is already attached to ubi%d",
>> +                               mtd->index, i);
>> +                       return -EEXIST;
>> +               }
>> +       }
>> +
>> +       /*
>> +        * Make sure this MTD device is not emulated on top of an UBI volume
>> +        * already. Well, generally this recursion works fine, but there are
>> +        * different problems like the UBI module takes a reference to itself
>> +        * by attaching (and thus, opening) the emulated MTD device. This
>> +        * results in inability to unload the module. And in general it makes
>> +        * no sense to attach emulated MTD devices, so we prohibit this.
>> +        */
>> +       if (mtd->type == MTD_UBIVOLUME) {
>> +               ubi_err("refuse attaching mtd%d - it is already emulated on "
>> +                       "top of UBI", mtd->index);
>> +               return -EINVAL;
>> +       }
>> +
>> +       if (ubi_num == UBI_DEV_NUM_AUTO) {
>> +               /* Search for an empty slot in the @ubi_devices array */
>> +               for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++)
>> +                       if (!ubi_devices[ubi_num])
>> +                               break;
>> +               if (ubi_num == UBI_MAX_DEVICES) {
>> +                       dbg_err("only %d UBI devices may be created", 
>> UBI_MAX_DEVICES);
>> +                       return -ENFILE;
>> +               }
>> +       } else {
>> +               if (ubi_num >= UBI_MAX_DEVICES)
>> +                       return -EINVAL;
>> +
>> +               /* Make sure ubi_num is not busy */
>> +               if (ubi_devices[ubi_num]) {
>> +                       dbg_err("ubi%d already exists", ubi_num);
>> +                       return -EEXIST;
>> +               }
>> +       }
>> +
>> +       ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL);
>> +       if (!ubi)
>> +               return -ENOMEM;
>> +
>> +       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);
>> +
>> +       ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
>> +
>> +       err = io_init(ubi);
>> +       if (err)
>> +               goto out_free;
>> +
>> +       ubi->peb_buf1 = vmalloc(ubi->peb_size);
>> +       if (!ubi->peb_buf1)
>> +               goto out_free;
>> +
>> +       ubi->peb_buf2 = vmalloc(ubi->peb_size);
>> +       if (!ubi->peb_buf2)
>> +                goto out_free;
>> +
>> +#ifdef CONFIG_MTD_UBI_DEBUG
>> +       mutex_init(&ubi->dbg_buf_mutex);
>> +       ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
>> +       if (!ubi->dbg_peb_buf)
>> +                goto out_free;
>> +#endif
>> +
>> +       err = attach_by_scanning(ubi);
>> +       if (err) {
>> +               dbg_err("failed to attach by scanning, error %d", err);
>> +               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;
>> +
>> +       ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
>> +       if (IS_ERR(ubi->bgt_thread)) {
>> +               err = PTR_ERR(ubi->bgt_thread);
>> +               ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
>> +                       err);
>> +               goto out_uif;
>> +       }
>> +
>> +       ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
>> +       ubi_msg("MTD device name:            \"%s\"", mtd->name);
>> +       ubi_msg("MTD device size:            %llu MiB", ubi->flash_size >> 
>> 20);
>> +       ubi_msg("number of good PEBs:        %d", ubi->good_peb_count);
>> +       ubi_msg("number of bad PEBs:         %d", ubi->bad_peb_count);
>> +       ubi_msg("max. allowed volumes:       %d", ubi->vtbl_slots);
>> +       ubi_msg("wear-leveling threshold:    %d", 
>> CONFIG_MTD_UBI_WL_THRESHOLD);
>> +       ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
>> +       ubi_msg("number of user volumes:     %d",
>> +               ubi->vol_count - UBI_INT_VOL_COUNT);
>> +       ubi_msg("available PEBs:             %d", ubi->avail_pebs);
>> +       ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs);
>> +       ubi_msg("number of PEBs reserved for bad PEB handling: %d",
>> +               ubi->beb_rsvd_pebs);
>> +       ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
>
> All these should also be off by default IMO.

These messages are default on kernel. If you want to off, we can add
the another configuration to ubi_msg macro

Thank you,
Kyungmin Park
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to