Compare commits

..

1 Commits

Author SHA1 Message Date
Christopher Haster
2db5dc80c2 Update copyright notice 2022-03-20 23:03:52 -05:00
13 changed files with 47 additions and 46 deletions

View File

@@ -1,3 +1,4 @@
Copyright (c) 2022, The littlefs authors.
Copyright (c) 2017, Arm Limited. All rights reserved. Copyright (c) 2017, Arm Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,

14
SPEC.md
View File

@@ -233,19 +233,19 @@ Metadata tag fields:
into a 3-bit abstract type and an 8-bit chunk field. Note that the value into a 3-bit abstract type and an 8-bit chunk field. Note that the value
`0x000` is invalid and not assigned a type. `0x000` is invalid and not assigned a type.
1. **Type1 (3-bits)** - Abstract type of the tag. Groups the tags into 3. **Type1 (3-bits)** - Abstract type of the tag. Groups the tags into
8 categories that facilitate bitmasked lookups. 8 categories that facilitate bitmasked lookups.
2. **Chunk (8-bits)** - Chunk field used for various purposes by the different 4. **Chunk (8-bits)** - Chunk field used for various purposes by the different
abstract types. type1+chunk+id form a unique identifier for each tag in the abstract types. type1+chunk+id form a unique identifier for each tag in the
metadata block. metadata block.
3. **Id (10-bits)** - File id associated with the tag. Each file in a metadata 5. **Id (10-bits)** - File id associated with the tag. Each file in a metadata
block gets a unique id which is used to associate tags with that file. The block gets a unique id which is used to associate tags with that file. The
special value `0x3ff` is used for any tags that are not associated with a special value `0x3ff` is used for any tags that are not associated with a
file, such as directory and global metadata. file, such as directory and global metadata.
4. **Length (10-bits)** - Length of the data in bytes. The special value 6. **Length (10-bits)** - Length of the data in bytes. The special value
`0x3ff` indicates that this tag has been deleted. `0x3ff` indicates that this tag has been deleted.
## Metadata types ## Metadata types

View File

@@ -1,6 +1,7 @@
/* /*
* Block device emulated in a file * Block device emulated in a file
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@@ -80,7 +81,7 @@ int lfs_filebd_read(const struct lfs_config *cfg, lfs_block_t block,
LFS_ASSERT(size % cfg->read_size == 0); LFS_ASSERT(size % cfg->read_size == 0);
LFS_ASSERT(block < cfg->block_count); LFS_ASSERT(block < cfg->block_count);
// zero for reproducibility (in case file is truncated) // zero for reproducability (in case file is truncated)
if (bd->cfg->erase_value != -1) { if (bd->cfg->erase_value != -1) {
memset(buffer, bd->cfg->erase_value, size); memset(buffer, bd->cfg->erase_value, size);
} }

View File

@@ -1,6 +1,7 @@
/* /*
* Block device emulated in a file * Block device emulated in a file
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */

View File

@@ -1,6 +1,7 @@
/* /*
* Block device emulated in RAM * Block device emulated in RAM
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@@ -32,12 +33,10 @@ int lfs_rambd_createcfg(const struct lfs_config *cfg,
} }
} }
// zero for reproducibility? // zero for reproducability?
if (bd->cfg->erase_value != -1) { if (bd->cfg->erase_value != -1) {
memset(bd->buffer, bd->cfg->erase_value, memset(bd->buffer, bd->cfg->erase_value,
cfg->block_size * cfg->block_count); cfg->block_size * cfg->block_count);
} else {
memset(bd->buffer, 0, cfg->block_size * cfg->block_count);
} }
LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", 0); LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", 0);

View File

@@ -1,6 +1,7 @@
/* /*
* Block device emulated in RAM * Block device emulated in RAM
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */

View File

@@ -2,6 +2,7 @@
* Testing block device, wraps filebd and rambd while providing a bunch * Testing block device, wraps filebd and rambd while providing a bunch
* of hooks for testing littlefs in various conditions. * of hooks for testing littlefs in various conditions.
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */

View File

@@ -2,6 +2,7 @@
* Testing block device, wraps filebd and rambd while providing a bunch * Testing block device, wraps filebd and rambd while providing a bunch
* of hooks for testing littlefs in various conditions. * of hooks for testing littlefs in various conditions.
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */

23
lfs.c
View File

@@ -1,6 +1,7 @@
/* /*
* The little filesystem * The little filesystem
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@@ -11,7 +12,6 @@
#define LFS_BLOCK_INLINE ((lfs_block_t)-2) #define LFS_BLOCK_INLINE ((lfs_block_t)-2)
/// Caching block device operations /// /// Caching block device operations ///
static inline void lfs_cache_drop(lfs_t *lfs, lfs_cache_t *rcache) { static inline void lfs_cache_drop(lfs_t *lfs, lfs_cache_t *rcache) {
// do not zero, cheaper if cache is readonly or only going to be // do not zero, cheaper if cache is readonly or only going to be
// written with identical data (during relocates) // written with identical data (during relocates)
@@ -269,26 +269,22 @@ static inline int lfs_pair_cmp(
paira[0] == pairb[1] || paira[1] == pairb[0]); paira[0] == pairb[1] || paira[1] == pairb[0]);
} }
#ifndef LFS_READONLY
static inline bool lfs_pair_sync( static inline bool lfs_pair_sync(
const lfs_block_t paira[2], const lfs_block_t paira[2],
const lfs_block_t pairb[2]) { const lfs_block_t pairb[2]) {
return (paira[0] == pairb[0] && paira[1] == pairb[1]) || return (paira[0] == pairb[0] && paira[1] == pairb[1]) ||
(paira[0] == pairb[1] && paira[1] == pairb[0]); (paira[0] == pairb[1] && paira[1] == pairb[0]);
} }
#endif
static inline void lfs_pair_fromle32(lfs_block_t pair[2]) { static inline void lfs_pair_fromle32(lfs_block_t pair[2]) {
pair[0] = lfs_fromle32(pair[0]); pair[0] = lfs_fromle32(pair[0]);
pair[1] = lfs_fromle32(pair[1]); pair[1] = lfs_fromle32(pair[1]);
} }
#ifndef LFS_READONLY
static inline void lfs_pair_tole32(lfs_block_t pair[2]) { static inline void lfs_pair_tole32(lfs_block_t pair[2]) {
pair[0] = lfs_tole32(pair[0]); pair[0] = lfs_tole32(pair[0]);
pair[1] = lfs_tole32(pair[1]); pair[1] = lfs_tole32(pair[1]);
} }
#endif
// operations on 32-bit entry tags // operations on 32-bit entry tags
typedef uint32_t lfs_tag_t; typedef uint32_t lfs_tag_t;
@@ -370,7 +366,6 @@ static inline bool lfs_gstate_iszero(const lfs_gstate_t *a) {
return true; return true;
} }
#ifndef LFS_READONLY
static inline bool lfs_gstate_hasorphans(const lfs_gstate_t *a) { static inline bool lfs_gstate_hasorphans(const lfs_gstate_t *a) {
return lfs_tag_size(a->tag); return lfs_tag_size(a->tag);
} }
@@ -382,7 +377,6 @@ static inline uint8_t lfs_gstate_getorphans(const lfs_gstate_t *a) {
static inline bool lfs_gstate_hasmove(const lfs_gstate_t *a) { static inline bool lfs_gstate_hasmove(const lfs_gstate_t *a) {
return lfs_tag_type1(a->tag); return lfs_tag_type1(a->tag);
} }
#endif
static inline bool lfs_gstate_hasmovehere(const lfs_gstate_t *a, static inline bool lfs_gstate_hasmovehere(const lfs_gstate_t *a,
const lfs_block_t *pair) { const lfs_block_t *pair) {
@@ -395,13 +389,11 @@ static inline void lfs_gstate_fromle32(lfs_gstate_t *a) {
a->pair[1] = lfs_fromle32(a->pair[1]); a->pair[1] = lfs_fromle32(a->pair[1]);
} }
#ifndef LFS_READONLY
static inline void lfs_gstate_tole32(lfs_gstate_t *a) { static inline void lfs_gstate_tole32(lfs_gstate_t *a) {
a->tag = lfs_tole32(a->tag); a->tag = lfs_tole32(a->tag);
a->pair[0] = lfs_tole32(a->pair[0]); a->pair[0] = lfs_tole32(a->pair[0]);
a->pair[1] = lfs_tole32(a->pair[1]); a->pair[1] = lfs_tole32(a->pair[1]);
} }
#endif
// other endianness operations // other endianness operations
static void lfs_ctz_fromle32(struct lfs_ctz *ctz) { static void lfs_ctz_fromle32(struct lfs_ctz *ctz) {
@@ -425,7 +417,6 @@ static inline void lfs_superblock_fromle32(lfs_superblock_t *superblock) {
superblock->attr_max = lfs_fromle32(superblock->attr_max); superblock->attr_max = lfs_fromle32(superblock->attr_max);
} }
#ifndef LFS_READONLY
static inline void lfs_superblock_tole32(lfs_superblock_t *superblock) { static inline void lfs_superblock_tole32(lfs_superblock_t *superblock) {
superblock->version = lfs_tole32(superblock->version); superblock->version = lfs_tole32(superblock->version);
superblock->block_size = lfs_tole32(superblock->block_size); superblock->block_size = lfs_tole32(superblock->block_size);
@@ -434,7 +425,6 @@ static inline void lfs_superblock_tole32(lfs_superblock_t *superblock) {
superblock->file_max = lfs_tole32(superblock->file_max); superblock->file_max = lfs_tole32(superblock->file_max);
superblock->attr_max = lfs_tole32(superblock->attr_max); superblock->attr_max = lfs_tole32(superblock->attr_max);
} }
#endif
#ifndef LFS_NO_ASSERT #ifndef LFS_NO_ASSERT
static bool lfs_mlist_isopen(struct lfs_mlist *head, static bool lfs_mlist_isopen(struct lfs_mlist *head,
@@ -1460,7 +1450,7 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
} }
} }
// zero for reproducibility in case initial block is unreadable // zero for reproducability in case initial block is unreadable
dir->rev = 0; dir->rev = 0;
// rather than clobbering one of the blocks we just pretend // rather than clobbering one of the blocks we just pretend
@@ -1520,6 +1510,7 @@ static int lfs_dir_split(lfs_t *lfs,
lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount, lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,
lfs_mdir_t *source, uint16_t split, uint16_t end) { lfs_mdir_t *source, uint16_t split, uint16_t end) {
// create tail directory // create tail directory
lfs_alloc_ack(lfs);
lfs_mdir_t tail; lfs_mdir_t tail;
int err = lfs_dir_alloc(lfs, &tail); int err = lfs_dir_alloc(lfs, &tail);
if (err) { if (err) {
@@ -2740,6 +2731,7 @@ static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
} }
#endif #endif
#ifndef LFS_READONLY
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
if (file->flags & LFS_F_READING) { if (file->flags & LFS_F_READING) {
if (!(file->flags & LFS_F_INLINE)) { if (!(file->flags & LFS_F_INLINE)) {
@@ -2748,7 +2740,6 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
file->flags &= ~LFS_F_READING; file->flags &= ~LFS_F_READING;
} }
#ifndef LFS_READONLY
if (file->flags & LFS_F_WRITING) { if (file->flags & LFS_F_WRITING) {
lfs_off_t pos = file->pos; lfs_off_t pos = file->pos;
@@ -2815,10 +2806,10 @@ relocate:
file->pos = pos; file->pos = pos;
} }
#endif
return 0; return 0;
} }
#endif
#ifndef LFS_READONLY #ifndef LFS_READONLY
static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file) { static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file) {
@@ -3091,11 +3082,13 @@ static lfs_soff_t lfs_file_rawseek(lfs_t *lfs, lfs_file_t *file,
return npos; return npos;
} }
#ifndef LFS_READONLY
// write out everything beforehand, may be noop if rdonly // write out everything beforehand, may be noop if rdonly
int err = lfs_file_flush(lfs, file); int err = lfs_file_flush(lfs, file);
if (err) { if (err) {
return err; return err;
} }
#endif
// update pos // update pos
file->pos = npos; file->pos = npos;
@@ -4082,7 +4075,7 @@ static int lfs_fs_relocate(lfs_t *lfs,
lfs_fs_prepmove(lfs, 0x3ff, NULL); lfs_fs_prepmove(lfs, 0x3ff, NULL);
} }
// replace bad pair, either we clean up desync, or no desync occurred // replace bad pair, either we clean up desync, or no desync occured
lfs_pair_tole32(newpair); lfs_pair_tole32(newpair);
err = lfs_dir_commit(lfs, &parent, LFS_MKATTRS( err = lfs_dir_commit(lfs, &parent, LFS_MKATTRS(
{LFS_MKTAG_IF(moveid != 0x3ff, {LFS_MKTAG_IF(moveid != 0x3ff,

37
lfs.h
View File

@@ -1,6 +1,7 @@
/* /*
* The little filesystem * The little filesystem
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@@ -159,49 +160,49 @@ struct lfs_config {
// information to the block device operations // information to the block device operations
void *context; void *context;
// Read a region in a block. Negative error codes are propagated // Read a region in a block. Negative error codes are propogated
// to the user. // to the user.
int (*read)(const struct lfs_config *c, lfs_block_t block, int (*read)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size); lfs_off_t off, void *buffer, lfs_size_t size);
// Program a region in a block. The block must have previously // Program a region in a block. The block must have previously
// been erased. Negative error codes are propagated to the user. // been erased. Negative error codes are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad. // May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*prog)(const struct lfs_config *c, lfs_block_t block, int (*prog)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size); lfs_off_t off, const void *buffer, lfs_size_t size);
// Erase a block. A block must be erased before being programmed. // Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes // The state of an erased block is undefined. Negative error codes
// are propagated to the user. // are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad. // May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*erase)(const struct lfs_config *c, lfs_block_t block); int (*erase)(const struct lfs_config *c, lfs_block_t block);
// Sync the state of the underlying block device. Negative error codes // Sync the state of the underlying block device. Negative error codes
// are propagated to the user. // are propogated to the user.
int (*sync)(const struct lfs_config *c); int (*sync)(const struct lfs_config *c);
#ifdef LFS_THREADSAFE #ifdef LFS_THREADSAFE
// Lock the underlying block device. Negative error codes // Lock the underlying block device. Negative error codes
// are propagated to the user. // are propogated to the user.
int (*lock)(const struct lfs_config *c); int (*lock)(const struct lfs_config *c);
// Unlock the underlying block device. Negative error codes // Unlock the underlying block device. Negative error codes
// are propagated to the user. // are propogated to the user.
int (*unlock)(const struct lfs_config *c); int (*unlock)(const struct lfs_config *c);
#endif #endif
// Minimum size of a block read in bytes. All read operations will be a // Minimum size of a block read. All read operations will be a
// multiple of this value. // multiple of this value.
lfs_size_t read_size; lfs_size_t read_size;
// Minimum size of a block program in bytes. All program operations will be // Minimum size of a block program. All program operations will be a
// a multiple of this value. // multiple of this value.
lfs_size_t prog_size; lfs_size_t prog_size;
// Size of an erasable block in bytes. This does not impact ram consumption // Size of an erasable block. This does not impact ram consumption and
// and may be larger than the physical erase size. However, non-inlined // may be larger than the physical erase size. However, non-inlined files
// files take up at minimum one block. Must be a multiple of the read and // take up at minimum one block. Must be a multiple of the read
// program sizes. // and program sizes.
lfs_size_t block_size; lfs_size_t block_size;
// Number of erasable blocks on the device. // Number of erasable blocks on the device.
@@ -215,11 +216,11 @@ struct lfs_config {
// Set to -1 to disable block-level wear-leveling. // Set to -1 to disable block-level wear-leveling.
int32_t block_cycles; int32_t block_cycles;
// Size of block caches in bytes. Each cache buffers a portion of a block in // Size of block caches. Each cache buffers a portion of a block in RAM.
// RAM. The littlefs needs a read cache, a program cache, and one additional // The littlefs needs a read cache, a program cache, and one additional
// cache per file. Larger caches can improve performance by storing more // cache per file. Larger caches can improve performance by storing more
// data and reducing the number of disk accesses. Must be a multiple of the // data and reducing the number of disk accesses. Must be a multiple of
// read and program sizes, and a factor of the block size. // the read and program sizes, and a factor of the block size.
lfs_size_t cache_size; lfs_size_t cache_size;
// Size of the lookahead buffer in bytes. A larger lookahead buffer // Size of the lookahead buffer in bytes. A larger lookahead buffer
@@ -485,7 +486,7 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
// Returns the size of the attribute, or a negative error code on failure. // Returns the size of the attribute, or a negative error code on failure.
// Note, the returned size is the size of the attribute on disk, irrespective // Note, the returned size is the size of the attribute on disk, irrespective
// of the size of the buffer. This can be used to dynamically allocate a buffer // of the size of the buffer. This can be used to dynamically allocate a buffer
// or check for existence. // or check for existance.
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
uint8_t type, void *buffer, lfs_size_t size); uint8_t type, void *buffer, lfs_size_t size);

View File

@@ -1,6 +1,7 @@
/* /*
* lfs util functions * lfs util functions
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */

View File

@@ -1,6 +1,7 @@
/* /*
* lfs utility functions * lfs utility functions
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */

View File

@@ -565,7 +565,7 @@ class TestSuite:
path=self.path)) path=self.path))
mk.write('\n') mk.write('\n')
# add truly global defines globally # add truely global defines globally
for k, v in sorted(self.defines.items()): for k, v in sorted(self.defines.items()):
mk.write('%s.test: override CFLAGS += -D%s=%r\n' mk.write('%s.test: override CFLAGS += -D%s=%r\n'
% (self.path, k, v)) % (self.path, k, v))
@@ -656,7 +656,7 @@ def main(**args):
for path in glob.glob(testpath): for path in glob.glob(testpath):
suites.append(TestSuite(path, classes, defines, filter, **args)) suites.append(TestSuite(path, classes, defines, filter, **args))
# sort for reproducibility # sort for reproducability
suites = sorted(suites) suites = sorted(suites)
# generate permutations # generate permutations