fastmap.c (5ca97ad83800938e8aeea622821a26d69d2052bf) fastmap.c (daef3dd1f0ae71bf04a32af4ef643baf040bb73d)
1/*
2 * Copyright (c) 2012 Linutronix GmbH
1/*
2 * Copyright (c) 2012 Linutronix GmbH
3 * Copyright (c) 2014 sigma star gmbh
3 * Author: Richard Weinberger <richard@nod.at>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 */
15
16#include <linux/crc32.h>
17#include "ubi.h"
18
19/**
4 * Author: Richard Weinberger <richard@nod.at>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 */
16
17#include <linux/crc32.h>
18#include "ubi.h"
19
20/**
21 * init_seen - allocate memory for used for debugging.
22 * @ubi: UBI device description object
23 */
24static inline int *init_seen(struct ubi_device *ubi)
25{
26 int *ret;
27
28 if (!ubi_dbg_chk_fastmap(ubi))
29 return NULL;
30
31 ret = kcalloc(ubi->peb_count, sizeof(int), GFP_KERNEL);
32 if (!ret)
33 return ERR_PTR(-ENOMEM);
34
35 return ret;
36}
37
38/**
39 * free_seen - free the seen logic integer array.
40 * @seen: integer array of @ubi->peb_count size
41 */
42static inline void free_seen(int *seen)
43{
44 kfree(seen);
45}
46
47/**
48 * set_seen - mark a PEB as seen.
49 * @ubi: UBI device description object
50 * @pnum: The PEB to be makred as seen
51 * @seen: integer array of @ubi->peb_count size
52 */
53static inline void set_seen(struct ubi_device *ubi, int pnum, int *seen)
54{
55 if (!ubi_dbg_chk_fastmap(ubi) || !seen)
56 return;
57
58 seen[pnum] = 1;
59}
60
61/**
62 * self_check_seen - check whether all PEB have been seen by fastmap.
63 * @ubi: UBI device description object
64 * @seen: integer array of @ubi->peb_count size
65 */
66static int self_check_seen(struct ubi_device *ubi, int *seen)
67{
68 int pnum, ret = 0;
69
70 if (!ubi_dbg_chk_fastmap(ubi) || !seen)
71 return 0;
72
73 for (pnum = 0; pnum < ubi->peb_count; pnum++) {
74 if (!seen[pnum] && ubi->lookuptbl[pnum]) {
75 ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum);
76 ret = -EINVAL;
77 }
78 }
79
80 return ret;
81}
82
83/**
20 * ubi_calc_fm_size - calculates the fastmap size in bytes for an UBI device.
21 * @ubi: UBI device description object
22 */
23size_t ubi_calc_fm_size(struct ubi_device *ubi)
24{
25 size_t size;
26
27 size = sizeof(struct ubi_fm_sb) + \

--- 997 unchanged lines hidden (view full) ---

1025 struct ubi_fm_eba *feba;
1026 struct rb_node *node;
1027 struct ubi_wl_entry *wl_e;
1028 struct ubi_volume *vol;
1029 struct ubi_vid_hdr *avhdr, *dvhdr;
1030 struct ubi_work *ubi_wrk;
1031 int ret, i, j, free_peb_count, used_peb_count, vol_count;
1032 int scrub_peb_count, erase_peb_count;
84 * ubi_calc_fm_size - calculates the fastmap size in bytes for an UBI device.
85 * @ubi: UBI device description object
86 */
87size_t ubi_calc_fm_size(struct ubi_device *ubi)
88{
89 size_t size;
90
91 size = sizeof(struct ubi_fm_sb) + \

--- 997 unchanged lines hidden (view full) ---

1089 struct ubi_fm_eba *feba;
1090 struct rb_node *node;
1091 struct ubi_wl_entry *wl_e;
1092 struct ubi_volume *vol;
1093 struct ubi_vid_hdr *avhdr, *dvhdr;
1094 struct ubi_work *ubi_wrk;
1095 int ret, i, j, free_peb_count, used_peb_count, vol_count;
1096 int scrub_peb_count, erase_peb_count;
1097 int *seen_pebs = NULL;
1033
1034 fm_raw = ubi->fm_buf;
1035 memset(ubi->fm_buf, 0, ubi->fm_size);
1036
1037 avhdr = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID);
1038 if (!avhdr) {
1039 ret = -ENOMEM;
1040 goto out;
1041 }
1042
1043 dvhdr = new_fm_vhdr(ubi, UBI_FM_DATA_VOLUME_ID);
1044 if (!dvhdr) {
1045 ret = -ENOMEM;
1046 goto out_kfree;
1047 }
1048
1098
1099 fm_raw = ubi->fm_buf;
1100 memset(ubi->fm_buf, 0, ubi->fm_size);
1101
1102 avhdr = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID);
1103 if (!avhdr) {
1104 ret = -ENOMEM;
1105 goto out;
1106 }
1107
1108 dvhdr = new_fm_vhdr(ubi, UBI_FM_DATA_VOLUME_ID);
1109 if (!dvhdr) {
1110 ret = -ENOMEM;
1111 goto out_kfree;
1112 }
1113
1114 seen_pebs = init_seen(ubi);
1115 if (IS_ERR(seen_pebs)) {
1116 ret = PTR_ERR(seen_pebs);
1117 goto out_kfree;
1118 }
1119
1049 spin_lock(&ubi->volumes_lock);
1050 spin_lock(&ubi->wl_lock);
1051
1052 fmsb = (struct ubi_fm_sb *)fm_raw;
1053 fm_pos += sizeof(*fmsb);
1054 ubi_assert(fm_pos <= ubi->fm_size);
1055
1056 fmh = (struct ubi_fm_hdr *)(fm_raw + fm_pos);

--- 14 unchanged lines hidden (view full) ---

1071 vol_count = 0;
1072
1073 fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
1074 fm_pos += sizeof(*fmpl1);
1075 fmpl1->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
1076 fmpl1->size = cpu_to_be16(ubi->fm_pool.size);
1077 fmpl1->max_size = cpu_to_be16(ubi->fm_pool.max_size);
1078
1120 spin_lock(&ubi->volumes_lock);
1121 spin_lock(&ubi->wl_lock);
1122
1123 fmsb = (struct ubi_fm_sb *)fm_raw;
1124 fm_pos += sizeof(*fmsb);
1125 ubi_assert(fm_pos <= ubi->fm_size);
1126
1127 fmh = (struct ubi_fm_hdr *)(fm_raw + fm_pos);

--- 14 unchanged lines hidden (view full) ---

1142 vol_count = 0;
1143
1144 fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
1145 fm_pos += sizeof(*fmpl1);
1146 fmpl1->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
1147 fmpl1->size = cpu_to_be16(ubi->fm_pool.size);
1148 fmpl1->max_size = cpu_to_be16(ubi->fm_pool.max_size);
1149
1079 for (i = 0; i < ubi->fm_pool.size; i++)
1150 for (i = 0; i < ubi->fm_pool.size; i++) {
1080 fmpl1->pebs[i] = cpu_to_be32(ubi->fm_pool.pebs[i]);
1151 fmpl1->pebs[i] = cpu_to_be32(ubi->fm_pool.pebs[i]);
1152 set_seen(ubi, ubi->fm_pool.pebs[i], seen_pebs);
1153 }
1081
1082 fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
1083 fm_pos += sizeof(*fmpl2);
1084 fmpl2->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
1085 fmpl2->size = cpu_to_be16(ubi->fm_wl_pool.size);
1086 fmpl2->max_size = cpu_to_be16(ubi->fm_wl_pool.max_size);
1087
1154
1155 fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
1156 fm_pos += sizeof(*fmpl2);
1157 fmpl2->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
1158 fmpl2->size = cpu_to_be16(ubi->fm_wl_pool.size);
1159 fmpl2->max_size = cpu_to_be16(ubi->fm_wl_pool.max_size);
1160
1088 for (i = 0; i < ubi->fm_wl_pool.size; i++)
1161 for (i = 0; i < ubi->fm_wl_pool.size; i++) {
1089 fmpl2->pebs[i] = cpu_to_be32(ubi->fm_wl_pool.pebs[i]);
1162 fmpl2->pebs[i] = cpu_to_be32(ubi->fm_wl_pool.pebs[i]);
1163 set_seen(ubi, ubi->fm_wl_pool.pebs[i], seen_pebs);
1164 }
1090
1091 for (node = rb_first(&ubi->free); node; node = rb_next(node)) {
1092 wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
1093 fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
1094
1095 fec->pnum = cpu_to_be32(wl_e->pnum);
1165
1166 for (node = rb_first(&ubi->free); node; node = rb_next(node)) {
1167 wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
1168 fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
1169
1170 fec->pnum = cpu_to_be32(wl_e->pnum);
1171 set_seen(ubi, wl_e->pnum, seen_pebs);
1096 fec->ec = cpu_to_be32(wl_e->ec);
1097
1098 free_peb_count++;
1099 fm_pos += sizeof(*fec);
1100 ubi_assert(fm_pos <= ubi->fm_size);
1101 }
1102 fmh->free_peb_count = cpu_to_be32(free_peb_count);
1103
1104 for (node = rb_first(&ubi->used); node; node = rb_next(node)) {
1105 wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
1106 fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
1107
1108 fec->pnum = cpu_to_be32(wl_e->pnum);
1172 fec->ec = cpu_to_be32(wl_e->ec);
1173
1174 free_peb_count++;
1175 fm_pos += sizeof(*fec);
1176 ubi_assert(fm_pos <= ubi->fm_size);
1177 }
1178 fmh->free_peb_count = cpu_to_be32(free_peb_count);
1179
1180 for (node = rb_first(&ubi->used); node; node = rb_next(node)) {
1181 wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
1182 fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
1183
1184 fec->pnum = cpu_to_be32(wl_e->pnum);
1185 set_seen(ubi, wl_e->pnum, seen_pebs);
1109 fec->ec = cpu_to_be32(wl_e->ec);
1110
1111 used_peb_count++;
1112 fm_pos += sizeof(*fec);
1113 ubi_assert(fm_pos <= ubi->fm_size);
1114 }
1115
1116 for (i = 0; i < UBI_PROT_QUEUE_LEN; i++) {

--- 10 unchanged lines hidden (view full) ---

1127 }
1128 fmh->used_peb_count = cpu_to_be32(used_peb_count);
1129
1130 for (node = rb_first(&ubi->scrub); node; node = rb_next(node)) {
1131 wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
1132 fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
1133
1134 fec->pnum = cpu_to_be32(wl_e->pnum);
1186 fec->ec = cpu_to_be32(wl_e->ec);
1187
1188 used_peb_count++;
1189 fm_pos += sizeof(*fec);
1190 ubi_assert(fm_pos <= ubi->fm_size);
1191 }
1192
1193 for (i = 0; i < UBI_PROT_QUEUE_LEN; i++) {

--- 10 unchanged lines hidden (view full) ---

1204 }
1205 fmh->used_peb_count = cpu_to_be32(used_peb_count);
1206
1207 for (node = rb_first(&ubi->scrub); node; node = rb_next(node)) {
1208 wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
1209 fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
1210
1211 fec->pnum = cpu_to_be32(wl_e->pnum);
1212 set_seen(ubi, wl_e->pnum, seen_pebs);
1135 fec->ec = cpu_to_be32(wl_e->ec);
1136
1137 scrub_peb_count++;
1138 fm_pos += sizeof(*fec);
1139 ubi_assert(fm_pos <= ubi->fm_size);
1140 }
1141 fmh->scrub_peb_count = cpu_to_be32(scrub_peb_count);
1142
1143
1144 list_for_each_entry(ubi_wrk, &ubi->works, list) {
1145 if (ubi_is_erase_work(ubi_wrk)) {
1146 wl_e = ubi_wrk->e;
1147 ubi_assert(wl_e);
1148
1149 fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
1150
1151 fec->pnum = cpu_to_be32(wl_e->pnum);
1213 fec->ec = cpu_to_be32(wl_e->ec);
1214
1215 scrub_peb_count++;
1216 fm_pos += sizeof(*fec);
1217 ubi_assert(fm_pos <= ubi->fm_size);
1218 }
1219 fmh->scrub_peb_count = cpu_to_be32(scrub_peb_count);
1220
1221
1222 list_for_each_entry(ubi_wrk, &ubi->works, list) {
1223 if (ubi_is_erase_work(ubi_wrk)) {
1224 wl_e = ubi_wrk->e;
1225 ubi_assert(wl_e);
1226
1227 fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
1228
1229 fec->pnum = cpu_to_be32(wl_e->pnum);
1230 set_seen(ubi, wl_e->pnum, seen_pebs);
1152 fec->ec = cpu_to_be32(wl_e->ec);
1153
1154 erase_peb_count++;
1155 fm_pos += sizeof(*fec);
1156 ubi_assert(fm_pos <= ubi->fm_size);
1157 }
1158 }
1159 fmh->erase_peb_count = cpu_to_be32(erase_peb_count);

--- 43 unchanged lines hidden (view full) ---

1203 ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avhdr);
1204 if (ret) {
1205 ubi_err(ubi, "unable to write vid_hdr to fastmap SB!");
1206 goto out_kfree;
1207 }
1208
1209 for (i = 0; i < new_fm->used_blocks; i++) {
1210 fmsb->block_loc[i] = cpu_to_be32(new_fm->e[i]->pnum);
1231 fec->ec = cpu_to_be32(wl_e->ec);
1232
1233 erase_peb_count++;
1234 fm_pos += sizeof(*fec);
1235 ubi_assert(fm_pos <= ubi->fm_size);
1236 }
1237 }
1238 fmh->erase_peb_count = cpu_to_be32(erase_peb_count);

--- 43 unchanged lines hidden (view full) ---

1282 ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avhdr);
1283 if (ret) {
1284 ubi_err(ubi, "unable to write vid_hdr to fastmap SB!");
1285 goto out_kfree;
1286 }
1287
1288 for (i = 0; i < new_fm->used_blocks; i++) {
1289 fmsb->block_loc[i] = cpu_to_be32(new_fm->e[i]->pnum);
1290 set_seen(ubi, new_fm->e[i]->pnum, seen_pebs);
1211 fmsb->block_ec[i] = cpu_to_be32(new_fm->e[i]->ec);
1212 }
1213
1214 fmsb->data_crc = 0;
1215 fmsb->data_crc = cpu_to_be32(crc32(UBI_CRC32_INIT, fm_raw,
1216 ubi->fm_size));
1217
1218 for (i = 1; i < new_fm->used_blocks; i++) {

--- 17 unchanged lines hidden (view full) ---

1236 new_fm->e[i]->pnum);
1237 goto out_kfree;
1238 }
1239 }
1240
1241 ubi_assert(new_fm);
1242 ubi->fm = new_fm;
1243
1291 fmsb->block_ec[i] = cpu_to_be32(new_fm->e[i]->ec);
1292 }
1293
1294 fmsb->data_crc = 0;
1295 fmsb->data_crc = cpu_to_be32(crc32(UBI_CRC32_INIT, fm_raw,
1296 ubi->fm_size));
1297
1298 for (i = 1; i < new_fm->used_blocks; i++) {

--- 17 unchanged lines hidden (view full) ---

1316 new_fm->e[i]->pnum);
1317 goto out_kfree;
1318 }
1319 }
1320
1321 ubi_assert(new_fm);
1322 ubi->fm = new_fm;
1323
1324 ret = self_check_seen(ubi, seen_pebs);
1244 dbg_bld("fastmap written!");
1245
1246out_kfree:
1247 ubi_free_vid_hdr(ubi, avhdr);
1248 ubi_free_vid_hdr(ubi, dvhdr);
1325 dbg_bld("fastmap written!");
1326
1327out_kfree:
1328 ubi_free_vid_hdr(ubi, avhdr);
1329 ubi_free_vid_hdr(ubi, dvhdr);
1330 free_seen(seen_pebs);
1249out:
1250 return ret;
1251}
1252
1253/**
1254 * erase_block - Manually erase a PEB.
1255 * @ubi: UBI device object
1256 * @pnum: PEB to be erased

--- 297 unchanged lines hidden ---
1331out:
1332 return ret;
1333}
1334
1335/**
1336 * erase_block - Manually erase a PEB.
1337 * @ubi: UBI device object
1338 * @pnum: PEB to be erased

--- 297 unchanged lines hidden ---