mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	WIP branches in dir
This commit is contained in:
		
							
								
								
									
										198
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										198
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -789,6 +789,7 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs, | |||||||
|  |  | ||||||
|         uint16_t tempcount = 0; |         uint16_t tempcount = 0; | ||||||
|         lfs_block_t temptail[2] = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}; |         lfs_block_t temptail[2] = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}; | ||||||
|  |         lfs_block_t tempbranch[2] = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}; | ||||||
|         bool tempsplit = false; |         bool tempsplit = false; | ||||||
|         lfs_stag_t tempbesttag = besttag; |         lfs_stag_t tempbesttag = besttag; | ||||||
|  |  | ||||||
| @@ -861,6 +862,8 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs, | |||||||
|                 dir->count = tempcount; |                 dir->count = tempcount; | ||||||
|                 dir->tail[0] = temptail[0]; |                 dir->tail[0] = temptail[0]; | ||||||
|                 dir->tail[1] = temptail[1]; |                 dir->tail[1] = temptail[1]; | ||||||
|  |                 dir->branch[0] = tempbranch[0]; | ||||||
|  |                 dir->branch[1] = tempbranch[1]; | ||||||
|                 dir->split = tempsplit; |                 dir->split = tempsplit; | ||||||
|  |  | ||||||
|                 // reset crc |                 // reset crc | ||||||
| @@ -914,6 +917,28 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs, | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 lfs_pair_fromle32(temptail); |                 lfs_pair_fromle32(temptail); | ||||||
|  |  | ||||||
|  |                 // TODO hm | ||||||
|  |                 if (tempsplit) { | ||||||
|  |                     tempbranch[0] = temptail[0]; | ||||||
|  |                     tempbranch[1] = temptail[1]; | ||||||
|  |                 } | ||||||
|  |             } else if (lfs_tag_type3(tag) == LFS_TYPE_BRANCH) { | ||||||
|  |                 if (lfs_tag_isdelete(tag)) { | ||||||
|  |                     tempbranch[0] = LFS_BLOCK_NULL; | ||||||
|  |                     tempbranch[1] = LFS_BLOCK_NULL; | ||||||
|  |                 } else { | ||||||
|  |                     // TODO endianness | ||||||
|  |                     err = lfs_bd_read(lfs, | ||||||
|  |                             NULL, &lfs->rcache, lfs->cfg->block_size, | ||||||
|  |                             dir->pair[0], off+sizeof(tag), &tempbranch, 8); | ||||||
|  |                     if (err) { | ||||||
|  |                         if (err == LFS_ERR_CORRUPT) { | ||||||
|  |                             dir->erased = false; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // found a match for our fetcher? |             // found a match for our fetcher? | ||||||
| @@ -1165,6 +1190,8 @@ nextname: | |||||||
|             npair[0] = dir->tail[0]; |             npair[0] = dir->tail[0]; | ||||||
|             npair[1] = dir->tail[1]; |             npair[1] = dir->tail[1]; | ||||||
|             if (!dir->split) { |             if (!dir->split) { | ||||||
|  | //                npair[0] = dir->branch[0]; | ||||||
|  | //                npair[1] = dir->branch[1]; | ||||||
|                 ttag = lfs_dir_get(lfs, dir, |                 ttag = lfs_dir_get(lfs, dir, | ||||||
|                         LFS_MKTAG(0x7ff, 0, 0), |                         LFS_MKTAG(0x7ff, 0, 0), | ||||||
|                         LFS_MKTAG(LFS_TYPE_BRANCH, 0, sizeof(npair)), |                         LFS_MKTAG(LFS_TYPE_BRANCH, 0, sizeof(npair)), | ||||||
| @@ -1173,6 +1200,7 @@ nextname: | |||||||
|                     return ttag; |                     return ttag; | ||||||
|                 } |                 } | ||||||
|                 lfs_pair_fromle32(npair); |                 lfs_pair_fromle32(npair); | ||||||
|  |                 assert(ttag == LFS_ERR_NOENT || lfs_pair_cmp(npair, dir->branch) == 0); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // ttag may be NOENT or may be marked null explicitly |             // ttag may be NOENT or may be marked null explicitly | ||||||
| @@ -1381,6 +1409,8 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) { | |||||||
|     dir->count = 0; |     dir->count = 0; | ||||||
|     dir->tail[0] = LFS_BLOCK_NULL; |     dir->tail[0] = LFS_BLOCK_NULL; | ||||||
|     dir->tail[1] = LFS_BLOCK_NULL; |     dir->tail[1] = LFS_BLOCK_NULL; | ||||||
|  |     dir->branch[0] = LFS_BLOCK_NULL; | ||||||
|  |     dir->branch[1] = LFS_BLOCK_NULL; | ||||||
|     dir->erased = false; |     dir->erased = false; | ||||||
|     dir->split = false; |     dir->split = false; | ||||||
|  |  | ||||||
| @@ -1481,15 +1511,20 @@ static int lfs_dir_split(lfs_t *lfs, | |||||||
|     tail.split = dir->split; |     tail.split = dir->split; | ||||||
|     tail.tail[0] = dir->tail[0]; |     tail.tail[0] = dir->tail[0]; | ||||||
|     tail.tail[1] = dir->tail[1]; |     tail.tail[1] = dir->tail[1]; | ||||||
|  |     tail.branch[0] = dir->branch[0]; | ||||||
|  |     tail.branch[1] = dir->branch[1]; | ||||||
|  |  | ||||||
|     err = lfs_dir_compact(lfs, &tail, attrs, attrcount, source, split, end); |     err = lfs_dir_compact(lfs, &tail, attrs, attrcount, source, split, end); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     dir->split = false; | ||||||
|     dir->tail[0] = tail.pair[0]; |     dir->tail[0] = tail.pair[0]; | ||||||
|     dir->tail[1] = tail.pair[1]; |     dir->tail[1] = tail.pair[1]; | ||||||
|     dir->split = true; |     dir->branch[0] = tail.pair[0]; | ||||||
|  |     dir->branch[1] = tail.pair[1]; | ||||||
|  |     //dir->split = true; | ||||||
|  |  | ||||||
|     // update root if needed |     // update root if needed | ||||||
|     if (lfs_pair_cmp(dir->pair, lfs->root) == 0 && split == 0) { |     if (lfs_pair_cmp(dir->pair, lfs->root) == 0 && split == 0) { | ||||||
| @@ -1685,36 +1720,68 @@ static int lfs_dir_compact(lfs_t *lfs, | |||||||
|                     return err; |                     return err; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // Also commit branch or turn branch+tail into explicit branch |                 if (dir->split) { | ||||||
|                 // and tail. This helps handling of relocations. You may wonder |                     dir->branch[0] = dir->tail[0]; | ||||||
|                 // why we even have the branch+tail type, and that is simply |                     dir->branch[1] = dir->tail[1]; | ||||||
|                 // because of backwards compatibility. |  | ||||||
|                 // |  | ||||||
|                 // Note we don't need to convert to/from le32 because we commit |  | ||||||
|                 // it straight to disk |  | ||||||
|                 lfs_stag_t btag = 0; |  | ||||||
|                 lfs_block_t bpair[2] = {dir->tail[0], dir->tail[1]}; |  | ||||||
|                 if (!dir->split) { |  | ||||||
|                     btag = lfs_dir_get(lfs, source, |  | ||||||
|                             LFS_MKTAG(0x7ff, 0, 0), |  | ||||||
|                             LFS_MKTAG(LFS_TYPE_BRANCH, 0, sizeof(bpair)), |  | ||||||
|                             bpair); |  | ||||||
|                     if (btag < 0 && btag != LFS_ERR_NOENT) { |  | ||||||
|                         return btag; |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (btag != LFS_ERR_NOENT) { | //                // Also commit branch or turn branch+tail into explicit branch | ||||||
|                     err = lfs_dir_commitattr(lfs, &commit, | //                // and tail. This helps handling of relocations. You may wonder | ||||||
|                             LFS_MKTAG(LFS_TYPE_BRANCH, 0x3ff, 8), | //                // why we even have the branch+tail type, and that is simply | ||||||
|                             bpair); | //                // because of backwards compatibility. | ||||||
|                     if (err) { | //                // | ||||||
|                         if (err == LFS_ERR_CORRUPT) { | //                // Note we don't need to convert to/from le32 because we commit | ||||||
|                             goto relocate; | //                // it straight to disk | ||||||
|                         } | //                lfs_stag_t btag = 0; | ||||||
|                         return err; | //                lfs_block_t bpair[2] = {dir->tail[0], dir->tail[1]}; | ||||||
|  | //                if (!dir->split) { | ||||||
|  | //                    btag = lfs_dir_get(lfs, source, | ||||||
|  | //                            LFS_MKTAG(0x7ff, 0, 0), | ||||||
|  | //                            LFS_MKTAG(LFS_TYPE_BRANCH, 0, sizeof(bpair)), | ||||||
|  | //                            bpair); | ||||||
|  | //                    if (btag < 0 && btag != LFS_ERR_NOENT) { | ||||||
|  | //                        return btag; | ||||||
|  | //                    } | ||||||
|  | //                } | ||||||
|  | // | ||||||
|  | //                if (btag != LFS_ERR_NOENT) { | ||||||
|  | //                    err = lfs_dir_commitattr(lfs, &commit, | ||||||
|  | //                            LFS_MKTAG(LFS_TYPE_BRANCH, 0x3ff, 8), | ||||||
|  | //                            bpair); | ||||||
|  | //                    if (err) { | ||||||
|  | //                        if (err == LFS_ERR_CORRUPT) { | ||||||
|  | //                            goto relocate; | ||||||
|  | //                        } | ||||||
|  | //                        return err; | ||||||
|  | //                    } | ||||||
|  | //                } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // TODO comment these | ||||||
|  |             // commit branch | ||||||
|  |             if (!lfs_pair_isnull(dir->branch)) { | ||||||
|  |                 LFS_ASSERT(dir->branch[0] < lfs->cfg->block_count && | ||||||
|  |                         dir->branch[1] < lfs->cfg->block_count); | ||||||
|  |                 err = lfs_dir_commitattr(lfs, &commit, | ||||||
|  |                         LFS_MKTAG(LFS_TYPE_BRANCH, 0x3ff, 8), | ||||||
|  |                         dir->branch); | ||||||
|  |                 if (err) { | ||||||
|  |                     if (err == LFS_ERR_CORRUPT) { | ||||||
|  |                         goto relocate; | ||||||
|                     } |                     } | ||||||
|  |                     return err; | ||||||
|                 } |                 } | ||||||
|  | //            } else if (dir->split && !lfs_pair_isnull(dir->tail)) { | ||||||
|  | //                // commit branch from tail? | ||||||
|  | //                err = lfs_dir_commitattr(lfs, &commit, | ||||||
|  | //                        LFS_MKTAG(LFS_TYPE_BRANCH, 0x3ff, 8), | ||||||
|  | //                        dir->tail); | ||||||
|  | //                if (err) { | ||||||
|  | //                    if (err == LFS_ERR_CORRUPT) { | ||||||
|  | //                        goto relocate; | ||||||
|  | //                    } | ||||||
|  | //                    return err; | ||||||
|  | //                } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // bring over gstate? |             // bring over gstate? | ||||||
| @@ -1910,6 +1977,20 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, | |||||||
|             dir->tail[1] = ((lfs_block_t*)attrs[i].buffer)[1]; |             dir->tail[1] = ((lfs_block_t*)attrs[i].buffer)[1]; | ||||||
|             dir->split = (lfs_tag_chunk(attrs[i].tag) & 1); |             dir->split = (lfs_tag_chunk(attrs[i].tag) & 1); | ||||||
|             lfs_pair_fromle32(dir->tail); |             lfs_pair_fromle32(dir->tail); | ||||||
|  |             // TODO hm | ||||||
|  |             if (dir->split) { | ||||||
|  |                 dir->branch[0] = dir->tail[0]; | ||||||
|  |                 dir->branch[1] = dir->tail[1]; | ||||||
|  |             } | ||||||
|  |         } else if (lfs_tag_type3(attrs[i].tag) == LFS_TYPE_BRANCH) { | ||||||
|  |             if (lfs_tag_isdelete(attrs[i].tag)) { | ||||||
|  |                 dir->branch[0] = 0xffffffff; | ||||||
|  |                 dir->branch[1] = 0xffffffff; | ||||||
|  |             } else { | ||||||
|  |                 dir->branch[0] = ((lfs_block_t*)attrs[i].buffer)[0]; | ||||||
|  |                 dir->branch[1] = ((lfs_block_t*)attrs[i].buffer)[1]; | ||||||
|  |                 // TODO endianness? | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2077,30 +2158,32 @@ compact: | |||||||
|  |  | ||||||
|     for (struct lfs_mlist *d = lfs->mlist; d; d = d->next) { |     for (struct lfs_mlist *d = lfs->mlist; d; d = d->next) { | ||||||
|         if (lfs_pair_cmp(d->m.pair, olddir.pair) == 0) { |         if (lfs_pair_cmp(d->m.pair, olddir.pair) == 0) { | ||||||
|             while (d->id >= d->m.count) { |             while (d->id >= d->m.count && !lfs_pair_isnull(d->m.branch)) { | ||||||
|                 // we split and id is on tail now | //                 | ||||||
|                 // TODO should I make this a common function? | // | ||||||
|                 // TODO use softtail? | //                // we split and id is on tail now | ||||||
|                 lfs_stag_t ttag = 0; | //                // TODO should I make this a common function? | ||||||
|                 lfs_block_t npair[2] = {d->m.tail[0], d->m.tail[1]}; | //                // TODO use softtail? | ||||||
|                 if (!d->m.split) { | //                lfs_stag_t ttag = 0; | ||||||
|                     ttag = lfs_dir_get(lfs, &d->m, | //                lfs_block_t npair[2] = {d->m.tail[0], d->m.tail[1]}; | ||||||
|                             LFS_MKTAG(0x7ff, 0, 0), | //                if (!d->m.split) { | ||||||
|                             LFS_MKTAG(LFS_TYPE_BRANCH, 0, sizeof(npair)), | //                    ttag = lfs_dir_get(lfs, &d->m, | ||||||
|                             npair); | //                            LFS_MKTAG(0x7ff, 0, 0), | ||||||
|                     if (ttag < 0 && ttag != LFS_ERR_NOENT) { | //                            LFS_MKTAG(LFS_TYPE_BRANCH, 0, sizeof(npair)), | ||||||
|                         return ttag; | //                            npair); | ||||||
|                     } | //                    if (ttag < 0 && ttag != LFS_ERR_NOENT) { | ||||||
|                     lfs_pair_fromle32(npair); | //                        return ttag; | ||||||
|                 } | //                    } | ||||||
|  | //                    lfs_pair_fromle32(npair); | ||||||
|                 // ttag may be NOENT or may be marked null explicitly | //                } | ||||||
|                 if (ttag == LFS_ERR_NOENT || lfs_pair_isnull(npair)) { | // | ||||||
|                     break; | //                // ttag may be NOENT or may be marked null explicitly | ||||||
|                 } | //                if (ttag == LFS_ERR_NOENT || lfs_pair_isnull(npair)) { | ||||||
|  | //                    break; | ||||||
|  | //                } | ||||||
|  |  | ||||||
|                 d->id -= d->m.count; |                 d->id -= d->m.count; | ||||||
|                 int err = lfs_dir_fetch(lfs, &d->m, npair); |                 int err = lfs_dir_fetch(lfs, &d->m, d->m.branch); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     return err; | ||||||
|                 } |                 } | ||||||
| @@ -4422,14 +4505,6 @@ static int lfs_fs_deorphan(lfs_t *lfs) { | |||||||
|                 return tag; |                 return tag; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             lfs_block_t pair[2]; |  | ||||||
|             lfs_stag_t res = lfs_dir_get(lfs, &parent, |  | ||||||
|                     LFS_MKTAG(0x7ff, 0x3ff, 0), tag, pair); |  | ||||||
|             if (res < 0) { |  | ||||||
|                 return res; |  | ||||||
|             } |  | ||||||
|             lfs_pair_fromle32(pair); |  | ||||||
|  |  | ||||||
|             // Half-orphans can also be true orphans if there is a better |             // Half-orphans can also be true orphans if there is a better | ||||||
|             // child. Currently the child must be our successor. |             // child. Currently the child must be our successor. | ||||||
|             if (tag == LFS_ERR_NOENT) { |             if (tag == LFS_ERR_NOENT) { | ||||||
| @@ -4450,7 +4525,16 @@ static int lfs_fs_deorphan(lfs_t *lfs) { | |||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             lfs_block_t pair[2]; | ||||||
|  |             lfs_stag_t res = lfs_dir_get(lfs, &parent, | ||||||
|  |                     LFS_MKTAG(0x7ff, 0x3ff, 0), tag, pair); | ||||||
|  |             if (res < 0) { | ||||||
|  |                 return res; | ||||||
|  |             } | ||||||
|  |             lfs_pair_fromle32(pair); | ||||||
|  |  | ||||||
|             if (!lfs_pair_sync(pair, pdir.tail)) { |             if (!lfs_pair_sync(pair, pdir.tail)) { | ||||||
|  |                 assert(false); | ||||||
|                 // we have desynced |                 // we have desynced | ||||||
|                 LFS_DEBUG("Fixing half-orphan " |                 LFS_DEBUG("Fixing half-orphan " | ||||||
|                         "%"PRIx32" %"PRIx32" -> %"PRIx32" %"PRIx32, |                         "%"PRIx32" %"PRIx32" -> %"PRIx32" %"PRIx32, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user