aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2018-05-28 16:04:33 -0400
committerRichard Weinberger <richard@nod.at>2018-06-07 09:53:16 -0400
commit34653fd8c46e771585fce5975e4243f8fd401914 (patch)
tree2e0c2d723829de99308aa9d9a88ad7449ed14d9c
parent781932375ffc6411713ee0926ccae8596ed0261c (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.c1
-rw-r--r--drivers/mtd/ubi/eba.c4
-rw-r--r--drivers/mtd/ubi/fastmap.c20
-rw-r--r--drivers/mtd/ubi/ubi.h11
-rw-r--r--drivers/mtd/ubi/vmt.c1
-rw-r--r--drivers/mtd/ubi/vtbl.c16
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
556out_free: 560out_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
1103int 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
1118void 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);
965int ubi_update_fastmap(struct ubi_device *ubi); 972int ubi_update_fastmap(struct ubi_device *ubi);
966int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, 973int 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);
975int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count);
976void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol);
968#else 977#else
969static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; } 978static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; }
979int static inline ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count) { return 0; }
980static 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)
849out_free: 862out_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 }