mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Simplified the internal xored-globals implementation
There wasn't much use (and inconsistent compiler support) for storing small values next to the unaligned lfs_global_t struct. So instead, I've rounded the struct up to the nearest word to try to take advantage of the alignment in xor and memset operations. I've also moved the global fetching into lfs_mount, since that was the only use of the operation. This allows for some variable reuse in the mount function.
This commit is contained in:
		
							
								
								
									
										165
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										165
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -265,7 +265,6 @@ static int32_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t dir[2], | |||||||
|         lfs_mdir_t *parent); |         lfs_mdir_t *parent); | ||||||
| static int lfs_fs_relocate(lfs_t *lfs, | static int lfs_fs_relocate(lfs_t *lfs, | ||||||
|         const lfs_block_t oldpair[2], lfs_block_t newpair[2]); |         const lfs_block_t oldpair[2], lfs_block_t newpair[2]); | ||||||
| static int lfs_fs_scan(lfs_t *lfs); |  | ||||||
| static int lfs_fs_forceconsistency(lfs_t *lfs); | static int lfs_fs_forceconsistency(lfs_t *lfs); | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -410,14 +409,14 @@ static inline lfs_size_t lfs_tagsize(uint32_t tag) { | |||||||
|  |  | ||||||
| // operations on set of globals | // operations on set of globals | ||||||
| static inline void lfs_globalxor(lfs_global_t *a, const lfs_global_t *b) { | static inline void lfs_globalxor(lfs_global_t *a, const lfs_global_t *b) { | ||||||
|     for (int i = 0; i < sizeof(lfs_global_t)/2; i++) { |     for (int i = 0; i < sizeof(lfs_global_t)/4; i++) { | ||||||
|         a->u16[i] ^= b->u16[i]; |         a->u32[i] ^= b->u32[i]; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline bool lfs_globaliszero(const lfs_global_t *a) { | static inline bool lfs_globaliszero(const lfs_global_t *a) { | ||||||
|     for (int i = 0; i < sizeof(lfs_global_t)/2; i++) { |     for (int i = 0; i < sizeof(lfs_global_t)/4; i++) { | ||||||
|         if (a->u16[i] != 0) { |         if (a->u32[i] != 0) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -425,53 +424,26 @@ static inline bool lfs_globaliszero(const lfs_global_t *a) { | |||||||
| } | } | ||||||
|  |  | ||||||
| static inline void lfs_globalzero(lfs_global_t *a) { | static inline void lfs_globalzero(lfs_global_t *a) { | ||||||
|     memset(a->u16, 0x00, sizeof(lfs_global_t)); |     lfs_globalxor(a, a); | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline void lfs_globalones(lfs_global_t *a) { |  | ||||||
|     memset(a->u16, 0xff, sizeof(lfs_global_t)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline void lfs_globalxormove(lfs_global_t *a, |  | ||||||
|         const lfs_block_t pair[2], uint16_t id) { |  | ||||||
|     a->u16[0] ^= id; |  | ||||||
|     for (int i = 0; i < sizeof(lfs_block_t[2])/2; i++) { |  | ||||||
|         a->u16[1+i] ^= ((uint16_t*)pair)[i]; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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) { | static inline void lfs_globalfromle32(lfs_global_t *a) { | ||||||
|     a->u16[0] = lfs_fromle16(a->u16[0]); |     lfs_pairfromle32(a->s.movepair); | ||||||
|     lfs_pairfromle32((lfs_block_t*)&a->u16[1]); |     a->s.moveid = lfs_fromle16(a->s.moveid); | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline void lfs_globaltole32(lfs_global_t *a) { | static inline void lfs_globaltole32(lfs_global_t *a) { | ||||||
|     a->u16[0] = lfs_tole16(a->u16[0]); |     lfs_pairtole32(a->s.movepair); | ||||||
|     lfs_pairtole32((lfs_block_t*)&a->u16[1]); |     a->s.moveid = lfs_tole16(a->s.moveid); | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline const lfs_block_t *lfs_globalmovepair(const lfs_t *lfs) { |  | ||||||
|     return (const lfs_block_t*)&lfs->globals.u16[1]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline uint16_t lfs_globalmoveid(const lfs_t *lfs) { |  | ||||||
|     return 0x3ff & lfs->globals.u16[0]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline bool lfs_globalisdeorphaned(const lfs_t *lfs) { |  | ||||||
|     return 0x8000 & lfs->globals.u16[0]; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline void lfs_globalmove(lfs_t *lfs, | static inline void lfs_globalmove(lfs_t *lfs, | ||||||
|         const lfs_block_t pair[2], uint16_t id) { |         const lfs_block_t pair[2], uint16_t id) { | ||||||
|     lfs_global_t diff; |     lfs_global_t diff; | ||||||
|     lfs_globalzero(&diff); |     lfs_globalzero(&diff); | ||||||
|     lfs_globalxormove(&diff, lfs_globalmovepair(lfs), lfs_globalmoveid(lfs)); |     diff.s.movepair[0] ^= lfs->globals.s.movepair[0] ^ pair[0]; | ||||||
|     lfs_globalxormove(&diff, pair, id); |     diff.s.movepair[1] ^= lfs->globals.s.movepair[1] ^ pair[1]; | ||||||
|  |     diff.s.moveid      ^= lfs->globals.s.moveid      ^ id; | ||||||
|     lfs_globalfromle32(&lfs->locals); |     lfs_globalfromle32(&lfs->locals); | ||||||
|     lfs_globalxor(&lfs->locals, &diff); |     lfs_globalxor(&lfs->locals, &diff); | ||||||
|     lfs_globaltole32(&lfs->locals); |     lfs_globaltole32(&lfs->locals); | ||||||
| @@ -479,11 +451,8 @@ static inline void lfs_globalmove(lfs_t *lfs, | |||||||
| } | } | ||||||
|  |  | ||||||
| static inline void lfs_globaldeorphaned(lfs_t *lfs, bool deorphaned) { | static inline void lfs_globaldeorphaned(lfs_t *lfs, bool deorphaned) { | ||||||
|     deorphaned ^= lfs_globalisdeorphaned(lfs); |     lfs->locals.s.deorphaned  ^= lfs->globals.s.deorphaned ^ deorphaned; | ||||||
|     lfs_globalfromle32(&lfs->locals); |     lfs->globals.s.deorphaned ^= lfs->globals.s.deorphaned ^ deorphaned; | ||||||
|     lfs_globalxordeorphaned(&lfs->locals, deorphaned); |  | ||||||
|     lfs_globaltole32(&lfs->locals); |  | ||||||
|     lfs_globalxordeorphaned(&lfs->globals, deorphaned); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -696,7 +665,8 @@ static int lfs_commitglobals(lfs_t *lfs, struct lfs_commit *commit, | |||||||
|  |  | ||||||
|     lfs_globalxor(locals, &lfs->locals); |     lfs_globalxor(locals, &lfs->locals); | ||||||
|     int err = lfs_commitattr(lfs, commit, |     int err = lfs_commitattr(lfs, commit, | ||||||
|             LFS_MKTAG(LFS_TYPE_GLOBALS, 0x3ff, sizeof(lfs_global_t)), locals); |             LFS_MKTAG(LFS_TYPE_GLOBALS + locals->s.deorphaned, | ||||||
|  |                 0x3ff, sizeof(lfs_global_t)), locals); | ||||||
|     lfs_globalxor(locals, &lfs->locals); |     lfs_globalxor(locals, &lfs->locals); | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
| @@ -893,6 +863,7 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|                     } |                     } | ||||||
|                     lfs_pairfromle32(temptail); |                     lfs_pairfromle32(temptail); | ||||||
|                 } else if (lfs_tagsubtype(tag) == LFS_TYPE_GLOBALS) { |                 } else if (lfs_tagsubtype(tag) == LFS_TYPE_GLOBALS) { | ||||||
|  |                     templocals.s.deorphaned = (lfs_tagtype(tag) & 1); | ||||||
|                     err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag), |                     err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag), | ||||||
|                             &templocals, sizeof(templocals)); |                             &templocals, sizeof(templocals)); | ||||||
|                     if (err) { |                     if (err) { | ||||||
| @@ -929,11 +900,11 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|         // consider what we have good enough |         // consider what we have good enough | ||||||
|         if (dir->off > 0) { |         if (dir->off > 0) { | ||||||
|             // synthetic move |             // synthetic move | ||||||
|             if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0) { |             if (lfs_paircmp(dir->pair, lfs->globals.s.movepair) == 0) { | ||||||
|                 if (lfs_globalmoveid(lfs) == lfs_tagid(foundtag)) { |                 if (lfs->globals.s.moveid == lfs_tagid(foundtag)) { | ||||||
|                     foundtag = LFS_ERR_NOENT; |                     foundtag = LFS_ERR_NOENT; | ||||||
|                 } else if (lfs_tagisvalid(foundtag) && |                 } else if (lfs_tagisvalid(foundtag) && | ||||||
|                         lfs_globalmoveid(lfs) < lfs_tagid(foundtag)) { |                         lfs->globals.s.moveid < lfs_tagid(foundtag)) { | ||||||
|                     foundtag -= LFS_MKTAG(0, 1, 0); |                     foundtag -= LFS_MKTAG(0, 1, 0); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -963,8 +934,8 @@ static int lfs_dir_fetch(lfs_t *lfs, | |||||||
| static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir, | static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir, | ||||||
|         uint32_t getmask, uint32_t gettag, void *buffer) { |         uint32_t getmask, uint32_t gettag, void *buffer) { | ||||||
|     int32_t getdiff = 0; |     int32_t getdiff = 0; | ||||||
|     if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0 && |     if (lfs_paircmp(dir->pair, lfs->globals.s.movepair) == 0 && | ||||||
|             lfs_tagid(gettag) <= lfs_globalmoveid(lfs)) { |             lfs_tagid(gettag) <= lfs->globals.s.moveid) { | ||||||
|         // synthetic moves |         // synthetic moves | ||||||
|         getdiff = LFS_MKTAG(0, 1, 0); |         getdiff = LFS_MKTAG(0, 1, 0); | ||||||
|     } |     } | ||||||
| @@ -1166,18 +1137,17 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, | |||||||
|     lfs_mattr_t cancelattr; |     lfs_mattr_t cancelattr; | ||||||
|     lfs_global_t canceldiff; |     lfs_global_t canceldiff; | ||||||
|     lfs_globalzero(&canceldiff); |     lfs_globalzero(&canceldiff); | ||||||
|     if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0) { |     if (lfs_paircmp(dir->pair, lfs->globals.s.movepair) == 0) { | ||||||
|         // Wait, we have the move? Just cancel this out here |         // Wait, we have the move? Just cancel this out here | ||||||
|         // We need to, or else the move can become outdated |         // We need to, or else the move can become outdated | ||||||
|         lfs_globalxormove(&canceldiff, |         canceldiff.s.movepair[0] ^= lfs->globals.s.movepair[0] ^ 0xffffffff; | ||||||
|                 lfs_globalmovepair(lfs), lfs_globalmoveid(lfs)); |         canceldiff.s.movepair[1] ^= lfs->globals.s.movepair[1] ^ 0xffffffff; | ||||||
|         lfs_globalxormove(&canceldiff,  |         canceldiff.s.moveid      ^= lfs->globals.s.moveid      ^ 0x3ff; | ||||||
|                 (lfs_block_t[2]){0xffffffff, 0xffffffff}, 0x3ff); |  | ||||||
|         lfs_globalfromle32(&lfs->locals); |         lfs_globalfromle32(&lfs->locals); | ||||||
|         lfs_globalxor(&lfs->locals, &canceldiff); |         lfs_globalxor(&lfs->locals, &canceldiff); | ||||||
|         lfs_globaltole32(&lfs->locals); |         lfs_globaltole32(&lfs->locals); | ||||||
|  |  | ||||||
|         cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs_globalmoveid(lfs), 0); |         cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs->globals.s.moveid, 0); | ||||||
|         cancelattr.next = attrs; |         cancelattr.next = attrs; | ||||||
|         attrs = &cancelattr; |         attrs = &cancelattr; | ||||||
|     } |     } | ||||||
| @@ -2814,7 +2784,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     lfs->root[0] = 0xffffffff; |     lfs->root[0] = 0xffffffff; | ||||||
|     lfs->root[1] = 0xffffffff; |     lfs->root[1] = 0xffffffff; | ||||||
|     lfs->mlist = NULL; |     lfs->mlist = NULL; | ||||||
|     lfs_globalones(&lfs->globals); |     lfs->globals.s.movepair[0] = 0xffffffff; | ||||||
|  |     lfs->globals.s.movepair[1] = 0xffffffff; | ||||||
|  |     lfs->globals.s.moveid = 0x3ff; | ||||||
|  |     lfs->globals.s.deorphaned = true; | ||||||
|     lfs_globalzero(&lfs->locals); |     lfs_globalzero(&lfs->locals); | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| @@ -2920,8 +2893,8 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     lfs_alloc_ack(lfs); |     lfs_alloc_ack(lfs); | ||||||
|  |  | ||||||
|     // load superblock |     // load superblock | ||||||
|     lfs_mdir_t dir; |     lfs_mdir_t superdir; | ||||||
|     err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1}); |     err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1}); | ||||||
|     if (err) { |     if (err) { | ||||||
|         if (err == LFS_ERR_CORRUPT) { |         if (err == LFS_ERR_CORRUPT) { | ||||||
|             LFS_ERROR("Invalid superblock at %d %d", 0, 1); |             LFS_ERROR("Invalid superblock at %d %d", 0, 1); | ||||||
| @@ -2930,7 +2903,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     lfs_superblock_t superblock; |     lfs_superblock_t superblock; | ||||||
|     int32_t res = lfs_dir_get(lfs, &dir, 0x7ffff000, |     int32_t res = lfs_dir_get(lfs, &superdir, 0x7ffff000, | ||||||
|             LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)), |             LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)), | ||||||
|             &superblock); |             &superblock); | ||||||
|     if (res < 0) { |     if (res < 0) { | ||||||
| @@ -2951,7 +2924,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|         return LFS_ERR_INVAL; |         return LFS_ERR_INVAL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     res = lfs_dir_get(lfs, &dir, 0x7ffff000, |     res = lfs_dir_get(lfs, &superdir, 0x7ffff000, | ||||||
|             LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(lfs->root)), |             LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(lfs->root)), | ||||||
|             &lfs->root); |             &lfs->root); | ||||||
|     if (res < 0) { |     if (res < 0) { | ||||||
| @@ -2990,9 +2963,26 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // scan for any global updates |     // scan for any global updates | ||||||
|     err = lfs_fs_scan(lfs); |     lfs_mdir_t dir = {.tail = {0, 1}}; | ||||||
|     if (err) { |     while (!lfs_pairisnull(dir.tail)) { | ||||||
|         return err; |         int err = lfs_dir_fetch(lfs, &dir, dir.tail); | ||||||
|  |         if (err) { | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // xor together indirect deletes | ||||||
|  |         lfs_globalxor(&lfs->locals, &dir.locals); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // update littlefs with globals | ||||||
|  |     lfs_globalfromle32(&lfs->locals); | ||||||
|  |     lfs_globalxor(&lfs->globals, &lfs->locals); | ||||||
|  |     lfs_globalzero(&lfs->locals); | ||||||
|  |     if (!lfs_pairisnull(lfs->globals.s.movepair)) { | ||||||
|  |         LFS_DEBUG("Found move %d %d %d", | ||||||
|  |                 lfs->globals.s.movepair[0], | ||||||
|  |                 lfs->globals.s.movepair[1], | ||||||
|  |                 lfs->globals.s.moveid); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| @@ -3186,41 +3176,10 @@ static int lfs_fs_relocate(lfs_t *lfs, | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_fs_scan(lfs_t *lfs) { |  | ||||||
|     if (lfs_pairisnull(lfs->root)) { |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // iterate over all directory directory entries |  | ||||||
|     lfs_mdir_t dir = {.tail = {0, 1}}; |  | ||||||
|     while (!lfs_pairisnull(dir.tail)) { |  | ||||||
|         int err = lfs_dir_fetch(lfs, &dir, dir.tail); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // xor together indirect deletes |  | ||||||
|         lfs_globalxor(&lfs->locals, &dir.locals); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // update littlefs with globals |  | ||||||
|     lfs_globalfromle32(&lfs->locals); |  | ||||||
|     lfs_globalxor(&lfs->globals, &lfs->locals); |  | ||||||
|     lfs_globalzero(&lfs->locals); |  | ||||||
|     if (!lfs_pairisnull(lfs_globalmovepair(lfs))) { |  | ||||||
|         LFS_DEBUG("Found move %d %d %d", |  | ||||||
|                 lfs_globalmovepair(lfs)[0], |  | ||||||
|                 lfs_globalmovepair(lfs)[1], |  | ||||||
|                 lfs_globalmoveid(lfs)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int lfs_fs_forceconsistency(lfs_t *lfs) { | static int lfs_fs_forceconsistency(lfs_t *lfs) { | ||||||
|     if (!lfs_globalisdeorphaned(lfs)) { |     if (!lfs->globals.s.deorphaned) { | ||||||
|         LFS_DEBUG("Found orphans %d", |         LFS_DEBUG("Found orphans %d", | ||||||
|                 lfs_globalisdeorphaned(lfs)); |                 lfs->globals.s.deorphaned); | ||||||
|  |  | ||||||
|         // Fix any orphans |         // Fix any orphans | ||||||
|         lfs_mdir_t pdir = {.split = true}; |         lfs_mdir_t pdir = {.split = true}; | ||||||
| @@ -3292,16 +3251,16 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) { | |||||||
|         lfs_globaldeorphaned(lfs, false); |         lfs_globaldeorphaned(lfs, false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (lfs_globalmoveid(lfs) != 0x3ff) { |     if (lfs->globals.s.moveid != 0x3ff) { | ||||||
|         // Fix bad moves |         // Fix bad moves | ||||||
|         LFS_DEBUG("Fixing move %d %d %d", |         LFS_DEBUG("Fixing move %d %d %d", | ||||||
|                 lfs_globalmovepair(lfs)[0], |                 lfs->globals.s.movepair[0], | ||||||
|                 lfs_globalmovepair(lfs)[1], |                 lfs->globals.s.movepair[1], | ||||||
|                 lfs_globalmoveid(lfs)); |                 lfs->globals.s.moveid); | ||||||
|  |  | ||||||
|         // fetch and delete the moved entry |         // fetch and delete the moved entry | ||||||
|         lfs_mdir_t movedir; |         lfs_mdir_t movedir; | ||||||
|         int err = lfs_dir_fetch(lfs, &movedir, lfs_globalmovepair(lfs)); |         int err = lfs_dir_fetch(lfs, &movedir, lfs->globals.s.movepair); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -287,18 +287,23 @@ typedef struct lfs_cache { | |||||||
| } lfs_cache_t; | } lfs_cache_t; | ||||||
|  |  | ||||||
| typedef union lfs_global { | typedef union lfs_global { | ||||||
|     uint16_t u16[5]; |     uint32_t u32[3]; | ||||||
|  |     struct { | ||||||
|  |         lfs_block_t movepair[2]; | ||||||
|  |         uint16_t moveid; | ||||||
|  |         bool deorphaned; | ||||||
|  |     } s; | ||||||
| } lfs_global_t; | } lfs_global_t; | ||||||
|  |  | ||||||
| typedef struct lfs_mdir { | typedef struct lfs_mdir { | ||||||
|     lfs_block_t pair[2]; |     lfs_block_t pair[2]; | ||||||
|     lfs_block_t tail[2]; |  | ||||||
|     uint32_t rev; |     uint32_t rev; | ||||||
|     uint32_t etag; |     uint32_t etag; | ||||||
|     lfs_off_t off; |     lfs_off_t off; | ||||||
|     uint16_t count; |     uint16_t count; | ||||||
|     bool erased; |     bool erased; | ||||||
|     bool split; |     bool split; | ||||||
|  |     lfs_block_t tail[2]; | ||||||
|     lfs_global_t locals; |     lfs_global_t locals; | ||||||
| } lfs_mdir_t; | } lfs_mdir_t; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user