diff options
author | Richard Weinberger <richard@nod.at> | 2012-09-26 11:51:47 -0400 |
---|---|---|
committer | Artem Bityutskiy <artem.bityutskiy@linux.intel.com> | 2012-10-03 05:29:38 -0400 |
commit | dac6e2087a4143cfc3fc1017bf24b9d4be3055b7 (patch) | |
tree | 8df8b04fb233e2558b16f8ead80e2e2338c8df64 /drivers/mtd/ubi | |
parent | 8974b15c6e84e686201d382c7d459aa9c8c96572 (diff) |
UBI: Add fastmap stuff to attach.c
- Export compare_lebs() as fastmap needs this function.
- Implement fastmap scan logic.
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r-- | drivers/mtd/ubi/attach.c | 386 | ||||
-rw-r--r-- | drivers/mtd/ubi/build.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 2 |
3 files changed, 260 insertions, 130 deletions
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index f7adf53e4f45..fec406b4553d 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c | |||
@@ -300,7 +300,7 @@ static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai, | |||
300 | } | 300 | } |
301 | 301 | ||
302 | /** | 302 | /** |
303 | * compare_lebs - find out which logical eraseblock is newer. | 303 | * ubi_compare_lebs - find out which logical eraseblock is newer. |
304 | * @ubi: UBI device description object | 304 | * @ubi: UBI device description object |
305 | * @aeb: first logical eraseblock to compare | 305 | * @aeb: first logical eraseblock to compare |
306 | * @pnum: physical eraseblock number of the second logical eraseblock to | 306 | * @pnum: physical eraseblock number of the second logical eraseblock to |
@@ -319,7 +319,7 @@ static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai, | |||
319 | * o bit 2 is cleared: the older LEB is not corrupted; | 319 | * o bit 2 is cleared: the older LEB is not corrupted; |
320 | * o bit 2 is set: the older LEB is corrupted. | 320 | * o bit 2 is set: the older LEB is corrupted. |
321 | */ | 321 | */ |
322 | static int compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, | 322 | int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, |
323 | int pnum, const struct ubi_vid_hdr *vid_hdr) | 323 | int pnum, const struct ubi_vid_hdr *vid_hdr) |
324 | { | 324 | { |
325 | void *buf; | 325 | void *buf; |
@@ -337,7 +337,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, | |||
337 | * support these images anymore. Well, those images still work, | 337 | * support these images anymore. Well, those images still work, |
338 | * but only if no unclean reboots happened. | 338 | * but only if no unclean reboots happened. |
339 | */ | 339 | */ |
340 | ubi_err("unsupported on-flash UBI format\n"); | 340 | ubi_err("unsupported on-flash UBI format"); |
341 | return -EINVAL; | 341 | return -EINVAL; |
342 | } | 342 | } |
343 | 343 | ||
@@ -507,7 +507,7 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, | |||
507 | * sequence numbers. We still can attach these images, unless | 507 | * sequence numbers. We still can attach these images, unless |
508 | * there is a need to distinguish between old and new | 508 | * there is a need to distinguish between old and new |
509 | * eraseblocks, in which case we'll refuse the image in | 509 | * eraseblocks, in which case we'll refuse the image in |
510 | * 'compare_lebs()'. In other words, we attach old clean | 510 | * 'ubi_compare_lebs()'. In other words, we attach old clean |
511 | * images, but refuse attaching old images with duplicated | 511 | * images, but refuse attaching old images with duplicated |
512 | * logical eraseblocks because there was an unclean reboot. | 512 | * logical eraseblocks because there was an unclean reboot. |
513 | */ | 513 | */ |
@@ -523,7 +523,7 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, | |||
523 | * Now we have to drop the older one and preserve the newer | 523 | * Now we have to drop the older one and preserve the newer |
524 | * one. | 524 | * one. |
525 | */ | 525 | */ |
526 | cmp_res = compare_lebs(ubi, aeb, pnum, vid_hdr); | 526 | cmp_res = ubi_compare_lebs(ubi, aeb, pnum, vid_hdr); |
527 | if (cmp_res < 0) | 527 | if (cmp_res < 0) |
528 | return cmp_res; | 528 | return cmp_res; |
529 | 529 | ||
@@ -748,7 +748,7 @@ struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, | |||
748 | /** | 748 | /** |
749 | * check_corruption - check the data area of PEB. | 749 | * check_corruption - check the data area of PEB. |
750 | * @ubi: UBI device description object | 750 | * @ubi: UBI device description object |
751 | * @vid_hrd: the (corrupted) VID header of this PEB | 751 | * @vid_hdr: the (corrupted) VID header of this PEB |
752 | * @pnum: the physical eraseblock number to check | 752 | * @pnum: the physical eraseblock number to check |
753 | * | 753 | * |
754 | * This is a helper function which is used to distinguish between VID header | 754 | * This is a helper function which is used to distinguish between VID header |
@@ -810,6 +810,8 @@ out_unlock: | |||
810 | * @ubi: UBI device description object | 810 | * @ubi: UBI device description object |
811 | * @ai: attaching information | 811 | * @ai: attaching information |
812 | * @pnum: the physical eraseblock number | 812 | * @pnum: the physical eraseblock number |
813 | * @vid: The volume ID of the found volume will be stored in this pointer | ||
814 | * @sqnum: The sqnum of the found volume will be stored in this pointer | ||
813 | * | 815 | * |
814 | * This function reads UBI headers of PEB @pnum, checks them, and adds | 816 | * This function reads UBI headers of PEB @pnum, checks them, and adds |
815 | * information about this PEB to the corresponding list or RB-tree in the | 817 | * information about this PEB to the corresponding list or RB-tree in the |
@@ -817,10 +819,10 @@ out_unlock: | |||
817 | * successfully handled and a negative error code in case of failure. | 819 | * successfully handled and a negative error code in case of failure. |
818 | */ | 820 | */ |
819 | static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, | 821 | static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, |
820 | int pnum) | 822 | int pnum, int *vid, unsigned long long *sqnum) |
821 | { | 823 | { |
822 | long long uninitialized_var(ec); | 824 | long long uninitialized_var(ec); |
823 | int err, bitflips = 0, vol_id, ec_err = 0; | 825 | int err, bitflips = 0, vol_id = -1, ec_err = 0; |
824 | 826 | ||
825 | dbg_bld("scan PEB %d", pnum); | 827 | dbg_bld("scan PEB %d", pnum); |
826 | 828 | ||
@@ -991,14 +993,21 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, | |||
991 | } | 993 | } |
992 | 994 | ||
993 | vol_id = be32_to_cpu(vidh->vol_id); | 995 | vol_id = be32_to_cpu(vidh->vol_id); |
996 | if (vid) | ||
997 | *vid = vol_id; | ||
998 | if (sqnum) | ||
999 | *sqnum = be64_to_cpu(vidh->sqnum); | ||
994 | if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) { | 1000 | if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) { |
995 | int lnum = be32_to_cpu(vidh->lnum); | 1001 | int lnum = be32_to_cpu(vidh->lnum); |
996 | 1002 | ||
997 | /* Unsupported internal volume */ | 1003 | /* Unsupported internal volume */ |
998 | switch (vidh->compat) { | 1004 | switch (vidh->compat) { |
999 | case UBI_COMPAT_DELETE: | 1005 | case UBI_COMPAT_DELETE: |
1000 | ubi_msg("\"delete\" compatible internal volume %d:%d found, will remove it", | 1006 | if (vol_id != UBI_FM_SB_VOLUME_ID |
1001 | vol_id, lnum); | 1007 | && vol_id != UBI_FM_DATA_VOLUME_ID) { |
1008 | ubi_msg("\"delete\" compatible internal volume %d:%d found, will remove it", | ||
1009 | vol_id, lnum); | ||
1010 | } | ||
1002 | err = add_to_list(ai, pnum, vol_id, lnum, | 1011 | err = add_to_list(ai, pnum, vol_id, lnum, |
1003 | ec, 1, &ai->erase); | 1012 | ec, 1, &ai->erase); |
1004 | if (err) | 1013 | if (err) |
@@ -1121,51 +1130,126 @@ static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai) | |||
1121 | } | 1130 | } |
1122 | 1131 | ||
1123 | /** | 1132 | /** |
1133 | * destroy_av - free volume attaching information. | ||
1134 | * @av: volume attaching information | ||
1135 | * @ai: attaching information | ||
1136 | * | ||
1137 | * This function destroys the volume attaching information. | ||
1138 | */ | ||
1139 | static void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av) | ||
1140 | { | ||
1141 | struct ubi_ainf_peb *aeb; | ||
1142 | struct rb_node *this = av->root.rb_node; | ||
1143 | |||
1144 | while (this) { | ||
1145 | if (this->rb_left) | ||
1146 | this = this->rb_left; | ||
1147 | else if (this->rb_right) | ||
1148 | this = this->rb_right; | ||
1149 | else { | ||
1150 | aeb = rb_entry(this, struct ubi_ainf_peb, u.rb); | ||
1151 | this = rb_parent(this); | ||
1152 | if (this) { | ||
1153 | if (this->rb_left == &aeb->u.rb) | ||
1154 | this->rb_left = NULL; | ||
1155 | else | ||
1156 | this->rb_right = NULL; | ||
1157 | } | ||
1158 | |||
1159 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1160 | } | ||
1161 | } | ||
1162 | kfree(av); | ||
1163 | } | ||
1164 | |||
1165 | /** | ||
1166 | * destroy_ai - destroy attaching information. | ||
1167 | * @ai: attaching information | ||
1168 | */ | ||
1169 | static void destroy_ai(struct ubi_attach_info *ai) | ||
1170 | { | ||
1171 | struct ubi_ainf_peb *aeb, *aeb_tmp; | ||
1172 | struct ubi_ainf_volume *av; | ||
1173 | struct rb_node *rb; | ||
1174 | |||
1175 | list_for_each_entry_safe(aeb, aeb_tmp, &ai->alien, u.list) { | ||
1176 | list_del(&aeb->u.list); | ||
1177 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1178 | } | ||
1179 | list_for_each_entry_safe(aeb, aeb_tmp, &ai->erase, u.list) { | ||
1180 | list_del(&aeb->u.list); | ||
1181 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1182 | } | ||
1183 | list_for_each_entry_safe(aeb, aeb_tmp, &ai->corr, u.list) { | ||
1184 | list_del(&aeb->u.list); | ||
1185 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1186 | } | ||
1187 | list_for_each_entry_safe(aeb, aeb_tmp, &ai->free, u.list) { | ||
1188 | list_del(&aeb->u.list); | ||
1189 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1190 | } | ||
1191 | |||
1192 | /* Destroy the volume RB-tree */ | ||
1193 | rb = ai->volumes.rb_node; | ||
1194 | while (rb) { | ||
1195 | if (rb->rb_left) | ||
1196 | rb = rb->rb_left; | ||
1197 | else if (rb->rb_right) | ||
1198 | rb = rb->rb_right; | ||
1199 | else { | ||
1200 | av = rb_entry(rb, struct ubi_ainf_volume, rb); | ||
1201 | |||
1202 | rb = rb_parent(rb); | ||
1203 | if (rb) { | ||
1204 | if (rb->rb_left == &av->rb) | ||
1205 | rb->rb_left = NULL; | ||
1206 | else | ||
1207 | rb->rb_right = NULL; | ||
1208 | } | ||
1209 | |||
1210 | destroy_av(ai, av); | ||
1211 | } | ||
1212 | } | ||
1213 | |||
1214 | if (ai->aeb_slab_cache) | ||
1215 | kmem_cache_destroy(ai->aeb_slab_cache); | ||
1216 | |||
1217 | kfree(ai); | ||
1218 | } | ||
1219 | |||
1220 | /** | ||
1124 | * scan_all - scan entire MTD device. | 1221 | * scan_all - scan entire MTD device. |
1125 | * @ubi: UBI device description object | 1222 | * @ubi: UBI device description object |
1223 | * @ai: attach info object | ||
1224 | * @start: start scanning at this PEB | ||
1126 | * | 1225 | * |
1127 | * This function does full scanning of an MTD device and returns complete | 1226 | * This function does full scanning of an MTD device and returns complete |
1128 | * information about it in form of a "struct ubi_attach_info" object. In case | 1227 | * information about it in form of a "struct ubi_attach_info" object. In case |
1129 | * of failure, an error code is returned. | 1228 | * of failure, an error code is returned. |
1130 | */ | 1229 | */ |
1131 | static struct ubi_attach_info *scan_all(struct ubi_device *ubi) | 1230 | static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai, |
1231 | int start) | ||
1132 | { | 1232 | { |
1133 | int err, pnum; | 1233 | int err, pnum; |
1134 | struct rb_node *rb1, *rb2; | 1234 | struct rb_node *rb1, *rb2; |
1135 | struct ubi_ainf_volume *av; | 1235 | struct ubi_ainf_volume *av; |
1136 | struct ubi_ainf_peb *aeb; | 1236 | struct ubi_ainf_peb *aeb; |
1137 | struct ubi_attach_info *ai; | ||
1138 | |||
1139 | ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL); | ||
1140 | if (!ai) | ||
1141 | return ERR_PTR(-ENOMEM); | ||
1142 | |||
1143 | INIT_LIST_HEAD(&ai->corr); | ||
1144 | INIT_LIST_HEAD(&ai->free); | ||
1145 | INIT_LIST_HEAD(&ai->erase); | ||
1146 | INIT_LIST_HEAD(&ai->alien); | ||
1147 | ai->volumes = RB_ROOT; | ||
1148 | 1237 | ||
1149 | err = -ENOMEM; | 1238 | err = -ENOMEM; |
1150 | ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache", | ||
1151 | sizeof(struct ubi_ainf_peb), | ||
1152 | 0, 0, NULL); | ||
1153 | if (!ai->aeb_slab_cache) | ||
1154 | goto out_ai; | ||
1155 | 1239 | ||
1156 | ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); | 1240 | ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); |
1157 | if (!ech) | 1241 | if (!ech) |
1158 | goto out_ai; | 1242 | return err; |
1159 | 1243 | ||
1160 | vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); | 1244 | vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); |
1161 | if (!vidh) | 1245 | if (!vidh) |
1162 | goto out_ech; | 1246 | goto out_ech; |
1163 | 1247 | ||
1164 | for (pnum = 0; pnum < ubi->peb_count; pnum++) { | 1248 | for (pnum = start; pnum < ubi->peb_count; pnum++) { |
1165 | cond_resched(); | 1249 | cond_resched(); |
1166 | 1250 | ||
1167 | dbg_gen("process PEB %d", pnum); | 1251 | dbg_gen("process PEB %d", pnum); |
1168 | err = scan_peb(ubi, ai, pnum); | 1252 | err = scan_peb(ubi, ai, pnum, NULL, NULL); |
1169 | if (err < 0) | 1253 | if (err < 0) |
1170 | goto out_vidh; | 1254 | goto out_vidh; |
1171 | } | 1255 | } |
@@ -1210,32 +1294,144 @@ static struct ubi_attach_info *scan_all(struct ubi_device *ubi) | |||
1210 | ubi_free_vid_hdr(ubi, vidh); | 1294 | ubi_free_vid_hdr(ubi, vidh); |
1211 | kfree(ech); | 1295 | kfree(ech); |
1212 | 1296 | ||
1213 | return ai; | 1297 | return 0; |
1214 | 1298 | ||
1215 | out_vidh: | 1299 | out_vidh: |
1216 | ubi_free_vid_hdr(ubi, vidh); | 1300 | ubi_free_vid_hdr(ubi, vidh); |
1217 | out_ech: | 1301 | out_ech: |
1218 | kfree(ech); | 1302 | kfree(ech); |
1219 | out_ai: | 1303 | return err; |
1220 | ubi_destroy_ai(ai); | 1304 | } |
1221 | return ERR_PTR(err); | 1305 | |
1306 | #ifdef CONFIG_MTD_UBI_FASTMAP | ||
1307 | |||
1308 | /** | ||
1309 | * scan_fastmap - try to find a fastmap and attach from it. | ||
1310 | * @ubi: UBI device description object | ||
1311 | * @ai: attach info object | ||
1312 | * | ||
1313 | * Returns 0 on success, negative return values indicate an internal | ||
1314 | * error. | ||
1315 | * UBI_NO_FASTMAP denotes that no fastmap was found. | ||
1316 | * UBI_BAD_FASTMAP denotes that the found fastmap was invalid. | ||
1317 | */ | ||
1318 | static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info *ai) | ||
1319 | { | ||
1320 | int err, pnum, fm_anchor = -1; | ||
1321 | unsigned long long max_sqnum = 0; | ||
1322 | |||
1323 | err = -ENOMEM; | ||
1324 | |||
1325 | ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); | ||
1326 | if (!ech) | ||
1327 | goto out; | ||
1328 | |||
1329 | vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); | ||
1330 | if (!vidh) | ||
1331 | goto out_ech; | ||
1332 | |||
1333 | for (pnum = 0; pnum < UBI_FM_MAX_START; pnum++) { | ||
1334 | int vol_id = -1; | ||
1335 | unsigned long long sqnum = -1; | ||
1336 | cond_resched(); | ||
1337 | |||
1338 | dbg_gen("process PEB %d", pnum); | ||
1339 | err = scan_peb(ubi, ai, pnum, &vol_id, &sqnum); | ||
1340 | if (err < 0) | ||
1341 | goto out_vidh; | ||
1342 | |||
1343 | if (vol_id == UBI_FM_SB_VOLUME_ID && sqnum > max_sqnum) { | ||
1344 | max_sqnum = sqnum; | ||
1345 | fm_anchor = pnum; | ||
1346 | } | ||
1347 | } | ||
1348 | |||
1349 | ubi_free_vid_hdr(ubi, vidh); | ||
1350 | kfree(ech); | ||
1351 | |||
1352 | if (fm_anchor < 0) | ||
1353 | return UBI_NO_FASTMAP; | ||
1354 | |||
1355 | return ubi_scan_fastmap(ubi, ai, fm_anchor); | ||
1356 | |||
1357 | out_vidh: | ||
1358 | ubi_free_vid_hdr(ubi, vidh); | ||
1359 | out_ech: | ||
1360 | kfree(ech); | ||
1361 | out: | ||
1362 | return err; | ||
1363 | } | ||
1364 | |||
1365 | #endif | ||
1366 | |||
1367 | static struct ubi_attach_info *alloc_ai(const char *slab_name) | ||
1368 | { | ||
1369 | struct ubi_attach_info *ai; | ||
1370 | |||
1371 | ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL); | ||
1372 | if (!ai) | ||
1373 | return ai; | ||
1374 | |||
1375 | INIT_LIST_HEAD(&ai->corr); | ||
1376 | INIT_LIST_HEAD(&ai->free); | ||
1377 | INIT_LIST_HEAD(&ai->erase); | ||
1378 | INIT_LIST_HEAD(&ai->alien); | ||
1379 | ai->volumes = RB_ROOT; | ||
1380 | ai->aeb_slab_cache = kmem_cache_create(slab_name, | ||
1381 | sizeof(struct ubi_ainf_peb), | ||
1382 | 0, 0, NULL); | ||
1383 | if (!ai->aeb_slab_cache) { | ||
1384 | kfree(ai); | ||
1385 | ai = NULL; | ||
1386 | } | ||
1387 | |||
1388 | return ai; | ||
1222 | } | 1389 | } |
1223 | 1390 | ||
1224 | /** | 1391 | /** |
1225 | * ubi_attach - attach an MTD device. | 1392 | * ubi_attach - attach an MTD device. |
1226 | * @ubi: UBI device descriptor | 1393 | * @ubi: UBI device descriptor |
1394 | * @force_scan: if set to non-zero attach by scanning | ||
1227 | * | 1395 | * |
1228 | * This function returns zero in case of success and a negative error code in | 1396 | * This function returns zero in case of success and a negative error code in |
1229 | * case of failure. | 1397 | * case of failure. |
1230 | */ | 1398 | */ |
1231 | int ubi_attach(struct ubi_device *ubi) | 1399 | int ubi_attach(struct ubi_device *ubi, int force_scan) |
1232 | { | 1400 | { |
1233 | int err; | 1401 | int err; |
1234 | struct ubi_attach_info *ai; | 1402 | struct ubi_attach_info *ai; |
1235 | 1403 | ||
1236 | ai = scan_all(ubi); | 1404 | ai = alloc_ai("ubi_aeb_slab_cache"); |
1237 | if (IS_ERR(ai)) | 1405 | if (!ai) |
1238 | return PTR_ERR(ai); | 1406 | return -ENOMEM; |
1407 | |||
1408 | #ifdef CONFIG_MTD_UBI_FASTMAP | ||
1409 | /* On small flash devices we disable fastmap in any case. */ | ||
1410 | if ((int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) { | ||
1411 | ubi->fm_disabled = 1; | ||
1412 | force_scan = 1; | ||
1413 | } | ||
1414 | |||
1415 | if (force_scan) | ||
1416 | err = scan_all(ubi, ai, 0); | ||
1417 | else { | ||
1418 | err = scan_fast(ubi, ai); | ||
1419 | if (err > 0) { | ||
1420 | if (err != UBI_NO_FASTMAP) { | ||
1421 | destroy_ai(ai); | ||
1422 | ai = alloc_ai("ubi_aeb_slab_cache2"); | ||
1423 | if (!ai) | ||
1424 | return -ENOMEM; | ||
1425 | } | ||
1426 | |||
1427 | err = scan_all(ubi, ai, UBI_FM_MAX_START); | ||
1428 | } | ||
1429 | } | ||
1430 | #else | ||
1431 | err = scan_all(ubi, ai, 0); | ||
1432 | #endif | ||
1433 | if (err) | ||
1434 | goto out_ai; | ||
1239 | 1435 | ||
1240 | ubi->bad_peb_count = ai->bad_peb_count; | 1436 | ubi->bad_peb_count = ai->bad_peb_count; |
1241 | ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count; | 1437 | ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count; |
@@ -1256,7 +1452,29 @@ int ubi_attach(struct ubi_device *ubi) | |||
1256 | if (err) | 1452 | if (err) |
1257 | goto out_wl; | 1453 | goto out_wl; |
1258 | 1454 | ||
1259 | ubi_destroy_ai(ai); | 1455 | #ifdef CONFIG_MTD_UBI_FASTMAP |
1456 | if (ubi->fm && ubi->dbg->chk_gen) { | ||
1457 | struct ubi_attach_info *scan_ai; | ||
1458 | |||
1459 | scan_ai = alloc_ai("ubi_ckh_aeb_slab_cache"); | ||
1460 | if (!scan_ai) | ||
1461 | goto out_wl; | ||
1462 | |||
1463 | err = scan_all(ubi, scan_ai, 0); | ||
1464 | if (err) { | ||
1465 | destroy_ai(scan_ai); | ||
1466 | goto out_wl; | ||
1467 | } | ||
1468 | |||
1469 | err = self_check_eba(ubi, ai, scan_ai); | ||
1470 | destroy_ai(scan_ai); | ||
1471 | |||
1472 | if (err) | ||
1473 | goto out_wl; | ||
1474 | } | ||
1475 | #endif | ||
1476 | |||
1477 | destroy_ai(ai); | ||
1260 | return 0; | 1478 | return 0; |
1261 | 1479 | ||
1262 | out_wl: | 1480 | out_wl: |
@@ -1265,99 +1483,11 @@ out_vtbl: | |||
1265 | ubi_free_internal_volumes(ubi); | 1483 | ubi_free_internal_volumes(ubi); |
1266 | vfree(ubi->vtbl); | 1484 | vfree(ubi->vtbl); |
1267 | out_ai: | 1485 | out_ai: |
1268 | ubi_destroy_ai(ai); | 1486 | destroy_ai(ai); |
1269 | return err; | 1487 | return err; |
1270 | } | 1488 | } |
1271 | 1489 | ||
1272 | /** | 1490 | /** |
1273 | * destroy_av - free volume attaching information. | ||
1274 | * @av: volume attaching information | ||
1275 | * @ai: attaching information | ||
1276 | * | ||
1277 | * This function destroys the volume attaching information. | ||
1278 | */ | ||
1279 | static void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av) | ||
1280 | { | ||
1281 | struct ubi_ainf_peb *aeb; | ||
1282 | struct rb_node *this = av->root.rb_node; | ||
1283 | |||
1284 | while (this) { | ||
1285 | if (this->rb_left) | ||
1286 | this = this->rb_left; | ||
1287 | else if (this->rb_right) | ||
1288 | this = this->rb_right; | ||
1289 | else { | ||
1290 | aeb = rb_entry(this, struct ubi_ainf_peb, u.rb); | ||
1291 | this = rb_parent(this); | ||
1292 | if (this) { | ||
1293 | if (this->rb_left == &aeb->u.rb) | ||
1294 | this->rb_left = NULL; | ||
1295 | else | ||
1296 | this->rb_right = NULL; | ||
1297 | } | ||
1298 | |||
1299 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1300 | } | ||
1301 | } | ||
1302 | kfree(av); | ||
1303 | } | ||
1304 | |||
1305 | /** | ||
1306 | * ubi_destroy_ai - destroy attaching information. | ||
1307 | * @ai: attaching information | ||
1308 | */ | ||
1309 | void ubi_destroy_ai(struct ubi_attach_info *ai) | ||
1310 | { | ||
1311 | struct ubi_ainf_peb *aeb, *aeb_tmp; | ||
1312 | struct ubi_ainf_volume *av; | ||
1313 | struct rb_node *rb; | ||
1314 | |||
1315 | list_for_each_entry_safe(aeb, aeb_tmp, &ai->alien, u.list) { | ||
1316 | list_del(&aeb->u.list); | ||
1317 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1318 | } | ||
1319 | list_for_each_entry_safe(aeb, aeb_tmp, &ai->erase, u.list) { | ||
1320 | list_del(&aeb->u.list); | ||
1321 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1322 | } | ||
1323 | list_for_each_entry_safe(aeb, aeb_tmp, &ai->corr, u.list) { | ||
1324 | list_del(&aeb->u.list); | ||
1325 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1326 | } | ||
1327 | list_for_each_entry_safe(aeb, aeb_tmp, &ai->free, u.list) { | ||
1328 | list_del(&aeb->u.list); | ||
1329 | kmem_cache_free(ai->aeb_slab_cache, aeb); | ||
1330 | } | ||
1331 | |||
1332 | /* Destroy the volume RB-tree */ | ||
1333 | rb = ai->volumes.rb_node; | ||
1334 | while (rb) { | ||
1335 | if (rb->rb_left) | ||
1336 | rb = rb->rb_left; | ||
1337 | else if (rb->rb_right) | ||
1338 | rb = rb->rb_right; | ||
1339 | else { | ||
1340 | av = rb_entry(rb, struct ubi_ainf_volume, rb); | ||
1341 | |||
1342 | rb = rb_parent(rb); | ||
1343 | if (rb) { | ||
1344 | if (rb->rb_left == &av->rb) | ||
1345 | rb->rb_left = NULL; | ||
1346 | else | ||
1347 | rb->rb_right = NULL; | ||
1348 | } | ||
1349 | |||
1350 | destroy_av(ai, av); | ||
1351 | } | ||
1352 | } | ||
1353 | |||
1354 | if (ai->aeb_slab_cache) | ||
1355 | kmem_cache_destroy(ai->aeb_slab_cache); | ||
1356 | |||
1357 | kfree(ai); | ||
1358 | } | ||
1359 | |||
1360 | /** | ||
1361 | * self_check_ai - check the attaching information. | 1491 | * self_check_ai - check the attaching information. |
1362 | * @ubi: UBI device description object | 1492 | * @ubi: UBI device description object |
1363 | * @ai: attaching information | 1493 | * @ai: attaching information |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index c9b99be8f6d5..344b4cb49d4e 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -990,7 +990,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, | |||
990 | if (err) | 990 | if (err) |
991 | goto out_free; | 991 | goto out_free; |
992 | 992 | ||
993 | err = ubi_attach(ubi); | 993 | err = ubi_attach(ubi, 0); |
994 | if (err) { | 994 | if (err) { |
995 | ubi_err("failed to attach mtd%d, error %d", mtd->index, err); | 995 | ubi_err("failed to attach mtd%d, error %d", mtd->index, err); |
996 | goto out_debugging; | 996 | goto out_debugging; |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index b0d3ba2a3dea..7d57469723cf 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -710,7 +710,7 @@ struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, | |||
710 | void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av); | 710 | void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av); |
711 | struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, | 711 | struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, |
712 | struct ubi_attach_info *ai); | 712 | struct ubi_attach_info *ai); |
713 | int ubi_attach(struct ubi_device *ubi); | 713 | int ubi_attach(struct ubi_device *ubi, int force_scan); |
714 | void ubi_destroy_ai(struct ubi_attach_info *ai); | 714 | void ubi_destroy_ai(struct ubi_attach_info *ai); |
715 | 715 | ||
716 | /* vtbl.c */ | 716 | /* vtbl.c */ |