|
@@ -1201,6 +1201,102 @@ static void print_rsvd_warning(struct ubi_device *ubi,
|
|
|
ubi->corr_peb_count);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * self_check_eba - run a self check on the EBA table constructed by fastmap.
|
|
|
+ * @ubi: UBI device description object
|
|
|
+ * @ai_fastmap: UBI attach info object created by fastmap
|
|
|
+ * @ai_scan: UBI attach info object created by scanning
|
|
|
+ *
|
|
|
+ * Returns < 0 in case of an internal error, 0 otherwise.
|
|
|
+ * If a bad EBA table entry was found it will be printed out and
|
|
|
+ * ubi_assert() triggers.
|
|
|
+ */
|
|
|
+int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
|
|
|
+ struct ubi_attach_info *ai_scan)
|
|
|
+{
|
|
|
+ int i, j, num_volumes, ret = 0;
|
|
|
+ int **scan_eba, **fm_eba;
|
|
|
+ struct ubi_ainf_volume *av;
|
|
|
+ struct ubi_volume *vol;
|
|
|
+ struct ubi_ainf_peb *aeb;
|
|
|
+ struct rb_node *rb;
|
|
|
+
|
|
|
+ num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
|
|
|
+
|
|
|
+ scan_eba = kmalloc(sizeof(*scan_eba) * num_volumes, GFP_KERNEL);
|
|
|
+ if (!scan_eba)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ fm_eba = kmalloc(sizeof(*fm_eba) * num_volumes, GFP_KERNEL);
|
|
|
+ if (!fm_eba) {
|
|
|
+ kfree(scan_eba);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < num_volumes; i++) {
|
|
|
+ vol = ubi->volumes[i];
|
|
|
+ if (!vol)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ scan_eba[i] = kmalloc(vol->reserved_pebs * sizeof(**scan_eba),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!scan_eba[i]) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto out_free;
|
|
|
+ }
|
|
|
+
|
|
|
+ fm_eba[i] = kmalloc(vol->reserved_pebs * sizeof(**fm_eba),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!fm_eba[i]) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto out_free;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (j = 0; j < vol->reserved_pebs; j++)
|
|
|
+ scan_eba[i][j] = fm_eba[i][j] = UBI_LEB_UNMAPPED;
|
|
|
+
|
|
|
+ av = ubi_find_av(ai_scan, idx2vol_id(ubi, i));
|
|
|
+ if (!av)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb)
|
|
|
+ scan_eba[i][aeb->lnum] = aeb->pnum;
|
|
|
+
|
|
|
+ av = ubi_find_av(ai_fastmap, idx2vol_id(ubi, i));
|
|
|
+ if (!av)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb)
|
|
|
+ fm_eba[i][aeb->lnum] = aeb->pnum;
|
|
|
+
|
|
|
+ for (j = 0; j < vol->reserved_pebs; j++) {
|
|
|
+ if (scan_eba[i][j] != fm_eba[i][j]) {
|
|
|
+ if (scan_eba[i][j] == UBI_LEB_UNMAPPED ||
|
|
|
+ fm_eba[i][j] == UBI_LEB_UNMAPPED)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ubi_err("LEB:%i:%i is PEB:%i instead of %i!",
|
|
|
+ vol->vol_id, i, fm_eba[i][j],
|
|
|
+ scan_eba[i][j]);
|
|
|
+ ubi_assert(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+out_free:
|
|
|
+ for (i = 0; i < num_volumes; i++) {
|
|
|
+ if (!ubi->volumes[i])
|
|
|
+ continue;
|
|
|
+
|
|
|
+ kfree(scan_eba[i]);
|
|
|
+ kfree(fm_eba[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ kfree(scan_eba);
|
|
|
+ kfree(fm_eba);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ubi_eba_init - initialize the EBA sub-system using attaching information.
|
|
|
* @ubi: UBI device description object
|