Commit Graph

781 Commits

Author SHA1 Message Date
Christopher Haster bbb9e3873e Merge pull request #593 from tannewt/patch-1
Indent sub-portions of tag fields
2022-03-20 23:07:32 -05:00
Christopher Haster c6d3c48939 Merge pull request #569 from tniessen/fix-compilation-with-lfs_readonly
Fix compiler warnings when LFS_READONLY defined
2022-03-20 23:06:50 -05:00
Christopher Haster 2db5dc80c2 Update copyright notice 2022-03-20 23:03:52 -05:00
田昕 1363c9f9d4 fix bug:lfs_alloc will alloc one block repeatedly in multiple split
BUG CASE:Assume there are 6 blocks in littlefs, block 0,1,2,3 already allocated. 0 has a tail pair of {2, 3}. Now we try to write more into 0.
When writing to block 0, we will split(FIRST SPLIT), thus allocate block 4 and 5. Up to now , everything is as expected.
Then we will try to commit in block 4, during which split(SECOND SPLIT) is triggered again(In our case, some files are large, some are small, one split may not be enough).  Still as expected now.
BUG happens when we try to alloc a new block pair for the second split:
As lookahead buffer reaches the end , a new lookahead buffer will be generated from flash content, and block 4, 5 are unused blocks in the new lookahead buffer because they are not programed yet. HOWEVER, block 4,5 should be occupied in the first split!!!!!  The result is block 4,5 are allocated again(This is where things are getting wrong).

commit ce2c01f results in this bug. In the commit, a lfs_alloc_ack is inserted in lfs_dir_split, which will cause split to reset lfs->free.ack to block count.
In summary, this problem exists after 2.1.3.

Solution: don't call lfs_alloc_ack in lfs_dir_split.
2022-03-20 20:53:48 -05:00
Kongduino 5bc682a0d4 Typo
s/propogated/propagated/
2022-03-20 20:49:45 -05:00
Christopher Haster 8109f28266 Removed recursion from lfs_dir_traverse
lfs_dir_traverse is a bit unpleasant in that it is inherently a
recursive function, but without a strict bound of 4 calls (commit -> filter ->
move -> filter), and efforts to unroll the recursion comes at a
signification code cost.

It turns out the best solution I've found so far is to simple create an
explicit stack with an explicit bound of 4 calls (or more accurately,
3 pushed frames).

---

This actually highlights one of the bigger flaws in littlefs right now,
which is that this function, lfs_dir_traverse, takes O(n^2) disk reads
to traverse.

Note that LFS_FROM_MOVE can only occur once per commit, which is why
this code is O(n^2) and not O(n^4).
2022-03-20 04:27:54 -05:00
Christopher Haster fedf646c79 Removed recursion in file read/writes
This mostly just required separate functions for "lfs_file_rawwrite" and
"lfs_file_flushedwrite", since lfs_file_flush recursively invokes
lfs_file_rawread and lfs_file_rawwrite.

This comes at a code cost, but gives us bounded and measurable RAM usage
on this code path.
2022-03-20 04:25:24 -05:00
Christopher Haster 84da4c0b1a Removed recursion from commit/relocate code path
lfs_dir_commit originally relied heavily on tail-recursion, though at
least one path (through relocations) was not tail-recursive, and could
cause unbounded stack usage in extreme cases of bad blocks. (Keep in
mind even extreme cases of bad blocks should be in scope for littlefs).

In order to remove recursion from this code path, several changed were
raequired:

- The lfs_dir_compact logic had to be somewhat inverted. Instead of
  first compacting and then resolving issues such as relocations and
  orphans, the overarching lfs_dir_commit now contains a state-machine
  which after committing or compacting handles the extra changes to the
  filesystem in a single, non-recursive loop

- Instead of fixing all relocations recursively, >1 relocation requires
  defering to a full deorphan step. This step is unfortunately an
  additional n^2 process. It also required some changes to lfs_deorphan
  in order to ignore intentional orphans created as an intermediary in
  lfs_mkdir. Maybe in the future we should remove these.

- Tail recursion normally found in lfs_fs_deorphan had to be rewritten
  as a loop which restarts any time a new commit causes a relocation.
  This does show that the algorithm may not terminate, but only if every
  block is bad, which will eventually cause littlefs to run out of
  blocks to write to.
2022-03-20 04:24:44 -05:00
Christopher Haster 554e4b1444 Fixed Popen deadlock issue in test.py
As noted in Python's subprocess library:

> This will deadlock when using stdout=PIPE and/or stderr=PIPE and the
> child process generates enough output to a pipe such that it blocks
> waiting for the OS pipe buffer to accept more data.

Curiously, this only became a problem when updating to Ubuntu 20.04
in CI (python3.6 -> python3.8).
2022-03-20 03:44:39 -05:00
Christopher Haster fe8f3d4f18 Changed./scripts/struct.py to organize by header file
Avoids redundant counting of structs shared in multiple .c files, which
is very common. This is different from the other scripts,
code.py/data.py/stack.py, but this difference makes sense as struct
declarations have a very different lifetime.
2022-03-20 03:41:37 -05:00
Christopher Haster 316b019f41 In CI, determine loop devices dynamically to avoid conflicts with Ubuntu snaps
Introduced when updating CI to Ubuntu 20.04, Ubuntu snaps consume
loop devices, which conflict with out assumption that /dev/loop0
will always be unused. Changed to request a dynamic loop device from
losetup, though it would have been nice if Ubuntu snaps allocated
from the last device or something.
2022-03-20 03:39:23 -05:00
Christopher Haster 8475c8064d Limit ./scripts/structs.py to report structs in local .h files
This requires parsing an additional section of the dwarfinfo (--dwarf=rawlines)
to get the declaration file info.

---

Interpreting the results of ./scripts/structs.py reporting is a bit more
complicated than other scripts, structs aren't used in a consistent
manner so the cost of a large struct depends on the context in which it
is used.

But that being said, there really isn't much reason to report
internal-only structs. These structs really only exist for type-checking
in internal algorithms, and their cost will end up reflected in other RAM
measurements, either stack, heap, or other.
2022-03-20 03:39:23 -05:00
Christopher Haster 563af5f364 Cleaned up make clean 2022-03-20 03:39:23 -05:00
Christopher Haster 3b495bab79 Fixed spurious CI failure caused by multiple writers to .o files
GCC is a bit frustrating here, it really wants to generate every file in
a single command, which _is_ more efficient if our build system could
leverage this. But -fcallgraph-info is a rather novel flag, so we can't
really rely on it for generally compiling and testing littlefs.

The multi-file output gets in the way when we want an explicitly
separate rule for callgraph-info generation. We can't generate the
callgraph-info without generating the objects files.

This becomes a surprsing issue when parallel building (make -j) is used!
Suddenly we might end up with both the .o and .ci rules writing to .o
files, which creates a really difficult to track down issue of corrupted
.o files.

The temporary solution is to use an order-only prerequisite. This still
ends up building the .o files twice, but it's an acceptable tradeoff for
not requiring the -fcallgraph-info for all builds.
2022-03-20 03:39:18 -05:00
Christopher Haster e4adefd1d7 Fixed spurious encoding error
Using errors=replace in python utf-8 decoding makes these scripts more
resilient to underlying errors, rather than just throwing an unhelpfully
generic decode error.
2022-03-20 03:28:26 -05:00
Christopher Haster 9d54603ce2 Added new scripts to CI results
- Added to GitHub statuses (61 results)

- Reworked generated release table to include these (16 results, only thumb)

These also required a surprisingly large number of other changes:

- Bumbed CI Ubuntu version 18.04 -> 20.04, 22.04 is already on the
  horizon but not usable in GitHub yet

- Manualy upgrade to GCC v10, this is required for the -fcallgraph-info
  flag that scripts/stack.py uses.

- Increased paginated status queries to 100 per-page. If we have more
  statuses than this the status diffs may get much more complicated...

- Forced whitespace in generated release table to always be nbsp. GitHub
  tables get scrunched rather ugly without this, prefering margins to
  readable tables.

- Added limited support for "∞" results, since this is returned by
  ./scripts/stack.py for recursive functions.

As a side-note, this increases the number of statuses reported
per-commit from 6 to 61, so hopefully that doesn't cause any problems...
2022-03-20 03:28:26 -05:00
Christopher Haster 7ea2b515aa A few more tweaks to scripts
- Changed `make summary` to show a one line summary
- Added `make lfs.csv` rule, which is useful for finding more info with
  other scripts
- Fixed small issue in ./scripts/summary.py
- Added *.ci (callgraph) and *.csv (script output) to CI
2022-03-20 03:28:26 -05:00
Christopher Haster 55b3c538d5 Added ./script/summary.py
A full summary of static measurements (code size, stack usage, etc) can now
be found with:

    make summary

This is done through the combination of a new ./scripts/summary.py
script and the ability of existing scripts to merge into existing csv
files, allowing multiple results to be merged either in a pipeline, or
in parallel with a single ./script/summary.py call.

The ./scripts/summary.py script can also be used to quickly compare
different builds or configurations. This is a proper implementation
of a similar but hacky shell script that has already been very useful
for making optimization decisions:

    $ ./scripts/structs.py new.csv -d old.csv --summary
    name (2 added, 0 removed)               code             stack            structs
    TOTAL                                  28648 (-2.7%)      2448               1012

Also some other small tweaks to scripts:

- Removed state saving diff rules. This isn't the most useful way to
  handle comparing changes.

- Added short flags for --summary (-Y) and --files (-F), since these
  are quite often used.
2022-03-20 03:28:26 -05:00
Christopher Haster eb8be9f351 Some improvements to size scripts
- Added -L/--depth argument to show dependencies for scripts/stack.py,
  this replaces calls.py
- Additional internal restructuring to avoid repeated code
- Removed incorrect diff percentage when there is no actual size
- Consistent percentage rendering in test.py
2022-03-20 03:28:21 -05:00
Christopher Haster 50ad2adc96 Added make *-diff rules, quick commands to compare sizes
This required a patch to the --diff flag for the scripts to ignore
a missing file. This enables the useful one liner for making comparisons
with potentially missing previous versions:

    ./scripts/code.py lfs.o -d lfs.o.code.csv -o lfs.o.code.csv

    function (0 added, 0 removed)            old     new    diff
    TOTAL                                  25476   25476      +0

One downside, these previous files are easy to delete as a part of make
clean, which limits their usefulness for comparing configuration
changes...
2022-03-11 14:40:54 -06:00
Christopher Haster 0a2ff3b6ff Added scripts/structs.py for getting sizes of structs
Note this does include internal structs, so this should probably
be limited to informative purposes.
2022-03-11 14:40:54 -06:00
Christopher Haster d7582efec8 Changed script's CSV formats to allow for merging different measurements
- size  -> code_size
- size  -> data_size
- frame -> stack_frame
- limit -> stack_limit
- hits  -> coverage_hits
- count -> coverage_count
2022-03-11 14:40:54 -06:00
Christopher Haster f4c7af76f8 Added scripts/stack.py for viewing stack usage
Note this detects loops (recursion), and renders this as infinity.
Currently littlefs does have a single recursive function and you can see
how this infects the full call graph. Eventually this should be removed.
2022-03-11 14:40:54 -06:00
Christopher Haster 20c58dcbaa Added coverage-sort to scripts/coverage.py
scripts/coverage.py was missed originally because it's not ran as often
as the others. Since it requires run-time info, it's usually only used
in CI.
2022-03-11 14:39:38 -06:00
Christopher Haster f5286abe7a Added scripts/calls.py for viewing the callgraph directly 2022-03-11 14:39:36 -06:00
Christopher Haster 2cdabe810d Split out scripts/code.py into scripts/code.py and scripts/data.py
This is to avoid unexpected script behavior even though data.py should
always return 0 bytes for littlefs. Maybe a check for this should be
added to CI?
2022-03-11 14:39:36 -06:00
Christopher Haster b045436c23 Added size-sort options to scripts/code.py
Now with -s/--sort and -S/--reverse-sort for sorting the functions by
size.

You may wonder why add reverse-sort, since its utility doesn't seem
worth the cost to implement (these are just helper scripts after all),
the reason is that reverse-sort is quite useful on the command-line,
where scrollback may be truncated, and you only care about the larger
entries.

Outside of the command-line, normal sort is prefered.

Fortunately the difference is just the sign in the sort key.

Note this conflicts with the short --summary flag, so that has been
removed.
2022-03-11 14:36:23 -06:00
Scott Shawcroft 1877c40aac Indent sub-portions of tag fields
This makes the bit breakdown clearer.
2022-02-18 21:13:41 -06:00
Emilio Lopes e29e7aeefa Specify unit of the size members of the lfs_config struct
Fixes littlefs-project/littlefs#568
2022-02-18 21:09:19 -06:00
yog e334983767 don't use lfs_file_open() when LFS_NO_MALLOC is set 2022-02-18 20:57:20 -06:00
mikee47 4977fa0c0e Fix spelling errors 2022-01-29 09:52:00 +00:00
Tobias Nießen fdda3b4aa2 Always zero rambd buffer before first use
This fixes warnings produced by tools such as memcheck without
requiring the user to set an erase value.
2021-11-14 16:10:54 +01:00
Colin Foster 487df12dde Fail when block_size doesn't match config
With the previous commit, fail if the superblock block_size doesn't
match the config block_size.
2021-08-17 10:02:27 -07:00
Colin Foster 3efb8e44f3 Fail mount when the block size changes
When the on-disk block size doesn't match the config block size, it is
possible to get file corruption. For instance, if the num blocks was
0x200 and we re-mount with 0x100 files could be corrupt.

If we re-mount with a larger number of blocks things should be safer,
but could be handled with a resize option or perhaps a mount flag to
ignore this parameter.
2021-07-21 08:56:21 -07:00
Tobias Nießen 3ae87f4e29 Add littlefs-disk-img-viewer to README 2021-06-21 18:52:00 +02:00
Tobias Nießen fb2c311bb4 Fix compiler warnings when LFS_READONLY defined 2021-06-14 12:12:38 +02:00
Christopher Haster ead50807f1 Merge pull request #565 from tniessen/fix-link-to-test-bd
Fix link to test block device
v2.4.1
2021-06-12 12:35:34 -05:00
Christopher Haster 2f7596811d Merge pull request #529 from yamt/macos-make-test
scripts/test.py: Fix infinite busy loops on macOS
2021-06-12 12:35:25 -05:00
Tobias Nießen 1e423bae58 Fix link to test block device 2021-06-09 21:04:50 +02:00
YAMAMOTO Takashi 3bee4d9a19 scripts/test.py: Fix infinite busy loops on macOS
I confirmed that the same number of tests are run
with "make test" on:

    * Ubuntu with and without this change
    * macOS with this change

>   ====== results ======
>   tests passed 817/817 (100.00%)
>   tests failed 0/817 (0.00%)
2021-02-22 14:42:10 +09:00
Christopher Haster 1863dc7883 Merge pull request #519 from littlefs-project/devel
Minor release: v2.4
v2.4.0
2021-01-19 18:50:34 -06:00
Christopher Haster 3d4e4f2085 Bumped minor version to v2.4 2021-01-18 20:23:54 -06:00
Christopher Haster a2c744c8f8 Merge pull request #516 from littlefs-project/ci-revamp
Adopt GitHub Actions, bring in a number of script/Makefile improvements
2021-01-18 18:38:42 -06:00
Christopher Haster c0cc0a417e Enabled overriding of LFS_ASSERT/TRACE/DEBUG/etc
This is useful for testing the new erroring assert behavior in CI.
Asserts do not error by default, so this macro needs to be overriden.

It is possible to test this behavior using the existing option of
overriding lfs_util.h with a custom file, by using a small sed
one-line script. But this is much simpler.

This does raise the question if more of the configuration options in
lfs_util.h should be opened up for function-like macro overrides.
2021-01-18 14:01:53 -06:00
Christopher Haster bca64d76cf Merge branch 'devel' into ci-revamp
Needed to bring in new "error-asserts" configuration
2021-01-18 12:23:25 -06:00
Christopher Haster cab1d6cca6 Merge pull request #514 from mon/feature/assert_early_return
lfs_fs_preporphans: return int to alllow graceful LFS_ASSERT
2021-01-18 11:53:47 -06:00
Will c9eed1f181 Add test to ensure asserts can return 2021-01-18 11:50:39 -06:00
Will e7e4b352bd lfs_fs_preporphans ret int for graceful LFS_ASSERT 2021-01-18 11:50:33 -06:00
Christopher Haster 9449ef4be4 Merge pull request #511 from embeddedt/fix_lseek
Skip flushing file if lfs_file_rawseek() doesn't change position
2021-01-18 11:47:56 -06:00
Christopher Haster cfe779fc08 Merge pull request #508 from littlefs-project/fix-sanity-check
Moved sanity check in lfs_format after compaction
2021-01-18 11:47:23 -06:00