|
@@ -596,11 +596,11 @@ static int lfs_rawunmount(lfs_t *lfs);
|
|
|
#ifndef LFS_READONLY
|
|
#ifndef LFS_READONLY
|
|
|
static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
|
|
static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
|
|
|
lfs_t *lfs = (lfs_t*)p;
|
|
lfs_t *lfs = (lfs_t*)p;
|
|
|
- lfs_block_t off = ((block - lfs->free.off)
|
|
|
|
|
|
|
+ lfs_block_t off = ((block - lfs->lookahead.start)
|
|
|
+ lfs->block_count) % lfs->block_count;
|
|
+ lfs->block_count) % lfs->block_count;
|
|
|
|
|
|
|
|
- if (off < lfs->free.size) {
|
|
|
|
|
- lfs->free.buffer[off / 32] |= 1U << (off % 32);
|
|
|
|
|
|
|
+ if (off < lfs->lookahead.size) {
|
|
|
|
|
+ lfs->lookahead.buffer[off / 32] |= 1U << (off % 32);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -610,28 +610,31 @@ static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
|
|
|
// indicate allocated blocks have been committed into the filesystem, this
|
|
// indicate allocated blocks have been committed into the filesystem, this
|
|
|
// is to prevent blocks from being garbage collected in the middle of a
|
|
// is to prevent blocks from being garbage collected in the middle of a
|
|
|
// commit operation
|
|
// commit operation
|
|
|
-static void lfs_alloc_ack(lfs_t *lfs) {
|
|
|
|
|
- lfs->free.ack = lfs->block_count;
|
|
|
|
|
|
|
+static void lfs_alloc_ckpoint(lfs_t *lfs) {
|
|
|
|
|
+ lfs->lookahead.ckpoint = lfs->block_count;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// drop the lookahead buffer, this is done during mounting and failed
|
|
// drop the lookahead buffer, this is done during mounting and failed
|
|
|
// traversals in order to avoid invalid lookahead state
|
|
// traversals in order to avoid invalid lookahead state
|
|
|
static void lfs_alloc_drop(lfs_t *lfs) {
|
|
static void lfs_alloc_drop(lfs_t *lfs) {
|
|
|
- lfs->free.size = 0;
|
|
|
|
|
- lfs->free.i = 0;
|
|
|
|
|
- lfs_alloc_ack(lfs);
|
|
|
|
|
|
|
+ lfs->lookahead.size = 0;
|
|
|
|
|
+ lfs->lookahead.next = 0;
|
|
|
|
|
+ lfs_alloc_ckpoint(lfs);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#ifndef LFS_READONLY
|
|
#ifndef LFS_READONLY
|
|
|
static int lfs_fs_rawgc(lfs_t *lfs) {
|
|
static int lfs_fs_rawgc(lfs_t *lfs) {
|
|
|
- // Move free offset at the first unused block (lfs->free.i)
|
|
|
|
|
- // lfs->free.i is equal lfs->free.size when all blocks are used
|
|
|
|
|
- lfs->free.off = (lfs->free.off + lfs->free.i) % lfs->block_count;
|
|
|
|
|
- lfs->free.size = lfs_min(8*lfs->cfg->lookahead_size, lfs->free.ack);
|
|
|
|
|
- lfs->free.i = 0;
|
|
|
|
|
|
|
+ // Move free offset at the first unused block (lfs->lookahead.next)
|
|
|
|
|
+ // lfs->lookahead.next is equal lfs->lookahead.size when all blocks are used
|
|
|
|
|
+ lfs->lookahead.start = (lfs->lookahead.start + lfs->lookahead.next)
|
|
|
|
|
+ % lfs->block_count;
|
|
|
|
|
+ lfs->lookahead.size = lfs_min(
|
|
|
|
|
+ 8*lfs->cfg->lookahead_size,
|
|
|
|
|
+ lfs->lookahead.ckpoint);
|
|
|
|
|
+ lfs->lookahead.next = 0;
|
|
|
|
|
|
|
|
// find mask of free blocks from tree
|
|
// find mask of free blocks from tree
|
|
|
- memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size);
|
|
|
|
|
|
|
+ memset(lfs->lookahead.buffer, 0, lfs->cfg->lookahead_size);
|
|
|
int err = lfs_fs_rawtraverse(lfs, lfs_alloc_lookahead, lfs, true);
|
|
int err = lfs_fs_rawtraverse(lfs, lfs_alloc_lookahead, lfs, true);
|
|
|
if (err) {
|
|
if (err) {
|
|
|
lfs_alloc_drop(lfs);
|
|
lfs_alloc_drop(lfs);
|
|
@@ -645,22 +648,22 @@ static int lfs_fs_rawgc(lfs_t *lfs) {
|
|
|
#ifndef LFS_READONLY
|
|
#ifndef LFS_READONLY
|
|
|
static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
|
|
static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
|
|
|
while (true) {
|
|
while (true) {
|
|
|
- while (lfs->free.i != lfs->free.size) {
|
|
|
|
|
- lfs_block_t off = lfs->free.i;
|
|
|
|
|
- lfs->free.i += 1;
|
|
|
|
|
- lfs->free.ack -= 1;
|
|
|
|
|
|
|
+ while (lfs->lookahead.next != lfs->lookahead.size) {
|
|
|
|
|
+ lfs_block_t off = lfs->lookahead.next;
|
|
|
|
|
+ lfs->lookahead.next += 1;
|
|
|
|
|
+ lfs->lookahead.ckpoint -= 1;
|
|
|
|
|
|
|
|
- if (!(lfs->free.buffer[off / 32] & (1U << (off % 32)))) {
|
|
|
|
|
|
|
+ if (!(lfs->lookahead.buffer[off / 32] & (1U << (off % 32)))) {
|
|
|
// found a free block
|
|
// found a free block
|
|
|
- *block = (lfs->free.off + off) % lfs->block_count;
|
|
|
|
|
|
|
+ *block = (lfs->lookahead.start + off) % lfs->block_count;
|
|
|
|
|
|
|
|
// eagerly find next off so an alloc ack can
|
|
// eagerly find next off so an alloc ack can
|
|
|
// discredit old lookahead blocks
|
|
// discredit old lookahead blocks
|
|
|
- while (lfs->free.i != lfs->free.size &&
|
|
|
|
|
- (lfs->free.buffer[lfs->free.i / 32]
|
|
|
|
|
- & (1U << (lfs->free.i % 32)))) {
|
|
|
|
|
- lfs->free.i += 1;
|
|
|
|
|
- lfs->free.ack -= 1;
|
|
|
|
|
|
|
+ while (lfs->lookahead.next != lfs->lookahead.size &&
|
|
|
|
|
+ (lfs->lookahead.buffer[lfs->lookahead.next / 32]
|
|
|
|
|
+ & (1U << (lfs->lookahead.next % 32)))) {
|
|
|
|
|
+ lfs->lookahead.next += 1;
|
|
|
|
|
+ lfs->lookahead.ckpoint -= 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -668,9 +671,9 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// check if we have looked at all blocks since last ack
|
|
// check if we have looked at all blocks since last ack
|
|
|
- if (lfs->free.ack == 0) {
|
|
|
|
|
|
|
+ if (lfs->lookahead.ckpoint == 0) {
|
|
|
LFS_ERROR("No more free space %"PRIu32,
|
|
LFS_ERROR("No more free space %"PRIu32,
|
|
|
- lfs->free.i + lfs->free.off);
|
|
|
|
|
|
|
+ lfs->lookahead.next + lfs->lookahead.start);
|
|
|
return LFS_ERR_NOSPC;
|
|
return LFS_ERR_NOSPC;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -2586,7 +2589,7 @@ static int lfs_rawmkdir(lfs_t *lfs, const char *path) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// build up new directory
|
|
// build up new directory
|
|
|
- lfs_alloc_ack(lfs);
|
|
|
|
|
|
|
+ lfs_alloc_ckpoint(lfs);
|
|
|
lfs_mdir_t dir;
|
|
lfs_mdir_t dir;
|
|
|
err = lfs_dir_alloc(lfs, &dir);
|
|
err = lfs_dir_alloc(lfs, &dir);
|
|
|
if (err) {
|
|
if (err) {
|
|
@@ -3272,7 +3275,7 @@ relocate:
|
|
|
#ifndef LFS_READONLY
|
|
#ifndef LFS_READONLY
|
|
|
static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
|
|
static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
|
|
|
file->off = file->pos;
|
|
file->off = file->pos;
|
|
|
- lfs_alloc_ack(lfs);
|
|
|
|
|
|
|
+ lfs_alloc_ckpoint(lfs);
|
|
|
int err = lfs_file_relocate(lfs, file);
|
|
int err = lfs_file_relocate(lfs, file);
|
|
|
if (err) {
|
|
if (err) {
|
|
|
return err;
|
|
return err;
|
|
@@ -3535,7 +3538,7 @@ static lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// extend file with new blocks
|
|
// extend file with new blocks
|
|
|
- lfs_alloc_ack(lfs);
|
|
|
|
|
|
|
+ lfs_alloc_ckpoint(lfs);
|
|
|
int err = lfs_ctz_extend(lfs, &file->cache, &lfs->rcache,
|
|
int err = lfs_ctz_extend(lfs, &file->cache, &lfs->rcache,
|
|
|
file->block, file->pos,
|
|
file->block, file->pos,
|
|
|
&file->block, &file->off);
|
|
&file->block, &file->off);
|
|
@@ -3578,7 +3581,7 @@ relocate:
|
|
|
data += diff;
|
|
data += diff;
|
|
|
nsize -= diff;
|
|
nsize -= diff;
|
|
|
|
|
|
|
|
- lfs_alloc_ack(lfs);
|
|
|
|
|
|
|
+ lfs_alloc_ckpoint(lfs);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
return size;
|
|
@@ -4185,10 +4188,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
|
|
LFS_ASSERT(lfs->cfg->lookahead_size % 8 == 0 &&
|
|
LFS_ASSERT(lfs->cfg->lookahead_size % 8 == 0 &&
|
|
|
(uintptr_t)lfs->cfg->lookahead_buffer % 4 == 0);
|
|
(uintptr_t)lfs->cfg->lookahead_buffer % 4 == 0);
|
|
|
if (lfs->cfg->lookahead_buffer) {
|
|
if (lfs->cfg->lookahead_buffer) {
|
|
|
- lfs->free.buffer = lfs->cfg->lookahead_buffer;
|
|
|
|
|
|
|
+ lfs->lookahead.buffer = lfs->cfg->lookahead_buffer;
|
|
|
} else {
|
|
} else {
|
|
|
- lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead_size);
|
|
|
|
|
- if (!lfs->free.buffer) {
|
|
|
|
|
|
|
+ lfs->lookahead.buffer = lfs_malloc(lfs->cfg->lookahead_size);
|
|
|
|
|
+ if (!lfs->lookahead.buffer) {
|
|
|
err = LFS_ERR_NOMEM;
|
|
err = LFS_ERR_NOMEM;
|
|
|
goto cleanup;
|
|
goto cleanup;
|
|
|
}
|
|
}
|
|
@@ -4245,7 +4248,7 @@ static int lfs_deinit(lfs_t *lfs) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!lfs->cfg->lookahead_buffer) {
|
|
if (!lfs->cfg->lookahead_buffer) {
|
|
|
- lfs_free(lfs->free.buffer);
|
|
|
|
|
|
|
+ lfs_free(lfs->lookahead.buffer);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -4265,12 +4268,12 @@ static int lfs_rawformat(lfs_t *lfs, const struct lfs_config *cfg) {
|
|
|
LFS_ASSERT(cfg->block_count != 0);
|
|
LFS_ASSERT(cfg->block_count != 0);
|
|
|
|
|
|
|
|
// create free lookahead
|
|
// create free lookahead
|
|
|
- memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size);
|
|
|
|
|
- lfs->free.off = 0;
|
|
|
|
|
- lfs->free.size = lfs_min(8*lfs->cfg->lookahead_size,
|
|
|
|
|
|
|
+ memset(lfs->lookahead.buffer, 0, lfs->cfg->lookahead_size);
|
|
|
|
|
+ lfs->lookahead.start = 0;
|
|
|
|
|
+ lfs->lookahead.size = lfs_min(8*lfs->cfg->lookahead_size,
|
|
|
lfs->block_count);
|
|
lfs->block_count);
|
|
|
- lfs->free.i = 0;
|
|
|
|
|
- lfs_alloc_ack(lfs);
|
|
|
|
|
|
|
+ lfs->lookahead.next = 0;
|
|
|
|
|
+ lfs_alloc_ckpoint(lfs);
|
|
|
|
|
|
|
|
// create root dir
|
|
// create root dir
|
|
|
lfs_mdir_t root;
|
|
lfs_mdir_t root;
|
|
@@ -4478,7 +4481,7 @@ static int lfs_rawmount(lfs_t *lfs, const struct lfs_config *cfg) {
|
|
|
|
|
|
|
|
// setup free lookahead, to distribute allocations uniformly across
|
|
// setup free lookahead, to distribute allocations uniformly across
|
|
|
// boots, we start the allocator at a random location
|
|
// boots, we start the allocator at a random location
|
|
|
- lfs->free.off = lfs->seed % lfs->block_count;
|
|
|
|
|
|
|
+ lfs->lookahead.start = lfs->seed % lfs->block_count;
|
|
|
lfs_alloc_drop(lfs);
|
|
lfs_alloc_drop(lfs);
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -5451,10 +5454,10 @@ static int lfs1_mount(lfs_t *lfs, struct lfs1 *lfs1,
|
|
|
lfs->lfs1->root[1] = LFS_BLOCK_NULL;
|
|
lfs->lfs1->root[1] = LFS_BLOCK_NULL;
|
|
|
|
|
|
|
|
// setup free lookahead
|
|
// setup free lookahead
|
|
|
- lfs->free.off = 0;
|
|
|
|
|
- lfs->free.size = 0;
|
|
|
|
|
- lfs->free.i = 0;
|
|
|
|
|
- lfs_alloc_ack(lfs);
|
|
|
|
|
|
|
+ lfs->lookahead.start = 0;
|
|
|
|
|
+ lfs->lookahead.size = 0;
|
|
|
|
|
+ lfs->lookahead.next = 0;
|
|
|
|
|
+ lfs_alloc_ckpoint(lfs);
|
|
|
|
|
|
|
|
// load superblock
|
|
// load superblock
|
|
|
lfs1_dir_t dir;
|
|
lfs1_dir_t dir;
|