Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/littlefs-project/littlefs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Haster <chaster@utexas.edu>2018-08-08 17:37:43 +0300
committerChristopher Haster <chaster@utexas.edu>2018-10-17 04:53:25 +0300
commit20b669a23d50bf191dc7225527487f9148122b8c (patch)
treebdf581647c33eb7f4e470a97ee610583dfe108c3
parent10f45ac02f246c44b066d85dacd7cb43c0b7a521 (diff)
Fixed issue with big-endian CTZ lists intertwined in commit logic
Found while testing big-endian support. Basically, if littlefs is really really unlucky, the block allocator could kick in while committing a file's CTZ reference. If this happens, the block allocator will need to traverse all CTZ skip-lists in memory, including the skip-list we're committing. This means we can't convert the CTZ's endianness in place, and need to make a copy on big-endian systems. We rely on dead-code elimination from the compiler to make the conditional behaviour for big-endian vs little-endian system a noop determined by the lfs_tole32 intrinsic.
-rw-r--r--lfs.c12
-rw-r--r--lfs_util.h22
2 files changed, 18 insertions, 16 deletions
diff --git a/lfs.c b/lfs.c
index a950c4a..faa5bbe 100644
--- a/lfs.c
+++ b/lfs.c
@@ -2199,25 +2199,27 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
uint16_t type;
const void *buffer;
lfs_size_t size;
+ struct lfs_ctz ctz;
if (file->flags & LFS_F_INLINE) {
// inline the whole file
type = LFS_TYPE_INLINESTRUCT;
buffer = file->cache.buffer;
size = file->ctz.size;
- } else {
+ } else if (lfs_tole32(0x11223344) == 0x11223344) {
// update the ctz reference
type = LFS_TYPE_CTZSTRUCT;
- buffer = &file->ctz;
- size = sizeof(file->ctz);
+ // copy ctz so alloc will work during a relocate
+ ctz = file->ctz;
+ lfs_ctz_tole32(&ctz);
+ buffer = &ctz;
+ size = sizeof(ctz);
}
// commit file data and attributes
- lfs_ctz_tole32(&file->ctz);
err = lfs_dir_commit(lfs, &file->m,
LFS_MKATTR(type, file->id, buffer, size,
LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0,
NULL)));
- lfs_ctz_fromle32(&file->ctz);
if (err) {
if (err == LFS_ERR_NOSPC && (file->flags & LFS_F_INLINE)) {
goto relocate;
diff --git a/lfs_util.h b/lfs_util.h
index 80b4002..8a65694 100644
--- a/lfs_util.h
+++ b/lfs_util.h
@@ -11,8 +11,8 @@
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
//
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
-// provided by the config file. To start I would suggest copying lfs_util.h and
-// modifying as needed.
+// provided by the config file. To start, I would suggest copying lfs_util.h
+// and modifying as needed.
#ifdef LFS_CONFIG
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
#define LFS_STRINGIZE2(x) #x
@@ -88,6 +88,15 @@ static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
return (a < b) ? a : b;
}
+// Align to nearest multiple of a size
+static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
+ return a - (a % alignment);
+}
+
+static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
+ return lfs_aligndown(a + alignment-1, alignment);
+}
+
// Find the next smallest power of 2 less than or equal to a
static inline uint32_t lfs_npw2(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
@@ -177,15 +186,6 @@ static inline uint16_t lfs_tole16(uint16_t a) {
return lfs_fromle16(a);
}
-// Align to nearest multiple of a size
-static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
- return a - (a % alignment);
-}
-
-static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
- return lfs_aligndown(a + alignment-1, alignment);
-}
-
// Calculate CRC-32 with polynomial = 0x04c11db7
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);