Fixed corner case in block_cycles eviction logic
The problem was when we allocate a dir-pair, it's possible for the revision count to immediately overflow and the dir-pair be evicted and returned to the unused blocks without being written even once. In the case that block_cycles = 1, this made it impossible to ever create a dir-pair, even in lfs_format. I've also added a bit of logic to lfs_dir_alloc that will prevent any immediate evictions because of the revision count. found by TheLoneWolfling
This commit is contained in:
@@ -1316,15 +1316,14 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
|
|||||||
int err = lfs_bd_read(lfs,
|
int err = lfs_bd_read(lfs,
|
||||||
NULL, &lfs->rcache, sizeof(dir->rev),
|
NULL, &lfs->rcache, sizeof(dir->rev),
|
||||||
dir->pair[0], 0, &dir->rev, sizeof(dir->rev));
|
dir->pair[0], 0, &dir->rev, sizeof(dir->rev));
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
dir->rev = lfs_fromle32(dir->rev);
|
dir->rev = lfs_fromle32(dir->rev);
|
||||||
if (err && err != LFS_ERR_CORRUPT) {
|
if (err && err != LFS_ERR_CORRUPT) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure we don't immediately evict
|
||||||
|
dir->rev += dir->rev & 1;
|
||||||
|
|
||||||
// set defaults
|
// set defaults
|
||||||
dir->off = sizeof(dir->rev);
|
dir->off = sizeof(dir->rev);
|
||||||
dir->etag = 0xffffffff;
|
dir->etag = 0xffffffff;
|
||||||
@@ -1457,7 +1456,8 @@ static int lfs_dir_compact(lfs_t *lfs,
|
|||||||
|
|
||||||
// increment revision count
|
// increment revision count
|
||||||
dir->rev += 1;
|
dir->rev += 1;
|
||||||
if (lfs->cfg->block_cycles && dir->rev % lfs->cfg->block_cycles == 0) {
|
if (lfs->cfg->block_cycles &&
|
||||||
|
(dir->rev % (lfs->cfg->block_cycles+1) == 0)) {
|
||||||
if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) {
|
if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) {
|
||||||
// oh no! we're writing too much to the superblock,
|
// oh no! we're writing too much to the superblock,
|
||||||
// should we expand?
|
// should we expand?
|
||||||
|
|||||||
Reference in New Issue
Block a user