2105e502c5
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.
105 lines
3.6 KiB
C
105 lines
3.6 KiB
C
# simple shrink
|
|
[cases.test_shrink_simple]
|
|
defines.BLOCK_COUNT = [10, 15, 20]
|
|
defines.AFTER_BLOCK_COUNT = [5, 10, 15, 19]
|
|
if = "AFTER_BLOCK_COUNT <= BLOCK_COUNT"
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_format(&lfs, cfg) => 0;
|
|
lfs_mount(&lfs, cfg) => 0;
|
|
lfs_fs_shrink(&lfs, AFTER_BLOCK_COUNT) => 0;
|
|
lfs_unmount(&lfs);
|
|
if (BLOCK_COUNT != AFTER_BLOCK_COUNT) {
|
|
lfs_mount(&lfs, cfg) => LFS_ERR_INVAL;
|
|
}
|
|
lfs_t lfs2 = lfs;
|
|
struct lfs_config cfg2 = *cfg;
|
|
cfg2.block_count = AFTER_BLOCK_COUNT;
|
|
lfs2.cfg = &cfg2;
|
|
lfs_mount(&lfs2, &cfg2) => 0;
|
|
lfs_unmount(&lfs2) => 0;
|
|
'''
|
|
|
|
# shrinking full
|
|
[cases.test_shrink_full]
|
|
defines.BLOCK_COUNT = [10, 15, 20]
|
|
defines.AFTER_BLOCK_COUNT = [5, 7, 10, 12, 15, 17, 20]
|
|
defines.FILES_COUNT = [7, 8, 9, 10]
|
|
if = "AFTER_BLOCK_COUNT <= BLOCK_COUNT && FILES_COUNT + 2 < BLOCK_COUNT"
|
|
code = '''
|
|
lfs_t lfs;
|
|
lfs_format(&lfs, cfg) => 0;
|
|
// create FILES_COUNT files of BLOCK_SIZE - 50 bytes (to avoid inlining)
|
|
lfs_mount(&lfs, cfg) => 0;
|
|
for (int i = 0; i < FILES_COUNT + 1; i++) {
|
|
lfs_file_t file;
|
|
char path[1024];
|
|
sprintf(path, "file_%03d", i);
|
|
lfs_file_open(&lfs, &file, path,
|
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
|
char wbuffer[BLOCK_SIZE];
|
|
memset(wbuffer, 'b', BLOCK_SIZE);
|
|
// Ensure one block is taken per file, but that files are not inlined.
|
|
lfs_size_t size = BLOCK_SIZE - 0x40;
|
|
sprintf(wbuffer, "Hi %03d", i);
|
|
lfs_file_write(&lfs, &file, wbuffer, size) => size;
|
|
lfs_file_close(&lfs, &file) => 0;
|
|
}
|
|
|
|
int err = lfs_fs_shrink(&lfs, AFTER_BLOCK_COUNT);
|
|
if (err == 0) {
|
|
for (int i = 0; i < FILES_COUNT + 1; i++) {
|
|
lfs_file_t file;
|
|
char path[1024];
|
|
sprintf(path, "file_%03d", i);
|
|
lfs_file_open(&lfs, &file, path,
|
|
LFS_O_RDONLY ) => 0;
|
|
lfs_size_t size = BLOCK_SIZE - 0x40;
|
|
char wbuffer[size];
|
|
char wbuffer_ref[size];
|
|
// Ensure one block is taken per file, but that files are not inlined.
|
|
memset(wbuffer_ref, 'b', size);
|
|
sprintf(wbuffer_ref, "Hi %03d", i);
|
|
lfs_file_read(&lfs, &file, wbuffer, BLOCK_SIZE) => size;
|
|
lfs_file_close(&lfs, &file) => 0;
|
|
for (lfs_size_t j = 0; j < size; j++) {
|
|
wbuffer[j] => wbuffer_ref[j];
|
|
}
|
|
}
|
|
} else {
|
|
assert(err == LFS_ERR_NOTEMPTY);
|
|
}
|
|
|
|
lfs_unmount(&lfs) => 0;
|
|
if (err == 0 ) {
|
|
if ( AFTER_BLOCK_COUNT != BLOCK_COUNT ) {
|
|
lfs_mount(&lfs, cfg) => LFS_ERR_INVAL;
|
|
}
|
|
|
|
lfs_t lfs2 = lfs;
|
|
struct lfs_config cfg2 = *cfg;
|
|
cfg2.block_count = AFTER_BLOCK_COUNT;
|
|
lfs2.cfg = &cfg2;
|
|
lfs_mount(&lfs2, &cfg2) => 0;
|
|
for (int i = 0; i < FILES_COUNT + 1; i++) {
|
|
lfs_file_t file;
|
|
char path[1024];
|
|
sprintf(path, "file_%03d", i);
|
|
lfs_file_open(&lfs2, &file, path,
|
|
LFS_O_RDONLY ) => 0;
|
|
lfs_size_t size = BLOCK_SIZE - 0x40;
|
|
char wbuffer[size];
|
|
char wbuffer_ref[size];
|
|
// Ensure one block is taken per file, but that files are not inlined.
|
|
memset(wbuffer_ref, 'b', size);
|
|
sprintf(wbuffer_ref, "Hi %03d", i);
|
|
lfs_file_read(&lfs2, &file, wbuffer, BLOCK_SIZE) => size;
|
|
lfs_file_close(&lfs2, &file) => 0;
|
|
for (lfs_size_t j = 0; j < size; j++) {
|
|
wbuffer[j] => wbuffer_ref[j];
|
|
}
|
|
}
|
|
lfs_unmount(&lfs2);
|
|
}
|
|
'''
|