Add support for shrinking a filesystem
This PR adds a new `lfs_fs_shrink`, which functions similarly to `lfs_fs_grow`, but supports reducing the block count. This functions first checks that none of the removed block are in use. If it is the case, it will fail.
This commit is contained in:
@@ -524,6 +524,112 @@ code = '''
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
|
||||
# mount and grow the filesystem
|
||||
[cases.test_superblocks_shrink]
|
||||
defines.BLOCK_COUNT = 'ERASE_COUNT'
|
||||
defines.BLOCK_COUNT_2 = ['ERASE_COUNT/2', 'ERASE_COUNT/4', '2']
|
||||
defines.KNOWN_BLOCK_COUNT = [true, false]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
|
||||
if (KNOWN_BLOCK_COUNT) {
|
||||
cfg->block_count = BLOCK_COUNT;
|
||||
} else {
|
||||
cfg->block_count = 0;
|
||||
}
|
||||
|
||||
// mount with block_size < erase_size
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_fsinfo fsinfo;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT);
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
// same size is a noop
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_shrink(&lfs, BLOCK_COUNT) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT);
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT);
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
// grow to new size
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_shrink(&lfs, BLOCK_COUNT_2) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT_2);
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
if (KNOWN_BLOCK_COUNT) {
|
||||
cfg->block_count = BLOCK_COUNT_2;
|
||||
} else {
|
||||
cfg->block_count = 0;
|
||||
}
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT_2);
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
// mounting with the previous size should fail
|
||||
cfg->block_count = BLOCK_COUNT;
|
||||
lfs_mount(&lfs, cfg) => LFS_ERR_INVAL;
|
||||
|
||||
if (KNOWN_BLOCK_COUNT) {
|
||||
cfg->block_count = BLOCK_COUNT_2;
|
||||
} else {
|
||||
cfg->block_count = 0;
|
||||
}
|
||||
|
||||
// same size is a noop
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_shrink(&lfs, BLOCK_COUNT_2) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT_2);
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT_2);
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
// do some work
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT_2);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, "test",
|
||||
LFS_O_CREAT | LFS_O_EXCL | LFS_O_WRONLY) => 0;
|
||||
lfs_file_write(&lfs, &file, "hello!", 6) => 6;
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_fs_stat(&lfs, &fsinfo) => 0;
|
||||
assert(fsinfo.block_size == BLOCK_SIZE);
|
||||
assert(fsinfo.block_count == BLOCK_COUNT_2);
|
||||
lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0;
|
||||
uint8_t buffer[256];
|
||||
lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => 6;
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
assert(memcmp(buffer, "hello!", 6) == 0);
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
# test that metadata_max does not cause problems for superblock compaction
|
||||
[cases.test_superblocks_metadata_max]
|
||||
defines.METADATA_MAX = [
|
||||
|
||||
Reference in New Issue
Block a user