-
Notifications
You must be signed in to change notification settings - Fork 808
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
question: is it possible to "grow" the filesystem? #279
Comments
The issue #238 can help you |
Short answer is: lfs_fs_resize is a good idea. littlefs uses a garbage collection scheme, so if you increase the block device everything will work fine. But, as @ksstms pointed out in #238, there is a pesky block_size field in the superblock that becomes out of date. The field is also unused, so by pure coincidence, resizing the filesystem will work in the current version. But there will be problems if a future version of littlefs starts relying on this field. I think adding lfs_fs_resize is a good idea, similar to resize2fs or xfs_growfs as you mentioned. This would also make the filesystem forward compatible if we decide to remove the garbage collection (#75). |
Something like this, then? int lfs_fs_resize(lfs_t *lfs, lfs_size_t new_block_count) {
int err = 0;
// read existing superblock from disk
lfs_superblock_t superblock;
err = lfs_dir_get(lfs, &dir, LFS_MKTAG(0x7ff, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
&superblock);
if (err < 0) {
goto cleanup;
}
lfs_superblock_fromle32(&superblock);
// size can only be increased
if (new_block_count <= superblock.block_count) {
LFS_ERROR("Invalid new block count %d, not > %d", new_block_count,
superblock.block_count);
err = LFS_ERR_INVAL;
goto cleanup;
}
// update superblock block_count
superblock.block_count = new_block_count;
// write back the updated superblock to disk
lfs_superblock_tole32(&superblock);
err = lfs_dir_commit(lfs, lfs->root, LFS_MKATTRS(
{LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8), "littlefs"},
{LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
&superblock}));
if (err) {
goto cleanup;
}
// succeeded, use new block_count from hereon
lfs->cfg->block_count = new_block_count;
cleanup:
return err;
} and in On a related note, |
That looks good, would you be interested in creating a PR? Thoughts:
Also you're right mount should have more checks in place against block_size and block_count. |
I know this is pretty stale, but I'll add my two cents if this does get implemented...
I'd think lfs_fs_resize might be better. In the future maybe "shrink" would be supported, though it would be more complicated than "grow". Maybe return an "LFS_ERR_NOTSUPP" if trying to shrink...
As a user, I'd want the separate standalone operation. Maybe a flag during mount for "AUTORESIZE" or something similar... but being able to reason whether I want to attempt a resize vs reformat would be nice. My PR from #584 returns ERR_CORRUPT, but maybe ERR_INVAL or a new error code could return a size mismatch. |
My recommendation is that Summary:
I don't think an explicit |
There should be some indication of it growing. If there was data outside of the filesystem, the only way to have a chance to recover it would be between the That's why I'd suggested the AUTORESIZE option. If you don't care about data outside of the filesystem, run mount with that flag and let it grow on its own. If you do, run mount without that flag, then recover the data before formatting the whole filesystem. EDIT: There could also be an option to resize that gets passed into |
For tooling purposes, it'd also be practical to be able to generate a minimum size flash image in advance, and allow them to grow to whatever hardware they've been flashed on once they get mounted. The suggestion to add an AUTORESIZE mount flag seems to be the most convenient. |
Sorry about taking so long to get back to this. This is great discussions and with @kaetemi's PR (#702) I would like to see this get in to the next minor release. That being said, I'm against the autoresizing option for a couple reasons:
This is a good point, however instead of making Subject to change: // mount and resize if disk has grown
int err = lfs_mount(lfs, cfg);
if (err) {
return err;
}
err = lfs_fs_grow(lfs, cfg->block_count);
if (err) {
return err;
} Actually while writing this I realized you don't really need to check formatted blocks. We can make
There hasn't been a need for this API as littlefs has expected the block_size/block_count to be static and unchanging. But with this change we should probably add a way to query. Prior art suggests a form of fs-stat: struct lfs_fsstat fsstat;
int err = lfs_fs_stat(lfs, &fsstat);
if (err) {
return err;
}
printf("block_size: %d\n", fsstat.block_size);
printf("block_count: %d\n", fsstat.block_count);
printf("block_usage: %d\n", fsstat.block_usage); // same as lfs_fs_size
printf("name_max: %d\n", fsstat.name_max);
printf("file_max: %d\n", fsstat.file_max);
printf("attr_max: %d\n", fsstat.attr_max);
Shrinking a filesystem is much more difficult problem. A shrink operation would likely come as a separate fsck-like application with expensive runtime (think mutating almost every block in the filesystem) and risk of failure (the data may just not fit). And if we do see shrink as an additional behavior for |
I've gone ahead and added both |
If lfs is unmounted, and then the underlying block device size increases, is it possible to remount such that lfs can make use of the entire space? Like resize2fs or xfs_growfs, basically.
The text was updated successfully, but these errors were encountered: