diff options
| author | Richard Weinberger <richard@nod.at> | 2018-05-28 16:04:33 -0400 |
|---|---|---|
| committer | Richard Weinberger <richard@nod.at> | 2018-06-07 09:53:16 -0400 |
| commit | 34653fd8c46e771585fce5975e4243f8fd401914 (patch) | |
| tree | 2e0c2d723829de99308aa9d9a88ad7449ed14d9c | |
| parent | 781932375ffc6411713ee0926ccae8596ed0261c (diff) | |
ubi: fastmap: Check each mapping only once
Maintain a bitmap to keep track of which LEB->PEB mapping
was checked already.
That way we have to read back VID headers only once.
Signed-off-by: Richard Weinberger <richard@nod.at>
| -rw-r--r-- | drivers/mtd/ubi/build.c | 1 | ||||
| -rw-r--r-- | drivers/mtd/ubi/eba.c | 4 | ||||
| -rw-r--r-- | drivers/mtd/ubi/fastmap.c | 20 | ||||
| -rw-r--r-- | drivers/mtd/ubi/ubi.h | 11 | ||||
| -rw-r--r-- | drivers/mtd/ubi/vmt.c | 1 | ||||
| -rw-r--r-- | drivers/mtd/ubi/vtbl.c | 16 |
6 files changed, 52 insertions, 1 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 74425af840d6..d2a726654ff1 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
| @@ -526,6 +526,7 @@ void ubi_free_internal_volumes(struct ubi_device *ubi) | |||
| 526 | for (i = ubi->vtbl_slots; | 526 | for (i = ubi->vtbl_slots; |
| 527 | i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { | 527 | i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { |
| 528 | ubi_eba_replace_table(ubi->volumes[i], NULL); | 528 | ubi_eba_replace_table(ubi->volumes[i], NULL); |
| 529 | ubi_fastmap_destroy_checkmap(ubi->volumes[i]); | ||
| 529 | kfree(ubi->volumes[i]); | 530 | kfree(ubi->volumes[i]); |
| 530 | } | 531 | } |
| 531 | } | 532 | } |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 593a4f9d97e3..1ceab201a27b 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
| @@ -517,6 +517,9 @@ static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnu | |||
| 517 | if (!ubi->fast_attach) | 517 | if (!ubi->fast_attach) |
| 518 | return 0; | 518 | return 0; |
| 519 | 519 | ||
| 520 | if (!vol->checkmap || test_bit(lnum, vol->checkmap)) | ||
| 521 | return 0; | ||
| 522 | |||
| 520 | vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS); | 523 | vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS); |
| 521 | if (!vidb) | 524 | if (!vidb) |
| 522 | return -ENOMEM; | 525 | return -ENOMEM; |
| @@ -551,6 +554,7 @@ static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnu | |||
| 551 | goto out_free; | 554 | goto out_free; |
| 552 | } | 555 | } |
| 553 | 556 | ||
| 557 | set_bit(lnum, vol->checkmap); | ||
| 554 | err = 0; | 558 | err = 0; |
| 555 | 559 | ||
| 556 | out_free: | 560 | out_free: |
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 91705962ba73..462526a10537 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c | |||
| @@ -1100,6 +1100,26 @@ free_fm_sb: | |||
| 1100 | goto out; | 1100 | goto out; |
| 1101 | } | 1101 | } |
| 1102 | 1102 | ||
| 1103 | int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count) | ||
| 1104 | { | ||
| 1105 | struct ubi_device *ubi = vol->ubi; | ||
| 1106 | |||
| 1107 | if (!ubi->fast_attach) | ||
| 1108 | return 0; | ||
| 1109 | |||
| 1110 | vol->checkmap = kcalloc(BITS_TO_LONGS(leb_count), sizeof(unsigned long), | ||
| 1111 | GFP_KERNEL); | ||
| 1112 | if (!vol->checkmap) | ||
| 1113 | return -ENOMEM; | ||
| 1114 | |||
| 1115 | return 0; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) | ||
| 1119 | { | ||
| 1120 | kfree(vol->checkmap); | ||
| 1121 | } | ||
| 1122 | |||
| 1103 | /** | 1123 | /** |
| 1104 | * ubi_write_fastmap - writes a fastmap. | 1124 | * ubi_write_fastmap - writes a fastmap. |
| 1105 | * @ubi: UBI device object | 1125 | * @ubi: UBI device object |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 5fe62653995e..f5ba97c46160 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
| @@ -334,6 +334,9 @@ struct ubi_eba_leb_desc { | |||
| 334 | * @changing_leb: %1 if the atomic LEB change ioctl command is in progress | 334 | * @changing_leb: %1 if the atomic LEB change ioctl command is in progress |
| 335 | * @direct_writes: %1 if direct writes are enabled for this volume | 335 | * @direct_writes: %1 if direct writes are enabled for this volume |
| 336 | * | 336 | * |
| 337 | * @checkmap: bitmap to remember which PEB->LEB mappings got checked, | ||
| 338 | * protected by UBI LEB lock tree. | ||
| 339 | * | ||
| 337 | * The @corrupted field indicates that the volume's contents is corrupted. | 340 | * The @corrupted field indicates that the volume's contents is corrupted. |
| 338 | * Since UBI protects only static volumes, this field is not relevant to | 341 | * Since UBI protects only static volumes, this field is not relevant to |
| 339 | * dynamic volumes - it is user's responsibility to assure their data | 342 | * dynamic volumes - it is user's responsibility to assure their data |
| @@ -377,6 +380,10 @@ struct ubi_volume { | |||
| 377 | unsigned int updating:1; | 380 | unsigned int updating:1; |
| 378 | unsigned int changing_leb:1; | 381 | unsigned int changing_leb:1; |
| 379 | unsigned int direct_writes:1; | 382 | unsigned int direct_writes:1; |
| 383 | |||
| 384 | #ifdef CONFIG_MTD_UBI_FASTMAP | ||
| 385 | unsigned long *checkmap; | ||
| 386 | #endif | ||
| 380 | }; | 387 | }; |
| 381 | 388 | ||
| 382 | /** | 389 | /** |
| @@ -965,8 +972,12 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi); | |||
| 965 | int ubi_update_fastmap(struct ubi_device *ubi); | 972 | int ubi_update_fastmap(struct ubi_device *ubi); |
| 966 | int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, | 973 | int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, |
| 967 | struct ubi_attach_info *scan_ai); | 974 | struct ubi_attach_info *scan_ai); |
| 975 | int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count); | ||
| 976 | void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol); | ||
| 968 | #else | 977 | #else |
| 969 | static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; } | 978 | static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; } |
| 979 | int static inline ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count) { return 0; } | ||
| 980 | static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {} | ||
| 970 | #endif | 981 | #endif |
| 971 | 982 | ||
| 972 | /* block.c */ | 983 | /* block.c */ |
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 3fd8d7ff7a02..0be516780e92 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
| @@ -139,6 +139,7 @@ static void vol_release(struct device *dev) | |||
| 139 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); | 139 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
| 140 | 140 | ||
| 141 | ubi_eba_replace_table(vol, NULL); | 141 | ubi_eba_replace_table(vol, NULL); |
| 142 | ubi_fastmap_destroy_checkmap(vol); | ||
| 142 | kfree(vol); | 143 | kfree(vol); |
| 143 | } | 144 | } |
| 144 | 145 | ||
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 263743e7b741..94d7a865b135 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
| @@ -534,7 +534,7 @@ static int init_volumes(struct ubi_device *ubi, | |||
| 534 | const struct ubi_attach_info *ai, | 534 | const struct ubi_attach_info *ai, |
| 535 | const struct ubi_vtbl_record *vtbl) | 535 | const struct ubi_vtbl_record *vtbl) |
| 536 | { | 536 | { |
| 537 | int i, reserved_pebs = 0; | 537 | int i, err, reserved_pebs = 0; |
| 538 | struct ubi_ainf_volume *av; | 538 | struct ubi_ainf_volume *av; |
| 539 | struct ubi_volume *vol; | 539 | struct ubi_volume *vol; |
| 540 | 540 | ||
| @@ -620,6 +620,16 @@ static int init_volumes(struct ubi_device *ubi, | |||
| 620 | (long long)(vol->used_ebs - 1) * vol->usable_leb_size; | 620 | (long long)(vol->used_ebs - 1) * vol->usable_leb_size; |
| 621 | vol->used_bytes += av->last_data_size; | 621 | vol->used_bytes += av->last_data_size; |
| 622 | vol->last_eb_bytes = av->last_data_size; | 622 | vol->last_eb_bytes = av->last_data_size; |
| 623 | |||
| 624 | /* | ||
| 625 | * We use ubi->peb_count and not vol->reserved_pebs because | ||
| 626 | * we want to keep the code simple. Otherwise we'd have to | ||
| 627 | * resize/check the bitmap upon volume resize too. | ||
| 628 | * Allocating a few bytes more does not hurt. | ||
| 629 | */ | ||
| 630 | err = ubi_fastmap_init_checkmap(vol, ubi->peb_count); | ||
| 631 | if (err) | ||
| 632 | return err; | ||
| 623 | } | 633 | } |
| 624 | 634 | ||
| 625 | /* And add the layout volume */ | 635 | /* And add the layout volume */ |
| @@ -645,6 +655,9 @@ static int init_volumes(struct ubi_device *ubi, | |||
| 645 | reserved_pebs += vol->reserved_pebs; | 655 | reserved_pebs += vol->reserved_pebs; |
| 646 | ubi->vol_count += 1; | 656 | ubi->vol_count += 1; |
| 647 | vol->ubi = ubi; | 657 | vol->ubi = ubi; |
| 658 | err = ubi_fastmap_init_checkmap(vol, UBI_LAYOUT_VOLUME_EBS); | ||
| 659 | if (err) | ||
| 660 | return err; | ||
| 648 | 661 | ||
| 649 | if (reserved_pebs > ubi->avail_pebs) { | 662 | if (reserved_pebs > ubi->avail_pebs) { |
| 650 | ubi_err(ubi, "not enough PEBs, required %d, available %d", | 663 | ubi_err(ubi, "not enough PEBs, required %d, available %d", |
| @@ -849,6 +862,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai) | |||
| 849 | out_free: | 862 | out_free: |
| 850 | vfree(ubi->vtbl); | 863 | vfree(ubi->vtbl); |
| 851 | for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { | 864 | for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { |
| 865 | ubi_fastmap_destroy_checkmap(ubi->volumes[i]); | ||
| 852 | kfree(ubi->volumes[i]); | 866 | kfree(ubi->volumes[i]); |
| 853 | ubi->volumes[i] = NULL; | 867 | ubi->volumes[i] = NULL; |
| 854 | } | 868 | } |
