mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	WIP Changed deorphan to only use one pass for pred fix
This commit is contained in:
		
							
								
								
									
										153
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										153
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -451,31 +451,32 @@ static inline void lfs_global_zero(lfs_global_t *a) { | ||||
| } | ||||
|  | ||||
| static inline void lfs_global_fromle32(lfs_global_t *a) { | ||||
|     lfs_pair_fromle32(a->s.movepair); | ||||
|     a->s.moveid = lfs_fromle16(a->s.moveid); | ||||
|     lfs_pair_fromle32(a->l.movepair); | ||||
|     a->l.moveid = lfs_fromle16(a->l.moveid); | ||||
| } | ||||
|  | ||||
| static inline void lfs_global_tole32(lfs_global_t *a) { | ||||
|     lfs_pair_tole32(a->s.movepair); | ||||
|     a->s.moveid = lfs_tole16(a->s.moveid); | ||||
|     lfs_pair_tole32(a->l.movepair); | ||||
|     a->l.moveid = lfs_tole16(a->l.moveid); | ||||
| } | ||||
|  | ||||
| static inline void lfs_global_move(lfs_t *lfs, | ||||
|         const lfs_block_t pair[2], uint16_t id) { | ||||
|     lfs_global_t diff; | ||||
|     lfs_global_zero(&diff); | ||||
|     diff.s.movepair[0] ^= lfs->globals.s.movepair[0] ^ pair[0]; | ||||
|     diff.s.movepair[1] ^= lfs->globals.s.movepair[1] ^ pair[1]; | ||||
|     diff.s.moveid      ^= lfs->globals.s.moveid      ^ id; | ||||
|     diff.l.movepair[0] ^= lfs->globals.g.movepair[0] ^ pair[0]; | ||||
|     diff.l.movepair[1] ^= lfs->globals.g.movepair[1] ^ pair[1]; | ||||
|     diff.l.moveid      ^= lfs->globals.g.moveid      ^ id; | ||||
|     lfs_global_fromle32(&lfs->locals); | ||||
|     lfs_global_xor(&lfs->locals, &diff); | ||||
|     lfs_global_tole32(&lfs->locals); | ||||
|     lfs_global_xor(&lfs->globals, &diff); | ||||
| } | ||||
|  | ||||
| static inline void lfs_global_deorphaned(lfs_t *lfs, bool deorphaned) { | ||||
|     lfs->locals.s.deorphaned  ^= lfs->globals.s.deorphaned ^ deorphaned; | ||||
|     lfs->globals.s.deorphaned ^= lfs->globals.s.deorphaned ^ deorphaned; | ||||
| static inline void lfs_global_orphans(lfs_t *lfs, int8_t orphans) { | ||||
|     lfs->locals.l.deorphaned ^= (lfs->globals.g.orphans == 0); | ||||
|     lfs->locals.l.deorphaned ^= (lfs->globals.g.orphans + orphans == 0); | ||||
|     lfs->globals.g.orphans += orphans; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -688,7 +689,7 @@ static int lfs_commit_globals(lfs_t *lfs, struct lfs_commit *commit, | ||||
|  | ||||
|     lfs_global_xor(locals, &lfs->locals); | ||||
|     int err = lfs_commit_attr(lfs, commit, | ||||
|             LFS_MKTAG(LFS_TYPE_GLOBALS + locals->s.deorphaned, 0x3ff, 10), | ||||
|             LFS_MKTAG(LFS_TYPE_GLOBALS + locals->l.deorphaned, 0x3ff, 10), | ||||
|             locals); | ||||
|     lfs_global_xor(locals, &lfs->locals); | ||||
|     return err; | ||||
| @@ -907,7 +908,7 @@ static int32_t lfs_dir_fetchmatch(lfs_t *lfs, | ||||
|                     } | ||||
|                     lfs_pair_fromle32(temptail); | ||||
|                 } else if (lfs_tag_subtype(tag) == LFS_TYPE_GLOBALS) { | ||||
|                     templocals.s.deorphaned = (lfs_tag_type(tag) & 1); | ||||
|                     templocals.l.deorphaned = (lfs_tag_type(tag) & 1); | ||||
|                     err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag), | ||||
|                             &templocals, 10); | ||||
|                     if (err) { | ||||
| @@ -973,11 +974,11 @@ static int32_t lfs_dir_fetchmatch(lfs_t *lfs, | ||||
|         // consider what we have good enough | ||||
|         if (dir->off > 0) { | ||||
|             // synthetic move | ||||
|             if (lfs_pair_cmp(dir->pair, lfs->globals.s.movepair) == 0) { | ||||
|                 if (lfs->globals.s.moveid == lfs_tag_id(foundtag)) { | ||||
|             if (lfs_pair_cmp(dir->pair, lfs->globals.g.movepair) == 0) { | ||||
|                 if (lfs->globals.g.moveid == lfs_tag_id(foundtag)) { | ||||
|                     foundtag = LFS_ERR_NOENT; | ||||
|                 } else if (lfs_tag_isvalid(foundtag) && | ||||
|                         lfs->globals.s.moveid < lfs_tag_id(foundtag)) { | ||||
|                         lfs->globals.g.moveid < lfs_tag_id(foundtag)) { | ||||
|                     foundtag -= LFS_MKTAG(0, 1, 0); | ||||
|                 } | ||||
|             } | ||||
| @@ -1026,8 +1027,8 @@ static int32_t lfs_dir_find(lfs_t *lfs, | ||||
| static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir, | ||||
|         uint32_t getmask, uint32_t gettag, void *buffer) { | ||||
|     int32_t getdiff = 0; | ||||
|     if (lfs_pair_cmp(dir->pair, lfs->globals.s.movepair) == 0 && | ||||
|             lfs_tag_id(gettag) <= lfs->globals.s.moveid) { | ||||
|     if (lfs_pair_cmp(dir->pair, lfs->globals.g.movepair) == 0 && | ||||
|             lfs_tag_id(gettag) <= lfs->globals.g.moveid) { | ||||
|         // synthetic moves | ||||
|         getdiff = LFS_MKTAG(0, 1, 0); | ||||
|     } | ||||
| @@ -1270,17 +1271,17 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, | ||||
|     lfs_mattr_t cancelattr; | ||||
|     lfs_global_t canceldiff; | ||||
|     lfs_global_zero(&canceldiff); | ||||
|     if (lfs_pair_cmp(dir->pair, lfs->globals.s.movepair) == 0) { | ||||
|     if (lfs_pair_cmp(dir->pair, lfs->globals.g.movepair) == 0) { | ||||
|         // Wait, we have the move? Just cancel this out here | ||||
|         // We need to, or else the move can become outdated | ||||
|         canceldiff.s.movepair[0] ^= lfs->globals.s.movepair[0] ^ 0xffffffff; | ||||
|         canceldiff.s.movepair[1] ^= lfs->globals.s.movepair[1] ^ 0xffffffff; | ||||
|         canceldiff.s.moveid      ^= lfs->globals.s.moveid      ^ 0x3ff; | ||||
|         canceldiff.l.movepair[0] ^= lfs->globals.g.movepair[0] ^ 0xffffffff; | ||||
|         canceldiff.l.movepair[1] ^= lfs->globals.g.movepair[1] ^ 0xffffffff; | ||||
|         canceldiff.l.moveid      ^= lfs->globals.g.moveid      ^ 0x3ff; | ||||
|         lfs_global_fromle32(&lfs->locals); | ||||
|         lfs_global_xor(&lfs->locals, &canceldiff); | ||||
|         lfs_global_tole32(&lfs->locals); | ||||
|  | ||||
|         cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs->globals.s.moveid, 0); | ||||
|         cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs->globals.l.moveid, 0); | ||||
|         cancelattr.next = attrs; | ||||
|         attrs = &cancelattr; | ||||
|     } | ||||
| @@ -2636,7 +2637,7 @@ int lfs_remove(lfs_t *lfs, const char *path) { | ||||
|         } | ||||
|  | ||||
|         // mark fs as orphaned | ||||
|         lfs_global_deorphaned(lfs, false); | ||||
|         lfs_global_orphans(lfs, +1); | ||||
|     } | ||||
|  | ||||
|     // delete the entry | ||||
| @@ -2648,14 +2649,14 @@ int lfs_remove(lfs_t *lfs, const char *path) { | ||||
|     } | ||||
|  | ||||
|     if (lfs_tag_type(tag) == LFS_TYPE_DIR) { | ||||
|         // fix orphan | ||||
|         lfs_global_orphans(lfs, -1); | ||||
|  | ||||
|         err = lfs_fs_pred(lfs, dir.pair, &cwd); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         // fix orphan | ||||
|         lfs_global_deorphaned(lfs, true); | ||||
|  | ||||
|         // steal state | ||||
|         cwd.tail[0] = dir.tail[0]; | ||||
|         cwd.tail[1] = dir.tail[1]; | ||||
| @@ -2696,36 +2697,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | ||||
|     uint16_t newid = lfs_tag_id(prevtag); | ||||
|  | ||||
|     lfs_mdir_t prevdir; | ||||
|     if (prevtag != LFS_ERR_NOENT) { | ||||
|         // check that we have same type | ||||
|         if (lfs_tag_type(prevtag) != lfs_tag_type(oldtag)) { | ||||
|             return LFS_ERR_ISDIR; | ||||
|         } | ||||
|  | ||||
|         if (lfs_tag_type(prevtag) == LFS_TYPE_DIR) { | ||||
|             // must be empty before removal | ||||
|             lfs_block_t prevpair[2]; | ||||
|             int32_t res = lfs_dir_get(lfs, &newcwd, 0x7c3ff000, | ||||
|                     LFS_MKTAG(LFS_TYPE_STRUCT, newid, 8), prevpair); | ||||
|             if (res < 0) { | ||||
|                 return res; | ||||
|             } | ||||
|             lfs_pair_fromle32(prevpair); | ||||
|  | ||||
|             // must be empty before removal | ||||
|             err = lfs_dir_fetch(lfs, &prevdir, prevpair); | ||||
|             if (err) { | ||||
|                 return err; | ||||
|             } | ||||
|  | ||||
|             if (prevdir.count > 0 || prevdir.split) { | ||||
|                 return LFS_ERR_NOTEMPTY; | ||||
|             } | ||||
|  | ||||
|             // mark fs as orphaned | ||||
|             lfs_global_deorphaned(lfs, false); | ||||
|         } | ||||
|     } else { | ||||
|     if (prevtag == LFS_ERR_NOENT) { | ||||
|         // check that name fits | ||||
|         lfs_size_t nlen = strlen(newpath); | ||||
|         if (nlen > lfs->name_max) { | ||||
| @@ -2734,6 +2706,30 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | ||||
|  | ||||
|         // get next id | ||||
|         newid = newcwd.count; | ||||
|     } else if (lfs_tag_type(prevtag) != lfs_tag_type(oldtag)) { | ||||
|         return LFS_ERR_ISDIR; | ||||
|     } else if (lfs_tag_type(prevtag) == LFS_TYPE_DIR) { | ||||
|         // must be empty before removal | ||||
|         lfs_block_t prevpair[2]; | ||||
|         int32_t res = lfs_dir_get(lfs, &newcwd, 0x7c3ff000, | ||||
|                 LFS_MKTAG(LFS_TYPE_STRUCT, newid, 8), prevpair); | ||||
|         if (res < 0) { | ||||
|             return res; | ||||
|         } | ||||
|         lfs_pair_fromle32(prevpair); | ||||
|  | ||||
|         // must be empty before removal | ||||
|         err = lfs_dir_fetch(lfs, &prevdir, prevpair); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         if (prevdir.count > 0 || prevdir.split) { | ||||
|             return LFS_ERR_NOTEMPTY; | ||||
|         } | ||||
|  | ||||
|         // mark fs as orphaned | ||||
|         lfs_global_orphans(lfs, +1); | ||||
|     } | ||||
|  | ||||
|     // create move to fix later | ||||
| @@ -2758,14 +2754,14 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | ||||
|     } | ||||
|  | ||||
|     if (prevtag != LFS_ERR_NOENT && lfs_tag_type(prevtag) == LFS_TYPE_DIR) { | ||||
|         // fix orphan | ||||
|         lfs_global_orphans(lfs, -1); | ||||
|  | ||||
|         err = lfs_fs_pred(lfs, prevdir.pair, &newcwd); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         // fix orphan | ||||
|         lfs_global_deorphaned(lfs, true); | ||||
|  | ||||
|         // steal state | ||||
|         newcwd.tail[0] = prevdir.tail[0]; | ||||
|         newcwd.tail[1] = prevdir.tail[1]; | ||||
| @@ -2917,10 +2913,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | ||||
|     lfs->root[1] = 0xffffffff; | ||||
|     lfs->mlist = NULL; | ||||
|     lfs->seed = 0; | ||||
|     lfs->globals.s.movepair[0] = 0xffffffff; | ||||
|     lfs->globals.s.movepair[1] = 0xffffffff; | ||||
|     lfs->globals.s.moveid = 0x3ff; | ||||
|     lfs->globals.s.deorphaned = true; | ||||
|     lfs->globals.g.movepair[0] = 0xffffffff; | ||||
|     lfs->globals.g.movepair[1] = 0xffffffff; | ||||
|     lfs->globals.g.moveid = 0x3ff; | ||||
|     lfs->globals.g.orphans = 0; | ||||
|     lfs_global_zero(&lfs->locals); | ||||
|  | ||||
|     return 0; | ||||
| @@ -3089,11 +3085,11 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | ||||
|     lfs_global_fromle32(&lfs->locals); | ||||
|     lfs_global_xor(&lfs->globals, &lfs->locals); | ||||
|     lfs_global_zero(&lfs->locals); | ||||
|     if (!lfs_pair_isnull(lfs->globals.s.movepair)) { | ||||
|     if (!lfs_pair_isnull(lfs->globals.g.movepair)) { | ||||
|         LFS_DEBUG("Found move %"PRIu32" %"PRIu32" %"PRIu32, | ||||
|                 lfs->globals.s.movepair[0], | ||||
|                 lfs->globals.s.movepair[1], | ||||
|                 lfs->globals.s.moveid); | ||||
|                 lfs->globals.g.movepair[0], | ||||
|                 lfs->globals.g.movepair[1], | ||||
|                 lfs->globals.g.moveid); | ||||
|     } | ||||
|  | ||||
|     // setup free lookahead | ||||
| @@ -3254,7 +3250,8 @@ static int lfs_fs_relocate(lfs_t *lfs, | ||||
|  | ||||
|     if (tag != LFS_ERR_NOENT) { | ||||
|         // update disk, this creates a desync | ||||
|         lfs_global_deorphaned(lfs, false); | ||||
|         lfs_global_orphans(lfs, +1); | ||||
|  | ||||
|         lfs_pair_tole32(newpair); | ||||
|         int err = lfs_dir_commit(lfs, &parent, | ||||
|                 &(lfs_mattr_t){.tag=tag, .buffer=newpair}); | ||||
| @@ -3263,8 +3260,8 @@ static int lfs_fs_relocate(lfs_t *lfs, | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         // clean up bad block, which should now be a desync | ||||
|         return lfs_fs_deorphan(lfs); | ||||
|         // next step, clean up orphans | ||||
|         lfs_global_orphans(lfs, -1); | ||||
|     } | ||||
|  | ||||
|     // find pred | ||||
| @@ -3275,7 +3272,7 @@ static int lfs_fs_relocate(lfs_t *lfs, | ||||
|  | ||||
|     // if we can't find dir, it must be new | ||||
|     if (err != LFS_ERR_NOENT) { | ||||
|         // just replace bad pair, no desync can occur | ||||
|         // replace bad pair, either we clean up desync, or no desync occured | ||||
|         parent.tail[0] = newpair[0]; | ||||
|         parent.tail[1] = newpair[1]; | ||||
|         err = lfs_dir_commit(lfs, &parent, | ||||
| @@ -3359,20 +3356,20 @@ static int lfs_fs_deorphan(lfs_t *lfs) { | ||||
|     } | ||||
|  | ||||
|     // mark orphans as fixed | ||||
|     lfs_global_deorphaned(lfs, true); | ||||
|     lfs_global_orphans(lfs, -lfs->globals.g.orphans); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int lfs_fs_demove(lfs_t *lfs) { | ||||
|     // Fix bad moves | ||||
|     LFS_DEBUG("Fixing move %"PRIu32" %"PRIu32" %"PRIu32, | ||||
|             lfs->globals.s.movepair[0], | ||||
|             lfs->globals.s.movepair[1], | ||||
|             lfs->globals.s.moveid); | ||||
|             lfs->globals.g.movepair[0], | ||||
|             lfs->globals.g.movepair[1], | ||||
|             lfs->globals.g.moveid); | ||||
|  | ||||
|     // fetch and delete the moved entry | ||||
|     lfs_mdir_t movedir; | ||||
|     int err = lfs_dir_fetch(lfs, &movedir, lfs->globals.s.movepair); | ||||
|     int err = lfs_dir_fetch(lfs, &movedir, lfs->globals.g.movepair); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
| @@ -3387,14 +3384,14 @@ static int lfs_fs_demove(lfs_t *lfs) { | ||||
| } | ||||
|  | ||||
| static int lfs_fs_forceconsistency(lfs_t *lfs) { | ||||
|     if (!lfs->globals.s.deorphaned) { | ||||
|     if (lfs->globals.g.orphans) { | ||||
|         int err = lfs_fs_deorphan(lfs); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (lfs->globals.s.moveid != 0x3ff) { | ||||
|     if (lfs->globals.g.moveid != 0x3ff) { | ||||
|         int err = lfs_fs_demove(lfs); | ||||
|         if (err) { | ||||
|             return err; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user