diff options
| -rw-r--r-- | drivers/mtd/ubi/build.c | 69 | ||||
| -rw-r--r-- | drivers/mtd/ubi/eba.c | 15 | ||||
| -rw-r--r-- | drivers/mtd/ubi/ubi.h | 6 | ||||
| -rw-r--r-- | drivers/mtd/ubi/vmt.c | 2 | ||||
| -rw-r--r-- | drivers/mtd/ubi/vtbl.c | 11 | ||||
| -rw-r--r-- | drivers/mtd/ubi/wl.c | 1 | ||||
| -rw-r--r-- | include/mtd/ubi-header.h | 43 |
7 files changed, 121 insertions, 26 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 | */ | ||
| 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 | /** | ||
| 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; |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 7c05c6e1abc7..1f951e39c535 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
| @@ -341,9 +341,6 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 341 | { | 341 | { |
| 342 | int err, pnum, vol_id = vol->vol_id; | 342 | int err, pnum, vol_id = vol->vol_id; |
| 343 | 343 | ||
| 344 | ubi_assert(ubi->ref_count > 0); | ||
| 345 | ubi_assert(vol->ref_count > 0); | ||
| 346 | |||
| 347 | if (ubi->ro_mode) | 344 | if (ubi->ro_mode) |
| 348 | return -EROFS; | 345 | return -EROFS; |
| 349 | 346 | ||
| @@ -392,9 +389,6 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
| 392 | struct ubi_vid_hdr *vid_hdr; | 389 | struct ubi_vid_hdr *vid_hdr; |
| 393 | uint32_t uninitialized_var(crc); | 390 | uint32_t uninitialized_var(crc); |
| 394 | 391 | ||
| 395 | ubi_assert(ubi->ref_count > 0); | ||
| 396 | ubi_assert(vol->ref_count > 0); | ||
| 397 | |||
| 398 | err = leb_read_lock(ubi, vol_id, lnum); | 392 | err = leb_read_lock(ubi, vol_id, lnum); |
| 399 | if (err) | 393 | if (err) |
| 400 | return err; | 394 | return err; |
| @@ -618,9 +612,6 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
| 618 | int err, pnum, tries = 0, vol_id = vol->vol_id; | 612 | int err, pnum, tries = 0, vol_id = vol->vol_id; |
| 619 | struct ubi_vid_hdr *vid_hdr; | 613 | struct ubi_vid_hdr *vid_hdr; |
| 620 | 614 | ||
| 621 | ubi_assert(ubi->ref_count > 0); | ||
| 622 | ubi_assert(vol->ref_count > 0); | ||
| 623 | |||
| 624 | if (ubi->ro_mode) | 615 | if (ubi->ro_mode) |
| 625 | return -EROFS; | 616 | return -EROFS; |
| 626 | 617 | ||
| @@ -754,9 +745,6 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 754 | struct ubi_vid_hdr *vid_hdr; | 745 | struct ubi_vid_hdr *vid_hdr; |
| 755 | uint32_t crc; | 746 | uint32_t crc; |
| 756 | 747 | ||
| 757 | ubi_assert(ubi->ref_count > 0); | ||
| 758 | ubi_assert(vol->ref_count > 0); | ||
| 759 | |||
| 760 | if (ubi->ro_mode) | 748 | if (ubi->ro_mode) |
| 761 | return -EROFS; | 749 | return -EROFS; |
| 762 | 750 | ||
| @@ -871,9 +859,6 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 871 | struct ubi_vid_hdr *vid_hdr; | 859 | struct ubi_vid_hdr *vid_hdr; |
| 872 | uint32_t crc; | 860 | uint32_t crc; |
| 873 | 861 | ||
| 874 | ubi_assert(ubi->ref_count > 0); | ||
| 875 | ubi_assert(vol->ref_count > 0); | ||
| 876 | |||
| 877 | if (ubi->ro_mode) | 862 | if (ubi->ro_mode) |
| 878 | return -EROFS; | 863 | return -EROFS; |
| 879 | 864 | ||
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 90cdcad83cbb..a8cdbd0364fb 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
| @@ -250,9 +250,11 @@ struct ubi_wl_entry; | |||
| 250 | * @rsvd_pebs: count of reserved physical eraseblocks | 250 | * @rsvd_pebs: count of reserved physical eraseblocks |
| 251 | * @avail_pebs: count of available physical eraseblocks | 251 | * @avail_pebs: count of available physical eraseblocks |
| 252 | * @beb_rsvd_pebs: how many physical eraseblocks are reserved for bad PEB | 252 | * @beb_rsvd_pebs: how many physical eraseblocks are reserved for bad PEB |
| 253 | * handling | 253 | * handling |
| 254 | * @beb_rsvd_level: normal level of PEBs reserved for bad PEB handling | 254 | * @beb_rsvd_level: normal level of PEBs reserved for bad PEB handling |
| 255 | * | 255 | * |
| 256 | * @autoresize_vol_id: ID of the volume which has to be auto-resized at the end | ||
| 257 | * of UBI ititializetion | ||
| 256 | * @vtbl_slots: how many slots are available in the volume table | 258 | * @vtbl_slots: how many slots are available in the volume table |
| 257 | * @vtbl_size: size of the volume table in bytes | 259 | * @vtbl_size: size of the volume table in bytes |
| 258 | * @vtbl: in-RAM volume table copy | 260 | * @vtbl: in-RAM volume table copy |
| @@ -333,12 +335,14 @@ struct ubi_device { | |||
| 333 | int beb_rsvd_pebs; | 335 | int beb_rsvd_pebs; |
| 334 | int beb_rsvd_level; | 336 | int beb_rsvd_level; |
| 335 | 337 | ||
| 338 | int autoresize_vol_id; | ||
| 336 | int vtbl_slots; | 339 | int vtbl_slots; |
| 337 | int vtbl_size; | 340 | int vtbl_size; |
| 338 | struct ubi_vtbl_record *vtbl; | 341 | struct ubi_vtbl_record *vtbl; |
| 339 | struct mutex volumes_mutex; | 342 | struct mutex volumes_mutex; |
| 340 | 343 | ||
| 341 | int max_ec; | 344 | int max_ec; |
| 345 | /* TODO: mean_ec is not updated run-time, fix */ | ||
| 342 | int mean_ec; | 346 | int mean_ec; |
| 343 | 347 | ||
| 344 | /* EBA unit's stuff */ | 348 | /* EBA unit's stuff */ |
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 221ce70be569..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) { |
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 7a1a8a1da610..2fd9cf4cea7e 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
| @@ -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; |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 1142aabcfc8c..8bfb7434c993 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/mtd/ubi-header.h b/include/mtd/ubi-header.h index 74efa7763479..69d5d7e22899 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 |
| @@ -289,7 +326,8 @@ struct ubi_vid_hdr { | |||
| 289 | * @upd_marker: if volume update was started but not finished | 326 | * @upd_marker: if volume update was started but not finished |
| 290 | * @name_len: volume name length | 327 | * @name_len: volume name length |
| 291 | * @name: the volume name | 328 | * @name: the volume name |
| 292 | * @padding2: reserved, zeroes | 329 | * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG) |
| 330 | * @padding: reserved, zeroes | ||
| 293 | * @crc: a CRC32 checksum of the record | 331 | * @crc: a CRC32 checksum of the record |
| 294 | * | 332 | * |
| 295 | * The volume table records are stored in the volume table, which is stored in | 333 | * The volume table records are stored in the volume table, which is stored in |
| @@ -324,7 +362,8 @@ struct ubi_vtbl_record { | |||
| 324 | __u8 upd_marker; | 362 | __u8 upd_marker; |
| 325 | __be16 name_len; | 363 | __be16 name_len; |
| 326 | __u8 name[UBI_VOL_NAME_MAX+1]; | 364 | __u8 name[UBI_VOL_NAME_MAX+1]; |
| 327 | __u8 padding2[24]; | 365 | __u8 flags; |
| 366 | __u8 padding[23]; | ||
| 328 | __be32 crc; | 367 | __be32 crc; |
| 329 | } __attribute__ ((packed)); | 368 | } __attribute__ ((packed)); |
| 330 | 369 | ||
