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);