Compare commits

...

16 Commits

Author SHA1 Message Date
Christopher Haster
265692e709 Removed fsinfo.block_usage for now
In terms of ease-of-use, a user familiar with other filesystems expects
block_usage in fsinfo. But in terms of practicality, block_usage can be
expensive to find in littlefs, so if it's not needed in the resulting
fsinfo, that operation is wasteful.

It's not clear to me what the best course of action is, but since
block_usage can always be added to fsinfo later, but not removed without
breaking backwards compatibility, I'm leaving this out for now.

Block usage can still be found by explicitly calling lfs_fs_size.
2023-06-29 12:23:33 -05:00
Christopher Haster
c5fb3f181b Changed fsinfo.minor_version -> fsinfo.disk_version
Version are now returned with major/minor packed into 32-bits,
so 0x00020001 is the current disk version, for example.

1. This needed to change to use a disk_* prefix for consistency with the
   defines that already exist for LFS_VERSION/LFS_DISK_VERSION.

2. Encoding the version this way has the nice side effect of making 0 an
   invalid value. This is useful for adding a similar config option
   that needs to have reasonable default behavior for backwards
   compatibility.

In theory this uses more space, but in practice most other config/status
is 32-bits in littlefs. We would be wasting this space for alignment
anyways.
2023-06-06 22:03:00 -05:00
Christopher Haster
8610f7c36b Increased context on failures for Valgrind in CI
Valgrind output is very verbose but useful, with a default limit of 5
lines the output usually doesn't contain much useful info.
2023-06-06 22:02:14 -05:00
Christopher Haster
a51be18765 Removed previous-version lfsp_fs_stat checks in test_compat
This function naturally doesn't exist in the previous version. We should
eventually add these calls when we can expect the previous version to
support this function, though it's a bit unclear when that should happen.

Or maybe not! Maybe this is testing more of the previous version than we
really care about.
2023-06-06 22:00:26 -05:00
Christopher Haster
a7ccc1df59 Promoted lfs_gstate_needssuperblock to be available in readonly builds
Needed for minor version reporting in lfs_fs_stat to work correctly.
2023-06-06 15:59:45 -05:00
Christopher Haster
fdee127f74 Removed use of LFS_VERSION in test_compat
LFS_VERSION -> LFS_DISK_VERSION

These tests shouldn't depend on LFS_VERSION. It's a bit subtle, but
LFS_VERSION versions the API, and LFS_DISK_VERSION versions the
on-disk format, which is what test_compat should be testing.
2023-06-06 14:55:22 -05:00
Christopher Haster
87bbf1d374 Added lfs_fs_stat for access to filesystem status/configuration
Currently this includes:

- minor_version - on-disk minor version
- block_usage - estimated number of in-use blocks
- name_max - configurable name limit
- file_max - configurable file limit
- attr_max - configurable attr limit

These are currently the only configuration operations that need to be
written to disk. Other configuration is either needed to mount, such as
block_size, or does not change the on-disk representation, such as
read/prog_size.

This also includes the current block usage, which is common in other
filesystems, though a more expensive to find in littlefs. I figure it's
not unreasonable to make lfs_fs_stat no worse than block allocation,
hopefully this isn't a mistake. It may be worth caching the current
usage after the most recent lookahead scan.

More configuration may be added to this struct in the future.
2023-06-06 13:02:16 -05:00
Christopher Haster
66f07563c3 Merge pull request #832 from littlefs-project/remove-sys-types
Remove unnecessary sys/types.h include
2023-05-23 14:46:12 -05:00
Christopher Haster
5eed341059 Merge pull request #819 from benpicco/fix-AVR
Fix build for AVR
2023-05-23 14:45:34 -05:00
Christopher Haster
97e2526a81 Merge pull request #818 from littlefs-project/convince-github-littlefs-is-c
Convince GitHub littlefs is a C project
2023-05-23 14:44:48 -05:00
Christopher Haster
8a4ee65fc3 Removed unnecessary sys/types.h include
Likely included at some point for ssize_t, this is no longer needed and
causes some problems for embedded compilers.

Currently littlefs doesn't even use size_t/ssize_t in its definition of
lfs_size_t/lfs_ssize_t, so I don't think this will ever be required.

Found by LDong-Arm, vvn-git
2023-05-17 11:11:27 -05:00
Benjamin Valentin
6fda813ce8 Fix build for AVR
This fixes the overflowing left shift on 8 bit platforms.

    littlefs2/lfs.c: In function ‘lfs_dir_commitcrc’:
    littlefs2/lfs.c:1654:51: error: left shift count >= width of type [-Werror=shift-count-overflow]
             commit->ptag = ntag ^ ((0x80 & ~eperturb) << 24);
2023-05-05 12:11:20 +02:00
Christopher Haster
f2bc6a8e88 Reclassify .toml files as .c files on GitHub
With the new test framework, GitHub really wants to mark littlefs as a
python project. telling it to reclassify our test .toml files as C code
(which they are 95% of anyways) remedies this.

An alternative would be to add syntax=c vim modelines to the test/bench
files, which would also render them with C syntax highlighting on
GitHub. Unfortunately the interspersed toml metadata mucks this up,
making the result not very useful.
2023-05-04 14:01:04 -05:00
Christopher Haster
ec3ec86bcc Merge pull request #814 from littlefs-project/devel
Minor release: v2.6
2023-05-04 12:55:52 -05:00
Christopher Haster
405f33214a Merge pull request #812 from littlefs-project/mkconsistent
Add lfs_fs_mkconsistent
2023-04-30 23:26:04 -05:00
Christopher Haster
3dca02911f Merge pull request #811 from littlefs-project/fix-deorphan-repeatedly
Fix issue where lfs_fs_deorphan may run more than needed
2023-04-30 23:25:01 -05:00
7 changed files with 211 additions and 44 deletions

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
# GitHub really wants to mark littlefs as a python project, telling it to
# reclassify our test .toml files as C code (which they are 95% of anyways)
# remedies this
*.toml linguist-language=c

View File

@@ -371,7 +371,8 @@ jobs:
# on one geometry
- name: test-valgrind
run: |
TESTFLAGS="$TESTFLAGS --valgrind -Gdefault -Pnone" make test
TESTFLAGS="$TESTFLAGS --valgrind --context=1024 -Gdefault -Pnone" \
make test
# test that compilation is warning free under clang
# run with Clang, mostly to check for Clang-specific warnings

62
lfs.c
View File

@@ -415,11 +415,11 @@ static inline uint8_t lfs_gstate_getorphans(const lfs_gstate_t *a) {
static inline bool lfs_gstate_hasmove(const lfs_gstate_t *a) {
return lfs_tag_type1(a->tag);
}
#endif
static inline bool lfs_gstate_needssuperblock(const lfs_gstate_t *a) {
return lfs_tag_size(a->tag) >> 9;
}
#endif
static inline bool lfs_gstate_hasmovehere(const lfs_gstate_t *a,
const lfs_block_t *pair) {
@@ -535,7 +535,6 @@ static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file);
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file);
static int lfs_fs_deorphan(lfs_t *lfs, bool powerloss);
static void lfs_fs_prepsuperblock(lfs_t *lfs, bool needssuperblock);
static int lfs_fs_preporphans(lfs_t *lfs, int8_t orphans);
static void lfs_fs_prepmove(lfs_t *lfs,
uint16_t id, const lfs_block_t pair[2]);
@@ -546,6 +545,8 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t dir[2],
static int lfs_fs_forceconsistency(lfs_t *lfs);
#endif
static void lfs_fs_prepsuperblock(lfs_t *lfs, bool needssuperblock);
#ifdef LFS_MIGRATE
static int lfs1_traverse(lfs_t *lfs,
int (*cb)(void*, lfs_block_t), void *data);
@@ -1651,7 +1652,7 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
commit->off = noff;
// perturb valid bit?
commit->ptag = ntag ^ ((0x80 & ~eperturb) << 24);
commit->ptag = ntag ^ ((0x80UL & ~eperturb) << 24);
// reset crc for next commit
commit->crc = 0xffffffff;
@@ -4324,11 +4325,9 @@ static int lfs_rawmount(lfs_t *lfs, const struct lfs_config *cfg) {
"v%"PRIu16".%"PRIu16" < v%"PRIu16".%"PRIu16,
major_version, minor_version,
LFS_DISK_VERSION_MAJOR, LFS_DISK_VERSION_MINOR);
#ifndef LFS_READONLY
// note this bit is reserved on disk, so fetching more gstate
// will not interfere here
lfs_fs_prepsuperblock(lfs, true);
#endif
}
// check superblock configuration
@@ -4421,6 +4420,42 @@ static int lfs_rawunmount(lfs_t *lfs) {
/// Filesystem filesystem operations ///
static int lfs_fs_rawstat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
// if the superblock is up-to-date, we must be on the most recent
// minor version of littlefs
if (!lfs_gstate_needssuperblock(&lfs->gstate)) {
fsinfo->disk_version = LFS_DISK_VERSION;
// otherwise we need to read the minor version on disk
} else {
// fetch the superblock
lfs_mdir_t dir;
int err = lfs_dir_fetch(lfs, &dir, lfs->root);
if (err) {
return err;
}
lfs_superblock_t superblock;
lfs_stag_t tag = lfs_dir_get(lfs, &dir, LFS_MKTAG(0x7ff, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
&superblock);
if (tag < 0) {
return tag;
}
lfs_superblock_fromle32(&superblock);
// read the on-disk version
fsinfo->disk_version = superblock.version;
}
// other on-disk configuration, we cache all of these for internal use
fsinfo->name_max = lfs->name_max;
fsinfo->file_max = lfs->file_max;
fsinfo->attr_max = lfs->attr_max;
return 0;
}
int lfs_fs_rawtraverse(lfs_t *lfs,
int (*cb)(void *data, lfs_block_t block), void *data,
bool includeorphans) {
@@ -4631,12 +4666,10 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2],
}
#endif
#ifndef LFS_READONLY
static void lfs_fs_prepsuperblock(lfs_t *lfs, bool needssuperblock) {
lfs->gstate.tag = (lfs->gstate.tag & ~LFS_MKTAG(0, 0, 0x200))
| (uint32_t)needssuperblock << 9;
}
#endif
#ifndef LFS_READONLY
static int lfs_fs_preporphans(lfs_t *lfs, int8_t orphans) {
@@ -4934,6 +4967,7 @@ static lfs_ssize_t lfs_fs_rawsize(lfs_t *lfs) {
return size;
}
#ifdef LFS_MIGRATE
////// Migration from littelfs v1 below this //////
@@ -6053,6 +6087,20 @@ int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) {
return err;
}
int lfs_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
int err = LFS_LOCK(lfs->cfg);
if (err) {
return err;
}
LFS_TRACE("lfs_fs_stat(%p, %p)", (void*)lfs, (void*)fsinfo);
err = lfs_fs_rawstat(lfs, fsinfo);
LFS_TRACE("lfs_fs_stat -> %d", err);
LFS_UNLOCK(lfs->cfg);
return err;
}
lfs_ssize_t lfs_fs_size(lfs_t *lfs) {
int err = LFS_LOCK(lfs->cfg);
if (err) {

21
lfs.h
View File

@@ -280,6 +280,21 @@ struct lfs_info {
char name[LFS_NAME_MAX+1];
};
// Filesystem info structure
struct lfs_fsinfo {
// On-disk version.
uint32_t disk_version;
// Upper limit on the length of file names in bytes.
lfs_size_t name_max;
// Upper limit on the size of files in bytes.
lfs_size_t file_max;
// Upper limit on the size of custom attributes in bytes.
lfs_size_t attr_max;
};
// Custom attribute structure, used to describe custom attributes
// committed atomically during file writes.
struct lfs_attr {
@@ -659,6 +674,12 @@ int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
/// Filesystem-level filesystem operations
// Find on-disk info about the filesystem
//
// Fills out the fsinfo structure based on the filesystem found on-disk.
// Returns a negative error code on failure.
int lfs_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo);
// Finds the current size of the filesystem
//
// Note: Result is best effort. If files share COW structures, the returned

View File

@@ -23,7 +23,6 @@
// System includes
#include <stdint.h>
#include <stdbool.h>
#include <sys/types.h>
#include <string.h>
#include <inttypes.h>

View File

@@ -22,14 +22,16 @@ code = '''
#define STRINGIZE_(x) #x
#include STRINGIZE(LFSP)
#else
#define LFSP_VERSION LFS_VERSION
#define LFSP_VERSION_MAJOR LFS_VERSION_MAJOR
#define LFSP_VERSION_MINOR LFS_VERSION_MINOR
#define LFSP_DISK_VERSION LFS_DISK_VERSION
#define LFSP_DISK_VERSION_MAJOR LFS_DISK_VERSION_MAJOR
#define LFSP_DISK_VERSION_MINOR LFS_DISK_VERSION_MINOR
#define lfsp_t lfs_t
#define lfsp_config lfs_config
#define lfsp_format lfs_format
#define lfsp_mount lfs_mount
#define lfsp_unmount lfs_unmount
#define lfsp_fsinfo lfs_fsinfo
#define lfsp_fs_stat lfs_fs_stat
#define lfsp_dir_t lfs_dir_t
#define lfsp_info lfs_info
#define LFSP_TYPE_REG LFS_TYPE_REG
@@ -58,7 +60,7 @@ code = '''
# test we can mount in a new version
[cases.test_compat_forward_mount]
if = 'LFS_VERSION_MAJOR == LFSP_VERSION_MAJOR'
if = 'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR'
code = '''
// create the previous version
struct lfsp_config cfgp;
@@ -74,13 +76,19 @@ code = '''
// now test the new mount
lfs_t lfs;
lfs_mount(&lfs, cfg) => 0;
// we should be able to read the version using lfs_fs_stat
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFSP_DISK_VERSION);
lfs_unmount(&lfs) => 0;
'''
# test we can read dirs in a new version
[cases.test_compat_forward_read_dirs]
defines.COUNT = 5
if = 'LFS_VERSION_MAJOR == LFSP_VERSION_MAJOR'
if = 'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR'
code = '''
// create the previous version
struct lfsp_config cfgp;
@@ -102,6 +110,11 @@ code = '''
lfs_t lfs;
lfs_mount(&lfs, cfg) => 0;
// we should be able to read the version using lfs_fs_stat
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFSP_DISK_VERSION);
// can we list the directories?
lfs_dir_t dir;
lfs_dir_open(&lfs, &dir, "/") => 0;
@@ -132,7 +145,7 @@ code = '''
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 4
if = 'LFS_VERSION_MAJOR == LFSP_VERSION_MAJOR'
if = 'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR'
code = '''
// create the previous version
struct lfsp_config cfgp;
@@ -166,6 +179,11 @@ code = '''
lfs_t lfs;
lfs_mount(&lfs, cfg) => 0;
// we should be able to read the version using lfs_fs_stat
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFSP_DISK_VERSION);
// can we list the files?
lfs_dir_t dir;
lfs_dir_open(&lfs, &dir, "/") => 0;
@@ -214,7 +232,7 @@ code = '''
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 4
if = 'LFS_VERSION_MAJOR == LFSP_VERSION_MAJOR'
if = 'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR'
code = '''
// create the previous version
struct lfsp_config cfgp;
@@ -251,6 +269,11 @@ code = '''
lfs_t lfs;
lfs_mount(&lfs, cfg) => 0;
// we should be able to read the version using lfs_fs_stat
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFSP_DISK_VERSION);
// can we list the directories?
lfs_dir_t dir;
lfs_dir_open(&lfs, &dir, "/") => 0;
@@ -321,7 +344,7 @@ code = '''
# test we can write dirs in a new version
[cases.test_compat_forward_write_dirs]
defines.COUNT = 10
if = 'LFS_VERSION_MAJOR == LFSP_VERSION_MAJOR'
if = 'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR'
code = '''
// create the previous version
struct lfsp_config cfgp;
@@ -343,6 +366,11 @@ code = '''
lfs_t lfs;
lfs_mount(&lfs, cfg) => 0;
// we should be able to read the version using lfs_fs_stat
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFSP_DISK_VERSION);
// write another COUNT/2 dirs
for (lfs_size_t i = COUNT/2; i < COUNT; i++) {
char name[8];
@@ -380,7 +408,7 @@ code = '''
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 2
if = 'LFS_VERSION_MAJOR == LFSP_VERSION_MAJOR'
if = 'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR'
code = '''
// create the previous version
struct lfsp_config cfgp;
@@ -420,6 +448,11 @@ code = '''
lfs_t lfs;
lfs_mount(&lfs, cfg) => 0;
// we should be able to read the version using lfs_fs_stat
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFSP_DISK_VERSION);
// write half COUNT files
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
@@ -494,7 +527,7 @@ code = '''
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 2
if = 'LFS_VERSION_MAJOR == LFSP_VERSION_MAJOR'
if = 'LFS_DISK_VERSION_MAJOR == LFSP_DISK_VERSION_MAJOR'
code = '''
// create the previous version
struct lfsp_config cfgp;
@@ -537,6 +570,11 @@ code = '''
lfs_t lfs;
lfs_mount(&lfs, cfg) => 0;
// we should be able to read the version using lfs_fs_stat
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFSP_DISK_VERSION);
// write half COUNT files
prng = 42;
for (lfs_size_t i = 0; i < COUNT; i++) {
@@ -636,7 +674,7 @@ code = '''
# test we can mount in an old version
[cases.test_compat_backward_mount]
if = 'LFS_VERSION == LFSP_VERSION'
if = 'LFS_DISK_VERSION == LFSP_DISK_VERSION'
code = '''
// create the new version
lfs_t lfs;
@@ -651,13 +689,14 @@ code = '''
memcpy(&cfgp, cfg, sizeof(cfgp));
lfsp_t lfsp;
lfsp_mount(&lfsp, &cfgp) => 0;
lfsp_unmount(&lfsp) => 0;
'''
# test we can read dirs in an old version
[cases.test_compat_backward_read_dirs]
defines.COUNT = 5
if = 'LFS_VERSION == LFSP_VERSION'
if = 'LFS_DISK_VERSION == LFSP_DISK_VERSION'
code = '''
// create the new version
lfs_t lfs;
@@ -709,7 +748,7 @@ code = '''
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 4
if = 'LFS_VERSION == LFSP_VERSION'
if = 'LFS_DISK_VERSION == LFSP_DISK_VERSION'
code = '''
// create the new version
lfs_t lfs;
@@ -791,7 +830,7 @@ code = '''
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 4
if = 'LFS_VERSION == LFSP_VERSION'
if = 'LFS_DISK_VERSION == LFSP_DISK_VERSION'
code = '''
// create the new version
lfs_t lfs;
@@ -898,7 +937,7 @@ code = '''
# test we can write dirs in an old version
[cases.test_compat_backward_write_dirs]
defines.COUNT = 10
if = 'LFS_VERSION == LFSP_VERSION'
if = 'LFS_DISK_VERSION == LFSP_DISK_VERSION'
code = '''
// create the new version
lfs_t lfs;
@@ -957,7 +996,7 @@ code = '''
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 2
if = 'LFS_VERSION == LFSP_VERSION'
if = 'LFS_DISK_VERSION == LFSP_DISK_VERSION'
code = '''
// create the previous version
lfs_t lfs;
@@ -1071,7 +1110,7 @@ code = '''
defines.COUNT = 5
defines.SIZE = [4, 32, 512, 8192]
defines.CHUNK = 2
if = 'LFS_VERSION == LFSP_VERSION'
if = 'LFS_DISK_VERSION == LFSP_DISK_VERSION'
code = '''
// create the previous version
lfs_t lfs;
@@ -1316,45 +1355,54 @@ code = '''
// mount should still work
lfs_mount(&lfs, cfg) => 0;
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFS_DISK_VERSION-1);
lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0;
uint8_t buffer[8];
lfs_file_read(&lfs, &file, buffer, 8) => 8;
assert(memcmp(buffer, "testtest", 8) == 0);
lfs_file_close(&lfs, &file) => 0;
// minor version should be unchanged
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFS_DISK_VERSION-1);
lfs_unmount(&lfs) => 0;
// if we write, we need to bump the minor version
lfs_mount(&lfs, cfg) => 0;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFS_DISK_VERSION-1);
lfs_file_open(&lfs, &file, "test", LFS_O_WRONLY | LFS_O_TRUNC) => 0;
lfs_file_write(&lfs, &file, "teeeeest", 8) => 8;
lfs_file_close(&lfs, &file) => 0;
// minor version should have changed
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
lfs_dir_get(&lfs, &mdir, LFS_MKTAG(0x7ff, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
&superblock)
=> LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock));
lfs_superblock_fromle32(&superblock);
assert((superblock.version >> 16) & 0xffff == LFS_DISK_VERSION_MAJOR);
assert((superblock.version >> 0) & 0xffff == LFS_DISK_VERSION_MINOR);
// minor version should be changed
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFS_DISK_VERSION);
lfs_unmount(&lfs) => 0;
// and of course mount should still work
lfs_mount(&lfs, cfg) => 0;
// minor version should have changed
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFS_DISK_VERSION);
lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0;
lfs_file_read(&lfs, &file, buffer, 8) => 8;
assert(memcmp(buffer, "teeeeest", 8) == 0);
lfs_file_close(&lfs, &file) => 0;
// minor version should have changed
lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
lfs_dir_get(&lfs, &mdir, LFS_MKTAG(0x7ff, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
&superblock)
=> LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock));
lfs_superblock_fromle32(&superblock);
assert((superblock.version >> 16) & 0xffff == LFS_DISK_VERSION_MAJOR);
assert((superblock.version >> 0) & 0xffff == LFS_DISK_VERSION_MINOR);
// yep, still changed
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFS_DISK_VERSION);
lfs_unmount(&lfs) => 0;
'''

View File

@@ -34,6 +34,52 @@ code = '''
lfs_mount(&lfs, cfg) => LFS_ERR_CORRUPT;
'''
# test we can read superblock info through lfs_fs_stat
[cases.test_superblocks_stat]
code = '''
lfs_t lfs;
lfs_format(&lfs, cfg) => 0;
// test we can mount and read fsinfo
lfs_mount(&lfs, cfg) => 0;
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFS_DISK_VERSION);
assert(fsinfo.name_max == LFS_NAME_MAX);
assert(fsinfo.file_max == LFS_FILE_MAX);
assert(fsinfo.attr_max == LFS_ATTR_MAX);
lfs_unmount(&lfs) => 0;
'''
[cases.test_superblocks_stat_tweaked]
defines.TWEAKED_NAME_MAX = 63
defines.TWEAKED_FILE_MAX = '(1 << 16)-1'
defines.TWEAKED_ATTR_MAX = 512
code = '''
// create filesystem with tweaked params
struct lfs_config tweaked_cfg = *cfg;
tweaked_cfg.name_max = TWEAKED_NAME_MAX;
tweaked_cfg.file_max = TWEAKED_FILE_MAX;
tweaked_cfg.attr_max = TWEAKED_ATTR_MAX;
lfs_t lfs;
lfs_format(&lfs, &tweaked_cfg) => 0;
// test we can mount and read these params with the original config
lfs_mount(&lfs, cfg) => 0;
struct lfs_fsinfo fsinfo;
lfs_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.disk_version == LFS_DISK_VERSION);
assert(fsinfo.name_max == TWEAKED_NAME_MAX);
assert(fsinfo.file_max == TWEAKED_FILE_MAX);
assert(fsinfo.attr_max == TWEAKED_ATTR_MAX);
lfs_unmount(&lfs) => 0;
'''
# expanding superblock
[cases.test_superblocks_expand]
defines.BLOCK_CYCLES = [32, 33, 1]