Merge pull request #1094 from sosthene-nitrokey/shrink-fs

Add support for shrinking a filesystem
This commit is contained in:
Christopher Haster
2025-05-13 00:45:32 -05:00
committed by GitHub
5 changed files with 288 additions and 27 deletions
+50 -26
View File
@@ -5237,40 +5237,64 @@ static int lfs_fs_gc_(lfs_t *lfs) {
#endif
#ifndef LFS_READONLY
#ifdef LFS_SHRINKNONRELOCATING
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_SHRINKNONRELOCATING
// shrinking is not supported
LFS_ASSERT(block_count >= lfs->block_count);
if (block_count > lfs->block_count) {
lfs->block_count = block_count;
// fetch the root
lfs_mdir_t root;
int err = lfs_dir_fetch(lfs, &root, lfs->root);
if (err) {
return err;
}
// update the superblock
lfs_superblock_t superblock;
lfs_stag_t tag = lfs_dir_get(lfs, &root, LFS_MKTAG(0x7ff, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
&superblock);
if (tag < 0) {
return tag;
}
lfs_superblock_fromle32(&superblock);
superblock.block_count = lfs->block_count;
lfs_superblock_tole32(&superblock);
err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(
{tag, &superblock}));
#endif
#ifdef LFS_SHRINKNONRELOCATING
if (block_count < lfs->block_count) {
err = lfs_fs_traverse_(lfs, lfs_shrink_checkblock, &block_count, true);
if (err) {
return err;
}
}
#endif
lfs->block_count = block_count;
// fetch the root
lfs_mdir_t root;
err = lfs_dir_fetch(lfs, &root, lfs->root);
if (err) {
return err;
}
// update the superblock
lfs_superblock_t superblock;
lfs_stag_t tag = lfs_dir_get(lfs, &root, LFS_MKTAG(0x7ff, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
&superblock);
if (tag < 0) {
return tag;
}
lfs_superblock_fromle32(&superblock);
superblock.block_count = lfs->block_count;
lfs_superblock_tole32(&superblock);
err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(
{tag, &superblock}));
if (err) {
return err;
}
return 0;
}
#endif