Skip to content

Commit 4d18b5a

Browse files
Zhihao Chengrichardweinberger
authored andcommitted
ubi: fastmap: Fix missed ec updating after erasing old fastmap data block
After running fsstress on ubifs for a long time, UBI(16384 blocks, fastmap takes 2 blocks) has an erase block with different erase counters displayed from two views: From ubiscan view: PEB 8031 has erase counter 31581 ========================================================= from to count min avg max --------------------------------------------------------- 0 .. 9: 0 0 0 0 10 .. 99: 0 0 0 0 100 .. 999: 16383 290 315 781 1000 .. 9999: 0 0 0 0 10000 .. 99999: 1 31581 31581 31581 100000 .. inf: 0 0 0 0 --------------------------------------------------------- Total : 16384 290 317 31581 From detailed_erase_block_info view: PEB 8031 has erase counter 7 physical_block_number erase_count 8030 421 8031 7 # mem info is different from disk info 8032 434 8033 425 8034 431 Following process missed updating erase counter in wl_entry(in memory): ubi_update_fastmap for (i = 1; i < new_fm->used_blocks; i++) // update fastmap data if (!tmp_e) if (old_fm && old_fm->e[i]) erase_block(ubi, old_fm->e[i]->pnum) ret = ubi_io_sync_erase(ubi, pnum, 0) ec = be64_to_cpu(ec_hdr->ec) ec += ret ec_hdr->ec = cpu_to_be64(ec) ubi_io_write_ec_hdr(ubi, pnum, ec_hdr) // ec is updated on flash // ec is not updated in old_fm->e[i] (in memory) Fix it by passing wl_enter into erase_block() and updating erase counter in erase_block(). Fixes: dbb7d2a ("UBI: Add fastmap core") Signed-off-by: Zhihao Cheng <[email protected]> Signed-off-by: Richard Weinberger <[email protected]>
1 parent 60f2f4a commit 4d18b5a

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

drivers/mtd/ubi/fastmap.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,11 +1392,12 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
13921392
/**
13931393
* erase_block - Manually erase a PEB.
13941394
* @ubi: UBI device object
1395-
* @pnum: PEB to be erased
1395+
* @e: the physical eraseblock to erase
13961396
*
1397-
* Returns the new EC value on success, < 0 indicates an internal error.
1397+
* This function returns zero in case of success and a negative error code in
1398+
* case of failure.
13981399
*/
1399-
static int erase_block(struct ubi_device *ubi, int pnum)
1400+
static int erase_block(struct ubi_device *ubi, struct ubi_wl_entry *e)
14001401
{
14011402
int ret;
14021403
struct ubi_ec_hdr *ec_hdr;
@@ -1406,15 +1407,15 @@ static int erase_block(struct ubi_device *ubi, int pnum)
14061407
if (!ec_hdr)
14071408
return -ENOMEM;
14081409

1409-
ret = ubi_io_read_ec_hdr(ubi, pnum, ec_hdr, 0);
1410+
ret = ubi_io_read_ec_hdr(ubi, e->pnum, ec_hdr, 0);
14101411
if (ret < 0)
14111412
goto out;
14121413
else if (ret && ret != UBI_IO_BITFLIPS) {
14131414
ret = -EINVAL;
14141415
goto out;
14151416
}
14161417

1417-
ret = ubi_io_sync_erase(ubi, pnum, 0);
1418+
ret = ubi_io_sync_erase(ubi, e->pnum, 0);
14181419
if (ret < 0)
14191420
goto out;
14201421

@@ -1426,11 +1427,16 @@ static int erase_block(struct ubi_device *ubi, int pnum)
14261427
}
14271428

14281429
ec_hdr->ec = cpu_to_be64(ec);
1429-
ret = ubi_io_write_ec_hdr(ubi, pnum, ec_hdr);
1430+
ret = ubi_io_write_ec_hdr(ubi, e->pnum, ec_hdr);
14301431
if (ret < 0)
14311432
goto out;
14321433

1433-
ret = ec;
1434+
e->ec = ec;
1435+
spin_lock(&ubi->wl_lock);
1436+
if (e->ec > ubi->max_ec)
1437+
ubi->max_ec = e->ec;
1438+
spin_unlock(&ubi->wl_lock);
1439+
14341440
out:
14351441
kfree(ec_hdr);
14361442
return ret;
@@ -1576,7 +1582,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
15761582

15771583
if (!tmp_e) {
15781584
if (old_fm && old_fm->e[i]) {
1579-
ret = erase_block(ubi, old_fm->e[i]->pnum);
1585+
ret = erase_block(ubi, old_fm->e[i]);
15801586
if (ret < 0) {
15811587
ubi_err(ubi, "could not erase old fastmap PEB");
15821588

@@ -1628,7 +1634,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
16281634
if (old_fm) {
16291635
/* no fresh anchor PEB was found, reuse the old one */
16301636
if (!tmp_e) {
1631-
ret = erase_block(ubi, old_fm->e[0]->pnum);
1637+
ret = erase_block(ubi, old_fm->e[0]);
16321638
if (ret < 0) {
16331639
ubi_err(ubi, "could not erase old anchor PEB");
16341640

@@ -1640,7 +1646,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
16401646
goto err;
16411647
}
16421648
new_fm->e[0] = old_fm->e[0];
1643-
new_fm->e[0]->ec = ret;
16441649
old_fm->e[0] = NULL;
16451650
} else {
16461651
/* we've got a new anchor PEB, return the old one */

0 commit comments

Comments
 (0)