Skip to content

Commit 8f5ca34

Browse files
authored
Merge pull request #19 from mkaranki/update-to-v2.10.2
2 parents ed0531d + 358035e commit 8f5ca34

17 files changed

+702
-78
lines changed

Makefile

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ VALGRIND ?= valgrind
1818
GDB ?= gdb
1919
PERF ?= perf
2020

21+
# guess clang or gcc (clang sometimes masquerades as gcc because of
22+
# course it does)
23+
ifneq ($(shell $(CC) --version | grep clang),)
24+
NO_GCC = 1
25+
endif
26+
2127
SRC ?= $(filter-out $(wildcard *.t.* *.b.*),$(wildcard *.c))
2228
OBJ := $(SRC:%.c=$(BUILDDIR)/%.o)
2329
DEP := $(SRC:%.c=$(BUILDDIR)/%.d)
@@ -59,12 +65,15 @@ BENCH_PERF := $(BENCH_RUNNER:%=%.perf)
5965
BENCH_TRACE := $(BENCH_RUNNER:%=%.trace)
6066
BENCH_CSV := $(BENCH_RUNNER:%=%.csv)
6167

62-
CFLAGS += -fcallgraph-info=su
6368
CFLAGS += -g3
6469
CFLAGS += -I.
6570
CFLAGS += -std=c99 -Wall -Wextra -pedantic
6671
CFLAGS += -Wmissing-prototypes
72+
ifndef NO_GCC
73+
CFLAGS += -fcallgraph-info=su
6774
CFLAGS += -ftrack-macro-expansion=0
75+
endif
76+
6877
ifdef DEBUG
6978
CFLAGS += -O0
7079
else

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,47 @@ The tests assume a Linux environment and can be started with make:
199199
make test
200200
```
201201

202+
Tests are implemented in C in the .toml files found in the `tests` directory.
203+
When developing a feature or fixing a bug, it is frequently useful to run a
204+
single test case or suite of tests:
205+
206+
``` bash
207+
./scripts/test.py -l runners/test_runner # list available test suites
208+
./scripts/test.py -L runners/test_runner test_dirs # list available test cases
209+
./scripts/test.py runners/test_runner test_dirs # run a specific test suite
210+
```
211+
212+
If an assert fails in a test, test.py will try to print information about the
213+
failure:
214+
215+
``` bash
216+
tests/test_dirs.toml:1:failure: test_dirs_root:1g12gg2 (PROG_SIZE=16, ERASE_SIZE=512) failed
217+
tests/test_dirs.toml:5:assert: assert failed with 0, expected eq 42
218+
lfs_mount(&lfs, cfg) => 42;
219+
```
220+
221+
This includes the test id, which can be passed to test.py to run only that
222+
specific test permutation:
223+
224+
``` bash
225+
./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 # run a specific test permutation
226+
./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 --gdb # drop into gdb on failure
227+
```
228+
229+
Some other flags that may be useful:
230+
231+
```bash
232+
./scripts/test.py runners/test_runner -b -j # run tests in parallel
233+
./scripts/test.py runners/test_runner -v -O- # redirect stdout to stdout
234+
./scripts/test.py runners/test_runner -ddisk # capture resulting disk image
235+
```
236+
237+
See `-h/--help` for a full list of available flags:
238+
239+
``` bash
240+
./scripts/test.py --help
241+
```
242+
202243
## License
203244

204245
The littlefs is provided under the [BSD-3-Clause] license. See

bd/lfs_filebd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ int lfs_filebd_prog(const struct lfs_config *cfg, lfs_block_t block,
133133

134134
int lfs_filebd_erase(const struct lfs_config *cfg, lfs_block_t block) {
135135
LFS_FILEBD_TRACE("lfs_filebd_erase(%p, 0x%"PRIx32" (%"PRIu32"))",
136-
(void*)cfg, block, ((lfs_file_t*)cfg->context)->cfg->erase_size);
136+
(void*)cfg, block, ((lfs_filebd_t*)cfg->context)->cfg->erase_size);
137137
lfs_filebd_t *bd = cfg->context;
138138

139139
// check if erase is valid

lfs.c

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -407,18 +407,15 @@ struct lfs_diskoff {
407407

408408
// operations on global state
409409
static inline void lfs_gstate_xor(lfs_gstate_t *a, const lfs_gstate_t *b) {
410-
for (int i = 0; i < 3; i++) {
411-
((uint32_t*)a)[i] ^= ((const uint32_t*)b)[i];
412-
}
410+
a->tag ^= b->tag;
411+
a->pair[0] ^= b->pair[0];
412+
a->pair[1] ^= b->pair[1];
413413
}
414414

415415
static inline bool lfs_gstate_iszero(const lfs_gstate_t *a) {
416-
for (int i = 0; i < 3; i++) {
417-
if (((uint32_t*)a)[i] != 0) {
418-
return false;
419-
}
420-
}
421-
return true;
416+
return a->tag == 0
417+
&& a->pair[0] == 0
418+
&& a->pair[1] == 0;
422419
}
423420

424421
#ifndef LFS_READONLY
@@ -2374,7 +2371,8 @@ fixmlist:;
23742371
if (d->m.pair != pair) {
23752372
for (int i = 0; i < attrcount; i++) {
23762373
if (lfs_tag_type3(attrs[i].tag) == LFS_TYPE_DELETE &&
2377-
d->id == lfs_tag_id(attrs[i].tag)) {
2374+
d->id == lfs_tag_id(attrs[i].tag) &&
2375+
d->type != LFS_TYPE_DIR) {
23782376
d->m.pair[0] = LFS_BLOCK_NULL;
23792377
d->m.pair[1] = LFS_BLOCK_NULL;
23802378
} else if (lfs_tag_type3(attrs[i].tag) == LFS_TYPE_DELETE &&
@@ -2563,7 +2561,7 @@ static int lfs_dir_orphaningcommit(lfs_t *lfs, lfs_mdir_t *dir,
25632561
if (err != LFS_ERR_NOENT) {
25642562
if (lfs_gstate_hasorphans(&lfs->gstate)) {
25652563
// next step, clean up orphans
2566-
err = lfs_fs_preporphans(lfs, -hasparent);
2564+
err = lfs_fs_preporphans(lfs, -(int8_t)hasparent);
25672565
if (err) {
25682566
return err;
25692567
}
@@ -3939,7 +3937,9 @@ static int lfs_remove_(lfs_t *lfs, const char *path) {
39393937
}
39403938

39413939
lfs->mlist = dir.next;
3942-
if (lfs_tag_type3(tag) == LFS_TYPE_DIR) {
3940+
if (lfs_gstate_hasorphans(&lfs->gstate)) {
3941+
LFS_ASSERT(lfs_tag_type3(tag) == LFS_TYPE_DIR);
3942+
39433943
// fix orphan
39443944
err = lfs_fs_preporphans(lfs, -1);
39453945
if (err) {
@@ -4083,8 +4083,10 @@ static int lfs_rename_(lfs_t *lfs, const char *oldpath, const char *newpath) {
40834083
}
40844084

40854085
lfs->mlist = prevdir.next;
4086-
if (prevtag != LFS_ERR_NOENT
4087-
&& lfs_tag_type3(prevtag) == LFS_TYPE_DIR) {
4086+
if (lfs_gstate_hasorphans(&lfs->gstate)) {
4087+
LFS_ASSERT(prevtag != LFS_ERR_NOENT
4088+
&& lfs_tag_type3(prevtag) == LFS_TYPE_DIR);
4089+
40884090
// fix orphan
40894091
err = lfs_fs_preporphans(lfs, -1);
40904092
if (err) {
@@ -5240,40 +5242,64 @@ static int lfs_fs_gc_(lfs_t *lfs) {
52405242
#endif
52415243

52425244
#ifndef LFS_READONLY
5245+
#ifdef LFS_SHRINKNONRELOCATING
5246+
static int lfs_shrink_checkblock(void *data, lfs_block_t block) {
5247+
lfs_size_t threshold = *((lfs_size_t*)data);
5248+
if (block >= threshold) {
5249+
return LFS_ERR_NOTEMPTY;
5250+
}
5251+
return 0;
5252+
}
5253+
#endif
5254+
52435255
static int lfs_fs_grow_(lfs_t *lfs, lfs_size_t block_count) {
5244-
// shrinking is not supported
5245-
LFS_ASSERT(block_count >= lfs->block_count);
5256+
int err;
52465257

5247-
if (block_count > lfs->block_count) {
5248-
lfs->block_count = block_count;
5258+
if (block_count == lfs->block_count) {
5259+
return 0;
5260+
}
52495261

5250-
// fetch the root
5251-
lfs_mdir_t root;
5252-
int err = lfs_dir_fetch(lfs, &root, lfs->root);
5262+
5263+
#ifndef LFS_SHRINKNONRELOCATING
5264+
// shrinking is not supported
5265+
LFS_ASSERT(block_count >= lfs->block_count);
5266+
#endif
5267+
#ifdef LFS_SHRINKNONRELOCATING
5268+
if (block_count < lfs->block_count) {
5269+
err = lfs_fs_traverse_(lfs, lfs_shrink_checkblock, &block_count, true);
52535270
if (err) {
52545271
return err;
52555272
}
5273+
}
5274+
#endif
52565275

5257-
// update the superblock
5258-
lfs_superblock_t superblock;
5259-
lfs_stag_t tag = lfs_dir_get(lfs, &root, LFS_MKTAG(0x7ff, 0x3ff, 0),
5260-
LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
5261-
&superblock);
5262-
if (tag < 0) {
5263-
return tag;
5264-
}
5265-
lfs_superblock_fromle32(&superblock);
5276+
lfs->block_count = block_count;
52665277

5267-
superblock.block_count = lfs->block_count;
5278+
// fetch the root
5279+
lfs_mdir_t root;
5280+
err = lfs_dir_fetch(lfs, &root, lfs->root);
5281+
if (err) {
5282+
return err;
5283+
}
52685284

5269-
lfs_superblock_tole32(&superblock);
5270-
err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(
5271-
{tag, &superblock}));
5272-
if (err) {
5273-
return err;
5274-
}
5285+
// update the superblock
5286+
lfs_superblock_t superblock;
5287+
lfs_stag_t tag = lfs_dir_get(lfs, &root, LFS_MKTAG(0x7ff, 0x3ff, 0),
5288+
LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
5289+
&superblock);
5290+
if (tag < 0) {
5291+
return tag;
52755292
}
5293+
lfs_superblock_fromle32(&superblock);
5294+
5295+
superblock.block_count = lfs->block_count;
52765296

5297+
lfs_superblock_tole32(&superblock);
5298+
err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(
5299+
{tag, &superblock}));
5300+
if (err) {
5301+
return err;
5302+
}
52775303
return 0;
52785304
}
52795305
#endif
@@ -6293,7 +6319,7 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
62936319

62946320
lfs_soff_t res = lfs_file_size_(lfs, file);
62956321

6296-
LFS_TRACE("lfs_file_size -> %"PRId32, res);
6322+
LFS_TRACE("lfs_file_size -> %"PRIu32, res);
62976323
LFS_UNLOCK(lfs->cfg);
62986324
return res;
62996325
}

lfs.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ extern "C"
2121
// Software library version
2222
// Major (top-nibble), incremented on backwards incompatible changes
2323
// Minor (bottom-nibble), incremented on feature additions
24-
#define LFS_VERSION 0x0002000a
24+
#define LFS_VERSION 0x0002000b
2525
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
2626
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
2727

@@ -766,7 +766,11 @@ int lfs_fs_gc(lfs_t *lfs);
766766
// Grows the filesystem to a new size, updating the superblock with the new
767767
// block count.
768768
//
769-
// Note: This is irreversible.
769+
// If LFS_SHRINKNONRELOCATING is defined, this function will also accept
770+
// block_counts smaller than the current configuration, after checking
771+
// that none of the blocks that are being removed are in use.
772+
// Note that littlefs's pseudorandom block allocation means that
773+
// this is very unlikely to work in the general case.
770774
//
771775
// Returns a negative error code on failure.
772776
int lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count);

lfs_util.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,10 @@ static inline uint32_t lfs_fromle32(uint32_t a) {
195195
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
196196
return __builtin_bswap32(a);
197197
#else
198-
return (((uint8_t*)&a)[0] << 0) |
199-
(((uint8_t*)&a)[1] << 8) |
200-
(((uint8_t*)&a)[2] << 16) |
201-
(((uint8_t*)&a)[3] << 24);
198+
return ((uint32_t)((uint8_t*)&a)[0] << 0) |
199+
((uint32_t)((uint8_t*)&a)[1] << 8) |
200+
((uint32_t)((uint8_t*)&a)[2] << 16) |
201+
((uint32_t)((uint8_t*)&a)[3] << 24);
202202
#endif
203203
}
204204

@@ -218,10 +218,10 @@ static inline uint32_t lfs_frombe32(uint32_t a) {
218218
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
219219
return a;
220220
#else
221-
return (((uint8_t*)&a)[0] << 24) |
222-
(((uint8_t*)&a)[1] << 16) |
223-
(((uint8_t*)&a)[2] << 8) |
224-
(((uint8_t*)&a)[3] << 0);
221+
return ((uint32_t)((uint8_t*)&a)[0] << 24) |
222+
((uint32_t)((uint8_t*)&a)[1] << 16) |
223+
((uint32_t)((uint8_t*)&a)[2] << 8) |
224+
((uint32_t)((uint8_t*)&a)[3] << 0);
225225
#endif
226226
}
227227

@@ -231,8 +231,8 @@ static inline uint32_t lfs_tobe32(uint32_t a) {
231231

232232
// Calculate CRC-32 with polynomial = 0x04c11db7
233233
#ifdef LFS_CRC
234-
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
235-
return LFS_CRC(crc, buffer, size)
234+
static inline uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
235+
return LFS_CRC(crc, buffer, size);
236236
}
237237
#else
238238
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);

runners/bench_runner.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,13 @@ typedef struct bench_id {
123123

124124

125125
// bench suites are linked into a custom ld section
126+
#if defined(__APPLE__)
127+
extern struct bench_suite __start__bench_suites __asm("section$start$__DATA$_bench_suites");
128+
extern struct bench_suite __stop__bench_suites __asm("section$end$__DATA$_bench_suites");
129+
#else
126130
extern struct bench_suite __start__bench_suites;
127131
extern struct bench_suite __stop__bench_suites;
132+
#endif
128133

129134
const struct bench_suite *bench_suites = &__start__bench_suites;
130135
#define BENCH_SUITE_COUNT \

runners/test_runner.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,13 @@ typedef struct test_id {
136136

137137

138138
// test suites are linked into a custom ld section
139+
#if defined(__APPLE__)
140+
extern struct test_suite __start__test_suites __asm("section$start$__DATA$_test_suites");
141+
extern struct test_suite __stop__test_suites __asm("section$end$__DATA$_test_suites");
142+
#else
139143
extern struct test_suite __start__test_suites;
140144
extern struct test_suite __stop__test_suites;
145+
#endif
141146

142147
const struct test_suite *test_suites = &__start__test_suites;
143148
#define TEST_SUITE_COUNT \

scripts/bench.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,12 +404,15 @@ def write_case_functions(f, suite, case):
404404
f.writeln()
405405

406406
# create suite struct
407-
#
407+
f.writeln('#if defined(__APPLE__)')
408+
f.writeln('__attribute__((section("__DATA,_bench_suites")))')
409+
f.writeln('#else')
408410
# note we place this in the custom bench_suites section with
409411
# minimum alignment, otherwise GCC ups the alignment to
410412
# 32-bytes for some reason
411413
f.writeln('__attribute__((section("_bench_suites"), '
412414
'aligned(1)))')
415+
f.writeln('#endif')
413416
f.writeln('const struct bench_suite __bench__%s__suite = {'
414417
% suite.name)
415418
f.writeln(4*' '+'.name = "%s",' % suite.name)

scripts/changeprefix.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def changefile(from_prefix, to_prefix, from_path, to_path, *,
7373
shutil.copystat(from_path, to_path)
7474

7575
if to_path_temp:
76-
os.rename(to_path, from_path)
76+
shutil.move(to_path, from_path)
7777
elif from_path != '-':
7878
os.remove(from_path)
7979

0 commit comments

Comments
 (0)