aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/fastmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/fastmap.c')
-rw-r--r--drivers/mtd/ubi/fastmap.c162
1 files changed, 114 insertions, 48 deletions
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 762e25c6a2d2..db2625d3ecd9 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1300,31 +1300,87 @@ out:
1300/** 1300/**
1301 * invalidate_fastmap - destroys a fastmap. 1301 * invalidate_fastmap - destroys a fastmap.
1302 * @ubi: UBI device object 1302 * @ubi: UBI device object
1303 * @fm: the fastmap to be destroyed
1304 * 1303 *
1304 * This function ensures that upon next UBI attach a full scan
1305 * is issued. We need this if UBI is about to write a new fastmap
1306 * but is unable to do so. In this case we have two options:
1307 * a) Make sure that the current fastmap will not be usued upon
1308 * attach time and contine or b) fall back to RO mode to have the
1309 * current fastmap in a valid state.
1305 * Returns 0 on success, < 0 indicates an internal error. 1310 * Returns 0 on success, < 0 indicates an internal error.
1306 */ 1311 */
1307static int invalidate_fastmap(struct ubi_device *ubi, 1312static int invalidate_fastmap(struct ubi_device *ubi)
1308 struct ubi_fastmap_layout *fm)
1309{ 1313{
1310 int ret; 1314 int ret;
1311 struct ubi_vid_hdr *vh; 1315 struct ubi_fastmap_layout *fm;
1316 struct ubi_wl_entry *e;
1317 struct ubi_vid_hdr *vh = NULL;
1312 1318
1313 ret = erase_block(ubi, fm->e[0]->pnum); 1319 if (!ubi->fm)
1314 if (ret < 0) 1320 return 0;
1315 return ret; 1321
1322 ubi->fm = NULL;
1323
1324 ret = -ENOMEM;
1325 fm = kzalloc(sizeof(*fm), GFP_KERNEL);
1326 if (!fm)
1327 goto out;
1316 1328
1317 vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID); 1329 vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID);
1318 if (!vh) 1330 if (!vh)
1319 return -ENOMEM; 1331 goto out_free_fm;
1332
1333 ret = -ENOSPC;
1334 e = ubi_wl_get_fm_peb(ubi, 1);
1335 if (!e)
1336 goto out_free_fm;
1320 1337
1321 /* deleting the current fastmap SB is not enough, an old SB may exist, 1338 /*
1322 * so create a (corrupted) SB such that fastmap will find it and fall 1339 * Create fake fastmap such that UBI will fall back
1323 * back to scanning mode in any case */ 1340 * to scanning mode.
1341 */
1324 vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); 1342 vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
1325 ret = ubi_io_write_vid_hdr(ubi, fm->e[0]->pnum, vh); 1343 ret = ubi_io_write_vid_hdr(ubi, e->pnum, vh);
1344 if (ret < 0) {
1345 ubi_wl_put_fm_peb(ubi, e, 0, 0);
1346 goto out_free_fm;
1347 }
1326 1348
1349 fm->used_blocks = 1;
1350 fm->e[0] = e;
1351
1352 ubi->fm = fm;
1353
1354out:
1355 ubi_free_vid_hdr(ubi, vh);
1327 return ret; 1356 return ret;
1357
1358out_free_fm:
1359 kfree(fm);
1360 goto out;
1361}
1362
1363/**
1364 * return_fm_pebs - returns all PEBs used by a fastmap back to the
1365 * WL sub-system.
1366 * @ubi: UBI device object
1367 * @fm: fastmap layout object
1368 */
1369static void return_fm_pebs(struct ubi_device *ubi,
1370 struct ubi_fastmap_layout *fm)
1371{
1372 int i;
1373
1374 if (!fm)
1375 return;
1376
1377 for (i = 0; i < fm->used_blocks; i++) {
1378 if (fm->e[i]) {
1379 ubi_wl_put_fm_peb(ubi, fm->e[i], i,
1380 fm->to_be_tortured[i]);
1381 fm->e[i] = NULL;
1382 }
1383 }
1328} 1384}
1329 1385
1330/** 1386/**
@@ -1336,7 +1392,7 @@ static int invalidate_fastmap(struct ubi_device *ubi,
1336 */ 1392 */
1337int ubi_update_fastmap(struct ubi_device *ubi) 1393int ubi_update_fastmap(struct ubi_device *ubi)
1338{ 1394{
1339 int ret, i; 1395 int ret, i, j;
1340 struct ubi_fastmap_layout *new_fm, *old_fm; 1396 struct ubi_fastmap_layout *new_fm, *old_fm;
1341 struct ubi_wl_entry *tmp_e; 1397 struct ubi_wl_entry *tmp_e;
1342 1398
@@ -1376,34 +1432,40 @@ int ubi_update_fastmap(struct ubi_device *ubi)
1376 tmp_e = ubi_wl_get_fm_peb(ubi, 0); 1432 tmp_e = ubi_wl_get_fm_peb(ubi, 0);
1377 spin_unlock(&ubi->wl_lock); 1433 spin_unlock(&ubi->wl_lock);
1378 1434
1379 if (!tmp_e && !old_fm) { 1435 if (!tmp_e) {
1380 int j; 1436 if (old_fm && old_fm->e[i]) {
1381 ubi_err(ubi, "could not get any free erase block"); 1437 ret = erase_block(ubi, old_fm->e[i]->pnum);
1382 1438 if (ret < 0) {
1383 for (j = 1; j < i; j++) 1439 ubi_err(ubi, "could not erase old fastmap PEB");
1384 ubi_wl_put_fm_peb(ubi, new_fm->e[j], j, 0); 1440
1385 1441 for (j = 1; j < i; j++) {
1386 ret = -ENOSPC; 1442 ubi_wl_put_fm_peb(ubi, new_fm->e[j],
1387 goto err; 1443 j, 0);
1388 } else if (!tmp_e && old_fm && old_fm->e[i]) { 1444 new_fm->e[j] = NULL;
1389 ret = erase_block(ubi, old_fm->e[i]->pnum); 1445 }
1390 if (ret < 0) { 1446 goto err;
1391 int j; 1447 }
1392 1448 new_fm->e[i] = old_fm->e[i];
1393 for (j = 1; j < i; j++) 1449 old_fm->e[i] = NULL;
1394 ubi_wl_put_fm_peb(ubi, new_fm->e[j], 1450 } else {
1395 j, 0); 1451 ubi_err(ubi, "could not get any free erase block");
1452
1453 for (j = 1; j < i; j++) {
1454 ubi_wl_put_fm_peb(ubi, new_fm->e[j], j, 0);
1455 new_fm->e[j] = NULL;
1456 }
1396 1457
1397 ubi_err(ubi, "could not erase old fastmap PEB"); 1458 ret = -ENOSPC;
1398 goto err; 1459 goto err;
1399 } 1460 }
1400 new_fm->e[i] = old_fm->e[i];
1401 } else { 1461 } else {
1402 new_fm->e[i] = tmp_e; 1462 new_fm->e[i] = tmp_e;
1403 1463
1404 if (old_fm && old_fm->e[i]) 1464 if (old_fm && old_fm->e[i]) {
1405 ubi_wl_put_fm_peb(ubi, old_fm->e[i], i, 1465 ubi_wl_put_fm_peb(ubi, old_fm->e[i], i,
1406 old_fm->to_be_tortured[i]); 1466 old_fm->to_be_tortured[i]);
1467 old_fm->e[i] = NULL;
1468 }
1407 } 1469 }
1408 } 1470 }
1409 1471
@@ -1412,6 +1474,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
1412 for (i = new_fm->used_blocks; i < old_fm->used_blocks; i++) { 1474 for (i = new_fm->used_blocks; i < old_fm->used_blocks; i++) {
1413 ubi_wl_put_fm_peb(ubi, old_fm->e[i], i, 1475 ubi_wl_put_fm_peb(ubi, old_fm->e[i], i,
1414 old_fm->to_be_tortured[i]); 1476 old_fm->to_be_tortured[i]);
1477 old_fm->e[i] = NULL;
1415 } 1478 }
1416 } 1479 }
1417 1480
@@ -1424,29 +1487,33 @@ int ubi_update_fastmap(struct ubi_device *ubi)
1424 if (!tmp_e) { 1487 if (!tmp_e) {
1425 ret = erase_block(ubi, old_fm->e[0]->pnum); 1488 ret = erase_block(ubi, old_fm->e[0]->pnum);
1426 if (ret < 0) { 1489 if (ret < 0) {
1427 int i;
1428 ubi_err(ubi, "could not erase old anchor PEB"); 1490 ubi_err(ubi, "could not erase old anchor PEB");
1429 1491
1430 for (i = 1; i < new_fm->used_blocks; i++) 1492 for (i = 1; i < new_fm->used_blocks; i++) {
1431 ubi_wl_put_fm_peb(ubi, new_fm->e[i], 1493 ubi_wl_put_fm_peb(ubi, new_fm->e[i],
1432 i, 0); 1494 i, 0);
1495 new_fm->e[i] = NULL;
1496 }
1433 goto err; 1497 goto err;
1434 } 1498 }
1435 new_fm->e[0] = old_fm->e[0]; 1499 new_fm->e[0] = old_fm->e[0];
1436 new_fm->e[0]->ec = ret; 1500 new_fm->e[0]->ec = ret;
1501 old_fm->e[0] = NULL;
1437 } else { 1502 } else {
1438 /* we've got a new anchor PEB, return the old one */ 1503 /* we've got a new anchor PEB, return the old one */
1439 ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0, 1504 ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0,
1440 old_fm->to_be_tortured[0]); 1505 old_fm->to_be_tortured[0]);
1441 new_fm->e[0] = tmp_e; 1506 new_fm->e[0] = tmp_e;
1507 old_fm->e[0] = NULL;
1442 } 1508 }
1443 } else { 1509 } else {
1444 if (!tmp_e) { 1510 if (!tmp_e) {
1445 int i;
1446 ubi_err(ubi, "could not find any anchor PEB"); 1511 ubi_err(ubi, "could not find any anchor PEB");
1447 1512
1448 for (i = 1; i < new_fm->used_blocks; i++) 1513 for (i = 1; i < new_fm->used_blocks; i++) {
1449 ubi_wl_put_fm_peb(ubi, new_fm->e[i], i, 0); 1514 ubi_wl_put_fm_peb(ubi, new_fm->e[i], i, 0);
1515 new_fm->e[i] = NULL;
1516 }
1450 1517
1451 ret = -ENOSPC; 1518 ret = -ENOSPC;
1452 goto err; 1519 goto err;
@@ -1469,19 +1536,18 @@ out_unlock:
1469 return ret; 1536 return ret;
1470 1537
1471err: 1538err:
1472 kfree(new_fm);
1473
1474 ubi_warn(ubi, "Unable to write new fastmap, err=%i", ret); 1539 ubi_warn(ubi, "Unable to write new fastmap, err=%i", ret);
1475 1540
1476 ret = 0; 1541 ret = invalidate_fastmap(ubi);
1477 if (old_fm) { 1542 if (ret < 0) {
1478 ret = invalidate_fastmap(ubi, old_fm); 1543 ubi_err(ubi, "Unable to invalidiate current fastmap!");
1479 if (ret < 0) { 1544 ubi_ro_mode(ubi);
1480 ubi_err(ubi, "Unable to invalidiate current fastmap!"); 1545 } else {
1481 ubi_ro_mode(ubi); 1546 return_fm_pebs(ubi, old_fm);
1482 } 1547 return_fm_pebs(ubi, new_fm);
1483 else if (ret) 1548 ret = 0;
1484 ret = 0;
1485 } 1549 }
1550
1551 kfree(new_fm);
1486 goto out_unlock; 1552 goto out_unlock;
1487} 1553}