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 --- |