Lines Matching defs:lfs
8 #include "lfs.h"
31 static inline void lfs_cache_drop(lfs_t *lfs, lfs_cache_t *rcache) {
34 (void)lfs;
38 static inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) {
40 memset(pcache->buffer, 0xff, lfs->cfg->cache_size);
44 static int lfs_bd_read(lfs_t *lfs,
49 if (off+size > lfs->cfg->block_size
50 || (lfs->block_count && block >= lfs->block_count)) {
91 if (size >= hint && off % lfs->cfg->read_size == 0 &&
92 size >= lfs->cfg->read_size) {
94 diff = lfs_aligndown(diff, lfs->cfg->read_size);
95 int err = lfs->cfg->read(lfs->cfg, block, off, data, diff);
107 LFS_ASSERT(!lfs->block_count || block < lfs->block_count);
109 rcache->off = lfs_aligndown(off, lfs->cfg->read_size);
112 lfs_alignup(off+hint, lfs->cfg->read_size),
113 lfs->cfg->block_size)
115 lfs->cfg->cache_size);
116 int err = lfs->cfg->read(lfs->cfg, rcache->block,
127 static int lfs_bd_cmp(lfs_t *lfs,
138 int err = lfs_bd_read(lfs,
154 static int lfs_bd_crc(lfs_t *lfs,
162 int err = lfs_bd_read(lfs,
176 static int lfs_bd_flush(lfs_t *lfs,
179 LFS_ASSERT(pcache->block < lfs->block_count);
180 lfs_size_t diff = lfs_alignup(pcache->size, lfs->cfg->prog_size);
181 int err = lfs->cfg->prog(lfs->cfg, pcache->block,
190 lfs_cache_drop(lfs, rcache);
191 int res = lfs_bd_cmp(lfs,
203 lfs_cache_zero(lfs, pcache);
211 static int lfs_bd_sync(lfs_t *lfs,
213 lfs_cache_drop(lfs, rcache);
215 int err = lfs_bd_flush(lfs, pcache, rcache, validate);
220 err = lfs->cfg->sync(lfs->cfg);
227 static int lfs_bd_prog(lfs_t *lfs,
232 LFS_ASSERT(block == LFS_BLOCK_INLINE || block < lfs->block_count);
233 LFS_ASSERT(off + size <= lfs->cfg->block_size);
238 off < pcache->off + lfs->cfg->cache_size) {
241 lfs->cfg->cache_size - (off-pcache->off));
249 if (pcache->size == lfs->cfg->cache_size) {
251 int err = lfs_bd_flush(lfs, pcache, rcache, validate);
266 pcache->off = lfs_aligndown(off, lfs->cfg->prog_size);
275 static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) {
276 LFS_ASSERT(block < lfs->block_count);
277 int err = lfs->cfg->erase(lfs->cfg, block);
507 static void lfs_mlist_remove(lfs_t *lfs, struct lfs_mlist *mlist) {
508 for (struct lfs_mlist **p = &lfs->mlist; *p; p = &(*p)->next) {
516 static void lfs_mlist_append(lfs_t *lfs, struct lfs_mlist *mlist) {
517 mlist->next = lfs->mlist;
518 lfs->mlist = mlist;
522 static uint32_t lfs_fs_disk_version(lfs_t *lfs) {
523 (void)lfs;
525 if (lfs->cfg->disk_version) {
526 return lfs->cfg->disk_version;
534 static uint16_t lfs_fs_disk_version_major(lfs_t *lfs) {
535 return 0xffff & (lfs_fs_disk_version(lfs) >> 16);
539 static uint16_t lfs_fs_disk_version_minor(lfs_t *lfs) {
540 return 0xffff & (lfs_fs_disk_version(lfs) >> 0);
546 static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
548 static int lfs_dir_compact(lfs_t *lfs,
551 static lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,
553 static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file,
555 static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file);
556 static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file);
557 static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file);
559 static int lfs_fs_deorphan(lfs_t *lfs, bool powerloss);
560 static int lfs_fs_preporphans(lfs_t *lfs, int8_t orphans);
561 static void lfs_fs_prepmove(lfs_t *lfs,
563 static int lfs_fs_pred(lfs_t *lfs, const lfs_block_t dir[2],
565 static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t dir[2],
567 static int lfs_fs_forceconsistency(lfs_t *lfs);
570 static void lfs_fs_prepsuperblock(lfs_t *lfs, bool needssuperblock);
573 static int lfs1_traverse(lfs_t *lfs,
577 static int lfs_dir_rawrewind(lfs_t *lfs, lfs_dir_t *dir);
579 static lfs_ssize_t lfs_file_flushedread(lfs_t *lfs, lfs_file_t *file,
581 static lfs_ssize_t lfs_file_rawread(lfs_t *lfs, lfs_file_t *file,
583 static int lfs_file_rawclose(lfs_t *lfs, lfs_file_t *file);
584 static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file);
586 static lfs_ssize_t lfs_fs_rawsize(lfs_t *lfs);
587 static int lfs_fs_rawtraverse(lfs_t *lfs,
591 static int lfs_deinit(lfs_t *lfs);
592 static int lfs_rawunmount(lfs_t *lfs);
598 lfs_t *lfs = (lfs_t*)p;
599 lfs_block_t off = ((block - lfs->free.off)
600 + lfs->block_count) % lfs->block_count;
602 if (off < lfs->free.size) {
603 lfs->free.buffer[off / 32] |= 1U << (off % 32);
613 static void lfs_alloc_ack(lfs_t *lfs) {
614 lfs->free.ack = lfs->block_count;
619 static void lfs_alloc_drop(lfs_t *lfs) {
620 lfs->free.size = 0;
621 lfs->free.i = 0;
622 lfs_alloc_ack(lfs);
626 static int lfs_fs_rawgc(lfs_t *lfs) {
627 // Move free offset at the first unused block (lfs->free.i)
628 // lfs->free.i is equal lfs->free.size when all blocks are used
629 lfs->free.off = (lfs->free.off + lfs->free.i) % lfs->block_count;
630 lfs->free.size = lfs_min(8*lfs->cfg->lookahead_size, lfs->free.ack);
631 lfs->free.i = 0;
634 memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size);
635 int err = lfs_fs_rawtraverse(lfs, lfs_alloc_lookahead, lfs, true);
637 lfs_alloc_drop(lfs);
646 static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
648 while (lfs->free.i != lfs->free.size) {
649 lfs_block_t off = lfs->free.i;
650 lfs->free.i += 1;
651 lfs->free.ack -= 1;
653 if (!(lfs->free.buffer[off / 32] & (1U << (off % 32)))) {
655 *block = (lfs->free.off + off) % lfs->block_count;
659 while (lfs->free.i != lfs->free.size &&
660 (lfs->free.buffer[lfs->free.i / 32]
661 & (1U << (lfs->free.i % 32)))) {
662 lfs->free.i += 1;
663 lfs->free.ack -= 1;
671 if (lfs->free.ack == 0) {
673 lfs->free.i + lfs->free.off);
677 int err = lfs_fs_rawgc(lfs);
686 static lfs_stag_t lfs_dir_getslice(lfs_t *lfs, const lfs_mdir_t *dir,
693 if (lfs_gstate_hasmovehere(&lfs->gdisk, dir->pair) &&
695 lfs_tag_id(lfs->gdisk.tag) <= lfs_tag_id(gtag)) {
704 int err = lfs_bd_read(lfs,
705 NULL, &lfs->rcache, sizeof(ntag),
732 err = lfs_bd_read(lfs,
733 NULL, &lfs->rcache, diff,
748 static lfs_stag_t lfs_dir_get(lfs_t *lfs, const lfs_mdir_t *dir,
750 return lfs_dir_getslice(lfs, dir,
755 static int lfs_dir_getread(lfs_t *lfs, const lfs_mdir_t *dir,
760 if (off+size > lfs->cfg->block_size) {
803 rcache->off = lfs_aligndown(off, lfs->cfg->read_size);
804 rcache->size = lfs_min(lfs_alignup(off+hint, lfs->cfg->read_size),
805 lfs->cfg->cache_size);
806 int err = lfs_dir_getslice(lfs, dir, gmask, gtag,
877 static int lfs_dir_traverse(lfs_t *lfs,
897 int err = lfs_bd_read(lfs,
898 NULL, &lfs->rcache, sizeof(tag),
1072 static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
1082 if (lfs->block_count
1083 && (pair[0] >= lfs->block_count || pair[1] >= lfs->block_count)) {
1091 int err = lfs_bd_read(lfs,
1092 NULL, &lfs->rcache, sizeof(revs[i]),
1133 int err = lfs_bd_read(lfs,
1134 NULL, &lfs->rcache, lfs->cfg->block_size,
1153 } else if (off + lfs_tag_dsize(tag) > lfs->cfg->block_size) {
1162 err = lfs_bd_read(lfs,
1163 NULL, &lfs->rcache, lfs->cfg->block_size,
1184 lfs->seed = lfs_crc(lfs->seed, &crc, sizeof(crc));
1201 err = lfs_bd_crc(lfs,
1202 NULL, &lfs->rcache, lfs->cfg->block_size,
1231 err = lfs_bd_read(lfs,
1232 NULL, &lfs->rcache, lfs->cfg->block_size,
1242 err = lfs_bd_read(lfs,
1243 NULL, &lfs->rcache, lfs->cfg->block_size,
1293 if (maybeerased && dir->off % lfs->cfg->prog_size == 0) {
1300 if (lfs_fs_disk_version(lfs) < 0x00020001) {
1310 int err = lfs_bd_crc(lfs,
1311 NULL, &lfs->rcache, lfs->cfg->block_size,
1323 if (lfs_gstate_hasmovehere(&lfs->gdisk, dir->pair)) {
1324 if (lfs_tag_id(lfs->gdisk.tag) == lfs_tag_id(besttag)) {
1327 lfs_tag_id(lfs->gdisk.tag) < lfs_tag_id(besttag)) {
1351 static int lfs_dir_fetch(lfs_t *lfs,
1355 return (int)lfs_dir_fetchmatch(lfs, dir, pair,
1359 static int lfs_dir_getgstate(lfs_t *lfs, const lfs_mdir_t *dir,
1362 lfs_stag_t res = lfs_dir_get(lfs, dir, LFS_MKTAG(0x7ff, 0, 0),
1377 static int lfs_dir_getinfo(lfs_t *lfs, lfs_mdir_t *dir,
1386 lfs_stag_t tag = lfs_dir_get(lfs, dir, LFS_MKTAG(0x780, 0x3ff, 0),
1387 LFS_MKTAG(LFS_TYPE_NAME, id, lfs->name_max+1), info->name);
1395 tag = lfs_dir_get(lfs, dir, LFS_MKTAG(0x700, 0x3ff, 0),
1412 lfs_t *lfs;
1420 lfs_t *lfs = name->lfs;
1425 int res = lfs_bd_cmp(lfs,
1426 NULL, &lfs->rcache, diff,
1441 static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir,
1451 dir->tail[0] = lfs->root[0];
1452 dir->tail[1] = lfs->root[1];
1506 lfs_stag_t res = lfs_dir_get(lfs, dir, LFS_MKTAG(0x700, 0x3ff, 0),
1516 tag = lfs_dir_fetchmatch(lfs, dir, dir->tail,
1522 lfs, name, namelen});
1553 static int lfs_dir_commitprog(lfs_t *lfs, struct lfs_commit *commit,
1555 int err = lfs_bd_prog(lfs,
1556 &lfs->pcache, &lfs->rcache, false,
1570 static int lfs_dir_commitattr(lfs_t *lfs, struct lfs_commit *commit,
1580 int err = lfs_dir_commitprog(lfs, commit, &ntag, sizeof(ntag));
1587 err = lfs_dir_commitprog(lfs, commit, buffer, dsize-sizeof(tag));
1597 err = lfs_bd_read(lfs,
1598 NULL, &lfs->rcache, dsize-sizeof(tag)-i,
1604 err = lfs_dir_commitprog(lfs, commit, &dat, 1);
1618 static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
1625 lfs_min(commit->off + 5*sizeof(uint32_t), lfs->cfg->block_size),
1626 lfs->cfg->prog_size);
1645 if (noff >= end && noff <= lfs->cfg->block_size - lfs->cfg->prog_size) {
1648 int err = lfs_bd_read(lfs,
1649 NULL, &lfs->rcache, lfs->cfg->prog_size,
1658 if (lfs_fs_disk_version(lfs) <= 0x00020000) {
1666 .size = lfs->cfg->prog_size,
1669 err = lfs_bd_crc(lfs,
1670 NULL, &lfs->rcache, lfs->cfg->prog_size,
1677 err = lfs_dir_commitattr(lfs, commit,
1698 int err = lfs_bd_prog(lfs,
1699 &lfs->pcache, &lfs->rcache, false,
1719 if (noff >= end || noff >= lfs->pcache.off + lfs->cfg->cache_size) {
1721 int err = lfs_bd_sync(lfs, &lfs->pcache, &lfs->rcache, false);
1734 int err = lfs_bd_crc(lfs,
1735 NULL, &lfs->rcache, off1+sizeof(uint32_t),
1748 err = lfs_bd_crc(lfs,
1749 NULL, &lfs->rcache, sizeof(uint32_t),
1764 static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
1767 int err = lfs_alloc(lfs, &dir->pair[(i+1)%2]);
1778 int err = lfs_bd_read(lfs,
1779 NULL, &lfs->rcache, sizeof(dir->rev),
1789 if (lfs->cfg->block_cycles > 0) {
1790 dir->rev = lfs_alignup(dir->rev, ((lfs->cfg->block_cycles+1)|1));
1808 static int lfs_dir_drop(lfs_t *lfs, lfs_mdir_t *dir, lfs_mdir_t *tail) {
1810 int err = lfs_dir_getgstate(lfs, tail, &lfs->gdelta);
1817 err = lfs_dir_commit(lfs, dir, LFS_MKATTRS(
1829 static int lfs_dir_split(lfs_t *lfs,
1834 int err = lfs_dir_alloc(lfs, &tail);
1844 int res = lfs_dir_compact(lfs, &tail, attrs, attrcount, source, split, end);
1854 if (lfs_pair_cmp(dir->pair, lfs->root) == 0 && split == 0) {
1855 lfs->root[0] = tail.pair[0];
1856 lfs->root[1] = tail.pair[1];
1875 lfs_t *lfs;
1883 return lfs_dir_commitattr(commit->lfs, commit->commit, tag, buffer);
1888 static bool lfs_dir_needsrelocation(lfs_t *lfs, lfs_mdir_t *dir) {
1895 return (lfs->cfg->block_cycles > 0
1896 && ((dir->rev + 1) % ((lfs->cfg->block_cycles+1)|1) == 0));
1901 static int lfs_dir_compact(lfs_t *lfs,
1906 bool tired = lfs_dir_needsrelocation(lfs, dir);
1918 if (lfs->lfs1) {
1939 .end = (lfs->cfg->metadata_max ?
1940 lfs->cfg->metadata_max : lfs->cfg->block_size) - 8,
1944 int err = lfs_bd_erase(lfs, dir->pair[1]);
1954 err = lfs_dir_commitprog(lfs, &commit,
1965 err = lfs_dir_traverse(lfs,
1971 lfs, &commit});
1982 err = lfs_dir_commitattr(lfs, &commit,
1997 lfs_gstate_xor(&delta, &lfs->gdisk);
1998 lfs_gstate_xor(&delta, &lfs->gstate);
2000 lfs_gstate_xor(&delta, &lfs->gdelta);
2003 err = lfs_dir_getgstate(lfs, dir, &delta);
2010 err = lfs_dir_commitattr(lfs, &commit,
2022 err = lfs_dir_commitcrc(lfs, &commit);
2031 LFS_ASSERT(commit.off % lfs->cfg->prog_size == 0);
2037 lfs->gdelta = (lfs_gstate_t){0};
2039 lfs->gdisk = lfs->gstate;
2047 lfs_cache_drop(lfs, &lfs->pcache);
2060 int err = lfs_alloc(lfs, &dir->pair[1]);
2074 static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,
2087 int err = lfs_dir_traverse(lfs,
2110 lfs->cfg->block_size - 40,
2112 (lfs->cfg->metadata_max
2113 ? lfs->cfg->metadata_max
2114 : lfs->cfg->block_size)/2,
2115 lfs->cfg->prog_size))) {
2128 int err = lfs_dir_split(lfs, dir, attrs, attrcount,
2145 if (lfs_dir_needsrelocation(lfs, dir)
2149 lfs_ssize_t size = lfs_fs_rawsize(lfs);
2156 if ((lfs_size_t)size < lfs->block_count/2) {
2158 int err = lfs_dir_split(lfs, dir, attrs, attrcount,
2174 return lfs_dir_compact(lfs, dir, attrs, attrcount, source, begin, end);
2179 static int lfs_dir_relocatingcommit(lfs_t *lfs, lfs_mdir_t *dir,
2205 int err = lfs_fs_pred(lfs, dir->pair, pdir);
2225 .end = (lfs->cfg->metadata_max ?
2226 lfs->cfg->metadata_max : lfs->cfg->block_size) - 8,
2231 int err = lfs_dir_traverse(lfs,
2235 lfs, &commit});
2246 lfs_gstate_xor(&delta, &lfs->gstate);
2247 lfs_gstate_xor(&delta, &lfs->gdisk);
2248 lfs_gstate_xor(&delta, &lfs->gdelta);
2251 err = lfs_dir_getgstate(lfs, dir, &delta);
2257 err = lfs_dir_commitattr(lfs, &commit,
2269 err = lfs_dir_commitcrc(lfs, &commit);
2278 LFS_ASSERT(commit.off % lfs->cfg->prog_size == 0);
2282 lfs->gdisk = lfs->gstate;
2283 lfs->gdelta = (lfs_gstate_t){0};
2290 lfs_cache_drop(lfs, &lfs->pcache);
2292 state = lfs_dir_splittingcompact(lfs, dir, attrs, attrcount,
2309 for (struct lfs_mlist *d = lfs->mlist; d; d = d->next) {
2337 int err = lfs_dir_fetch(lfs, &d->m, d->m.tail);
2350 static int lfs_dir_orphaningcommit(lfs_t *lfs, lfs_mdir_t *dir,
2354 for (lfs_file_t *f = (lfs_file_t*)lfs->mlist; f; f = f->next) {
2357 f->ctz.size > lfs->cfg->cache_size) {
2358 int err = lfs_file_outline(lfs, f);
2363 err = lfs_file_flush(lfs, f);
2373 int state = lfs_dir_relocatingcommit(lfs, &ldir, dir->pair,
2392 int err = lfs_dir_getgstate(lfs, dir, &lfs->gdelta);
2401 state = lfs_dir_relocatingcommit(lfs, &pdir, lpair, LFS_MKATTRS(
2422 if (lfs_pair_cmp(lpair, lfs->root) == 0) {
2423 lfs->root[0] = ldir.pair[0];
2424 lfs->root[1] = ldir.pair[1];
2428 for (struct lfs_mlist *d = lfs->mlist; d; d = d->next) {
2442 lfs_stag_t tag = lfs_fs_parent(lfs, lpair, &pdir);
2451 int err = lfs_fs_preporphans(lfs, +1);
2459 if (lfs_gstate_hasmovehere(&lfs->gstate, pdir.pair)) {
2460 moveid = lfs_tag_id(lfs->gstate.tag);
2464 lfs_fs_prepmove(lfs, 0x3ff, NULL);
2472 state = lfs_dir_relocatingcommit(lfs, &pdir, ppair, LFS_MKATTRS(
2492 int err = lfs_fs_pred(lfs, lpair, &pdir);
2500 if (lfs_gstate_hasorphans(&lfs->gstate)) {
2502 err = lfs_fs_preporphans(lfs, -hasparent);
2511 if (lfs_gstate_hasmovehere(&lfs->gstate, pdir.pair)) {
2512 moveid = lfs_tag_id(lfs->gstate.tag);
2516 lfs_fs_prepmove(lfs, 0x3ff, NULL);
2523 state = lfs_dir_relocatingcommit(lfs, &pdir, lpair, LFS_MKATTRS(
2543 static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
2545 int orphans = lfs_dir_orphaningcommit(lfs, dir, attrs, attrcount);
2554 int err = lfs_fs_deorphan(lfs, false);
2567 static int lfs_rawmkdir(lfs_t *lfs, const char *path) {
2569 int err = lfs_fs_forceconsistency(lfs);
2575 cwd.next = lfs->mlist;
2577 err = lfs_dir_find(lfs, &cwd.m, &path, &id);
2584 if (nlen > lfs->name_max) {
2589 lfs_alloc_ack(lfs);
2591 err = lfs_dir_alloc(lfs, &dir);
2599 err = lfs_dir_fetch(lfs, &pred, pred.tail);
2607 err = lfs_dir_commit(lfs, &dir, LFS_MKATTRS(
2617 err = lfs_fs_preporphans(lfs, +1);
2628 lfs->mlist = &cwd;
2631 err = lfs_dir_commit(lfs, &pred, LFS_MKATTRS(
2635 lfs->mlist = cwd.next;
2639 lfs->mlist = cwd.next;
2640 err = lfs_fs_preporphans(lfs, -1);
2648 err = lfs_dir_commit(lfs, &cwd.m, LFS_MKATTRS(
2663 static int lfs_dir_rawopen(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
2664 lfs_stag_t tag = lfs_dir_find(lfs, &dir->m, &path, NULL);
2676 pair[0] = lfs->root[0];
2677 pair[1] = lfs->root[1];
2680 lfs_stag_t res = lfs_dir_get(lfs, &dir->m, LFS_MKTAG(0x700, 0x3ff, 0),
2689 int err = lfs_dir_fetch(lfs, &dir->m, pair);
2702 lfs_mlist_append(lfs, (struct lfs_mlist *)dir);
2707 static int lfs_dir_rawclose(lfs_t *lfs, lfs_dir_t *dir) {
2709 lfs_mlist_remove(lfs, (struct lfs_mlist *)dir);
2714 static int lfs_dir_rawread(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
2736 int err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail);
2744 int err = lfs_dir_getinfo(lfs, &dir->m, dir->id, info);
2759 static int lfs_dir_rawseek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
2761 int err = lfs_dir_rawrewind(lfs, dir);
2771 dir->id = (off > 0 && lfs_pair_cmp(dir->head, lfs->root) == 0);
2779 err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail);
2796 static lfs_soff_t lfs_dir_rawtell(lfs_t *lfs, lfs_dir_t *dir) {
2797 (void)lfs;
2801 static int lfs_dir_rawrewind(lfs_t *lfs, lfs_dir_t *dir) {
2803 int err = lfs_dir_fetch(lfs, &dir->m, dir->head);
2815 static int lfs_ctz_index(lfs_t *lfs, lfs_off_t *off) {
2817 lfs_off_t b = lfs->cfg->block_size - 2*4;
2828 static int lfs_ctz_find(lfs_t *lfs,
2838 lfs_off_t current = lfs_ctz_index(lfs, &(lfs_off_t){size-1});
2839 lfs_off_t target = lfs_ctz_index(lfs, &pos);
2846 int err = lfs_bd_read(lfs,
2863 static int lfs_ctz_extend(lfs_t *lfs,
2870 int err = lfs_alloc(lfs, &nblock);
2876 err = lfs_bd_erase(lfs, nblock);
2891 lfs_off_t index = lfs_ctz_index(lfs, &noff);
2895 if (noff != lfs->cfg->block_size) {
2898 err = lfs_bd_read(lfs,
2905 err = lfs_bd_prog(lfs,
2927 err = lfs_bd_prog(lfs, pcache, rcache, true,
2938 err = lfs_bd_read(lfs,
2957 lfs_cache_drop(lfs, pcache);
2962 static int lfs_ctz_traverse(lfs_t *lfs,
2970 lfs_off_t index = lfs_ctz_index(lfs, &(lfs_off_t){size-1});
2984 err = lfs_bd_read(lfs,
3007 static int lfs_file_rawopencfg(lfs_t *lfs, lfs_file_t *file,
3013 int err = lfs_fs_forceconsistency(lfs);
3031 lfs_stag_t tag = lfs_dir_find(lfs, &file->m, &path, &file->id);
3039 lfs_mlist_append(lfs, (struct lfs_mlist *)file);
3054 if (nlen > lfs->name_max) {
3060 err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS(
3088 tag = lfs_dir_get(lfs, &file->m, LFS_MKTAG(0x700, 0x3ff, 0),
3101 lfs_stag_t res = lfs_dir_get(lfs, &file->m,
3115 if (file->cfg->attrs[i].size > lfs->attr_max) {
3129 file->cache.buffer = lfs_malloc(lfs->cfg->cache_size);
3137 lfs_cache_zero(lfs, &file->cache);
3146 file->cache.size = lfs->cfg->cache_size;
3150 lfs_stag_t res = lfs_dir_get(lfs, &file->m,
3169 lfs_file_rawclose(lfs, file);
3174 static int lfs_file_rawopen(lfs_t *lfs, lfs_file_t *file,
3177 int err = lfs_file_rawopencfg(lfs, file, path, flags, &defaults);
3182 static int lfs_file_rawclose(lfs_t *lfs, lfs_file_t *file) {
3184 int err = lfs_file_rawsync(lfs, file);
3190 lfs_mlist_remove(lfs, (struct lfs_mlist*)file);
3202 static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
3206 int err = lfs_alloc(lfs, &nblock);
3211 err = lfs_bd_erase(lfs, nblock);
3223 err = lfs_dir_getread(lfs, &file->m,
3233 err = lfs_bd_read(lfs,
3234 &file->cache, &lfs->rcache, file->off-i,
3241 err = lfs_bd_prog(lfs,
3242 &lfs->pcache, &lfs->rcache, true,
3253 memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->cache_size);
3254 file->cache.block = lfs->pcache.block;
3255 file->cache.off = lfs->pcache.off;
3256 file->cache.size = lfs->pcache.size;
3257 lfs_cache_zero(lfs, &lfs->pcache);
3267 lfs_cache_drop(lfs, &lfs->pcache);
3273 static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
3275 lfs_alloc_ack(lfs);
3276 int err = lfs_file_relocate(lfs, file);
3286 static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
3289 lfs_cache_drop(lfs, &file->cache);
3305 .cache = lfs->rcache,
3307 lfs_cache_drop(lfs, &lfs->rcache);
3313 lfs_ssize_t res = lfs_file_flushedread(lfs, &orig, &data, 1);
3318 res = lfs_file_flushedwrite(lfs, file, &data, 1);
3324 if (lfs->rcache.block != LFS_BLOCK_NULL) {
3325 lfs_cache_drop(lfs, &orig.cache);
3326 lfs_cache_drop(lfs, &lfs->rcache);
3332 int err = lfs_bd_flush(lfs, &file->cache, &lfs->rcache, true);
3344 err = lfs_file_relocate(lfs, file);
3367 static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file) {
3373 int err = lfs_file_flush(lfs, file);
3403 err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS(
3419 static lfs_ssize_t lfs_file_flushedread(lfs_t *lfs, lfs_file_t *file,
3435 file->off == lfs->cfg->block_size) {
3437 int err = lfs_ctz_find(lfs, NULL, &file->cache,
3452 lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off);
3454 int err = lfs_dir_getread(lfs, &file->m,
3455 NULL, &file->cache, lfs->cfg->block_size,
3463 int err = lfs_bd_read(lfs,
3464 NULL, &file->cache, lfs->cfg->block_size,
3480 static lfs_ssize_t lfs_file_rawread(lfs_t *lfs, lfs_file_t *file,
3487 int err = lfs_file_flush(lfs, file);
3494 return lfs_file_flushedread(lfs, file, buffer, size);
3499 static lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,
3507 lfs->cfg->cache_size,
3508 (lfs->cfg->metadata_max ?
3509 lfs->cfg->metadata_max : lfs->cfg->block_size) / 8))) {
3511 int err = lfs_file_outline(lfs, file);
3521 file->off == lfs->cfg->block_size) {
3525 int err = lfs_ctz_find(lfs, NULL, &file->cache,
3534 lfs_cache_zero(lfs, &file->cache);
3538 lfs_alloc_ack(lfs);
3539 int err = lfs_ctz_extend(lfs, &file->cache, &lfs->rcache,
3555 lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off);
3557 int err = lfs_bd_prog(lfs, &file->cache, &lfs->rcache, true,
3569 err = lfs_file_relocate(lfs, file);
3581 lfs_alloc_ack(lfs);
3587 static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file,
3593 int err = lfs_file_flush(lfs, file);
3603 if (file->pos + size > lfs->file_max) {
3614 lfs_ssize_t res = lfs_file_flushedwrite(lfs, file, &(uint8_t){0}, 1);
3621 lfs_ssize_t nsize = lfs_file_flushedwrite(lfs, file, buffer, size);
3631 static lfs_soff_t lfs_file_rawseek(lfs_t *lfs, lfs_file_t *file,
3644 lfs_soff_t res = lfs_file_rawsize(lfs, file) + off;
3652 if (npos > lfs->file_max) {
3671 int oindex = lfs_ctz_index(lfs, &(lfs_off_t){file->pos});
3673 int nindex = lfs_ctz_index(lfs, &noff);
3684 int err = lfs_file_flush(lfs, file);
3695 static int lfs_file_rawtruncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
3703 lfs_off_t oldsize = lfs_file_rawsize(lfs, file);
3707 lfs->cfg->cache_size,
3708 (lfs->cfg->metadata_max ?
3709 lfs->cfg->metadata_max : lfs->cfg->block_size) / 8))) {
3711 lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_SET);
3717 lfs_cache_drop(lfs, &lfs->rcache);
3718 res = lfs_file_flushedread(lfs, file,
3719 lfs->rcache.buffer, size);
3729 file->cache.size = lfs->cfg->cache_size;
3730 memcpy(file->cache.buffer, lfs->rcache.buffer, size);
3734 int err = lfs_file_flush(lfs, file);
3740 err = lfs_ctz_find(lfs, NULL, &file->cache,
3756 lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_END);
3763 res = lfs_file_rawwrite(lfs, file, &(uint8_t){0}, 1);
3771 lfs_soff_t res = lfs_file_rawseek(lfs, file, pos, LFS_SEEK_SET);
3780 static lfs_soff_t lfs_file_rawtell(lfs_t *lfs, lfs_file_t *file) {
3781 (void)lfs;
3785 static int lfs_file_rawrewind(lfs_t *lfs, lfs_file_t *file) {
3786 lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_SET);
3794 static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file) {
3795 (void)lfs;
3808 static int lfs_rawstat(lfs_t *lfs, const char *path, struct lfs_info *info) {
3810 lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);
3815 return lfs_dir_getinfo(lfs, &cwd, lfs_tag_id(tag), info);
3819 static int lfs_rawremove(lfs_t *lfs, const char *path) {
3821 int err = lfs_fs_forceconsistency(lfs);
3827 lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);
3833 dir.next = lfs->mlist;
3837 lfs_stag_t res = lfs_dir_get(lfs, &cwd, LFS_MKTAG(0x700, 0x3ff, 0),
3844 err = lfs_dir_fetch(lfs, &dir.m, pair);
3854 err = lfs_fs_preporphans(lfs, +1);
3863 lfs->mlist = &dir;
3867 err = lfs_dir_commit(lfs, &cwd, LFS_MKATTRS(
3870 lfs->mlist = dir.next;
3874 lfs->mlist = dir.next;
3877 err = lfs_fs_preporphans(lfs, -1);
3882 err = lfs_fs_pred(lfs, dir.m.pair, &cwd);
3887 err = lfs_dir_drop(lfs, &cwd, &dir.m);
3898 static int lfs_rawrename(lfs_t *lfs, const char *oldpath, const char *newpath) {
3900 int err = lfs_fs_forceconsistency(lfs);
3907 lfs_stag_t oldtag = lfs_dir_find(lfs, &oldcwd, &oldpath, NULL);
3915 lfs_stag_t prevtag = lfs_dir_find(lfs, &newcwd, &newpath, &newid);
3926 prevdir.next = lfs->mlist;
3930 if (nlen > lfs->name_max) {
3948 lfs_stag_t res = lfs_dir_get(lfs, &newcwd, LFS_MKTAG(0x700, 0x3ff, 0),
3956 err = lfs_dir_fetch(lfs, &prevdir.m, prevpair);
3966 err = lfs_fs_preporphans(lfs, +1);
3975 lfs->mlist = &prevdir;
3979 lfs_fs_prepmove(lfs, newoldid, oldcwd.pair);
3983 err = lfs_dir_commit(lfs, &newcwd, LFS_MKATTRS(
3992 lfs->mlist = prevdir.next;
3998 if (!samepair && lfs_gstate_hasmove(&lfs->gstate)) {
4000 lfs_fs_prepmove(lfs, 0x3ff, NULL);
4001 err = lfs_dir_commit(lfs, &oldcwd, LFS_MKATTRS(
4004 lfs->mlist = prevdir.next;
4009 lfs->mlist = prevdir.next;
4013 err = lfs_fs_preporphans(lfs, -1);
4018 err = lfs_fs_pred(lfs, prevdir.m.pair, &newcwd);
4023 err = lfs_dir_drop(lfs, &newcwd, &prevdir.m);
4033 static lfs_ssize_t lfs_rawgetattr(lfs_t *lfs, const char *path,
4036 lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);
4045 int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
4051 tag = lfs_dir_get(lfs, &cwd, LFS_MKTAG(0x7ff, 0x3ff, 0),
4053 id, lfs_min(size, lfs->attr_max)),
4067 static int lfs_commitattr(lfs_t *lfs, const char *path,
4070 lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);
4079 int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
4085 return lfs_dir_commit(lfs, &cwd, LFS_MKATTRS(
4091 static int lfs_rawsetattr(lfs_t *lfs, const char *path,
4093 if (size > lfs->attr_max) {
4097 return lfs_commitattr(lfs, path, type, buffer, size);
4102 static int lfs_rawremoveattr(lfs_t *lfs, const char *path, uint8_t type) {
4103 return lfs_commitattr(lfs, path, type, NULL, 0x3ff);
4109 static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
4110 lfs->cfg = cfg;
4111 lfs->block_count = cfg->block_count; // May be 0
4116 LFS_ASSERT(!lfs->cfg->disk_version || (
4117 (0xffff & (lfs->cfg->disk_version >> 16))
4119 && (0xffff & (lfs->cfg->disk_version >> 0))
4129 // validate that the lfs-cfg sizes were initiated properly before
4131 LFS_ASSERT(lfs->cfg->read_size != 0);
4132 LFS_ASSERT(lfs->cfg->prog_size != 0);
4133 LFS_ASSERT(lfs->cfg->cache_size != 0);
4137 LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->read_size == 0);
4138 LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->prog_size == 0);
4139 LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->cache_size == 0);
4142 LFS_ASSERT(lfs->cfg->block_size >= 128);
4145 LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4))
4146 <= lfs->cfg->block_size);
4154 LFS_ASSERT(lfs->cfg->block_cycles != 0);
4158 if (lfs->cfg->read_buffer) {
4159 lfs->rcache.buffer = lfs->cfg->read_buffer;
4161 lfs->rcache.buffer = lfs_malloc(lfs->cfg->cache_size);
4162 if (!lfs->rcache.buffer) {
4169 if (lfs->cfg->prog_buffer) {
4170 lfs->pcache.buffer = lfs->cfg->prog_buffer;
4172 lfs->pcache.buffer = lfs_malloc(lfs->cfg->cache_size);
4173 if (!lfs->pcache.buffer) {
4180 lfs_cache_zero(lfs, &lfs->rcache);
4181 lfs_cache_zero(lfs, &lfs->pcache);
4184 LFS_ASSERT(lfs->cfg->lookahead_size > 0);
4185 LFS_ASSERT(lfs->cfg->lookahead_size % 8 == 0 &&
4186 (uintptr_t)lfs->cfg->lookahead_buffer % 4 == 0);
4187 if (lfs->cfg->lookahead_buffer) {
4188 lfs->free.buffer = lfs->cfg->lookahead_buffer;
4190 lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead_size);
4191 if (!lfs->free.buffer) {
4198 LFS_ASSERT(lfs->cfg->name_max <= LFS_NAME_MAX);
4199 lfs->name_max = lfs->cfg->name_max;
4200 if (!lfs->name_max) {
4201 lfs->name_max = LFS_NAME_MAX;
4204 LFS_ASSERT(lfs->cfg->file_max <= LFS_FILE_MAX);
4205 lfs->file_max = lfs->cfg->file_max;
4206 if (!lfs->file_max) {
4207 lfs->file_max = LFS_FILE_MAX;
4210 LFS_ASSERT(lfs->cfg->attr_max <= LFS_ATTR_MAX);
4211 lfs->attr_max = lfs->cfg->attr_max;
4212 if (!lfs->attr_max) {
4213 lfs->attr_max = LFS_ATTR_MAX;
4216 LFS_ASSERT(lfs->cfg->metadata_max <= lfs->cfg->block_size);
4219 lfs->root[0] = LFS_BLOCK_NULL;
4220 lfs->root[1] = LFS_BLOCK_NULL;
4221 lfs->mlist = NULL;
4222 lfs->seed = 0;
4223 lfs->gdisk = (lfs_gstate_t){0};
4224 lfs->gstate = (lfs_gstate_t){0};
4225 lfs->gdelta = (lfs_gstate_t){0};
4227 lfs->lfs1 = NULL;
4233 lfs_deinit(lfs);
4237 static int lfs_deinit(lfs_t *lfs) {
4239 if (!lfs->cfg->read_buffer) {
4240 lfs_free(lfs->rcache.buffer);
4243 if (!lfs->cfg->prog_buffer) {
4244 lfs_free(lfs->pcache.buffer);
4247 if (!lfs->cfg->lookahead_buffer) {
4248 lfs_free(lfs->free.buffer);
4257 static int lfs_rawformat(lfs_t *lfs, const struct lfs_config *cfg) {
4260 err = lfs_init(lfs, cfg);
4268 memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size);
4269 lfs->free.off = 0;
4270 lfs->free.size = lfs_min(8*lfs->cfg->lookahead_size,
4271 lfs->block_count);
4272 lfs->free.i = 0;
4273 lfs_alloc_ack(lfs);
4277 err = lfs_dir_alloc(lfs, &root);
4284 .version = lfs_fs_disk_version(lfs),
4285 .block_size = lfs->cfg->block_size,
4286 .block_count = lfs->block_count,
4287 .name_max = lfs->name_max,
4288 .file_max = lfs->file_max,
4289 .attr_max = lfs->attr_max,
4293 err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(
4305 err = lfs_dir_commit(lfs, &root, NULL, 0);
4311 err = lfs_dir_fetch(lfs, &root, (const lfs_block_t[2]){0, 1});
4318 lfs_deinit(lfs);
4324 static int lfs_rawmount(lfs_t *lfs, const struct lfs_config *cfg) {
4325 int err = lfs_init(lfs, cfg);
4351 lfs_stag_t tag = lfs_dir_fetchmatch(lfs, &dir, dir.tail,
4356 lfs, "littlefs", 8});
4365 lfs->root[0] = dir.pair[0];
4366 lfs->root[1] = dir.pair[1];
4370 tag = lfs_dir_get(lfs, &dir, LFS_MKTAG(0x7ff, 0x3ff, 0),
4382 if (major_version != lfs_fs_disk_version_major(lfs)
4383 || minor_version > lfs_fs_disk_version_minor(lfs)) {
4388 lfs_fs_disk_version_major(lfs),
4389 lfs_fs_disk_version_minor(lfs));
4397 if (minor_version < lfs_fs_disk_version_minor(lfs)) {
4402 lfs_fs_disk_version_major(lfs),
4403 lfs_fs_disk_version_minor(lfs));
4406 lfs_fs_prepsuperblock(lfs, true);
4411 if (superblock.name_max > lfs->name_max) {
4413 superblock.name_max, lfs->name_max);
4418 lfs->name_max = superblock.name_max;
4422 if (superblock.file_max > lfs->file_max) {
4424 superblock.file_max, lfs->file_max);
4429 lfs->file_max = superblock.file_max;
4433 if (superblock.attr_max > lfs->attr_max) {
4435 superblock.attr_max, lfs->attr_max);
4440 lfs->attr_max = superblock.attr_max;
4444 if (lfs->cfg->block_count
4445 && superblock.block_count != lfs->cfg->block_count) {
4447 superblock.block_count, lfs->cfg->block_count);
4452 lfs->block_count = superblock.block_count;
4454 if (superblock.block_size != lfs->cfg->block_size) {
4456 superblock.block_size, lfs->cfg->block_size);
4463 err = lfs_dir_getgstate(lfs, &dir, &lfs->gstate);
4470 if (!lfs_gstate_iszero(&lfs->gstate)) {
4472 lfs->gstate.tag,
4473 lfs->gstate.pair[0],
4474 lfs->gstate.pair[1]);
4476 lfs->gstate.tag += !lfs_tag_isvalid(lfs->gstate.tag);
4477 lfs->gdisk = lfs->gstate;
4481 lfs->free.off = lfs->seed % lfs->block_count;
4482 lfs_alloc_drop(lfs);
4487 lfs_rawunmount(lfs);
4491 static int lfs_rawunmount(lfs_t *lfs) {
4492 return lfs_deinit(lfs);
4497 static int lfs_fs_rawstat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
4500 if (!lfs_gstate_needssuperblock(&lfs->gstate)) {
4501 fsinfo->disk_version = lfs_fs_disk_version(lfs);
4507 int err = lfs_dir_fetch(lfs, &dir, lfs->root);
4513 lfs_stag_t tag = lfs_dir_get(lfs, &dir, LFS_MKTAG(0x7ff, 0x3ff, 0),
4526 fsinfo->block_size = lfs->cfg->block_size;
4527 fsinfo->block_count = lfs->block_count;
4530 fsinfo->name_max = lfs->name_max;
4531 fsinfo->file_max = lfs->file_max;
4532 fsinfo->attr_max = lfs->attr_max;
4537 int lfs_fs_rawtraverse(lfs_t *lfs,
4545 if (lfs->lfs1) {
4546 int err = lfs1_traverse(lfs, cb, data);
4551 dir.tail[0] = lfs->root[0];
4552 dir.tail[1] = lfs->root[1];
4581 int err = lfs_dir_fetch(lfs, &dir, dir.tail);
4588 lfs_stag_t tag = lfs_dir_get(lfs, &dir, LFS_MKTAG(0x700, 0x3ff, 0),
4599 err = lfs_ctz_traverse(lfs, NULL, &lfs->rcache,
4618 for (lfs_file_t *f = (lfs_file_t*)lfs->mlist; f; f = f->next) {
4624 int err = lfs_ctz_traverse(lfs, &f->cache, &lfs->rcache,
4632 int err = lfs_ctz_traverse(lfs, &f->cache, &lfs->rcache,
4645 static int lfs_fs_pred(lfs_t *lfs,
4671 int err = lfs_dir_fetch(lfs, pdir, pdir->tail);
4683 lfs_t *lfs;
4692 lfs_t *lfs = find->lfs;
4697 int err = lfs_bd_read(lfs,
4698 &lfs->pcache, &lfs->rcache, lfs->cfg->block_size,
4710 static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2],
4732 lfs_stag_t tag = lfs_dir_fetchmatch(lfs, parent, parent->tail,
4737 lfs, {pair[0], pair[1]}});
4747 static void lfs_fs_prepsuperblock(lfs_t *lfs, bool needssuperblock) {
4748 lfs->gstate.tag = (lfs->gstate.tag & ~LFS_MKTAG(0, 0, 0x200))
4753 static int lfs_fs_preporphans(lfs_t *lfs, int8_t orphans) {
4754 LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) > 0x000 || orphans >= 0);
4755 LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) < 0x1ff || orphans <= 0);
4756 lfs->gstate.tag += orphans;
4757 lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x800, 0, 0)) |
4758 ((uint32_t)lfs_gstate_hasorphans(&lfs->gstate) << 31));
4765 static void lfs_fs_prepmove(lfs_t *lfs,
4767 lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x7ff, 0x3ff, 0)) |
4769 lfs->gstate.pair[0] = (id != 0x3ff) ? pair[0] : 0;
4770 lfs->gstate.pair[1] = (id != 0x3ff) ? pair[1] : 0;
4775 static int lfs_fs_desuperblock(lfs_t *lfs) {
4776 if (!lfs_gstate_needssuperblock(&lfs->gstate)) {
4781 lfs->root[0],
4782 lfs->root[1]);
4785 int err = lfs_dir_fetch(lfs, &root, lfs->root);
4792 .version = lfs_fs_disk_version(lfs),
4793 .block_size = lfs->cfg->block_size,
4794 .block_count = lfs->block_count,
4795 .name_max = lfs->name_max,
4796 .file_max = lfs->file_max,
4797 .attr_max = lfs->attr_max,
4801 err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(
4808 lfs_fs_prepsuperblock(lfs, false);
4814 static int lfs_fs_demove(lfs_t *lfs) {
4815 if (!lfs_gstate_hasmove(&lfs->gdisk)) {
4821 lfs->gdisk.pair[0],
4822 lfs->gdisk.pair[1],
4823 lfs_tag_id(lfs->gdisk.tag));
4827 LFS_ASSERT(lfs_tag_type3(lfs->gdisk.tag) == LFS_TYPE_DELETE);
4831 int err = lfs_dir_fetch(lfs, &movedir, lfs->gdisk.pair);
4837 uint16_t moveid = lfs_tag_id(lfs->gdisk.tag);
4838 lfs_fs_prepmove(lfs, 0x3ff, NULL);
4839 err = lfs_dir_commit(lfs, &movedir, LFS_MKATTRS(
4850 static int lfs_fs_deorphan(lfs_t *lfs, bool powerloss) {
4851 if (!lfs_gstate_hasorphans(&lfs->gstate)) {
4872 int err = lfs_dir_fetch(lfs, &dir, pdir.tail);
4881 lfs_stag_t tag = lfs_fs_parent(lfs, pdir.tail, &parent);
4888 lfs_stag_t state = lfs_dir_get(lfs, &parent,
4906 if (lfs_gstate_hasmovehere(&lfs->gstate, pdir.pair)) {
4907 moveid = lfs_tag_id(lfs->gstate.tag);
4911 lfs_fs_prepmove(lfs, 0x3ff, NULL);
4915 state = lfs_dir_orphaningcommit(lfs, &pdir, LFS_MKATTRS(
4944 err = lfs_dir_getgstate(lfs, &dir, &lfs->gdelta);
4951 int state = lfs_dir_orphaningcommit(lfs, &pdir, LFS_MKATTRS(
4976 return lfs_fs_preporphans(lfs, -lfs_gstate_getorphans(&lfs->gstate));
4981 static int lfs_fs_forceconsistency(lfs_t *lfs) {
4982 int err = lfs_fs_desuperblock(lfs);
4987 err = lfs_fs_demove(lfs);
4992 err = lfs_fs_deorphan(lfs, true);
5002 int lfs_fs_rawmkconsistent(lfs_t *lfs) {
5004 int err = lfs_fs_forceconsistency(lfs);
5011 lfs_gstate_xor(&delta, &lfs->gdisk);
5012 lfs_gstate_xor(&delta, &lfs->gstate);
5016 err = lfs_dir_fetch(lfs, &root, lfs->root);
5021 err = lfs_dir_commit(lfs, &root, NULL, 0);
5038 static lfs_ssize_t lfs_fs_rawsize(lfs_t *lfs) {
5040 int err = lfs_fs_rawtraverse(lfs, lfs_fs_size_count, &size, false);
5049 int lfs_fs_rawgrow(lfs_t *lfs, lfs_size_t block_count) {
5051 LFS_ASSERT(block_count >= lfs->block_count);
5053 if (block_count > lfs->block_count) {
5054 lfs->block_count = block_count;
5058 int err = lfs_dir_fetch(lfs, &root, lfs->root);
5065 lfs_stag_t tag = lfs_dir_get(lfs, &root, LFS_MKTAG(0x7ff, 0x3ff, 0),
5073 superblock.block_count = lfs->block_count;
5076 err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(
5175 static int lfs1_bd_read(lfs_t *lfs, lfs_block_t block,
5179 return lfs_bd_read(lfs, &lfs->pcache, &lfs->rcache, size,
5183 static int lfs1_bd_crc(lfs_t *lfs, lfs_block_t block,
5187 int err = lfs1_bd_read(lfs, block, off+i, &c, 1);
5238 static int lfs1_dir_fetch(lfs_t *lfs,
5247 int err = lfs1_bd_read(lfs, tpair[i], 0, &test, sizeof(test));
5261 (0x7fffffff & test.size) > lfs->cfg->block_size) {
5269 err = lfs1_bd_crc(lfs, tpair[i], sizeof(test),
5300 static int lfs1_dir_next(lfs_t *lfs, lfs1_dir_t *dir, lfs1_entry_t *entry) {
5307 int err = lfs1_dir_fetch(lfs, dir, dir->d.tail);
5316 int err = lfs1_bd_read(lfs, dir->pair[0], dir->off,
5330 int lfs1_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
5331 if (lfs_pair_isnull(lfs->lfs1->root)) {
5348 int err = lfs1_dir_fetch(lfs, &dir, cwd);
5355 err = lfs1_bd_read(lfs, dir.pair[0], dir.off,
5364 err = lfs_ctz_traverse(lfs, NULL, &lfs->rcache,
5375 err = lfs_dir_fetch(lfs, &dir2, dir2.tail);
5399 static int lfs1_moved(lfs_t *lfs, const void *e) {
5400 if (lfs_pair_isnull(lfs->lfs1->root)) {
5406 int err = lfs1_dir_fetch(lfs, &cwd, (const lfs_block_t[2]){0, 1});
5414 err = lfs1_dir_fetch(lfs, &cwd, cwd.d.tail);
5420 err = lfs1_dir_next(lfs, &cwd, &entry);
5440 static int lfs1_mount(lfs_t *lfs, struct lfs1 *lfs1,
5444 err = lfs_init(lfs, cfg);
5449 lfs->lfs1 = lfs1;
5450 lfs->lfs1->root[0] = LFS_BLOCK_NULL;
5451 lfs->lfs1->root[1] = LFS_BLOCK_NULL;
5454 lfs->free.off = 0;
5455 lfs->free.size = 0;
5456 lfs->free.i = 0;
5457 lfs_alloc_ack(lfs);
5462 err = lfs1_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
5468 err = lfs1_bd_read(lfs, dir.pair[0], sizeof(dir.d),
5475 lfs->lfs1->root[0] = superblock.d.root[0];
5476 lfs->lfs1->root[1] = superblock.d.root[1];
5499 lfs_deinit(lfs);
5503 static int lfs1_unmount(lfs_t *lfs) {
5504 return lfs_deinit(lfs);
5508 static int lfs_rawmigrate(lfs_t *lfs, const struct lfs_config *cfg) {
5514 int err = lfs1_mount(lfs, &lfs1, cfg);
5524 dir1.d.tail[0] = lfs->lfs1->root[0];
5525 dir1.d.tail[1] = lfs->lfs1->root[1];
5528 err = lfs1_dir_fetch(lfs, &dir1, dir1.d.tail);
5534 err = lfs_dir_alloc(lfs, &dir2);
5542 lfs->root[0] = dir2.pair[0];
5543 lfs->root[1] = dir2.pair[1];
5545 err = lfs_dir_commit(lfs, &dir2, NULL, 0);
5552 err = lfs1_dir_next(lfs, &dir1, &entry1);
5563 int moved = lfs1_moved(lfs, &entry1.d.u);
5579 err = lfs1_bd_read(lfs, dir1.pair[0],
5589 err = lfs_dir_fetch(lfs, &dir2, lfs->root);
5595 err = lfs_dir_find(lfs, &dir2, &(const char*){name}, &id);
5602 err = lfs_dir_commit(lfs, &dir2, LFS_MKATTRS(
5620 err = lfs_dir_fetch(lfs, &dir2, lfs->root);
5626 err = lfs_dir_fetch(lfs, &dir2, dir2.tail);
5633 err = lfs_dir_commit(lfs, &dir2, LFS_MKATTRS(
5645 lfs->root[0], lfs->root[1], dir1.head[0], dir1.head[1]);
5647 err = lfs_bd_erase(lfs, dir1.head[1]);
5652 err = lfs_dir_fetch(lfs, &dir2, lfs->root);
5659 err = lfs_bd_read(lfs,
5660 NULL, &lfs->rcache, dir2.off,
5666 err = lfs_bd_prog(lfs,
5667 &lfs->pcache, &lfs->rcache, true,
5674 err = lfs_bd_flush(lfs, &lfs->pcache, &lfs->rcache, true);
5681 err = lfs1_dir_fetch(lfs, &dir1, (const lfs_block_t[2]){0, 1});
5692 dir2.tail[0] = lfs->lfs1->root[0];
5693 dir2.tail[1] = lfs->lfs1->root[1];
5699 .block_size = lfs->cfg->block_size,
5700 .block_count = lfs->cfg->block_count,
5701 .name_max = lfs->name_max,
5702 .file_max = lfs->file_max,
5703 .attr_max = lfs->attr_max,
5707 err = lfs_dir_commit(lfs, &dir2, LFS_MKATTRS(
5717 err = lfs_dir_fetch(lfs, &dir2, (const lfs_block_t[2]){0, 1});
5724 err = lfs_dir_commit(lfs, &dir2, NULL, 0);
5731 lfs1_unmount(lfs);
5753 int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
5767 (void*)lfs, (void*)cfg, cfg->context,
5775 err = lfs_rawformat(lfs, cfg);
5783 int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
5797 (void*)lfs, (void*)cfg, cfg->context,
5805 err = lfs_rawmount(lfs, cfg);
5812 int lfs_unmount(lfs_t *lfs) {
5813 int err = LFS_LOCK(lfs->cfg);
5817 LFS_TRACE("lfs_unmount(%p)", (void*)lfs);
5819 err = lfs_rawunmount(lfs);
5822 LFS_UNLOCK(lfs->cfg);
5827 int lfs_remove(lfs_t *lfs, const char *path) {
5828 int err = LFS_LOCK(lfs->cfg);
5832 LFS_TRACE("lfs_remove(%p, \"%s\")", (void*)lfs, path);
5834 err = lfs_rawremove(lfs, path);
5837 LFS_UNLOCK(lfs->cfg);
5843 int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
5844 int err = LFS_LOCK(lfs->cfg);
5848 LFS_TRACE("lfs_rename(%p, \"%s\", \"%s\")", (void*)lfs, oldpath, newpath);
5850 err = lfs_rawrename(lfs, oldpath, newpath);
5853 LFS_UNLOCK(lfs->cfg);
5858 int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
5859 int err = LFS_LOCK(lfs->cfg);
5863 LFS_TRACE("lfs_stat(%p, \"%s\", %p)", (void*)lfs, path, (void*)info);
5865 err = lfs_rawstat(lfs, path, info);
5868 LFS_UNLOCK(lfs->cfg);
5872 lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
5874 int err = LFS_LOCK(lfs->cfg);
5879 (void*)lfs, path, type, buffer, size);
5881 lfs_ssize_t res = lfs_rawgetattr(lfs, path, type, buffer, size);
5884 LFS_UNLOCK(lfs->cfg);
5889 int lfs_setattr(lfs_t *lfs, const char *path,
5891 int err = LFS_LOCK(lfs->cfg);
5896 (void*)lfs, path, type, buffer, size);
5898 err = lfs_rawsetattr(lfs, path, type, buffer, size);
5901 LFS_UNLOCK(lfs->cfg);
5907 int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) {
5908 int err = LFS_LOCK(lfs->cfg);
5912 LFS_TRACE("lfs_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs, path, type);
5914 err = lfs_rawremoveattr(lfs, path, type);
5917 LFS_UNLOCK(lfs->cfg);
5923 int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) {
5924 int err = LFS_LOCK(lfs->cfg);
5929 (void*)lfs, (void*)file, path, flags);
5930 LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
5932 err = lfs_file_rawopen(lfs, file, path, flags);
5935 LFS_UNLOCK(lfs->cfg);
5940 int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
5943 int err = LFS_LOCK(lfs->cfg);
5949 (void*)lfs, (void*)file, path, flags,
5951 LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
5953 err = lfs_file_rawopencfg(lfs, file, path, flags, cfg);
5956 LFS_UNLOCK(lfs->cfg);
5960 int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
5961 int err = LFS_LOCK(lfs->cfg);
5965 LFS_TRACE("lfs_file_close(%p, %p)", (void*)lfs, (void*)file);
5966 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
5968 err = lfs_file_rawclose(lfs, file);
5971 LFS_UNLOCK(lfs->cfg);
5976 int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
5977 int err = LFS_LOCK(lfs->cfg);
5981 LFS_TRACE("lfs_file_sync(%p, %p)", (void*)lfs, (void*)file);
5982 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
5984 err = lfs_file_rawsync(lfs, file);
5987 LFS_UNLOCK(lfs->cfg);
5992 lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
5994 int err = LFS_LOCK(lfs->cfg);
5999 (void*)lfs, (void*)file, buffer, size);
6000 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6002 lfs_ssize_t res = lfs_file_rawread(lfs, file, buffer, size);
6005 LFS_UNLOCK(lfs->cfg);
6010 lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
6012 int err = LFS_LOCK(lfs->cfg);
6017 (void*)lfs, (void*)file, buffer, size);
6018 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6020 lfs_ssize_t res = lfs_file_rawwrite(lfs, file, buffer, size);
6023 LFS_UNLOCK(lfs->cfg);
6028 lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
6030 int err = LFS_LOCK(lfs->cfg);
6035 (void*)lfs, (void*)file, off, whence);
6036 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6038 lfs_soff_t res = lfs_file_rawseek(lfs, file, off, whence);
6041 LFS_UNLOCK(lfs->cfg);
6046 int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
6047 int err = LFS_LOCK(lfs->cfg);
6052 (void*)lfs, (void*)file, size);
6053 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6055 err = lfs_file_rawtruncate(lfs, file, size);
6058 LFS_UNLOCK(lfs->cfg);
6063 lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) {
6064 int err = LFS_LOCK(lfs->cfg);
6068 LFS_TRACE("lfs_file_tell(%p, %p)", (void*)lfs, (void*)file);
6069 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6071 lfs_soff_t res = lfs_file_rawtell(lfs, file);
6074 LFS_UNLOCK(lfs->cfg);
6078 int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) {
6079 int err = LFS_LOCK(lfs->cfg);
6083 LFS_TRACE("lfs_file_rewind(%p, %p)", (void*)lfs, (void*)file);
6085 err = lfs_file_rawrewind(lfs, file);
6088 LFS_UNLOCK(lfs->cfg);
6092 lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
6093 int err = LFS_LOCK(lfs->cfg);
6097 LFS_TRACE("lfs_file_size(%p, %p)", (void*)lfs, (void*)file);
6098 LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
6100 lfs_soff_t res = lfs_file_rawsize(lfs, file);
6103 LFS_UNLOCK(lfs->cfg);
6108 int lfs_mkdir(lfs_t *lfs, const char *path) {
6109 int err = LFS_LOCK(lfs->cfg);
6113 LFS_TRACE("lfs_mkdir(%p, \"%s\")", (void*)lfs, path);
6115 err = lfs_rawmkdir(lfs, path);
6118 LFS_UNLOCK(lfs->cfg);
6123 int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
6124 int err = LFS_LOCK(lfs->cfg);
6128 LFS_TRACE("lfs_dir_open(%p, %p, \"%s\")", (void*)lfs, (void*)dir, path);
6129 LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)dir));
6131 err = lfs_dir_rawopen(lfs, dir, path);
6134 LFS_UNLOCK(lfs->cfg);
6138 int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {
6139 int err = LFS_LOCK(lfs->cfg);
6143 LFS_TRACE("lfs_dir_close(%p, %p)", (void*)lfs, (void*)dir);
6145 err = lfs_dir_rawclose(lfs, dir);
6148 LFS_UNLOCK(lfs->cfg);
6152 int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
6153 int err = LFS_LOCK(lfs->cfg);
6158 (void*)lfs, (void*)dir, (void*)info);
6160 err = lfs_dir_rawread(lfs, dir, info);
6163 LFS_UNLOCK(lfs->cfg);
6167 int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
6168 int err = LFS_LOCK(lfs->cfg);
6173 (void*)lfs, (void*)dir, off);
6175 err = lfs_dir_rawseek(lfs, dir, off);
6178 LFS_UNLOCK(lfs->cfg);
6182 lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir) {
6183 int err = LFS_LOCK(lfs->cfg);
6187 LFS_TRACE("lfs_dir_tell(%p, %p)", (void*)lfs, (void*)dir);
6189 lfs_soff_t res = lfs_dir_rawtell(lfs, dir);
6192 LFS_UNLOCK(lfs->cfg);
6196 int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) {
6197 int err = LFS_LOCK(lfs->cfg);
6201 LFS_TRACE("lfs_dir_rewind(%p, %p)", (void*)lfs, (void*)dir);
6203 err = lfs_dir_rawrewind(lfs, dir);
6206 LFS_UNLOCK(lfs->cfg);
6210 int lfs_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
6211 int err = LFS_LOCK(lfs->cfg);
6215 LFS_TRACE("lfs_fs_stat(%p, %p)", (void*)lfs, (void*)fsinfo);
6217 err = lfs_fs_rawstat(lfs, fsinfo);
6220 LFS_UNLOCK(lfs->cfg);
6224 lfs_ssize_t lfs_fs_size(lfs_t *lfs) {
6225 int err = LFS_LOCK(lfs->cfg);
6229 LFS_TRACE("lfs_fs_size(%p)", (void*)lfs);
6231 lfs_ssize_t res = lfs_fs_rawsize(lfs);
6234 LFS_UNLOCK(lfs->cfg);
6238 int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void *, lfs_block_t), void *data) {
6239 int err = LFS_LOCK(lfs->cfg);
6244 (void*)lfs, (void*)(uintptr_t)cb, data);
6246 err = lfs_fs_rawtraverse(lfs, cb, data, true);
6249 LFS_UNLOCK(lfs->cfg);
6254 int lfs_fs_gc(lfs_t *lfs) {
6255 int err = LFS_LOCK(lfs->cfg);
6259 LFS_TRACE("lfs_fs_gc(%p)", (void*)lfs);
6261 err = lfs_fs_rawgc(lfs);
6264 LFS_UNLOCK(lfs->cfg);
6270 int lfs_fs_mkconsistent(lfs_t *lfs) {
6271 int err = LFS_LOCK(lfs->cfg);
6275 LFS_TRACE("lfs_fs_mkconsistent(%p)", (void*)lfs);
6277 err = lfs_fs_rawmkconsistent(lfs);
6280 LFS_UNLOCK(lfs->cfg);
6286 int lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count) {
6287 int err = LFS_LOCK(lfs->cfg);
6291 LFS_TRACE("lfs_fs_grow(%p, %"PRIu32")", (void*)lfs, block_count);
6293 err = lfs_fs_rawgrow(lfs, block_count);
6296 LFS_UNLOCK(lfs->cfg);
6302 int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
6316 (void*)lfs, (void*)cfg, cfg->context,
6324 err = lfs_rawmigrate(lfs, cfg);