mirror of
https://gitee.com/openharmony/third_party_littlefs
synced 2025-02-09 01:07:39 +00:00
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.
This commit is contained in:
parent
10f45ac02f
commit
20b669a23d
12
lfs.c
12
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;
|
||||
|
22
lfs_util.h
22
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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user