mirror of
https://github.com/littlefs-project/littlefs.git
synced 2025-10-14 02:43:30 +08:00
fixup! Add support for shrinking a filesystem
This commit is contained in:
84
lfs.c
84
lfs.c
@@ -5233,12 +5233,41 @@ static int lfs_fs_gc_(lfs_t *lfs) {
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_fs_rewrite_block_count(lfs_t *lfs, lfs_size_t block_count) {
|
||||
#ifdef LFS_SHRINKIFCHEAP
|
||||
static int lfs_shrink_checkblock(void * data, lfs_block_t block) {
|
||||
lfs_size_t threshold = *((lfs_size_t *) data);
|
||||
if (block >= threshold) {
|
||||
return LFS_ERR_NOTEMPTY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lfs_fs_grow_(lfs_t *lfs, lfs_size_t block_count) {
|
||||
int err;
|
||||
|
||||
if (block_count == lfs->block_count) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef LFS_SHRINKIFCHEAP
|
||||
// shrinking is not supported
|
||||
LFS_ASSERT(block_count >= lfs->block_count);
|
||||
#endif
|
||||
#ifdef LFS_SHRINKIFCHEAP
|
||||
lfs_block_t threshold = block_count;
|
||||
err = lfs_fs_traverse_(lfs, lfs_shrink_checkblock, &threshold, true);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
lfs->block_count = block_count;
|
||||
|
||||
// fetch the root
|
||||
lfs_mdir_t root;
|
||||
int err = lfs_dir_fetch(lfs, &root, lfs->root);
|
||||
err = lfs_dir_fetch(lfs, &root, lfs->root);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -5263,41 +5292,6 @@ static int lfs_fs_rewrite_block_count(lfs_t *lfs, lfs_size_t block_count) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lfs_fs_grow_(lfs_t *lfs, lfs_size_t block_count) {
|
||||
// shrinking is not supported
|
||||
LFS_ASSERT(block_count >= lfs->block_count);
|
||||
|
||||
if (block_count > lfs->block_count) {
|
||||
return lfs_fs_rewrite_block_count(lfs, block_count);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lfs_shrink_check_block(void * data, lfs_block_t block) {
|
||||
lfs_size_t threshold = *((lfs_size_t *) data);
|
||||
if (block >= threshold) {
|
||||
return LFS_ERR_NOTEMPTY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lfs_fs_shrink_(lfs_t *lfs, lfs_size_t block_count) {
|
||||
if (block_count != lfs->block_count) {
|
||||
|
||||
lfs_block_t threshold = block_count;
|
||||
|
||||
int err = lfs_fs_traverse_(lfs, lfs_shrink_check_block, &threshold, true);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return lfs_fs_rewrite_block_count(lfs, block_count);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LFS_MIGRATE
|
||||
@@ -6514,22 +6508,6 @@ int lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
int lfs_fs_shrink(lfs_t *lfs, lfs_size_t block_count) {
|
||||
int err = LFS_LOCK(lfs->cfg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
LFS_TRACE("lfs_fs_shrink(%p, %"PRIu32")", (void*)lfs, block_count);
|
||||
|
||||
err = lfs_fs_shrink_(lfs, block_count);
|
||||
|
||||
LFS_TRACE("lfs_fs_shrink -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LFS_MIGRATE
|
||||
int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
int err = LFS_LOCK(cfg);
|
||||
|
15
lfs.h
15
lfs.h
@@ -766,23 +766,16 @@ int lfs_fs_gc(lfs_t *lfs);
|
||||
// Grows the filesystem to a new size, updating the superblock with the new
|
||||
// block count.
|
||||
//
|
||||
// if LFS_SHRINKIFCHEAP is defined, this function will also accept
|
||||
// block_counts smaller than the current configuration, after checking
|
||||
// that none of the blocks that are being removed are in use.
|
||||
//
|
||||
// Note: This is irreversible.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count);
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Shrinks the filesystem to a new size, updating the superblock with the new
|
||||
// block count.
|
||||
//
|
||||
// Note: This first checks that none of the blocks that are being removed are in use
|
||||
// and will fail if it is the case
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_fs_shrink(lfs_t *lfs, lfs_size_t block_count);
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
#ifdef LFS_MIGRATE
|
||||
// Attempts to migrate a previous version of littlefs
|
||||
|
@@ -7,7 +7,7 @@ code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_shrink(&lfs, AFTER_BLOCK_COUNT) => 0;
|
||||
lfs_fs_grow(&lfs, AFTER_BLOCK_COUNT) => 0;
|
||||
lfs_unmount(&lfs);
|
||||
if (BLOCK_COUNT != AFTER_BLOCK_COUNT) {
|
||||
lfs_mount(&lfs, cfg) => LFS_ERR_INVAL;
|
||||
@@ -46,7 +46,7 @@ code = '''
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
|
||||
int err = lfs_fs_shrink(&lfs, AFTER_BLOCK_COUNT);
|
||||
int err = lfs_fs_grow(&lfs, AFTER_BLOCK_COUNT);
|
||||
if (err == 0) {
|
||||
for (int i = 0; i < FILES_COUNT + 1; i++) {
|
||||
lfs_file_t file;
|
||||
|
@@ -550,7 +550,7 @@ code = '''
|
||||
|
||||
// same size is a noop
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_shrink(&lfs, BLOCK_COUNT) => 0;
|
||||
lfs_fs_grow(&lfs, BLOCK_COUNT) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT);
|
||||
@@ -564,7 +564,7 @@ code = '''
|
||||
|
||||
// grow to new size
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_shrink(&lfs, BLOCK_COUNT_2) => 0;
|
||||
lfs_fs_grow(&lfs, BLOCK_COUNT_2) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT_2);
|
||||
@@ -594,7 +594,7 @@ code = '''
|
||||
|
||||
// same size is a noop
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_shrink(&lfs, BLOCK_COUNT_2) => 0;
|
||||
lfs_fs_grow(&lfs, BLOCK_COUNT_2) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT_2);
|
||||
|
Reference in New Issue
Block a user