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-02 02:10:24 +0300
committerChristopher Haster <chaster@utexas.edu>2018-10-16 16:03:30 +0300
commit112fefc068c0f2d2d16967490283dd3db7d30529 (patch)
tree2ecc1d433d02b496a34777fed4e4844c2cb1dd2e
parent64df0a5e2092a86745def995b44298881a864b93 (diff)
Added back big-endian support again on the new metadata structures
The only interesting thing to note is that we now have to also support le16 due to storing the id outside of tags in the globals structure.
-rw-r--r--lfs.c189
-rw-r--r--lfs_util.h25
2 files changed, 131 insertions, 83 deletions
diff --git a/lfs.c b/lfs.c
index 25c9a57..439fbc1 100644
--- a/lfs.c
+++ b/lfs.c
@@ -264,7 +264,7 @@ static int lfs_pred(lfs_t *lfs, const lfs_block_t dir[2], lfs_mdir_t *pdir);
static int32_t lfs_parent(lfs_t *lfs, const lfs_block_t dir[2],
lfs_mdir_t *parent);
static int lfs_relocate(lfs_t *lfs,
- const lfs_block_t oldpair[2], const lfs_block_t newpair[2]);
+ const lfs_block_t oldpair[2], lfs_block_t newpair[2]);
int lfs_scan(lfs_t *lfs);
int lfs_fixmove(lfs_t *lfs);
int lfs_forceconsistency(lfs_t *lfs);
@@ -332,74 +332,6 @@ static void lfs_alloc_ack(lfs_t *lfs) {
}
-/// Endian swapping functions ///
-//static void lfs_dir_fromle32(struct lfs_disk_dir *d) {
-// d->rev = lfs_fromle32(d->rev);
-// d->size = lfs_fromle32(d->size);
-// d->tail[0] = lfs_fromle32(d->tail[0]);
-// d->tail[1] = lfs_fromle32(d->tail[1]);
-//}
-//
-//static void lfs_mdir_tole32(struct lfs_disk_dir *d) {
-// d->rev = lfs_tole32(d->rev);
-// d->size = lfs_tole32(d->size);
-// d->tail[0] = lfs_tole32(d->tail[0]);
-// d->tail[1] = lfs_tole32(d->tail[1]);
-//}
-//
-//static void lfs_entry_fromle32(struct lfs_disk_entry *d) {
-// d->u.dir[0] = lfs_fromle32(d->u.dir[0]);
-// d->u.dir[1] = lfs_fromle32(d->u.dir[1]);
-//}
-//
-//static void lfs_entry_tole32(struct lfs_disk_entry *d) {
-// d->u.dir[0] = lfs_tole32(d->u.dir[0]);
-// d->u.dir[1] = lfs_tole32(d->u.dir[1]);
-//}
-
-///*static*/ void lfs_superblock_fromle32(struct lfs_disk_superblock *d) {
-// d->root[0] = lfs_fromle32(d->root[0]);
-// d->root[1] = lfs_fromle32(d->root[1]);
-// d->block_size = lfs_fromle32(d->block_size);
-// d->block_count = lfs_fromle32(d->block_count);
-// d->version = lfs_fromle32(d->version);
-// d->inline_size = lfs_fromle32(d->inline_size);
-// d->attr_size = lfs_fromle32(d->attr_size);
-// d->name_size = lfs_fromle32(d->name_size);
-//}
-//
-///*static*/ void lfs_superblock_tole32(struct lfs_disk_superblock *d) {
-// d->root[0] = lfs_tole32(d->root[0]);
-// d->root[1] = lfs_tole32(d->root[1]);
-// d->block_size = lfs_tole32(d->block_size);
-// d->block_count = lfs_tole32(d->block_count);
-// d->version = lfs_tole32(d->version);
-// d->inline_size = lfs_tole32(d->inline_size);
-// d->attr_size = lfs_tole32(d->attr_size);
-// d->name_size = lfs_tole32(d->name_size);
-//}
-
-/// Other struct functions ///
-//static inline lfs_size_t lfs_entry_elen(const lfs_mattr_t *attr) {
-// return (lfs_size_t)(attr->d.elen) |
-// ((lfs_size_t)(attr->d.alen & 0xc0) << 2);
-//}
-//
-//static inline lfs_size_t lfs_entry_alen(const lfs_mattr_t *attr) {
-// return attr->d.alen & 0x3f;
-//}
-//
-//static inline lfs_size_t lfs_entry_nlen(const lfs_mattr_t *attr) {
-// return attr->d.nlen;
-//}
-//
-//static inline lfs_size_t lfs_entry_size(const lfs_mattr_t *attr) {
-// return 4 + lfs_entry_elen(attr) +
-// lfs_entry_alen(attr) +
-// lfs_entry_nlen(attr);
-//}
-
-
/// Metadata pair and directory operations ///
static inline void lfs_pairswap(lfs_block_t pair[2]) {
lfs_block_t t = pair[0];
@@ -425,6 +357,27 @@ static inline bool lfs_pairsync(
(paira[0] == pairb[1] && paira[1] == pairb[0]);
}
+static inline void lfs_pairfromle32(lfs_block_t *pair) {
+ pair[0] = lfs_fromle32(pair[0]);
+ pair[1] = lfs_fromle32(pair[1]);
+}
+
+static inline void lfs_pairtole32(lfs_block_t *pair) {
+ pair[0] = lfs_tole32(pair[0]);
+ pair[1] = lfs_tole32(pair[1]);
+}
+
+static void lfs_ctzfromle32(struct lfs_ctz *ctz) {
+ ctz->head = lfs_fromle32(ctz->head);
+ ctz->size = lfs_fromle32(ctz->size);
+}
+
+static void lfs_ctztole32(struct lfs_ctz *ctz) {
+ ctz->head = lfs_tole32(ctz->head);
+ ctz->size = lfs_tole32(ctz->size);
+}
+
+
/// Entry tag operations ///
#define LFS_MKTAG(type, id, size) \
(((uint32_t)(type) << 22) | ((uint32_t)(id) << 12) | (uint32_t)(size))
@@ -492,6 +445,16 @@ static inline void lfs_globalxordeorphaned(lfs_global_t *a, bool deorphaned) {
a->u16[0] ^= deorphaned << 15;
}
+static inline void lfs_globalfromle32(lfs_global_t *a) {
+ a->u16[0] = lfs_fromle16(a->u16[0]);
+ lfs_pairfromle32((lfs_block_t*)&a->u16[1]);
+}
+
+static inline void lfs_globaltole32(lfs_global_t *a) {
+ a->u16[0] = lfs_tole16(a->u16[0]);
+ lfs_pairtole32((lfs_block_t*)&a->u16[1]);
+}
+
static inline const lfs_block_t *lfs_globalmovepair(const lfs_t *lfs) {
return (const lfs_block_t*)&lfs->globals.u16[1];
}
@@ -510,13 +473,17 @@ static inline void lfs_globalmove(lfs_t *lfs,
lfs_globalzero(&diff);
lfs_globalxormove(&diff, lfs_globalmovepair(lfs), lfs_globalmoveid(lfs));
lfs_globalxormove(&diff, pair, id);
+ lfs_globalfromle32(&lfs->locals);
lfs_globalxor(&lfs->locals, &diff);
+ lfs_globaltole32(&lfs->locals);
lfs_globalxor(&lfs->globals, &diff);
}
static inline void lfs_globaldeorphaned(lfs_t *lfs, bool deorphaned) {
deorphaned ^= lfs_globalisdeorphaned(lfs);
+ lfs_globalfromle32(&lfs->locals);
lfs_globalxordeorphaned(&lfs->locals, deorphaned);
+ lfs_globaltole32(&lfs->locals);
lfs_globalxordeorphaned(&lfs->globals, deorphaned);
}
@@ -748,7 +715,8 @@ static int lfs_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
}
// build crc tag
- tag = (0x80000000 & ~lfs_fromle32(tag)) |
+ tag = lfs_fromle32(tag);
+ tag = (0x80000000 & ~tag) |
LFS_MKTAG(LFS_TYPE_CRC, 0x3ff,
off - (commit->off+sizeof(uint32_t)));
@@ -907,9 +875,11 @@ static int lfs_dir_compact(lfs_t *lfs,
if (!lfs_pairisnull(dir->tail)) {
// commit tail, which may be new after last size check
// TODO le32
+ lfs_pairtole32(dir->tail);
err = lfs_commitattr(lfs, &commit,
LFS_MKTAG(LFS_TYPE_TAIL + dir->split,
0x3ff, sizeof(dir->tail)), dir->tail);
+ lfs_pairfromle32(dir->tail);
if (err) {
if (err == LFS_ERR_CORRUPT) {
goto relocate;
@@ -1025,7 +995,9 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
lfs_globalmovepair(lfs), lfs_globalmoveid(lfs));
lfs_globalxormove(&canceldiff,
(lfs_block_t[2]){0xffffffff, 0xffffffff}, 0x3ff);
+ lfs_globalfromle32(&lfs->locals);
lfs_globalxor(&lfs->locals, &canceldiff);
+ lfs_globaltole32(&lfs->locals);
cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs_globalmoveid(lfs), 0);
cancelattr.next = attrs;
@@ -1089,7 +1061,9 @@ compact:
for (const lfs_mattr_t *a = attrs; a; a = a->next) {
if (lfs_tagtype(a->tag) != LFS_TYPE_DELETE) {
+ lfs_pairtole32(dir->tail);
int err = lfs_commitattr(lfs, &commit, a->tag, a->buffer);
+ lfs_pairfromle32(dir->tail);
if (err) {
if (err == LFS_ERR_NOSPC || err == LFS_ERR_CORRUPT) {
goto compact;
@@ -1173,10 +1147,10 @@ static int32_t lfs_dir_find(lfs_t *lfs,
uint32_t rev[2];
for (int i = 0; i < 2; i++) {
int err = lfs_bd_read(lfs, dir->pair[i], 0, &rev[i], sizeof(rev[i]));
- rev[i] = lfs_fromle32(rev[i]);
if (err) {
return err;
}
+ rev[i] = lfs_fromle32(rev[i]);
}
if (lfs_scmp(rev[1], rev[0]) > 0) {
@@ -1234,8 +1208,9 @@ static int32_t lfs_dir_find(lfs_t *lfs,
if (err) {
return err;
}
+ dcrc = lfs_fromle32(dcrc);
- if (crc != lfs_fromle32(dcrc)) {
+ if (crc != dcrc) {
dir->erased = false;
break;
}
@@ -1268,6 +1243,7 @@ static int32_t lfs_dir_find(lfs_t *lfs,
if (err) {
return err;
}
+ lfs_pairfromle32(temptail);
} else if (lfs_tagtype(tag) == LFS_TYPE_GLOBALS) {
err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag),
&templocals, sizeof(templocals));
@@ -1417,6 +1393,7 @@ nextname:
if (res < 0) {
return res;
}
+ lfs_pairfromle32(pair);
}
// find entry matching name
@@ -1462,6 +1439,7 @@ static int lfs_dir_getinfo(lfs_t *lfs, lfs_mdir_t *dir,
if (tag < 0) {
return tag;
}
+ lfs_ctzfromle32(&ctz);
if (lfs_tagtype(tag) == LFS_TYPE_CTZSTRUCT) {
info->size = ctz.size;
@@ -1510,11 +1488,13 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
uint16_t id = cwd.count;
cwd.tail[0] = dir.pair[0];
cwd.tail[1] = dir.pair[1];
+ lfs_pairtole32(dir.pair);
err = lfs_dir_commit(lfs, &cwd,
LFS_MKATTR(LFS_TYPE_DIR, id, path, nlen,
LFS_MKATTR(LFS_TYPE_DIRSTRUCT, id, dir.pair, sizeof(dir.pair),
LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, cwd.tail, sizeof(cwd.tail),
NULL))));
+ lfs_pairfromle32(dir.pair);
if (err) {
return err;
}
@@ -1546,6 +1526,7 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
if (res < 0) {
return res;
}
+ lfs_pairfromle32(pair);
}
// fetch first pair
@@ -1929,6 +1910,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
if (tag < 0) {
return tag;
}
+ lfs_ctzfromle32(&file->ctz);
}
// setup file struct
@@ -2170,14 +2152,28 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
return err;
}
- // either update the references or inline the whole file
+ uint16_t type;
+ const void *buffer;
+ lfs_size_t size;
+ if (file->flags & LFS_F_INLINE) {
+ // inline the whole file
+ type = LFS_TYPE_INLINESTRUCT;
+ buffer = file->cache.buffer;
+ size = file->ctz.size;
+ } else {
+ // update the ctz reference
+ type = LFS_TYPE_CTZSTRUCT;
+ buffer = &file->ctz;
+ size = sizeof(file->ctz);
+ }
+
+ // commit file data and attributes
+ lfs_ctztole32(&file->ctz);
int err = lfs_dir_commit(lfs, &cwd,
+ LFS_MKATTR(type, file->id, buffer, size,
LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0,
- (file->flags & LFS_F_INLINE) ?
- LFS_MKATTR(LFS_TYPE_INLINESTRUCT, file->id,
- file->cache.buffer, file->ctz.size, NULL) :
- LFS_MKATTR(LFS_TYPE_CTZSTRUCT, file->id,
- &file->ctz.head, sizeof(file->ctz), NULL)));
+ NULL)));
+ lfs_ctzfromle32(&file->ctz);
if (err) {
if (err == LFS_ERR_NOSPC && (file->flags & LFS_F_INLINE)) {
goto relocate;
@@ -2619,6 +2615,7 @@ int lfs_remove(lfs_t *lfs, const char *path) {
if (res < 0) {
return res;
}
+ lfs_pairfromle32(pair);
int err = lfs_dir_fetch(lfs, &dir, pair);
if (err) {
@@ -2708,6 +2705,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
if (res < 0) {
return res;
}
+ lfs_pairfromle32(prevpair);
// must be empty before removal
int err = lfs_dir_fetch(lfs, &prevdir, prevpair);
@@ -2920,6 +2918,24 @@ int lfs_fs_setattr(lfs_t *lfs,
/// Filesystem operations ///
+static inline void lfs_superblockfromle32(lfs_superblock_t *superblock) {
+ superblock->version = lfs_fromle32(superblock->version);
+ superblock->block_size = lfs_fromle32(superblock->block_size);
+ superblock->block_count = lfs_fromle32(superblock->block_count);
+ superblock->inline_size = lfs_fromle32(superblock->inline_size);
+ superblock->attr_size = lfs_fromle32(superblock->attr_size);
+ superblock->name_size = lfs_fromle32(superblock->name_size);
+}
+
+static inline void lfs_superblocktole32(lfs_superblock_t *superblock) {
+ superblock->version = lfs_tole32(superblock->version);
+ superblock->block_size = lfs_tole32(superblock->block_size);
+ superblock->block_count = lfs_tole32(superblock->block_count);
+ superblock->inline_size = lfs_tole32(superblock->inline_size);
+ superblock->attr_size = lfs_tole32(superblock->attr_size);
+ superblock->name_size = lfs_tole32(superblock->name_size);
+}
+
static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->cfg = cfg;
@@ -3070,10 +3086,14 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
.name_size = lfs->name_size,
};
+ lfs_superblocktole32(&superblock);
+ lfs_pairtole32(lfs->root);
err = lfs_dir_commit(lfs, &dir,
LFS_MKATTR(LFS_TYPE_SUPERBLOCK, 0, &superblock, sizeof(superblock),
LFS_MKATTR(LFS_TYPE_DIRSTRUCT, 0, lfs->root, sizeof(lfs->root),
NULL)));
+ lfs_pairfromle32(lfs->root);
+ lfs_superblockfromle32(&superblock);
if (err) {
return err;
}
@@ -3116,6 +3136,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
if (res < 0) {
return res;
}
+ lfs_superblockfromle32(&superblock);
if (memcmp(superblock.magic, "littlefs", 8) != 0) {
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
@@ -3136,6 +3157,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
if (res < 0) {
return res;
}
+ lfs_pairfromle32(lfs->root);
if (superblock.inline_size) {
if (superblock.inline_size > lfs->inline_size) {
@@ -3213,6 +3235,7 @@ int lfs_fs_traverse(lfs_t *lfs,
}
return tag;
}
+ lfs_ctzfromle32(&ctz);
if (lfs_tagtype(tag) == LFS_TYPE_CTZSTRUCT) {
int err = lfs_ctztraverse(lfs, &lfs->rcache, NULL,
@@ -3352,7 +3375,7 @@ static int32_t lfs_parent(lfs_t *lfs, const lfs_block_t pair[2],
// search for both orderings so we can reuse the find function
lfs_block_t child[2] = {pair[0], pair[1]};
-
+ lfs_pairtole32(child);
for (int i = 0; i < 2; i++) {
// iterate over all directory directory entries
parent->tail[0] = 0;
@@ -3374,7 +3397,7 @@ static int32_t lfs_parent(lfs_t *lfs, const lfs_block_t pair[2],
// TODO rename to lfs_dir_relocate?
static int lfs_relocate(lfs_t *lfs,
- const lfs_block_t oldpair[2], const lfs_block_t newpair[2]) {
+ const lfs_block_t oldpair[2], lfs_block_t newpair[2]) {
// TODO name lfs_dir_relocate?
// find parent
lfs_mdir_t parent;
@@ -3385,8 +3408,10 @@ static int lfs_relocate(lfs_t *lfs,
if (tag != LFS_ERR_NOENT) {
// update disk, this creates a desync
+ lfs_pairtole32(newpair);
int err = lfs_dir_commit(lfs, &parent,
&(lfs_mattr_t){.tag=tag, .buffer=newpair});
+ lfs_pairfromle32(newpair);
if (err) {
return err;
}
@@ -3415,7 +3440,7 @@ static int lfs_relocate(lfs_t *lfs,
parent.tail[1] = newpair[1];
int err = lfs_dir_commit(lfs, &parent,
LFS_MKATTR(LFS_TYPE_TAIL + parent.split, 0x3ff,
- newpair, sizeof(lfs_block_t[2]),
+ parent.tail, sizeof(parent.tail),
NULL));
if (err) {
return err;
@@ -3447,6 +3472,7 @@ int lfs_scan(lfs_t *lfs) {
// update littlefs with globals
// TODO does this only run once?
// TODO Should we inline this into init??
+ lfs_globalfromle32(&lfs->locals);
lfs_globalxor(&lfs->globals, &lfs->locals);
lfs_globalzero(&lfs->locals);
if (!lfs_pairisnull(lfs_globalmovepair(lfs))) {
@@ -3504,6 +3530,7 @@ int lfs_forceconsistency(lfs_t *lfs) {
if (res < 0) {
return res;
}
+ lfs_pairfromle32(pair);
if (!lfs_pairsync(pair, pdir.tail)) {
// we have desynced
diff --git a/lfs_util.h b/lfs_util.h
index ecd5dd3..6a577eb 100644
--- a/lfs_util.h
+++ b/lfs_util.h
@@ -136,7 +136,7 @@ static inline int lfs_scmp(uint32_t a, uint32_t b) {
return (int)(unsigned)(a - b);
}
-// Convert from 32-bit little-endian to native order
+// Convert between 32-bit little-endian and native order
static inline uint32_t lfs_fromle32(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && ( \
(defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
@@ -156,11 +156,32 @@ static inline uint32_t lfs_fromle32(uint32_t a) {
#endif
}
-// Convert to 32-bit little-endian from native order
static inline uint32_t lfs_tole32(uint32_t a) {
return lfs_fromle32(a);
}
+// Convert between 16-bit little-endian and native order
+static inline uint16_t lfs_fromle16(uint16_t a) {
+#if !defined(LFS_NO_INTRINSICS) && ( \
+ (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
+ (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
+ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
+ return a;
+#elif !defined(LFS_NO_INTRINSICS) && ( \
+ (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
+ (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
+ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
+ return __builtin_bswap16(a);
+#else
+ return (((uint8_t*)&a)[0] << 0) |
+ (((uint8_t*)&a)[1] << 8);
+#endif
+}
+
+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_alignup(uint32_t a, uint32_t alignment) {
return (a + alignment-1) - ((a + alignment-1) % alignment);