Skip to content

Commit 34653fd

Browse files
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 <[email protected]>
1 parent 7819323 commit 34653fd

File tree

6 files changed

+52
-1
lines changed

6 files changed

+52
-1
lines changed

drivers/mtd/ubi/build.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ void ubi_free_internal_volumes(struct ubi_device *ubi)
526526
for (i = ubi->vtbl_slots;
527527
i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
528528
ubi_eba_replace_table(ubi->volumes[i], NULL);
529+
ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
529530
kfree(ubi->volumes[i]);
530531
}
531532
}

drivers/mtd/ubi/eba.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,9 @@ static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnu
517517
if (!ubi->fast_attach)
518518
return 0;
519519

520+
if (!vol->checkmap || test_bit(lnum, vol->checkmap))
521+
return 0;
522+
520523
vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
521524
if (!vidb)
522525
return -ENOMEM;
@@ -551,6 +554,7 @@ static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnu
551554
goto out_free;
552555
}
553556

557+
set_bit(lnum, vol->checkmap);
554558
err = 0;
555559

556560
out_free:

drivers/mtd/ubi/fastmap.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,26 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
11001100
goto out;
11011101
}
11021102

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+
11031123
/**
11041124
* ubi_write_fastmap - writes a fastmap.
11051125
* @ubi: UBI device object

drivers/mtd/ubi/ubi.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,9 @@ struct ubi_eba_leb_desc {
334334
* @changing_leb: %1 if the atomic LEB change ioctl command is in progress
335335
* @direct_writes: %1 if direct writes are enabled for this volume
336336
*
337+
* @checkmap: bitmap to remember which PEB->LEB mappings got checked,
338+
* protected by UBI LEB lock tree.
339+
*
337340
* The @corrupted field indicates that the volume's contents is corrupted.
338341
* Since UBI protects only static volumes, this field is not relevant to
339342
* dynamic volumes - it is user's responsibility to assure their data
@@ -377,6 +380,10 @@ struct ubi_volume {
377380
unsigned int updating:1;
378381
unsigned int changing_leb:1;
379382
unsigned int direct_writes:1;
383+
384+
#ifdef CONFIG_MTD_UBI_FASTMAP
385+
unsigned long *checkmap;
386+
#endif
380387
};
381388

382389
/**
@@ -965,8 +972,12 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi);
965972
int ubi_update_fastmap(struct ubi_device *ubi);
966973
int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
967974
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);
968977
#else
969978
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) {}
970981
#endif
971982

972983
/* block.c */

drivers/mtd/ubi/vmt.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ static void vol_release(struct device *dev)
139139
struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
140140

141141
ubi_eba_replace_table(vol, NULL);
142+
ubi_fastmap_destroy_checkmap(vol);
142143
kfree(vol);
143144
}
144145

drivers/mtd/ubi/vtbl.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ static int init_volumes(struct ubi_device *ubi,
534534
const struct ubi_attach_info *ai,
535535
const struct ubi_vtbl_record *vtbl)
536536
{
537-
int i, reserved_pebs = 0;
537+
int i, err, reserved_pebs = 0;
538538
struct ubi_ainf_volume *av;
539539
struct ubi_volume *vol;
540540

@@ -620,6 +620,16 @@ static int init_volumes(struct ubi_device *ubi,
620620
(long long)(vol->used_ebs - 1) * vol->usable_leb_size;
621621
vol->used_bytes += av->last_data_size;
622622
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;
623633
}
624634

625635
/* And add the layout volume */
@@ -645,6 +655,9 @@ static int init_volumes(struct ubi_device *ubi,
645655
reserved_pebs += vol->reserved_pebs;
646656
ubi->vol_count += 1;
647657
vol->ubi = ubi;
658+
err = ubi_fastmap_init_checkmap(vol, UBI_LAYOUT_VOLUME_EBS);
659+
if (err)
660+
return err;
648661

649662
if (reserved_pebs > ubi->avail_pebs) {
650663
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)
849862
out_free:
850863
vfree(ubi->vtbl);
851864
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
865+
ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
852866
kfree(ubi->volumes[i]);
853867
ubi->volumes[i] = NULL;
854868
}

0 commit comments

Comments
 (0)