Lines Matching +full:- +full:minor
5 * SPDX-License-Identifier: BSD-3-Clause
10 #define LFS_BLOCK_NULL ((lfs_block_t)-1)
11 #define LFS_BLOCK_INLINE ((lfs_block_t)-2)
18 rcache->block = LFS_BLOCK_NULL; in lfs_cache_drop()
23 memset(pcache->buffer, 0xff, lfs->cfg->cache_size); in lfs_cache_zero()
24 pcache->block = LFS_BLOCK_NULL; in lfs_cache_zero()
32 if (block >= lfs->cfg->block_count || in lfs_bd_read()
33 off+size > lfs->cfg->block_size) { in lfs_bd_read()
40 if (pcache && block == pcache->block && in lfs_bd_read()
41 off < pcache->off + pcache->size) { in lfs_bd_read()
42 if (off >= pcache->off) { in lfs_bd_read()
44 diff = lfs_min(diff, pcache->size - (off-pcache->off)); in lfs_bd_read()
45 memcpy(data, &pcache->buffer[off-pcache->off], diff); in lfs_bd_read()
49 size -= diff; in lfs_bd_read()
54 diff = lfs_min(diff, pcache->off-off); in lfs_bd_read()
57 if (block == rcache->block && in lfs_bd_read()
58 off < rcache->off + rcache->size) { in lfs_bd_read()
59 if (off >= rcache->off) { in lfs_bd_read()
61 diff = lfs_min(diff, rcache->size - (off-rcache->off)); in lfs_bd_read()
62 memcpy(data, &rcache->buffer[off-rcache->off], diff); in lfs_bd_read()
66 size -= diff; in lfs_bd_read()
71 diff = lfs_min(diff, rcache->off-off); in lfs_bd_read()
74 if (size >= hint && off % lfs->cfg->read_size == 0 && in lfs_bd_read()
75 size >= lfs->cfg->read_size) { in lfs_bd_read()
77 diff = lfs_aligndown(diff, lfs->cfg->read_size); in lfs_bd_read()
78 int err = lfs->cfg->read(lfs->cfg, block, off, data, diff); in lfs_bd_read()
85 size -= diff; in lfs_bd_read()
90 LFS_ASSERT(block < lfs->cfg->block_count); in lfs_bd_read()
91 rcache->block = block; in lfs_bd_read()
92 rcache->off = lfs_aligndown(off, lfs->cfg->read_size); in lfs_bd_read()
93 rcache->size = lfs_min( in lfs_bd_read()
95 lfs_alignup(off+hint, lfs->cfg->read_size), in lfs_bd_read()
96 lfs->cfg->block_size) in lfs_bd_read()
97 - rcache->off, in lfs_bd_read()
98 lfs->cfg->cache_size); in lfs_bd_read()
99 int err = lfs->cfg->read(lfs->cfg, rcache->block, in lfs_bd_read()
100 rcache->off, rcache->buffer, rcache->size); in lfs_bd_read()
125 pcache, rcache, hint-i, in lfs_bd_cmp()
141 if (pcache->block != LFS_BLOCK_NULL && pcache->block != LFS_BLOCK_INLINE) { in lfs_bd_flush()
142 LFS_ASSERT(pcache->block < lfs->cfg->block_count); in lfs_bd_flush()
143 lfs_size_t diff = lfs_alignup(pcache->size, lfs->cfg->prog_size); in lfs_bd_flush()
144 int err = lfs->cfg->prog(lfs->cfg, pcache->block, in lfs_bd_flush()
145 pcache->off, pcache->buffer, diff); in lfs_bd_flush()
156 pcache->block, pcache->off, pcache->buffer, diff); in lfs_bd_flush()
181 err = lfs->cfg->sync(lfs->cfg); in lfs_bd_sync()
191 LFS_ASSERT(block == LFS_BLOCK_INLINE || block < lfs->cfg->block_count); in lfs_bd_prog()
192 LFS_ASSERT(off + size <= lfs->cfg->block_size); in lfs_bd_prog()
195 if (block == pcache->block && in lfs_bd_prog()
196 off >= pcache->off && in lfs_bd_prog()
197 off < pcache->off + lfs->cfg->cache_size) { in lfs_bd_prog()
200 lfs->cfg->cache_size - (off-pcache->off)); in lfs_bd_prog()
201 memcpy(&pcache->buffer[off-pcache->off], data, diff); in lfs_bd_prog()
205 size -= diff; in lfs_bd_prog()
207 pcache->size = lfs_max(pcache->size, off - pcache->off); in lfs_bd_prog()
208 if (pcache->size == lfs->cfg->cache_size) { in lfs_bd_prog()
221 LFS_ASSERT(pcache->block == LFS_BLOCK_NULL); in lfs_bd_prog()
224 pcache->block = block; in lfs_bd_prog()
225 pcache->off = lfs_aligndown(off, lfs->cfg->prog_size); in lfs_bd_prog()
226 pcache->size = 0; in lfs_bd_prog()
233 LFS_ASSERT(block < lfs->cfg->block_count); in lfs_bd_erase()
234 int err = lfs->cfg->erase(lfs->cfg, block); in lfs_bd_erase()
240 /// Small type-level utilities ///
276 // operations on 32-bit entry tags
294 return ((int32_t)(tag << 22) >> 22) == -1; in lfs_tag_isdelete()
357 return lfs_tag_size(a->tag); in lfs_gstate_hasorphans()
361 return lfs_tag_size(a->tag); in lfs_gstate_getorphans()
365 return lfs_tag_type1(a->tag); in lfs_gstate_hasmove()
370 return lfs_tag_type1(a->tag) && lfs_pair_cmp(a->pair, pair) == 0; in lfs_gstate_hasmovehere()
374 a->tag = lfs_fromle32(a->tag); in lfs_gstate_fromle32()
375 a->pair[0] = lfs_fromle32(a->pair[0]); in lfs_gstate_fromle32()
376 a->pair[1] = lfs_fromle32(a->pair[1]); in lfs_gstate_fromle32()
380 a->tag = lfs_tole32(a->tag); in lfs_gstate_tole32()
381 a->pair[0] = lfs_tole32(a->pair[0]); in lfs_gstate_tole32()
382 a->pair[1] = lfs_tole32(a->pair[1]); in lfs_gstate_tole32()
387 ctz->head = lfs_fromle32(ctz->head); in lfs_ctz_fromle32()
388 ctz->size = lfs_fromle32(ctz->size); in lfs_ctz_fromle32()
392 ctz->head = lfs_tole32(ctz->head); in lfs_ctz_tole32()
393 ctz->size = lfs_tole32(ctz->size); in lfs_ctz_tole32()
397 superblock->version = lfs_fromle32(superblock->version); in lfs_superblock_fromle32()
398 superblock->block_size = lfs_fromle32(superblock->block_size); in lfs_superblock_fromle32()
399 superblock->block_count = lfs_fromle32(superblock->block_count); in lfs_superblock_fromle32()
400 superblock->name_max = lfs_fromle32(superblock->name_max); in lfs_superblock_fromle32()
401 superblock->file_max = lfs_fromle32(superblock->file_max); in lfs_superblock_fromle32()
402 superblock->attr_max = lfs_fromle32(superblock->attr_max); in lfs_superblock_fromle32()
406 superblock->version = lfs_tole32(superblock->version); in lfs_superblock_tole32()
407 superblock->block_size = lfs_tole32(superblock->block_size); in lfs_superblock_tole32()
408 superblock->block_count = lfs_tole32(superblock->block_count); in lfs_superblock_tole32()
409 superblock->name_max = lfs_tole32(superblock->name_max); in lfs_superblock_tole32()
410 superblock->file_max = lfs_tole32(superblock->file_max); in lfs_superblock_tole32()
411 superblock->attr_max = lfs_tole32(superblock->attr_max); in lfs_superblock_tole32()
445 lfs_block_t off = ((block - lfs->free.off) in lfs_alloc_lookahead()
446 + lfs->cfg->block_count) % lfs->cfg->block_count; in lfs_alloc_lookahead()
448 if (off < lfs->free.size) { in lfs_alloc_lookahead()
449 lfs->free.buffer[off / 32] |= 1U << (off % 32); in lfs_alloc_lookahead()
456 lfs->free.ack = lfs->cfg->block_count; in lfs_alloc_ack()
462 lfs->free.off = lfs->seed % lfs->cfg->block_size; in lfs_alloc_reset()
463 lfs->free.size = 0; in lfs_alloc_reset()
464 lfs->free.i = 0; in lfs_alloc_reset()
470 while (lfs->free.i != lfs->free.size) { in lfs_alloc()
471 lfs_block_t off = lfs->free.i; in lfs_alloc()
472 lfs->free.i += 1; in lfs_alloc()
473 lfs->free.ack -= 1; in lfs_alloc()
475 if (!(lfs->free.buffer[off / 32] & (1U << (off % 32)))) { in lfs_alloc()
477 *block = (lfs->free.off + off) % lfs->cfg->block_count; in lfs_alloc()
481 while (lfs->free.i != lfs->free.size && in lfs_alloc()
482 (lfs->free.buffer[lfs->free.i / 32] in lfs_alloc()
483 & (1U << (lfs->free.i % 32)))) { in lfs_alloc()
484 lfs->free.i += 1; in lfs_alloc()
485 lfs->free.ack -= 1; in lfs_alloc()
493 if (lfs->free.ack == 0) { in lfs_alloc()
495 lfs->free.i + lfs->free.off); in lfs_alloc()
499 lfs->free.off = (lfs->free.off + lfs->free.size) in lfs_alloc()
500 % lfs->cfg->block_count; in lfs_alloc()
501 lfs->free.size = lfs_min(8*lfs->cfg->lookahead_size, lfs->free.ack); in lfs_alloc()
502 lfs->free.i = 0; in lfs_alloc()
505 memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size); in lfs_alloc()
518 lfs_off_t off = dir->off; in lfs_dir_getslice()
519 lfs_tag_t ntag = dir->etag; in lfs_dir_getslice()
522 if (lfs_gstate_hasmovehere(&lfs->gdisk, dir->pair) && in lfs_dir_getslice()
524 lfs_tag_id(lfs->gdisk.tag) <= lfs_tag_id(gtag)) { in lfs_dir_getslice()
526 gdiff -= LFS_MKTAG(0, 1, 0); in lfs_dir_getslice()
531 off -= lfs_tag_dsize(ntag); in lfs_dir_getslice()
534 NULL, &lfs->rcache, sizeof(ntag), in lfs_dir_getslice()
535 dir->pair[0], off, &ntag, sizeof(ntag)); in lfs_dir_getslice()
544 lfs_tag_id(tag) <= lfs_tag_id(gtag - gdiff)) { in lfs_dir_getslice()
546 (LFS_MKTAG(0, 0x3ff, 0) & (gtag - gdiff)))) { in lfs_dir_getslice()
555 if ((gmask & tag) == (gmask & (gtag - gdiff))) { in lfs_dir_getslice()
562 NULL, &lfs->rcache, diff, in lfs_dir_getslice()
563 dir->pair[0], off+sizeof(tag)+goff, gbuffer, diff); in lfs_dir_getslice()
568 memset((uint8_t*)gbuffer + diff, 0, gsize - diff); in lfs_dir_getslice()
589 if (off+size > lfs->cfg->block_size) { in lfs_dir_getread()
596 if (pcache && pcache->block == LFS_BLOCK_INLINE && in lfs_dir_getread()
597 off < pcache->off + pcache->size) { in lfs_dir_getread()
598 if (off >= pcache->off) { in lfs_dir_getread()
600 diff = lfs_min(diff, pcache->size - (off-pcache->off)); in lfs_dir_getread()
601 memcpy(data, &pcache->buffer[off-pcache->off], diff); in lfs_dir_getread()
605 size -= diff; in lfs_dir_getread()
610 diff = lfs_min(diff, pcache->off-off); in lfs_dir_getread()
613 if (rcache->block == LFS_BLOCK_INLINE && in lfs_dir_getread()
614 off < rcache->off + rcache->size) { in lfs_dir_getread()
615 if (off >= rcache->off) { in lfs_dir_getread()
617 diff = lfs_min(diff, rcache->size - (off-rcache->off)); in lfs_dir_getread()
618 memcpy(data, &rcache->buffer[off-rcache->off], diff); in lfs_dir_getread()
622 size -= diff; in lfs_dir_getread()
627 diff = lfs_min(diff, rcache->off-off); in lfs_dir_getread()
631 rcache->block = LFS_BLOCK_INLINE; in lfs_dir_getread()
632 rcache->off = lfs_aligndown(off, lfs->cfg->read_size); in lfs_dir_getread()
633 rcache->size = lfs_min(lfs_alignup(off+hint, lfs->cfg->read_size), in lfs_dir_getread()
634 lfs->cfg->cache_size); in lfs_dir_getread()
636 rcache->off, rcache->buffer, rcache->size); in lfs_dir_getread()
684 if (off+lfs_tag_dsize(ptag) < dir->off) { in lfs_dir_traverse()
687 NULL, &lfs->rcache, sizeof(tag), in lfs_dir_traverse()
688 dir->pair[0], off, &tag, sizeof(tag)); in lfs_dir_traverse()
694 disk.block = dir->pair[0]; in lfs_dir_traverse()
702 attrcount -= 1; in lfs_dir_traverse()
713 // for some minor optimizations in lfs_dir_traverse()
734 // handle special cases for mcu-side operations in lfs_dir_traverse()
744 fromid, fromid+1, toid-fromid+diff, in lfs_dir_traverse()
773 lfs_stag_t besttag = -1; in lfs_dir_fetchmatch()
777 if (pair[0] >= lfs->cfg->block_count || pair[1] >= lfs->cfg->block_count) { in lfs_dir_fetchmatch()
786 NULL, &lfs->rcache, sizeof(revs[i]), in lfs_dir_fetchmatch()
799 dir->pair[0] = pair[(r+0)%2]; in lfs_dir_fetchmatch()
800 dir->pair[1] = pair[(r+1)%2]; in lfs_dir_fetchmatch()
801 dir->rev = revs[(r+0)%2]; in lfs_dir_fetchmatch()
802 dir->off = 0; // nonzero = found some commits in lfs_dir_fetchmatch()
814 dir->rev = lfs_tole32(dir->rev); in lfs_dir_fetchmatch()
815 uint32_t crc = lfs_crc(0xffffffff, &dir->rev, sizeof(dir->rev)); in lfs_dir_fetchmatch()
816 dir->rev = lfs_fromle32(dir->rev); in lfs_dir_fetchmatch()
823 NULL, &lfs->rcache, lfs->cfg->block_size, in lfs_dir_fetchmatch()
824 dir->pair[0], off, &tag, sizeof(tag)); in lfs_dir_fetchmatch()
828 dir->erased = false; in lfs_dir_fetchmatch()
839 dir->erased = (lfs_tag_type1(ptag) == LFS_TYPE_CRC && in lfs_dir_fetchmatch()
840 dir->off % lfs->cfg->prog_size == 0); in lfs_dir_fetchmatch()
842 } else if (off + lfs_tag_dsize(tag) > lfs->cfg->block_size) { in lfs_dir_fetchmatch()
843 dir->erased = false; in lfs_dir_fetchmatch()
853 NULL, &lfs->rcache, lfs->cfg->block_size, in lfs_dir_fetchmatch()
854 dir->pair[0], off+sizeof(tag), &dcrc, sizeof(dcrc)); in lfs_dir_fetchmatch()
857 dir->erased = false; in lfs_dir_fetchmatch()
865 dir->erased = false; in lfs_dir_fetchmatch()
874 lfs->seed ^= crc; in lfs_dir_fetchmatch()
878 dir->off = off + lfs_tag_dsize(tag); in lfs_dir_fetchmatch()
879 dir->etag = ptag; in lfs_dir_fetchmatch()
880 dir->count = tempcount; in lfs_dir_fetchmatch()
881 dir->tail[0] = temptail[0]; in lfs_dir_fetchmatch()
882 dir->tail[1] = temptail[1]; in lfs_dir_fetchmatch()
883 dir->split = tempsplit; in lfs_dir_fetchmatch()
894 NULL, &lfs->rcache, lfs->cfg->block_size, in lfs_dir_fetchmatch()
895 dir->pair[0], off+j, &dat, 1); in lfs_dir_fetchmatch()
898 dir->erased = false; in lfs_dir_fetchmatch()
919 } else if (tempbesttag != -1 && in lfs_dir_fetchmatch()
927 NULL, &lfs->rcache, lfs->cfg->block_size, in lfs_dir_fetchmatch()
928 dir->pair[0], off+sizeof(tag), &temptail, 8); in lfs_dir_fetchmatch()
931 dir->erased = false; in lfs_dir_fetchmatch()
941 dir->pair[0], off+sizeof(tag)}); in lfs_dir_fetchmatch()
944 dir->erased = false; in lfs_dir_fetchmatch()
957 tempbesttag = -1; in lfs_dir_fetchmatch()
967 if (dir->off > 0) { in lfs_dir_fetchmatch()
969 if (lfs_gstate_hasmovehere(&lfs->gdisk, dir->pair)) { in lfs_dir_fetchmatch()
970 if (lfs_tag_id(lfs->gdisk.tag) == lfs_tag_id(besttag)) { in lfs_dir_fetchmatch()
972 } else if (besttag != -1 && in lfs_dir_fetchmatch()
973 lfs_tag_id(lfs->gdisk.tag) < lfs_tag_id(besttag)) { in lfs_dir_fetchmatch()
974 besttag -= LFS_MKTAG(0, 1, 0); in lfs_dir_fetchmatch()
980 *id = lfs_min(lfs_tag_id(besttag), dir->count); in lfs_dir_fetchmatch()
985 } else if (lfs_tag_id(besttag) < dir->count) { in lfs_dir_fetchmatch()
993 lfs_pair_swap(dir->pair); in lfs_dir_fetchmatch()
994 dir->rev = revs[(r+1)%2]; in lfs_dir_fetchmatch()
998 dir->pair[0], dir->pair[1]); in lfs_dir_fetchmatch()
1004 // note, mask=-1, tag=-1 can never match a tag since this in lfs_dir_fetch()
1007 (lfs_tag_t)-1, (lfs_tag_t)-1, NULL, NULL, NULL); in lfs_dir_fetch()
1032 strcpy(info->name, "/"); in lfs_dir_getinfo()
1033 info->type = LFS_TYPE_DIR; in lfs_dir_getinfo()
1038 LFS_MKTAG(LFS_TYPE_NAME, id, lfs->name_max+1), info->name); in lfs_dir_getinfo()
1043 info->type = lfs_tag_type3(tag); in lfs_dir_getinfo()
1054 info->size = ctz.size; in lfs_dir_getinfo()
1056 info->size = lfs_tag_size(tag); in lfs_dir_getinfo()
1071 lfs_t *lfs = name->lfs; in lfs_dir_find_match()
1075 lfs_size_t diff = lfs_min(name->size, lfs_tag_size(tag)); in lfs_dir_find_match()
1077 NULL, &lfs->rcache, diff, in lfs_dir_find_match()
1078 disk->block, disk->off, name->name, diff); in lfs_dir_find_match()
1084 if (name->size != lfs_tag_size(tag)) { in lfs_dir_find_match()
1085 return (name->size < lfs_tag_size(tag)) ? LFS_CMP_LT : LFS_CMP_GT; in lfs_dir_find_match()
1102 dir->tail[0] = lfs->root[0]; in lfs_dir_find()
1103 dir->tail[1] = lfs->root[1]; in lfs_dir_find()
1130 depth -= 1; in lfs_dir_find()
1158 LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), dir->tail); in lfs_dir_find()
1162 lfs_pair_fromle32(dir->tail); in lfs_dir_find()
1167 tag = lfs_dir_fetchmatch(lfs, dir, dir->tail, in lfs_dir_find()
1182 if (!dir->split) { in lfs_dir_find()
1206 &lfs->pcache, &lfs->rcache, false, in lfs_dir_commitprog()
1207 commit->block, commit->off , in lfs_dir_commitprog()
1213 commit->crc = lfs_crc(commit->crc, buffer, size); in lfs_dir_commitprog()
1214 commit->off += size; in lfs_dir_commitprog()
1222 if (commit->off + dsize > commit->end) { in lfs_dir_commitattr()
1227 lfs_tag_t ntag = lfs_tobe32((tag & 0x7fffffff) ^ commit->ptag); in lfs_dir_commitattr()
1235 err = lfs_dir_commitprog(lfs, commit, buffer, dsize-sizeof(tag)); in lfs_dir_commitattr()
1242 for (lfs_off_t i = 0; i < dsize-sizeof(tag); i++) { in lfs_dir_commitattr()
1246 NULL, &lfs->rcache, dsize-sizeof(tag)-i, in lfs_dir_commitattr()
1247 disk->block, disk->off+i, &dat, 1); in lfs_dir_commitattr()
1259 commit->ptag = tag & 0x7fffffff; in lfs_dir_commitattr()
1264 const lfs_off_t off1 = commit->off; in lfs_dir_commitcrc()
1265 const uint32_t crc1 = commit->crc; in lfs_dir_commitcrc()
1268 lfs->cfg->prog_size); in lfs_dir_commitcrc()
1273 while (commit->off < end) { in lfs_dir_commitcrc()
1274 lfs_off_t off = commit->off + sizeof(lfs_tag_t); in lfs_dir_commitcrc()
1275 lfs_off_t noff = lfs_min(end - off, 0x3fe) + off; in lfs_dir_commitcrc()
1277 noff = lfs_min(noff, end - 2*sizeof(uint32_t)); in lfs_dir_commitcrc()
1283 NULL, &lfs->rcache, sizeof(tag), in lfs_dir_commitcrc()
1284 commit->block, noff, &tag, sizeof(tag)); in lfs_dir_commitcrc()
1291 tag = LFS_MKTAG(LFS_TYPE_CRC + reset, 0x3ff, noff - off); in lfs_dir_commitcrc()
1295 footer[0] = lfs_tobe32(tag ^ commit->ptag); in lfs_dir_commitcrc()
1296 commit->crc = lfs_crc(commit->crc, &footer[0], sizeof(footer[0])); in lfs_dir_commitcrc()
1297 footer[1] = lfs_tole32(commit->crc); in lfs_dir_commitcrc()
1299 &lfs->pcache, &lfs->rcache, false, in lfs_dir_commitcrc()
1300 commit->block, commit->off, &footer, sizeof(footer)); in lfs_dir_commitcrc()
1305 commit->off += sizeof(tag)+lfs_tag_size(tag); in lfs_dir_commitcrc()
1306 commit->ptag = tag ^ ((lfs_tag_t)reset << 31); in lfs_dir_commitcrc()
1307 commit->crc = 0xffffffff; // reset crc for next "commit" in lfs_dir_commitcrc()
1311 int err = lfs_bd_sync(lfs, &lfs->pcache, &lfs->rcache, false); in lfs_dir_commitcrc()
1317 lfs_off_t off = commit->begin; in lfs_dir_commitcrc()
1331 NULL, &lfs->rcache, noff+sizeof(uint32_t)-i, in lfs_dir_commitcrc()
1332 commit->block, i, &dat, 1); in lfs_dir_commitcrc()
1346 off = lfs_min(end - noff, 0x3fe) + noff; in lfs_dir_commitcrc()
1348 off = lfs_min(off, end - 2*sizeof(uint32_t)); in lfs_dir_commitcrc()
1359 int err = lfs_alloc(lfs, &dir->pair[(i+1)%2]); in lfs_dir_alloc()
1366 dir->rev = 0; in lfs_dir_alloc()
1371 NULL, &lfs->rcache, sizeof(dir->rev), in lfs_dir_alloc()
1372 dir->pair[0], 0, &dir->rev, sizeof(dir->rev)); in lfs_dir_alloc()
1373 dir->rev = lfs_fromle32(dir->rev); in lfs_dir_alloc()
1379 dir->rev += dir->rev & 1; in lfs_dir_alloc()
1382 dir->off = sizeof(dir->rev); in lfs_dir_alloc()
1383 dir->etag = 0xffffffff; in lfs_dir_alloc()
1384 dir->count = 0; in lfs_dir_alloc()
1385 dir->tail[0] = LFS_BLOCK_NULL; in lfs_dir_alloc()
1386 dir->tail[1] = LFS_BLOCK_NULL; in lfs_dir_alloc()
1387 dir->erased = false; in lfs_dir_alloc()
1388 dir->split = false; in lfs_dir_alloc()
1396 int err = lfs_dir_getgstate(lfs, tail, &lfs->gdelta); in lfs_dir_drop()
1402 lfs_pair_tole32(tail->tail); in lfs_dir_drop()
1404 {LFS_MKTAG(LFS_TYPE_TAIL + tail->split, 0x3ff, 8), tail->tail})); in lfs_dir_drop()
1405 lfs_pair_fromle32(tail->tail); in lfs_dir_drop()
1424 tail.split = dir->split; in lfs_dir_split()
1425 tail.tail[0] = dir->tail[0]; in lfs_dir_split()
1426 tail.tail[1] = dir->tail[1]; in lfs_dir_split()
1433 dir->tail[0] = tail.pair[0]; in lfs_dir_split()
1434 dir->tail[1] = tail.pair[1]; in lfs_dir_split()
1435 dir->split = true; in lfs_dir_split()
1438 if (lfs_pair_cmp(dir->pair, lfs->root) == 0 && split == 0) { in lfs_dir_split()
1439 lfs->root[0] = tail.pair[0]; in lfs_dir_split()
1440 lfs->root[1] = tail.pair[1]; in lfs_dir_split()
1461 return lfs_dir_commitattr(commit->lfs, commit->commit, tag, buffer); in lfs_dir_commit_commit()
1468 const lfs_block_t oldpair[2] = {dir->pair[0], dir->pair[1]}; in lfs_dir_compact()
1473 while (end - begin > 1) { in lfs_dir_compact()
1480 begin, end, -begin, in lfs_dir_compact()
1489 if (end - begin < 0xff && in lfs_dir_compact()
1490 size <= lfs_min(lfs->cfg->block_size - 36, in lfs_dir_compact()
1491 lfs_alignup(lfs->cfg->block_size/2, in lfs_dir_compact()
1492 lfs->cfg->prog_size))) { in lfs_dir_compact()
1499 uint16_t split = (end - begin) / 2; in lfs_dir_compact()
1506 if (err == LFS_ERR_NOSPC && size <= lfs->cfg->block_size - 36) { in lfs_dir_compact()
1516 dir->rev += 1; in lfs_dir_compact()
1518 // this is how littlefs wear-levels at the metadata-pair level. Note that we in lfs_dir_compact()
1523 if (lfs->cfg->block_cycles > 0 && in lfs_dir_compact()
1524 (dir->rev % ((lfs->cfg->block_cycles+1)|1) == 0)) { in lfs_dir_compact()
1525 if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) { in lfs_dir_compact()
1535 if ((lfs_size_t)res < lfs->cfg->block_count/2) { in lfs_dir_compact()
1536 LFS_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev); in lfs_dir_compact()
1550 } else if (lfs->lfs1) { in lfs_dir_compact()
1570 .block = dir->pair[1], in lfs_dir_compact()
1576 .end = lfs->cfg->block_size - 8, in lfs_dir_compact()
1580 int err = lfs_bd_erase(lfs, dir->pair[1]); in lfs_dir_compact()
1589 dir->rev = lfs_tole32(dir->rev); in lfs_dir_compact()
1591 &dir->rev, sizeof(dir->rev)); in lfs_dir_compact()
1592 dir->rev = lfs_fromle32(dir->rev); in lfs_dir_compact()
1605 begin, end, -begin, in lfs_dir_compact()
1616 if (!lfs_pair_isnull(dir->tail)) { in lfs_dir_compact()
1617 lfs_pair_tole32(dir->tail); in lfs_dir_compact()
1619 LFS_MKTAG(LFS_TYPE_TAIL + dir->split, 0x3ff, 8), in lfs_dir_compact()
1620 dir->tail); in lfs_dir_compact()
1621 lfs_pair_fromle32(dir->tail); in lfs_dir_compact()
1633 lfs_gstate_xor(&delta, &lfs->gdisk); in lfs_dir_compact()
1634 lfs_gstate_xor(&delta, &lfs->gstate); in lfs_dir_compact()
1636 lfs_gstate_xor(&delta, &lfs->gdelta); in lfs_dir_compact()
1667 LFS_ASSERT(commit.off % lfs->cfg->prog_size == 0); in lfs_dir_compact()
1668 lfs_pair_swap(dir->pair); in lfs_dir_compact()
1669 dir->count = end - begin; in lfs_dir_compact()
1670 dir->off = commit.off; in lfs_dir_compact()
1671 dir->etag = commit.ptag; in lfs_dir_compact()
1673 lfs->gdelta = (lfs_gstate_t){0}; in lfs_dir_compact()
1675 lfs->gdisk = lfs->gstate; in lfs_dir_compact()
1683 lfs_cache_drop(lfs, &lfs->pcache); in lfs_dir_compact()
1685 LFS_DEBUG("Bad block at 0x%"PRIx32, dir->pair[1]); in lfs_dir_compact()
1689 if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) { in lfs_dir_compact()
1691 dir->pair[1]); in lfs_dir_compact()
1696 int err = lfs_alloc(lfs, &dir->pair[1]); in lfs_dir_compact()
1708 "-> {0x%"PRIx32", 0x%"PRIx32"}", in lfs_dir_compact()
1709 oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); in lfs_dir_compact()
1710 int err = lfs_fs_relocate(lfs, oldpair, dir->pair); in lfs_dir_compact()
1723 for (lfs_file_t *f = (lfs_file_t*)lfs->mlist; f; f = f->next) { in lfs_dir_commit()
1724 if (dir != &f->m && lfs_pair_cmp(f->m.pair, dir->pair) == 0 && in lfs_dir_commit()
1725 f->type == LFS_TYPE_REG && (f->flags & LFS_F_INLINE) && in lfs_dir_commit()
1726 f->ctz.size > lfs->cfg->cache_size) { in lfs_dir_commit()
1744 dir->count += 1; in lfs_dir_commit()
1746 LFS_ASSERT(dir->count > 0); in lfs_dir_commit()
1747 dir->count -= 1; in lfs_dir_commit()
1750 dir->tail[0] = ((lfs_block_t*)attrs[i].buffer)[0]; in lfs_dir_commit()
1751 dir->tail[1] = ((lfs_block_t*)attrs[i].buffer)[1]; in lfs_dir_commit()
1752 dir->split = (lfs_tag_chunk(attrs[i].tag) & 1); in lfs_dir_commit()
1753 lfs_pair_fromle32(dir->tail); in lfs_dir_commit()
1758 if (hasdelete && dir->count == 0) { in lfs_dir_commit()
1760 int err = lfs_fs_pred(lfs, dir->pair, &pdir); in lfs_dir_commit()
1775 if (dir->erased || dir->count >= 0xff) { in lfs_dir_commit()
1778 .block = dir->pair[0], in lfs_dir_commit()
1779 .off = dir->off, in lfs_dir_commit()
1780 .ptag = dir->etag, in lfs_dir_commit()
1783 .begin = dir->off, in lfs_dir_commit()
1784 .end = lfs->cfg->block_size - 8, in lfs_dir_commit()
1788 lfs_pair_tole32(dir->tail); in lfs_dir_commit()
1790 dir, dir->off, dir->etag, attrs, attrcount, in lfs_dir_commit()
1794 lfs_pair_fromle32(dir->tail); in lfs_dir_commit()
1805 lfs_gstate_xor(&delta, &lfs->gstate); in lfs_dir_commit()
1806 lfs_gstate_xor(&delta, &lfs->gdisk); in lfs_dir_commit()
1807 lfs_gstate_xor(&delta, &lfs->gdelta); in lfs_dir_commit()
1840 LFS_ASSERT(commit.off % lfs->cfg->prog_size == 0); in lfs_dir_commit()
1841 dir->off = commit.off; in lfs_dir_commit()
1842 dir->etag = commit.ptag; in lfs_dir_commit()
1844 lfs->gdisk = lfs->gstate; in lfs_dir_commit()
1845 lfs->gdelta = (lfs_gstate_t){0}; in lfs_dir_commit()
1849 lfs_cache_drop(lfs, &lfs->pcache); in lfs_dir_commit()
1852 dir, 0, dir->count); in lfs_dir_commit()
1860 // metadata-pairs that we may have affected in lfs_dir_commit()
1866 for (struct lfs_mlist *d = lfs->mlist; d; d = d->next) { in lfs_dir_commit()
1867 if (&d->m != dir && lfs_pair_cmp(d->m.pair, olddir.pair) == 0) { in lfs_dir_commit()
1868 d->m = *dir; in lfs_dir_commit()
1871 d->id == lfs_tag_id(attrs[i].tag)) { in lfs_dir_commit()
1872 d->m.pair[0] = LFS_BLOCK_NULL; in lfs_dir_commit()
1873 d->m.pair[1] = LFS_BLOCK_NULL; in lfs_dir_commit()
1875 d->id > lfs_tag_id(attrs[i].tag)) { in lfs_dir_commit()
1876 d->id -= 1; in lfs_dir_commit()
1877 if (d->type == LFS_TYPE_DIR) { in lfs_dir_commit()
1878 ((lfs_dir_t*)d)->pos -= 1; in lfs_dir_commit()
1881 d->id >= lfs_tag_id(attrs[i].tag)) { in lfs_dir_commit()
1882 d->id += 1; in lfs_dir_commit()
1883 if (d->type == LFS_TYPE_DIR) { in lfs_dir_commit()
1884 ((lfs_dir_t*)d)->pos += 1; in lfs_dir_commit()
1891 for (struct lfs_mlist *d = lfs->mlist; d; d = d->next) { in lfs_dir_commit()
1892 if (lfs_pair_cmp(d->m.pair, olddir.pair) == 0) { in lfs_dir_commit()
1893 while (d->id >= d->m.count && d->m.split) { in lfs_dir_commit()
1895 d->id -= d->m.count; in lfs_dir_commit()
1896 int err = lfs_dir_fetch(lfs, &d->m, d->m.tail); in lfs_dir_commit()
1914 LFS_TRACE("lfs_mkdir -> %d", err); in lfs_mkdir()
1919 cwd.next = lfs->mlist; in lfs_mkdir()
1923 LFS_TRACE("lfs_mkdir -> %d", (err < 0) ? err : LFS_ERR_EXIST); in lfs_mkdir()
1929 if (nlen > lfs->name_max) { in lfs_mkdir()
1930 LFS_TRACE("lfs_mkdir -> %d", LFS_ERR_NAMETOOLONG); in lfs_mkdir()
1939 LFS_TRACE("lfs_mkdir -> %d", err); in lfs_mkdir()
1948 LFS_TRACE("lfs_mkdir -> %d", err); in lfs_mkdir()
1959 LFS_TRACE("lfs_mkdir -> %d", err); in lfs_mkdir()
1974 lfs->mlist = &cwd; in lfs_mkdir()
1981 lfs->mlist = cwd.next; in lfs_mkdir()
1982 LFS_TRACE("lfs_mkdir -> %d", err); in lfs_mkdir()
1986 lfs->mlist = cwd.next; in lfs_mkdir()
1987 lfs_fs_preporphans(lfs, -1); in lfs_mkdir()
2000 LFS_TRACE("lfs_mkdir -> %d", err); in lfs_mkdir()
2004 LFS_TRACE("lfs_mkdir -> %d", 0); in lfs_mkdir()
2010 lfs_stag_t tag = lfs_dir_find(lfs, &dir->m, &path, NULL); in lfs_dir_open()
2012 LFS_TRACE("lfs_dir_open -> %"PRId32, tag); in lfs_dir_open()
2017 LFS_TRACE("lfs_dir_open -> %d", LFS_ERR_NOTDIR); in lfs_dir_open()
2024 pair[0] = lfs->root[0]; in lfs_dir_open()
2025 pair[1] = lfs->root[1]; in lfs_dir_open()
2028 lfs_stag_t res = lfs_dir_get(lfs, &dir->m, LFS_MKTAG(0x700, 0x3ff, 0), in lfs_dir_open()
2031 LFS_TRACE("lfs_dir_open -> %"PRId32, res); in lfs_dir_open()
2038 int err = lfs_dir_fetch(lfs, &dir->m, pair); in lfs_dir_open()
2040 LFS_TRACE("lfs_dir_open -> %d", err); in lfs_dir_open()
2045 dir->head[0] = dir->m.pair[0]; in lfs_dir_open()
2046 dir->head[1] = dir->m.pair[1]; in lfs_dir_open()
2047 dir->id = 0; in lfs_dir_open()
2048 dir->pos = 0; in lfs_dir_open()
2051 dir->type = LFS_TYPE_DIR; in lfs_dir_open()
2052 dir->next = (lfs_dir_t*)lfs->mlist; in lfs_dir_open()
2053 lfs->mlist = (struct lfs_mlist*)dir; in lfs_dir_open()
2055 LFS_TRACE("lfs_dir_open -> %d", 0); in lfs_dir_open()
2062 for (struct lfs_mlist **p = &lfs->mlist; *p; p = &(*p)->next) { in lfs_dir_close()
2064 *p = (*p)->next; in lfs_dir_close()
2069 LFS_TRACE("lfs_dir_close -> %d", 0); in lfs_dir_close()
2079 if (dir->pos == 0) { in lfs_dir_read()
2080 info->type = LFS_TYPE_DIR; in lfs_dir_read()
2081 strcpy(info->name, "."); in lfs_dir_read()
2082 dir->pos += 1; in lfs_dir_read()
2083 LFS_TRACE("lfs_dir_read -> %d", true); in lfs_dir_read()
2085 } else if (dir->pos == 1) { in lfs_dir_read()
2086 info->type = LFS_TYPE_DIR; in lfs_dir_read()
2087 strcpy(info->name, ".."); in lfs_dir_read()
2088 dir->pos += 1; in lfs_dir_read()
2089 LFS_TRACE("lfs_dir_read -> %d", true); in lfs_dir_read()
2094 if (dir->id == dir->m.count) { in lfs_dir_read()
2095 if (!dir->m.split) { in lfs_dir_read()
2096 LFS_TRACE("lfs_dir_read -> %d", false); in lfs_dir_read()
2100 int err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail); in lfs_dir_read()
2102 LFS_TRACE("lfs_dir_read -> %d", err); in lfs_dir_read()
2106 dir->id = 0; in lfs_dir_read()
2109 int err = lfs_dir_getinfo(lfs, &dir->m, dir->id, info); in lfs_dir_read()
2111 LFS_TRACE("lfs_dir_read -> %d", err); in lfs_dir_read()
2115 dir->id += 1; in lfs_dir_read()
2121 dir->pos += 1; in lfs_dir_read()
2122 LFS_TRACE("lfs_dir_read -> %d", true); in lfs_dir_read()
2132 LFS_TRACE("lfs_dir_seek -> %d", err); in lfs_dir_seek()
2137 dir->pos = lfs_min(2, off); in lfs_dir_seek()
2138 off -= dir->pos; in lfs_dir_seek()
2141 dir->id = (off > 0 && lfs_pair_cmp(dir->head, lfs->root) == 0); in lfs_dir_seek()
2144 int diff = lfs_min(dir->m.count - dir->id, off); in lfs_dir_seek()
2145 dir->id += diff; in lfs_dir_seek()
2146 dir->pos += diff; in lfs_dir_seek()
2147 off -= diff; in lfs_dir_seek()
2149 if (dir->id == dir->m.count) { in lfs_dir_seek()
2150 if (!dir->m.split) { in lfs_dir_seek()
2151 LFS_TRACE("lfs_dir_seek -> %d", LFS_ERR_INVAL); in lfs_dir_seek()
2155 err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail); in lfs_dir_seek()
2157 LFS_TRACE("lfs_dir_seek -> %d", err); in lfs_dir_seek()
2161 dir->id = 0; in lfs_dir_seek()
2165 LFS_TRACE("lfs_dir_seek -> %d", 0); in lfs_dir_seek()
2172 LFS_TRACE("lfs_dir_tell -> %"PRId32, dir->pos); in lfs_dir_tell()
2173 return dir->pos; in lfs_dir_tell()
2179 int err = lfs_dir_fetch(lfs, &dir->m, dir->head); in lfs_dir_rewind()
2181 LFS_TRACE("lfs_dir_rewind -> %d", err); in lfs_dir_rewind()
2185 dir->id = 0; in lfs_dir_rewind()
2186 dir->pos = 0; in lfs_dir_rewind()
2187 LFS_TRACE("lfs_dir_rewind -> %d", 0); in lfs_dir_rewind()
2195 lfs_off_t b = lfs->cfg->block_size - 2*4; in lfs_ctz_index()
2201 i = (size - 4*(lfs_popc(i-1)+2)) / b; in lfs_ctz_index()
2202 *off = size - b*i - 4*lfs_popc(i); in lfs_ctz_index()
2216 lfs_off_t current = lfs_ctz_index(lfs, &(lfs_off_t){size-1}); in lfs_ctz_find()
2221 lfs_npw2(current-target+1) - 1, in lfs_ctz_find()
2232 current -= 1 << skip; in lfs_ctz_find()
2267 lfs_size_t noff = size - 1; in lfs_ctz_extend()
2272 if (noff != lfs->cfg->block_size) { in lfs_ctz_extend()
2276 NULL, rcache, noff-i, in lfs_ctz_extend()
2314 if (i != skips-1) { in lfs_ctz_extend()
2346 lfs_off_t index = lfs_ctz_index(lfs, &(lfs_off_t){size-1}); in lfs_ctz_traverse()
2359 int count = 2 - (index & 1); in lfs_ctz_traverse()
2369 for (int i = 0; i < count-1; i++) { in lfs_ctz_traverse()
2376 head = heads[count-1]; in lfs_ctz_traverse()
2377 index -= count; in lfs_ctz_traverse()
2389 (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count); in lfs_file_opencfg()
2395 LFS_TRACE("lfs_file_opencfg -> %d", err); in lfs_file_opencfg()
2402 file->cfg = cfg; in lfs_file_opencfg()
2403 file->flags = flags | LFS_F_OPENED; in lfs_file_opencfg()
2404 file->pos = 0; in lfs_file_opencfg()
2405 file->off = 0; in lfs_file_opencfg()
2406 file->cache.buffer = NULL; in lfs_file_opencfg()
2409 lfs_stag_t tag = lfs_dir_find(lfs, &file->m, &path, &file->id); in lfs_file_opencfg()
2410 if (tag < 0 && !(tag == LFS_ERR_NOENT && file->id != 0x3ff)) { in lfs_file_opencfg()
2416 file->type = LFS_TYPE_REG; in lfs_file_opencfg()
2417 file->next = (lfs_file_t*)lfs->mlist; in lfs_file_opencfg()
2418 lfs->mlist = (struct lfs_mlist*)file; in lfs_file_opencfg()
2428 if (nlen > lfs->name_max) { in lfs_file_opencfg()
2434 err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS( in lfs_file_opencfg()
2435 {LFS_MKTAG(LFS_TYPE_CREATE, file->id, 0)}, in lfs_file_opencfg()
2436 {LFS_MKTAG(LFS_TYPE_REG, file->id, nlen), path}, in lfs_file_opencfg()
2437 {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0)})); in lfs_file_opencfg()
2452 tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0); in lfs_file_opencfg()
2453 file->flags |= LFS_F_DIRTY; in lfs_file_opencfg()
2456 tag = lfs_dir_get(lfs, &file->m, LFS_MKTAG(0x700, 0x3ff, 0), in lfs_file_opencfg()
2457 LFS_MKTAG(LFS_TYPE_STRUCT, file->id, 8), &file->ctz); in lfs_file_opencfg()
2462 lfs_ctz_fromle32(&file->ctz); in lfs_file_opencfg()
2466 for (unsigned i = 0; i < file->cfg->attr_count; i++) { in lfs_file_opencfg()
2467 if ((file->flags & 3) != LFS_O_WRONLY) { in lfs_file_opencfg()
2468 lfs_stag_t res = lfs_dir_get(lfs, &file->m, in lfs_file_opencfg()
2470 LFS_MKTAG(LFS_TYPE_USERATTR + file->cfg->attrs[i].type, in lfs_file_opencfg()
2471 file->id, file->cfg->attrs[i].size), in lfs_file_opencfg()
2472 file->cfg->attrs[i].buffer); in lfs_file_opencfg()
2479 if ((file->flags & 3) != LFS_O_RDONLY) { in lfs_file_opencfg()
2480 if (file->cfg->attrs[i].size > lfs->attr_max) { in lfs_file_opencfg()
2485 file->flags |= LFS_F_DIRTY; in lfs_file_opencfg()
2490 if (file->cfg->buffer) { in lfs_file_opencfg()
2491 file->cache.buffer = file->cfg->buffer; in lfs_file_opencfg()
2493 file->cache.buffer = lfs_malloc(lfs->cfg->cache_size); in lfs_file_opencfg()
2494 if (!file->cache.buffer) { in lfs_file_opencfg()
2501 lfs_cache_zero(lfs, &file->cache); in lfs_file_opencfg()
2505 file->ctz.head = LFS_BLOCK_INLINE; in lfs_file_opencfg()
2506 file->ctz.size = lfs_tag_size(tag); in lfs_file_opencfg()
2507 file->flags |= LFS_F_INLINE; in lfs_file_opencfg()
2508 file->cache.block = file->ctz.head; in lfs_file_opencfg()
2509 file->cache.off = 0; in lfs_file_opencfg()
2510 file->cache.size = lfs->cfg->cache_size; in lfs_file_opencfg()
2513 if (file->ctz.size > 0) { in lfs_file_opencfg()
2514 lfs_stag_t res = lfs_dir_get(lfs, &file->m, in lfs_file_opencfg()
2516 LFS_MKTAG(LFS_TYPE_STRUCT, file->id, in lfs_file_opencfg()
2517 lfs_min(file->cache.size, 0x3fe)), in lfs_file_opencfg()
2518 file->cache.buffer); in lfs_file_opencfg()
2526 LFS_TRACE("lfs_file_opencfg -> %d", 0); in lfs_file_opencfg()
2531 file->flags |= LFS_F_ERRED; in lfs_file_opencfg()
2533 LFS_TRACE("lfs_file_opencfg -> %d", err); in lfs_file_opencfg()
2543 LFS_TRACE("lfs_file_open -> %d", err); in lfs_file_open()
2549 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_close()
2554 for (struct lfs_mlist **p = &lfs->mlist; *p; p = &(*p)->next) { in lfs_file_close()
2556 *p = (*p)->next; in lfs_file_close()
2562 if (!file->cfg->buffer) { in lfs_file_close()
2563 lfs_free(file->cache.buffer); in lfs_file_close()
2566 file->flags &= ~LFS_F_OPENED; in lfs_file_close()
2567 LFS_TRACE("lfs_file_close -> %d", err); in lfs_file_close()
2572 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_relocate()
2591 for (lfs_off_t i = 0; i < file->off; i++) { in lfs_file_relocate()
2593 if (file->flags & LFS_F_INLINE) { in lfs_file_relocate()
2594 err = lfs_dir_getread(lfs, &file->m, in lfs_file_relocate()
2596 NULL, &file->cache, file->off-i, in lfs_file_relocate()
2598 LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0), in lfs_file_relocate()
2605 &file->cache, &lfs->rcache, file->off-i, in lfs_file_relocate()
2606 file->block, i, &data, 1); in lfs_file_relocate()
2613 &lfs->pcache, &lfs->rcache, true, in lfs_file_relocate()
2624 memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->cache_size); in lfs_file_relocate()
2625 file->cache.block = lfs->pcache.block; in lfs_file_relocate()
2626 file->cache.off = lfs->pcache.off; in lfs_file_relocate()
2627 file->cache.size = lfs->pcache.size; in lfs_file_relocate()
2628 lfs_cache_zero(lfs, &lfs->pcache); in lfs_file_relocate()
2630 file->block = nblock; in lfs_file_relocate()
2631 file->flags |= LFS_F_WRITING; in lfs_file_relocate()
2638 lfs_cache_drop(lfs, &lfs->pcache); in lfs_file_relocate()
2643 file->off = file->pos; in lfs_file_outline()
2650 file->flags &= ~LFS_F_INLINE; in lfs_file_outline()
2655 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_flush()
2657 if (file->flags & LFS_F_READING) { in lfs_file_flush()
2658 if (!(file->flags & LFS_F_INLINE)) { in lfs_file_flush()
2659 lfs_cache_drop(lfs, &file->cache); in lfs_file_flush()
2661 file->flags &= ~LFS_F_READING; in lfs_file_flush()
2664 if (file->flags & LFS_F_WRITING) { in lfs_file_flush()
2665 lfs_off_t pos = file->pos; in lfs_file_flush()
2667 if (!(file->flags & LFS_F_INLINE)) { in lfs_file_flush()
2670 .ctz.head = file->ctz.head, in lfs_file_flush()
2671 .ctz.size = file->ctz.size, in lfs_file_flush()
2673 .pos = file->pos, in lfs_file_flush()
2674 .cache = lfs->rcache, in lfs_file_flush()
2676 lfs_cache_drop(lfs, &lfs->rcache); in lfs_file_flush()
2678 while (file->pos < file->ctz.size) { in lfs_file_flush()
2693 if (lfs->rcache.block != LFS_BLOCK_NULL) { in lfs_file_flush()
2695 lfs_cache_drop(lfs, &lfs->rcache); in lfs_file_flush()
2701 int err = lfs_bd_flush(lfs, &file->cache, &lfs->rcache, true); in lfs_file_flush()
2712 LFS_DEBUG("Bad block at 0x%"PRIx32, file->block); in lfs_file_flush()
2719 file->pos = lfs_max(file->pos, file->ctz.size); in lfs_file_flush()
2723 file->ctz.head = file->block; in lfs_file_flush()
2724 file->ctz.size = file->pos; in lfs_file_flush()
2725 file->flags &= ~LFS_F_WRITING; in lfs_file_flush()
2726 file->flags |= LFS_F_DIRTY; in lfs_file_flush()
2728 file->pos = pos; in lfs_file_flush()
2736 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_sync()
2738 if (file->flags & LFS_F_ERRED) { in lfs_file_sync()
2740 LFS_TRACE("lfs_file_sync -> %d", 0); in lfs_file_sync()
2746 file->flags |= LFS_F_ERRED; in lfs_file_sync()
2747 LFS_TRACE("lfs_file_sync -> %d", err); in lfs_file_sync()
2751 if ((file->flags & LFS_F_DIRTY) && in lfs_file_sync()
2752 !lfs_pair_isnull(file->m.pair)) { in lfs_file_sync()
2758 if (file->flags & LFS_F_INLINE) { in lfs_file_sync()
2761 buffer = file->cache.buffer; in lfs_file_sync()
2762 size = file->ctz.size; in lfs_file_sync()
2767 ctz = file->ctz; in lfs_file_sync()
2774 err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS( in lfs_file_sync()
2775 {LFS_MKTAG(type, file->id, size), buffer}, in lfs_file_sync()
2776 {LFS_MKTAG(LFS_FROM_USERATTRS, file->id, in lfs_file_sync()
2777 file->cfg->attr_count), file->cfg->attrs})); in lfs_file_sync()
2779 file->flags |= LFS_F_ERRED; in lfs_file_sync()
2780 LFS_TRACE("lfs_file_sync -> %d", err); in lfs_file_sync()
2784 file->flags &= ~LFS_F_DIRTY; in lfs_file_sync()
2787 LFS_TRACE("lfs_file_sync -> %d", 0); in lfs_file_sync()
2795 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_read()
2796 LFS_ASSERT((file->flags & 3) != LFS_O_WRONLY); in lfs_file_read()
2801 if (file->flags & LFS_F_WRITING) { in lfs_file_read()
2805 LFS_TRACE("lfs_file_read -> %d", err); in lfs_file_read()
2810 if (file->pos >= file->ctz.size) { in lfs_file_read()
2812 LFS_TRACE("lfs_file_read -> %d", 0); in lfs_file_read()
2816 size = lfs_min(size, file->ctz.size - file->pos); in lfs_file_read()
2821 if (!(file->flags & LFS_F_READING) || in lfs_file_read()
2822 file->off == lfs->cfg->block_size) { in lfs_file_read()
2823 if (!(file->flags & LFS_F_INLINE)) { in lfs_file_read()
2824 int err = lfs_ctz_find(lfs, NULL, &file->cache, in lfs_file_read()
2825 file->ctz.head, file->ctz.size, in lfs_file_read()
2826 file->pos, &file->block, &file->off); in lfs_file_read()
2828 LFS_TRACE("lfs_file_read -> %d", err); in lfs_file_read()
2832 file->block = LFS_BLOCK_INLINE; in lfs_file_read()
2833 file->off = file->pos; in lfs_file_read()
2836 file->flags |= LFS_F_READING; in lfs_file_read()
2840 lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off); in lfs_file_read()
2841 if (file->flags & LFS_F_INLINE) { in lfs_file_read()
2842 int err = lfs_dir_getread(lfs, &file->m, in lfs_file_read()
2843 NULL, &file->cache, lfs->cfg->block_size, in lfs_file_read()
2845 LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0), in lfs_file_read()
2846 file->off, data, diff); in lfs_file_read()
2848 LFS_TRACE("lfs_file_read -> %d", err); in lfs_file_read()
2853 NULL, &file->cache, lfs->cfg->block_size, in lfs_file_read()
2854 file->block, file->off, data, diff); in lfs_file_read()
2856 LFS_TRACE("lfs_file_read -> %d", err); in lfs_file_read()
2861 file->pos += diff; in lfs_file_read()
2862 file->off += diff; in lfs_file_read()
2864 nsize -= diff; in lfs_file_read()
2867 LFS_TRACE("lfs_file_read -> %"PRId32, size); in lfs_file_read()
2875 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_write()
2876 LFS_ASSERT((file->flags & 3) != LFS_O_RDONLY); in lfs_file_write()
2881 if (file->flags & LFS_F_READING) { in lfs_file_write()
2885 LFS_TRACE("lfs_file_write -> %d", err); in lfs_file_write()
2890 if ((file->flags & LFS_O_APPEND) && file->pos < file->ctz.size) { in lfs_file_write()
2891 file->pos = file->ctz.size; in lfs_file_write()
2894 if (file->pos + size > lfs->file_max) { in lfs_file_write()
2896 LFS_TRACE("lfs_file_write -> %d", LFS_ERR_FBIG); in lfs_file_write()
2900 if (!(file->flags & LFS_F_WRITING) && file->pos > file->ctz.size) { in lfs_file_write()
2902 lfs_off_t pos = file->pos; in lfs_file_write()
2903 file->pos = file->ctz.size; in lfs_file_write()
2905 while (file->pos < pos) { in lfs_file_write()
2908 LFS_TRACE("lfs_file_write -> %"PRId32, res); in lfs_file_write()
2914 if ((file->flags & LFS_F_INLINE) && in lfs_file_write()
2915 lfs_max(file->pos+nsize, file->ctz.size) > in lfs_file_write()
2917 lfs->cfg->cache_size, lfs->cfg->block_size/8))) { in lfs_file_write()
2921 file->flags |= LFS_F_ERRED; in lfs_file_write()
2922 LFS_TRACE("lfs_file_write -> %d", err); in lfs_file_write()
2929 if (!(file->flags & LFS_F_WRITING) || in lfs_file_write()
2930 file->off == lfs->cfg->block_size) { in lfs_file_write()
2931 if (!(file->flags & LFS_F_INLINE)) { in lfs_file_write()
2932 if (!(file->flags & LFS_F_WRITING) && file->pos > 0) { in lfs_file_write()
2934 int err = lfs_ctz_find(lfs, NULL, &file->cache, in lfs_file_write()
2935 file->ctz.head, file->ctz.size, in lfs_file_write()
2936 file->pos-1, &file->block, &file->off); in lfs_file_write()
2938 file->flags |= LFS_F_ERRED; in lfs_file_write()
2939 LFS_TRACE("lfs_file_write -> %d", err); in lfs_file_write()
2944 lfs_cache_zero(lfs, &file->cache); in lfs_file_write()
2949 int err = lfs_ctz_extend(lfs, &file->cache, &lfs->rcache, in lfs_file_write()
2950 file->block, file->pos, in lfs_file_write()
2951 &file->block, &file->off); in lfs_file_write()
2953 file->flags |= LFS_F_ERRED; in lfs_file_write()
2954 LFS_TRACE("lfs_file_write -> %d", err); in lfs_file_write()
2958 file->block = LFS_BLOCK_INLINE; in lfs_file_write()
2959 file->off = file->pos; in lfs_file_write()
2962 file->flags |= LFS_F_WRITING; in lfs_file_write()
2966 lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off); in lfs_file_write()
2968 int err = lfs_bd_prog(lfs, &file->cache, &lfs->rcache, true, in lfs_file_write()
2969 file->block, file->off, data, diff); in lfs_file_write()
2974 file->flags |= LFS_F_ERRED; in lfs_file_write()
2975 LFS_TRACE("lfs_file_write -> %d", err); in lfs_file_write()
2983 file->flags |= LFS_F_ERRED; in lfs_file_write()
2984 LFS_TRACE("lfs_file_write -> %d", err); in lfs_file_write()
2989 file->pos += diff; in lfs_file_write()
2990 file->off += diff; in lfs_file_write()
2992 nsize -= diff; in lfs_file_write()
2997 file->flags &= ~LFS_F_ERRED; in lfs_file_write()
2998 LFS_TRACE("lfs_file_write -> %"PRId32, size); in lfs_file_write()
3006 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_seek()
3011 LFS_TRACE("lfs_file_seek -> %d", err); in lfs_file_seek()
3016 lfs_off_t npos = file->pos; in lfs_file_seek()
3020 npos = file->pos + off; in lfs_file_seek()
3022 npos = file->ctz.size + off; in lfs_file_seek()
3025 if (npos > lfs->file_max) { in lfs_file_seek()
3027 LFS_TRACE("lfs_file_seek -> %d", LFS_ERR_INVAL); in lfs_file_seek()
3032 file->pos = npos; in lfs_file_seek()
3033 LFS_TRACE("lfs_file_seek -> %"PRId32, npos); in lfs_file_seek()
3040 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_truncate()
3041 LFS_ASSERT((file->flags & 3) != LFS_O_RDONLY); in lfs_file_truncate()
3044 LFS_TRACE("lfs_file_truncate -> %d", LFS_ERR_INVAL); in lfs_file_truncate()
3048 lfs_off_t pos = file->pos; in lfs_file_truncate()
3054 LFS_TRACE("lfs_file_truncate -> %d", err); in lfs_file_truncate()
3059 err = lfs_ctz_find(lfs, NULL, &file->cache, in lfs_file_truncate()
3060 file->ctz.head, file->ctz.size, in lfs_file_truncate()
3061 size, &file->block, &file->off); in lfs_file_truncate()
3063 LFS_TRACE("lfs_file_truncate -> %d", err); in lfs_file_truncate()
3067 file->ctz.head = file->block; in lfs_file_truncate()
3068 file->ctz.size = size; in lfs_file_truncate()
3069 file->flags |= LFS_F_DIRTY | LFS_F_READING; in lfs_file_truncate()
3072 if (file->pos != oldsize) { in lfs_file_truncate()
3075 LFS_TRACE("lfs_file_truncate -> %"PRId32, res); in lfs_file_truncate()
3081 while (file->pos < size) { in lfs_file_truncate()
3084 LFS_TRACE("lfs_file_truncate -> %"PRId32, res); in lfs_file_truncate()
3093 LFS_TRACE("lfs_file_truncate -> %"PRId32, res); in lfs_file_truncate()
3097 LFS_TRACE("lfs_file_truncate -> %d", 0); in lfs_file_truncate()
3103 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_tell()
3105 LFS_TRACE("lfs_file_tell -> %"PRId32, file->pos); in lfs_file_tell()
3106 return file->pos; in lfs_file_tell()
3113 LFS_TRACE("lfs_file_rewind -> %"PRId32, res); in lfs_file_rewind()
3117 LFS_TRACE("lfs_file_rewind -> %d", 0); in lfs_file_rewind()
3123 LFS_ASSERT(file->flags & LFS_F_OPENED); in lfs_file_size()
3125 if (file->flags & LFS_F_WRITING) { in lfs_file_size()
3126 LFS_TRACE("lfs_file_size -> %"PRId32, in lfs_file_size()
3127 lfs_max(file->pos, file->ctz.size)); in lfs_file_size()
3128 return lfs_max(file->pos, file->ctz.size); in lfs_file_size()
3130 LFS_TRACE("lfs_file_size -> %"PRId32, file->ctz.size); in lfs_file_size()
3131 return file->ctz.size; in lfs_file_size()
3142 LFS_TRACE("lfs_stat -> %"PRId32, tag); in lfs_stat()
3147 LFS_TRACE("lfs_stat -> %d", err); in lfs_stat()
3156 LFS_TRACE("lfs_remove -> %d", err); in lfs_remove()
3163 LFS_TRACE("lfs_remove -> %"PRId32, (tag < 0) ? tag : LFS_ERR_INVAL); in lfs_remove()
3168 dir.next = lfs->mlist; in lfs_remove()
3175 LFS_TRACE("lfs_remove -> %"PRId32, res); in lfs_remove()
3182 LFS_TRACE("lfs_remove -> %d", err); in lfs_remove()
3187 LFS_TRACE("lfs_remove -> %d", LFS_ERR_NOTEMPTY); in lfs_remove()
3198 lfs->mlist = &dir; in lfs_remove()
3205 lfs->mlist = dir.next; in lfs_remove()
3206 LFS_TRACE("lfs_remove -> %d", err); in lfs_remove()
3210 lfs->mlist = dir.next; in lfs_remove()
3213 lfs_fs_preporphans(lfs, -1); in lfs_remove()
3217 LFS_TRACE("lfs_remove -> %d", err); in lfs_remove()
3223 LFS_TRACE("lfs_remove -> %d", err); in lfs_remove()
3228 LFS_TRACE("lfs_remove -> %d", 0); in lfs_remove()
3238 LFS_TRACE("lfs_rename -> %d", err); in lfs_rename()
3246 LFS_TRACE("lfs_rename -> %"PRId32, in lfs_rename()
3257 LFS_TRACE("lfs_rename -> %"PRId32, in lfs_rename()
3267 prevdir.next = lfs->mlist; in lfs_rename()
3271 if (nlen > lfs->name_max) { in lfs_rename()
3272 LFS_TRACE("lfs_rename -> %d", LFS_ERR_NAMETOOLONG); in lfs_rename()
3283 LFS_TRACE("lfs_rename -> %d", LFS_ERR_ISDIR); in lfs_rename()
3287 LFS_TRACE("lfs_rename -> %d", 0); in lfs_rename()
3295 LFS_TRACE("lfs_rename -> %"PRId32, res); in lfs_rename()
3303 LFS_TRACE("lfs_rename -> %d", err); in lfs_rename()
3308 LFS_TRACE("lfs_rename -> %d", LFS_ERR_NOTEMPTY); in lfs_rename()
3319 lfs->mlist = &prevdir; in lfs_rename()
3336 lfs->mlist = prevdir.next; in lfs_rename()
3337 LFS_TRACE("lfs_rename -> %d", err); in lfs_rename()
3343 if (!samepair && lfs_gstate_hasmove(&lfs->gstate)) { in lfs_rename()
3349 lfs->mlist = prevdir.next; in lfs_rename()
3350 LFS_TRACE("lfs_rename -> %d", err); in lfs_rename()
3355 lfs->mlist = prevdir.next; in lfs_rename()
3358 lfs_fs_preporphans(lfs, -1); in lfs_rename()
3362 LFS_TRACE("lfs_rename -> %d", err); in lfs_rename()
3368 LFS_TRACE("lfs_rename -> %d", err); in lfs_rename()
3373 LFS_TRACE("lfs_rename -> %d", 0); in lfs_rename()
3384 LFS_TRACE("lfs_getattr -> %"PRId32, tag); in lfs_getattr()
3392 int err = lfs_dir_fetch(lfs, &cwd, lfs->root); in lfs_getattr()
3394 LFS_TRACE("lfs_getattr -> %d", err); in lfs_getattr()
3401 id, lfs_min(size, lfs->attr_max)), in lfs_getattr()
3405 LFS_TRACE("lfs_getattr -> %d", LFS_ERR_NOATTR); in lfs_getattr()
3409 LFS_TRACE("lfs_getattr -> %"PRId32, tag); in lfs_getattr()
3414 LFS_TRACE("lfs_getattr -> %"PRId32, size); in lfs_getattr()
3430 int err = lfs_dir_fetch(lfs, &cwd, lfs->root); in lfs_commitattr()
3444 if (size > lfs->attr_max) { in lfs_setattr()
3445 LFS_TRACE("lfs_setattr -> %d", LFS_ERR_NOSPC); in lfs_setattr()
3450 LFS_TRACE("lfs_setattr -> %d", err); in lfs_setattr()
3457 LFS_TRACE("lfs_removeattr -> %d", err); in lfs_removeattr()
3464 lfs->cfg = cfg; in lfs_init()
3467 // validate that the lfs-cfg sizes were initiated properly before in lfs_init()
3469 LFS_ASSERT(lfs->cfg->read_size != 0); in lfs_init()
3470 LFS_ASSERT(lfs->cfg->prog_size != 0); in lfs_init()
3471 LFS_ASSERT(lfs->cfg->cache_size != 0); in lfs_init()
3475 LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->read_size == 0); in lfs_init()
3476 LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->prog_size == 0); in lfs_init()
3477 LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->cache_size == 0); in lfs_init()
3480 LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4)) in lfs_init()
3481 <= lfs->cfg->block_size); in lfs_init()
3487 // range of 100-1000, or set block_cycles to -1 to disable block-level in lfs_init()
3488 // wear-leveling. in lfs_init()
3489 LFS_ASSERT(lfs->cfg->block_cycles != 0); in lfs_init()
3493 if (lfs->cfg->read_buffer) { in lfs_init()
3494 lfs->rcache.buffer = lfs->cfg->read_buffer; in lfs_init()
3496 lfs->rcache.buffer = lfs_malloc(lfs->cfg->cache_size); in lfs_init()
3497 if (!lfs->rcache.buffer) { in lfs_init()
3504 if (lfs->cfg->prog_buffer) { in lfs_init()
3505 lfs->pcache.buffer = lfs->cfg->prog_buffer; in lfs_init()
3507 lfs->pcache.buffer = lfs_malloc(lfs->cfg->cache_size); in lfs_init()
3508 if (!lfs->pcache.buffer) { in lfs_init()
3515 lfs_cache_zero(lfs, &lfs->rcache); in lfs_init()
3516 lfs_cache_zero(lfs, &lfs->pcache); in lfs_init()
3518 // setup lookahead, must be multiple of 64-bits, 32-bit aligned in lfs_init()
3519 LFS_ASSERT(lfs->cfg->lookahead_size > 0); in lfs_init()
3520 LFS_ASSERT(lfs->cfg->lookahead_size % 8 == 0 && in lfs_init()
3521 (uintptr_t)lfs->cfg->lookahead_buffer % 4 == 0); in lfs_init()
3522 if (lfs->cfg->lookahead_buffer) { in lfs_init()
3523 lfs->free.buffer = lfs->cfg->lookahead_buffer; in lfs_init()
3525 lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead_size); in lfs_init()
3526 if (!lfs->free.buffer) { in lfs_init()
3533 LFS_ASSERT(lfs->cfg->name_max <= LFS_NAME_MAX); in lfs_init()
3534 lfs->name_max = lfs->cfg->name_max; in lfs_init()
3535 if (!lfs->name_max) { in lfs_init()
3536 lfs->name_max = LFS_NAME_MAX; in lfs_init()
3539 LFS_ASSERT(lfs->cfg->file_max <= LFS_FILE_MAX); in lfs_init()
3540 lfs->file_max = lfs->cfg->file_max; in lfs_init()
3541 if (!lfs->file_max) { in lfs_init()
3542 lfs->file_max = LFS_FILE_MAX; in lfs_init()
3545 LFS_ASSERT(lfs->cfg->attr_max <= LFS_ATTR_MAX); in lfs_init()
3546 lfs->attr_max = lfs->cfg->attr_max; in lfs_init()
3547 if (!lfs->attr_max) { in lfs_init()
3548 lfs->attr_max = LFS_ATTR_MAX; in lfs_init()
3552 lfs->root[0] = LFS_BLOCK_NULL; in lfs_init()
3553 lfs->root[1] = LFS_BLOCK_NULL; in lfs_init()
3554 lfs->mlist = NULL; in lfs_init()
3555 lfs->seed = 0; in lfs_init()
3556 lfs->gdisk = (lfs_gstate_t){0}; in lfs_init()
3557 lfs->gstate = (lfs_gstate_t){0}; in lfs_init()
3558 lfs->gdelta = (lfs_gstate_t){0}; in lfs_init()
3560 lfs->lfs1 = NULL; in lfs_init()
3572 if (!lfs->cfg->read_buffer) { in lfs_deinit()
3573 lfs_free(lfs->rcache.buffer); in lfs_deinit()
3576 if (!lfs->cfg->prog_buffer) { in lfs_deinit()
3577 lfs_free(lfs->pcache.buffer); in lfs_deinit()
3580 if (!lfs->cfg->lookahead_buffer) { in lfs_deinit()
3581 lfs_free(lfs->free.buffer); in lfs_deinit()
3597 (void*)lfs, (void*)cfg, cfg->context, in lfs_format()
3598 (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, in lfs_format()
3599 (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, in lfs_format()
3600 cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, in lfs_format()
3601 cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, in lfs_format()
3602 cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, in lfs_format()
3603 cfg->name_max, cfg->file_max, cfg->attr_max); in lfs_format()
3608 LFS_TRACE("lfs_format -> %d", err); in lfs_format()
3613 memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size); in lfs_format()
3614 lfs->free.off = 0; in lfs_format()
3615 lfs->free.size = lfs_min(8*lfs->cfg->lookahead_size, in lfs_format()
3616 lfs->cfg->block_count); in lfs_format()
3617 lfs->free.i = 0; in lfs_format()
3630 .block_size = lfs->cfg->block_size, in lfs_format()
3631 .block_count = lfs->cfg->block_count, in lfs_format()
3632 .name_max = lfs->name_max, in lfs_format()
3633 .file_max = lfs->file_max, in lfs_format()
3634 .attr_max = lfs->attr_max, in lfs_format()
3664 LFS_TRACE("lfs_format -> %d", err); in lfs_format()
3678 (void*)lfs, (void*)cfg, cfg->context, in lfs_mount()
3679 (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, in lfs_mount()
3680 (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, in lfs_mount()
3681 cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, in lfs_mount()
3682 cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, in lfs_mount()
3683 cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, in lfs_mount()
3684 cfg->name_max, cfg->file_max, cfg->attr_max); in lfs_mount()
3687 LFS_TRACE("lfs_mount -> %d", err); in lfs_mount()
3695 if (cycle >= lfs->cfg->block_count/2) { in lfs_mount()
3717 lfs->root[0] = dir.pair[0]; in lfs_mount()
3718 lfs->root[1] = dir.pair[1]; in lfs_mount()
3744 if (superblock.name_max > lfs->name_max) { in lfs_mount()
3746 superblock.name_max, lfs->name_max); in lfs_mount()
3751 lfs->name_max = superblock.name_max; in lfs_mount()
3755 if (superblock.file_max > lfs->file_max) { in lfs_mount()
3757 superblock.file_max, lfs->file_max); in lfs_mount()
3762 lfs->file_max = superblock.file_max; in lfs_mount()
3766 if (superblock.attr_max > lfs->attr_max) { in lfs_mount()
3768 superblock.attr_max, lfs->attr_max); in lfs_mount()
3773 lfs->attr_max = superblock.attr_max; in lfs_mount()
3778 err = lfs_dir_getgstate(lfs, &dir, &lfs->gstate); in lfs_mount()
3785 if (lfs_pair_isnull(lfs->root)) { in lfs_mount()
3791 if (!lfs_gstate_iszero(&lfs->gstate)) { in lfs_mount()
3793 lfs->gstate.tag, in lfs_mount()
3794 lfs->gstate.pair[0], in lfs_mount()
3795 lfs->gstate.pair[1]); in lfs_mount()
3797 lfs->gstate.tag += !lfs_tag_isvalid(lfs->gstate.tag); in lfs_mount()
3798 lfs->gdisk = lfs->gstate; in lfs_mount()
3803 LFS_TRACE("lfs_mount -> %d", 0); in lfs_mount()
3808 LFS_TRACE("lfs_mount -> %d", err); in lfs_mount()
3815 LFS_TRACE("lfs_unmount -> %d", err); in lfs_unmount()
3829 if (lfs->lfs1) { in lfs_fs_traverseraw()
3835 dir.tail[0] = lfs->root[0]; in lfs_fs_traverseraw()
3836 dir.tail[1] = lfs->root[1]; in lfs_fs_traverseraw()
3842 if (cycle >= lfs->cfg->block_count/2) { in lfs_fs_traverseraw()
3874 err = lfs_ctz_traverse(lfs, NULL, &lfs->rcache, in lfs_fs_traverseraw()
3892 for (lfs_file_t *f = (lfs_file_t*)lfs->mlist; f; f = f->next) { in lfs_fs_traverseraw()
3893 if (f->type != LFS_TYPE_REG) { in lfs_fs_traverseraw()
3897 if ((f->flags & LFS_F_DIRTY) && !(f->flags & LFS_F_INLINE)) { in lfs_fs_traverseraw()
3898 int err = lfs_ctz_traverse(lfs, &f->cache, &lfs->rcache, in lfs_fs_traverseraw()
3899 f->ctz.head, f->ctz.size, cb, data); in lfs_fs_traverseraw()
3905 if ((f->flags & LFS_F_WRITING) && !(f->flags & LFS_F_INLINE)) { in lfs_fs_traverseraw()
3906 int err = lfs_ctz_traverse(lfs, &f->cache, &lfs->rcache, in lfs_fs_traverseraw()
3907 f->block, f->pos, cb, data); in lfs_fs_traverseraw()
3922 LFS_TRACE("lfs_fs_traverse -> %d", 0); in lfs_fs_traverse()
3929 pdir->tail[0] = 0; in lfs_fs_pred()
3930 pdir->tail[1] = 1; in lfs_fs_pred()
3932 while (!lfs_pair_isnull(pdir->tail)) { in lfs_fs_pred()
3933 if (cycle >= lfs->cfg->block_count/2) { in lfs_fs_pred()
3939 if (lfs_pair_cmp(pdir->tail, pair) == 0) { in lfs_fs_pred()
3943 int err = lfs_dir_fetch(lfs, pdir, pdir->tail); in lfs_fs_pred()
3960 lfs_t *lfs = find->lfs; in lfs_fs_parent_match()
3966 &lfs->pcache, &lfs->rcache, lfs->cfg->block_size, in lfs_fs_parent_match()
3967 disk->block, disk->off, &child, sizeof(child)); in lfs_fs_parent_match()
3973 return (lfs_pair_cmp(child, find->pair) == 0) ? LFS_CMP_EQ : LFS_CMP_LT; in lfs_fs_parent_match()
3979 parent->tail[0] = 0; in lfs_fs_parent()
3980 parent->tail[1] = 1; in lfs_fs_parent()
3982 while (!lfs_pair_isnull(parent->tail)) { in lfs_fs_parent()
3983 if (cycle >= lfs->cfg->block_count/2) { in lfs_fs_parent()
3989 lfs_stag_t tag = lfs_dir_fetchmatch(lfs, parent, parent->tail, in lfs_fs_parent()
4006 if (lfs_pair_cmp(oldpair, lfs->root) == 0) { in lfs_fs_relocate()
4007 lfs->root[0] = newpair[0]; in lfs_fs_relocate()
4008 lfs->root[1] = newpair[1]; in lfs_fs_relocate()
4012 for (struct lfs_mlist *d = lfs->mlist; d; d = d->next) { in lfs_fs_relocate()
4013 if (lfs_pair_cmp(oldpair, d->m.pair) == 0) { in lfs_fs_relocate()
4014 d->m.pair[0] = newpair[0]; in lfs_fs_relocate()
4015 d->m.pair[1] = newpair[1]; in lfs_fs_relocate()
4018 if (d->type == LFS_TYPE_DIR && in lfs_fs_relocate()
4019 lfs_pair_cmp(oldpair, ((lfs_dir_t*)d)->head) == 0) { in lfs_fs_relocate()
4020 ((lfs_dir_t*)d)->head[0] = newpair[0]; in lfs_fs_relocate()
4021 ((lfs_dir_t*)d)->head[1] = newpair[1]; in lfs_fs_relocate()
4039 if (lfs_gstate_hasmovehere(&lfs->gstate, parent.pair)) { in lfs_fs_relocate()
4040 moveid = lfs_tag_id(lfs->gstate.tag); in lfs_fs_relocate()
4046 tag -= LFS_MKTAG(0, 1, 0); in lfs_fs_relocate()
4061 lfs_fs_preporphans(lfs, -1); in lfs_fs_relocate()
4075 if (lfs_gstate_hasmovehere(&lfs->gstate, parent.pair)) { in lfs_fs_relocate()
4076 moveid = lfs_tag_id(lfs->gstate.tag); in lfs_fs_relocate()
4099 LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) > 0 || orphans >= 0); in lfs_fs_preporphans()
4100 lfs->gstate.tag += orphans; in lfs_fs_preporphans()
4101 lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x800, 0, 0)) | in lfs_fs_preporphans()
4102 ((uint32_t)lfs_gstate_hasorphans(&lfs->gstate) << 31)); in lfs_fs_preporphans()
4107 lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x7ff, 0x3ff, 0)) | in lfs_fs_prepmove()
4109 lfs->gstate.pair[0] = (id != 0x3ff) ? pair[0] : 0; in lfs_fs_prepmove()
4110 lfs->gstate.pair[1] = (id != 0x3ff) ? pair[1] : 0; in lfs_fs_prepmove()
4114 if (!lfs_gstate_hasmove(&lfs->gdisk)) { in lfs_fs_demove()
4120 lfs->gdisk.pair[0], in lfs_fs_demove()
4121 lfs->gdisk.pair[1], in lfs_fs_demove()
4122 lfs_tag_id(lfs->gdisk.tag)); in lfs_fs_demove()
4126 int err = lfs_dir_fetch(lfs, &movedir, lfs->gdisk.pair); in lfs_fs_demove()
4132 uint16_t moveid = lfs_tag_id(lfs->gdisk.tag); in lfs_fs_demove()
4144 if (!lfs_gstate_hasorphans(&lfs->gstate)) { in lfs_fs_deorphan()
4192 LFS_DEBUG("Fixing half-orphan {0x%"PRIx32", 0x%"PRIx32"} " in lfs_fs_deorphan()
4193 "-> {0x%"PRIx32", 0x%"PRIx32"}", in lfs_fs_deorphan()
4213 lfs_fs_preporphans(lfs, -lfs_gstate_getorphans(&lfs->gstate)); in lfs_fs_deorphan()
4243 LFS_TRACE("lfs_fs_size -> %d", err); in lfs_fs_size()
4247 LFS_TRACE("lfs_fs_size -> %d", err); in lfs_fs_size()
4257 // Major (top-nibble), incremented on backwards incompatible changes
4258 // Minor (bottom-nibble), incremented on feature additions
4263 // Version of On-disk data structures
4264 // Major (top-nibble), incremented on backwards incompatible changes
4265 // Minor (bottom-nibble), incremented on feature additions
4334 /// Low-level wrappers v1->v2 ///
4343 return lfs_bd_read(lfs, &lfs->pcache, &lfs->rcache, size, in lfs1_bd_read()
4365 d->rev = lfs_fromle32(d->rev); in lfs1_dir_fromle32()
4366 d->size = lfs_fromle32(d->size); in lfs1_dir_fromle32()
4367 d->tail[0] = lfs_fromle32(d->tail[0]); in lfs1_dir_fromle32()
4368 d->tail[1] = lfs_fromle32(d->tail[1]); in lfs1_dir_fromle32()
4372 d->rev = lfs_tole32(d->rev); in lfs1_dir_tole32()
4373 d->size = lfs_tole32(d->size); in lfs1_dir_tole32()
4374 d->tail[0] = lfs_tole32(d->tail[0]); in lfs1_dir_tole32()
4375 d->tail[1] = lfs_tole32(d->tail[1]); in lfs1_dir_tole32()
4379 d->u.dir[0] = lfs_fromle32(d->u.dir[0]); in lfs1_entry_fromle32()
4380 d->u.dir[1] = lfs_fromle32(d->u.dir[1]); in lfs1_entry_fromle32()
4384 d->u.dir[0] = lfs_tole32(d->u.dir[0]); in lfs1_entry_tole32()
4385 d->u.dir[1] = lfs_tole32(d->u.dir[1]); in lfs1_entry_tole32()
4389 d->root[0] = lfs_fromle32(d->root[0]); in lfs1_superblock_fromle32()
4390 d->root[1] = lfs_fromle32(d->root[1]); in lfs1_superblock_fromle32()
4391 d->block_size = lfs_fromle32(d->block_size); in lfs1_superblock_fromle32()
4392 d->block_count = lfs_fromle32(d->block_count); in lfs1_superblock_fromle32()
4393 d->version = lfs_fromle32(d->version); in lfs1_superblock_fromle32()
4399 return 4 + entry->d.elen + entry->d.alen + entry->d.nlen; in lfs1_entry_size()
4420 if (valid && lfs_scmp(test.rev, dir->d.rev) < 0) { in lfs1_dir_fetch()
4425 (0x7fffffff & test.size) > lfs->cfg->block_size) { in lfs1_dir_fetch()
4434 (0x7fffffff & test.size) - sizeof(test), &crc); in lfs1_dir_fetch()
4449 dir->pair[0] = tpair[(i+0) % 2]; in lfs1_dir_fetch()
4450 dir->pair[1] = tpair[(i+1) % 2]; in lfs1_dir_fetch()
4451 dir->off = sizeof(dir->d); in lfs1_dir_fetch()
4452 dir->d = test; in lfs1_dir_fetch()
4465 while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) { in lfs1_dir_next()
4466 if (!(0x80000000 & dir->d.size)) { in lfs1_dir_next()
4467 entry->off = dir->off; in lfs1_dir_next()
4471 int err = lfs1_dir_fetch(lfs, dir, dir->d.tail); in lfs1_dir_next()
4476 dir->off = sizeof(dir->d); in lfs1_dir_next()
4477 dir->pos += sizeof(dir->d) + 4; in lfs1_dir_next()
4480 int err = lfs1_bd_read(lfs, dir->pair[0], dir->off, in lfs1_dir_next()
4481 &entry->d, sizeof(entry->d)); in lfs1_dir_next()
4482 lfs1_entry_fromle32(&entry->d); in lfs1_dir_next()
4487 entry->off = dir->off; in lfs1_dir_next()
4488 dir->off += lfs1_entry_size(entry); in lfs1_dir_next()
4489 dir->pos += lfs1_entry_size(entry); in lfs1_dir_next()
4495 if (lfs_pair_isnull(lfs->lfs1->root)) { in lfs1_traverse()
4518 while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { in lfs1_traverse()
4528 err = lfs_ctz_traverse(lfs, NULL, &lfs->rcache, in lfs1_traverse()
4564 if (lfs_pair_isnull(lfs->lfs1->root)) { in lfs1_moved()
4613 lfs->lfs1 = lfs1; in lfs1_mount()
4614 lfs->lfs1->root[0] = LFS_BLOCK_NULL; in lfs1_mount()
4615 lfs->lfs1->root[1] = LFS_BLOCK_NULL; in lfs1_mount()
4618 lfs->free.off = 0; in lfs1_mount()
4619 lfs->free.size = 0; in lfs1_mount()
4620 lfs->free.i = 0; in lfs1_mount()
4639 lfs->lfs1->root[0] = superblock.d.root[0]; in lfs1_mount()
4640 lfs->lfs1->root[1] = superblock.d.root[1]; in lfs1_mount()
4682 (void*)lfs, (void*)cfg, cfg->context, in lfs_migrate()
4683 (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, in lfs_migrate()
4684 (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, in lfs_migrate()
4685 cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, in lfs_migrate()
4686 cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, in lfs_migrate()
4687 cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, in lfs_migrate()
4688 cfg->name_max, cfg->file_max, cfg->attr_max); in lfs_migrate()
4692 LFS_TRACE("lfs_migrate -> %d", err); in lfs_migrate()
4701 dir1.d.tail[0] = lfs->lfs1->root[0]; in lfs_migrate()
4702 dir1.d.tail[1] = lfs->lfs1->root[1]; in lfs_migrate()
4719 lfs->root[0] = dir2.pair[0]; in lfs_migrate()
4720 lfs->root[1] = dir2.pair[1]; in lfs_migrate()
4766 err = lfs_dir_fetch(lfs, &dir2, lfs->root); in lfs_migrate()
4797 err = lfs_dir_fetch(lfs, &dir2, lfs->root); in lfs_migrate()
4821 "-> {0x%"PRIx32", 0x%"PRIx32"}", in lfs_migrate()
4822 lfs->root[0], lfs->root[1], dir1.head[0], dir1.head[1]); in lfs_migrate()
4829 err = lfs_dir_fetch(lfs, &dir2, lfs->root); in lfs_migrate()
4837 NULL, &lfs->rcache, dir2.off, in lfs_migrate()
4844 &lfs->pcache, &lfs->rcache, true, in lfs_migrate()
4851 err = lfs_bd_flush(lfs, &lfs->pcache, &lfs->rcache, true); in lfs_migrate()
4869 dir2.tail[0] = lfs->lfs1->root[0]; in lfs_migrate()
4870 dir2.tail[1] = lfs->lfs1->root[1]; in lfs_migrate()
4876 .block_size = lfs->cfg->block_size, in lfs_migrate()
4877 .block_count = lfs->cfg->block_count, in lfs_migrate()
4878 .name_max = lfs->name_max, in lfs_migrate()
4879 .file_max = lfs->file_max, in lfs_migrate()
4880 .attr_max = lfs->attr_max, in lfs_migrate()
4909 LFS_TRACE("lfs_migrate -> %d", err); in lfs_migrate()