diff options
| -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 */ |
