mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-11-01 00:38:29 +01:00 
			
		
		
		
	WIP fixed some more things
This commit is contained in:
		
							
								
								
									
										131
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -804,8 +804,11 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs, | ||||
|             // next commit not yet programmed or we're not in valid range | ||||
|             if (!lfs_tag_isvalid(tag) || | ||||
|                     off + lfs_tag_dsize(tag) > lfs->cfg->block_size) { | ||||
|                 //printf("read block %d valid %d ntag %08x ptag %08x off %d (off %d dsize %dblock %d)\n", dir->pair[0], lfs_tag_isvalid(tag), tag, ptag, dir->off, off, lfs_tag_dsize(tag), lfs->cfg->block_size); | ||||
|                 //printf("read block %d erased = %d\n", dir->pair[0], (lfs_tag_type1(ptag) == LFS_TYPE_CRC && dir->off % lfs->cfg->prog_size == 0)); | ||||
|                 dir->erased = (lfs_tag_type1(ptag) == LFS_TYPE_CRC && | ||||
|                         dir->off % lfs->cfg->prog_size == 0); | ||||
|                         dir->off % lfs->cfg->prog_size == 0 && | ||||
|                         !lfs_tag_isvalid(tag)); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
| @@ -1230,6 +1233,7 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) { | ||||
|     const lfs_off_t off1 = commit->off + sizeof(lfs_tag_t); | ||||
|     const lfs_off_t end = lfs_alignup(off1 + sizeof(uint32_t), | ||||
|             lfs->cfg->prog_size); | ||||
|     uint32_t ncrc = commit->crc; | ||||
|  | ||||
|     // create crc tags to fill up remainder of commit, note that | ||||
|     // padding is not crcd, which lets fetches skip padding but | ||||
| @@ -1266,6 +1270,7 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         ncrc = commit->crc; | ||||
|         commit->off += sizeof(tag)+lfs_tag_size(tag); | ||||
|         commit->ptag = tag ^ ((lfs_tag_t)reset << 31); | ||||
|         commit->crc = LFS_BLOCK_NULL; // reset crc for next "commit" | ||||
| @@ -1292,6 +1297,13 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) { | ||||
|                 return err; | ||||
|             } | ||||
|  | ||||
|             // check against written crc to detect if block is readonly | ||||
|             // (we may pick up old commits) | ||||
| // TODO rm me? | ||||
| //            if (i == noff && crc != ncrc) { | ||||
| //                return LFS_ERR_CORRUPT; | ||||
| //            } | ||||
|  | ||||
|             crc = lfs_crc(crc, &dat, 1); | ||||
|         } | ||||
|  | ||||
| @@ -1320,6 +1332,9 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // zero for reproducability in case initial block is unreadable | ||||
|     dir->rev = 0; | ||||
|  | ||||
|     // rather than clobbering one of the blocks we just pretend | ||||
|     // the revision may be valid | ||||
|     int err = lfs_bd_read(lfs, | ||||
| @@ -1385,6 +1400,7 @@ static int lfs_dir_split(lfs_t *lfs, | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     //dir->rev += 1; // TODO really? | ||||
|     dir->tail[0] = tail.pair[0]; | ||||
|     dir->tail[1] = tail.pair[1]; | ||||
|     dir->split = true; | ||||
| @@ -1420,9 +1436,9 @@ static int lfs_dir_compact(lfs_t *lfs, | ||||
|         lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount, | ||||
|         lfs_mdir_t *source, uint16_t begin, uint16_t end) { | ||||
|     // save some state in case block is bad | ||||
|     const lfs_block_t oldpair[2] = {dir->pair[1], dir->pair[0]}; | ||||
|     const lfs_block_t oldpair[2] = {dir->pair[0], dir->pair[1]}; | ||||
|     bool relocated = false; | ||||
|     bool exhausted = false; | ||||
|     bool tired = false; | ||||
|  | ||||
|     // should we split? | ||||
|     while (end - begin > 1) { | ||||
| @@ -1468,9 +1484,9 @@ static int lfs_dir_compact(lfs_t *lfs, | ||||
|     } | ||||
|  | ||||
|     // increment revision count | ||||
|     dir->rev += 1; | ||||
|     uint32_t nrev = dir->rev + 1; | ||||
|     if (lfs->cfg->block_cycles > 0 && | ||||
|             (dir->rev % (lfs->cfg->block_cycles+1) == 0)) { | ||||
|             (nrev % (lfs->cfg->block_cycles+1) == 0)) { | ||||
|         if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) { | ||||
|             // oh no! we're writing too much to the superblock, | ||||
|             // should we expand? | ||||
| @@ -1482,7 +1498,8 @@ static int lfs_dir_compact(lfs_t *lfs, | ||||
|             // do we have extra space? littlefs can't reclaim this space | ||||
|             // by itself, so expand cautiously | ||||
|             if ((lfs_size_t)res < lfs->cfg->block_count/2) { | ||||
|                 LFS_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev); | ||||
|                 LFS_DEBUG("Expanding superblock at rev %"PRIu32, nrev); | ||||
|                 //dir->rev += 1; // TODO hmm | ||||
|                 int err = lfs_dir_split(lfs, dir, attrs, attrcount, | ||||
|                         source, begin, end); | ||||
|                 if (err && err != LFS_ERR_NOSPC) { | ||||
| @@ -1506,7 +1523,7 @@ static int lfs_dir_compact(lfs_t *lfs, | ||||
| #endif | ||||
|         } else { | ||||
|             // we're writing too much, time to relocate | ||||
|             exhausted = true; | ||||
|             tired = true; | ||||
|             goto relocate; | ||||
|         } | ||||
|     } | ||||
| @@ -1535,10 +1552,10 @@ static int lfs_dir_compact(lfs_t *lfs, | ||||
|             } | ||||
|  | ||||
|             // write out header | ||||
|             dir->rev = lfs_tole32(dir->rev); | ||||
|             nrev = lfs_tole32(nrev); | ||||
|             err = lfs_dir_commitprog(lfs, &commit, | ||||
|                     &dir->rev, sizeof(dir->rev)); | ||||
|             dir->rev = lfs_fromle32(dir->rev); | ||||
|                     &nrev, sizeof(nrev)); | ||||
|             nrev = lfs_fromle32(nrev); | ||||
|             if (err) { | ||||
|                 if (err == LFS_ERR_CORRUPT) { | ||||
|                     goto relocate; | ||||
| @@ -1612,17 +1629,35 @@ static int lfs_dir_compact(lfs_t *lfs, | ||||
|                 return err; | ||||
|             } | ||||
|  | ||||
|             // successful compaction, swap dir pair to indicate most recent | ||||
|             // TODO huh? | ||||
|             LFS_ASSERT(commit.off % lfs->cfg->prog_size == 0); | ||||
|             lfs_pair_swap(dir->pair); | ||||
|             dir->count = end - begin; | ||||
|             dir->off = commit.off; | ||||
|             dir->etag = commit.ptag; | ||||
|             // update gstate | ||||
|             lfs->gdelta = (lfs_gstate_t){0}; | ||||
|             if (!relocated) { | ||||
|                 lfs->gdisk = lfs->gstate; | ||||
|             } | ||||
|  | ||||
|             // TODO here?? | ||||
|             if (relocated) { | ||||
|                 // update references if we relocated | ||||
|                 LFS_DEBUG("Relocating %"PRIx32" %"PRIx32" -> %"PRIx32" %"PRIx32, | ||||
|                         oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); | ||||
|                 err = lfs_fs_relocate(lfs, oldpair, dir->pair); | ||||
|                 if (err) { | ||||
|                     // TODO make better | ||||
|                     dir->pair[1] = oldpair[1]; // | ||||
|                     return err; | ||||
|                 } | ||||
|                 LFS_DEBUG("Relocated %"PRIx32" %"PRIx32" -> %"PRIx32" %"PRIx32, | ||||
|                         oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); | ||||
|             } | ||||
|  | ||||
|             // successful compaction, swap dir pair to indicate most recent | ||||
|             lfs_pair_swap(dir->pair); | ||||
|             dir->rev = nrev; | ||||
|             dir->count = end - begin; | ||||
|             dir->off = commit.off; | ||||
|             dir->etag = commit.ptag; | ||||
|         } | ||||
|         break; | ||||
|  | ||||
| @@ -1630,36 +1665,26 @@ relocate: | ||||
|         // commit was corrupted, drop caches and prepare to relocate block | ||||
|         relocated = true; | ||||
|         lfs_cache_drop(lfs, &lfs->pcache); | ||||
|         if (!exhausted) { | ||||
|         if (!tired) { | ||||
|             LFS_DEBUG("Bad block at %"PRIx32, dir->pair[1]); | ||||
|         } | ||||
|  | ||||
|         // can't relocate superblock, filesystem is now frozen | ||||
|         if (lfs_pair_cmp(oldpair, (const lfs_block_t[2]){0, 1}) == 0) { | ||||
|             LFS_WARN("Superblock %"PRIx32" has become unwritable", oldpair[1]); | ||||
|         if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) { | ||||
|             LFS_WARN("Superblock %"PRIx32" has become unwritable", dir->pair[1]); | ||||
|             return LFS_ERR_NOSPC; | ||||
|         } | ||||
|  | ||||
|         // relocate half of pair | ||||
|         int err = lfs_alloc(lfs, &dir->pair[1]); | ||||
|         if (err && (err != LFS_ERR_NOSPC || !exhausted)) { | ||||
|         if (err && (err != LFS_ERR_NOSPC || !tired)) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         exhausted = false; | ||||
|         tired = false; | ||||
|         continue; | ||||
|     } | ||||
|  | ||||
|     if (relocated) { | ||||
|         // update references if we relocated | ||||
|         LFS_DEBUG("Relocating %"PRIx32" %"PRIx32" -> %"PRIx32" %"PRIx32, | ||||
|                 oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); | ||||
|         int err = lfs_fs_relocate(lfs, oldpair, dir->pair); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -2204,16 +2229,16 @@ static int lfs_ctz_extend(lfs_t *lfs, | ||||
|                 return 0; | ||||
|             } | ||||
|  | ||||
|             size -= 1; | ||||
|             lfs_off_t index = lfs_ctz_index(lfs, &size); | ||||
|             size += 1; | ||||
|             lfs_size_t noff = size - 1; | ||||
|             lfs_off_t index = lfs_ctz_index(lfs, &noff); | ||||
|             noff = noff + 1; | ||||
|  | ||||
|             // just copy out the last block if it is incomplete | ||||
|             if (size != lfs->cfg->block_size) { | ||||
|                 for (lfs_off_t i = 0; i < size; i++) { | ||||
|             if (noff != lfs->cfg->block_size) { | ||||
|                 for (lfs_off_t i = 0; i < noff; i++) { | ||||
|                     uint8_t data; | ||||
|                     err = lfs_bd_read(lfs, | ||||
|                             NULL, rcache, size-i, | ||||
|                             NULL, rcache, noff-i, | ||||
|                             head, i, &data, 1); | ||||
|                     if (err) { | ||||
|                         return err; | ||||
| @@ -2231,19 +2256,19 @@ static int lfs_ctz_extend(lfs_t *lfs, | ||||
|                 } | ||||
|  | ||||
|                 *block = nblock; | ||||
|                 *off = size; | ||||
|                 *off = noff; | ||||
|                 return 0; | ||||
|             } | ||||
|  | ||||
|             // append block | ||||
|             index += 1; | ||||
|             lfs_size_t skips = lfs_ctz(index) + 1; | ||||
|  | ||||
|             lfs_block_t nhead = head; | ||||
|             for (lfs_off_t i = 0; i < skips; i++) { | ||||
|                 head = lfs_tole32(head); | ||||
|                 nhead = lfs_tole32(nhead); | ||||
|                 err = lfs_bd_prog(lfs, pcache, rcache, true, | ||||
|                         nblock, 4*i, &head, 4); | ||||
|                 head = lfs_fromle32(head); | ||||
|                         nblock, 4*i, &nhead, 4); | ||||
|                 nhead = lfs_fromle32(nhead); | ||||
|                 if (err) { | ||||
|                     if (err == LFS_ERR_CORRUPT) { | ||||
|                         goto relocate; | ||||
| @@ -2253,15 +2278,15 @@ static int lfs_ctz_extend(lfs_t *lfs, | ||||
|  | ||||
|                 if (i != skips-1) { | ||||
|                     err = lfs_bd_read(lfs, | ||||
|                             NULL, rcache, sizeof(head), | ||||
|                             head, 4*i, &head, sizeof(head)); | ||||
|                     head = lfs_fromle32(head); | ||||
|                             NULL, rcache, sizeof(nhead), | ||||
|                             nhead, 4*i, &nhead, sizeof(nhead)); | ||||
|                     nhead = lfs_fromle32(nhead); | ||||
|                     if (err) { | ||||
|                         return err; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 LFS_ASSERT(head >= 2 && head <= lfs->cfg->block_count); | ||||
|                 LFS_ASSERT(nhead >= 2 && nhead <= lfs->cfg->block_count); | ||||
|             } | ||||
|  | ||||
|             *block = nblock; | ||||
| @@ -3821,6 +3846,17 @@ int lfs_fs_traverse(lfs_t *lfs, | ||||
|                     LFS_TRACE("lfs_fs_traverse -> %d", err); | ||||
|                     return err; | ||||
|                 } | ||||
|             } else if (lfs_gstate_hasorphans(&lfs->gstate) && | ||||
|                     lfs_tag_type3(tag) == LFS_TYPE_DIRSTRUCT) { | ||||
|                 // TODO HMMMMMM HMMMMMMMMMMMMMMMMMMM | ||||
|                 for (int i = 0; i < 2; i++) { | ||||
|                     //printf("HMM %x\n", (&ctz.head)[i]); | ||||
|                     err = cb(data, (&ctz.head)[i]); | ||||
|                     if (err) { | ||||
|                         LFS_TRACE("lfs_fs_traverse -> %d", err); | ||||
|                         return err; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -3902,7 +3938,9 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2], | ||||
|     // use fetchmatch with callback to find pairs | ||||
|     parent->tail[0] = 0; | ||||
|     parent->tail[1] = 1; | ||||
|     int i = 0; | ||||
|     while (!lfs_pair_isnull(parent->tail)) { | ||||
|         i += 1; | ||||
|         lfs_stag_t tag = lfs_dir_fetchmatch(lfs, parent, parent->tail, | ||||
|                 LFS_MKTAG(0x7ff, 0, 0x3ff), | ||||
|                 LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, 8), | ||||
| @@ -3910,6 +3948,7 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2], | ||||
|                 lfs_fs_parent_match, &(struct lfs_fs_parent_match){ | ||||
|                     lfs, {pair[0], pair[1]}}); | ||||
|         if (tag && tag != LFS_ERR_NOENT) { | ||||
|             //printf("PARENT %d\n", i); | ||||
|             return tag; | ||||
|         } | ||||
|     } | ||||
| @@ -3966,6 +4005,7 @@ static int lfs_fs_relocate(lfs_t *lfs, | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //printf("parent %x %x\n", parent.pair[0], parent.pair[1]); | ||||
|         lfs_pair_tole32(newpair); | ||||
|         int err = lfs_dir_commit(lfs, &parent, LFS_MKATTRS( | ||||
|                 {LFS_MKTAG_IF(moveid != 0x3ff, | ||||
| @@ -4000,6 +4040,7 @@ static int lfs_fs_relocate(lfs_t *lfs, | ||||
|         } | ||||
|  | ||||
|         // replace bad pair, either we clean up desync, or no desync occured | ||||
|         //printf("pred %x %x\n", parent.pair[0], parent.pair[1]); | ||||
|         lfs_pair_tole32(newpair); | ||||
|         err = lfs_dir_commit(lfs, &parent, LFS_MKATTRS( | ||||
|                 {LFS_MKTAG_IF(moveid != 0x3ff, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user