Skip to content

Commit 4c35c86

Browse files
committed
Added different sources for commits, now with disk->disk moves
Previously, commits could only come from memory in RAM. This meant any entries had to be buffered in their entirety before they could be moved to a different directory pair. By adding parameters for specifying commits from existing entries stored on disk, we allow any sized entries to be moved between directory pairs with a fixed RAM cost.
1 parent 49698e4 commit 4c35c86

File tree

1 file changed

+55
-30
lines changed

1 file changed

+55
-30
lines changed

lfs.c

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,18 @@ static int lfs_dir_fetch(lfs_t *lfs,
486486
struct lfs_region {
487487
lfs_off_t oldoff;
488488
lfs_size_t oldlen;
489-
const void *newdata;
489+
490+
enum lfs_region_source {
491+
LFS_FROM_MEM,
492+
LFS_FROM_DISK,
493+
} source;
494+
union {
495+
const void *mem;
496+
struct {
497+
lfs_block_t block;
498+
lfs_off_t off;
499+
} disk;
500+
} u;
490501
lfs_size_t newlen;
491502
};
492503

@@ -527,42 +538,49 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
527538
}
528539

529540
int i = 0;
541+
int j = 0;
530542
lfs_off_t oldoff = sizeof(dir->d);
531543
lfs_off_t newoff = sizeof(dir->d);
532544
while (newoff < (0x7fffffff & dir->d.size)-4) {
545+
while (i < count && oldoff == regions[i].oldoff &&
546+
j == regions[i].newlen) {
547+
oldoff += regions[i].oldlen;
548+
i += 1;
549+
j = 0;
550+
}
551+
552+
uint8_t data;
533553
if (i < count && regions[i].oldoff == oldoff) {
534-
lfs_crc(&crc, regions[i].newdata, regions[i].newlen);
535-
err = lfs_bd_prog(lfs, dir->pair[0],
536-
newoff, regions[i].newdata, regions[i].newlen);
537-
if (err) {
538-
if (err == LFS_ERR_CORRUPT) {
539-
goto relocate;
554+
if (regions[i].source == LFS_FROM_DISK) {
555+
err = lfs_bd_read(lfs, regions[i].u.disk.block,
556+
regions[i].u.disk.off + j, &data, 1);
557+
if (err) {
558+
return err;
540559
}
541-
return err;
560+
} else {
561+
data = ((const uint8_t *)regions[i].u.mem)[j];
542562
}
543563

544-
oldoff += regions[i].oldlen;
545-
newoff += regions[i].newlen;
546-
i += 1;
564+
j += 1;
547565
} else {
548-
uint8_t data;
549566
err = lfs_bd_read(lfs, oldpair[1], oldoff, &data, 1);
550567
if (err) {
551568
return err;
552569
}
553570

554-
lfs_crc(&crc, &data, 1);
555-
err = lfs_bd_prog(lfs, dir->pair[0], newoff, &data, 1);
556-
if (err) {
557-
if (err == LFS_ERR_CORRUPT) {
558-
goto relocate;
559-
}
560-
return err;
561-
}
562-
563571
oldoff += 1;
564-
newoff += 1;
565572
}
573+
574+
lfs_crc(&crc, &data, 1);
575+
err = lfs_bd_prog(lfs, dir->pair[0], newoff, &data, 1);
576+
if (err) {
577+
if (err == LFS_ERR_CORRUPT) {
578+
goto relocate;
579+
}
580+
return err;
581+
}
582+
583+
newoff += 1;
566584
}
567585

568586
crc = lfs_tole32(crc);
@@ -643,8 +661,10 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
643661
lfs_entry_t *entry, const void *data) {
644662
lfs_entry_tole32(&entry->d);
645663
int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){
646-
{entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)},
647-
{entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen}
664+
{entry->off, sizeof(entry->d),
665+
LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)},
666+
{entry->off+sizeof(entry->d), entry->d.nlen,
667+
LFS_FROM_MEM, {.mem = data}, entry->d.nlen}
648668
}, data ? 2 : 1);
649669
lfs_entry_fromle32(&entry->d);
650670
return err;
@@ -659,8 +679,10 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
659679

660680
lfs_entry_tole32(&entry->d);
661681
int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){
662-
{entry->off, 0, &entry->d, sizeof(entry->d)},
663-
{entry->off, 0, data, entry->d.nlen}
682+
{entry->off, 0,
683+
LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)},
684+
{entry->off, 0,
685+
LFS_FROM_MEM, {.mem = data}, entry->d.nlen}
664686
}, 2);
665687
lfs_entry_fromle32(&entry->d);
666688
return err;
@@ -679,8 +701,10 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
679701
entry->off = dir->d.size - 4;
680702
lfs_entry_tole32(&entry->d);
681703
err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){
682-
{entry->off, 0, &entry->d, sizeof(entry->d)},
683-
{entry->off, 0, data, entry->d.nlen}
704+
{entry->off, 0,
705+
LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)},
706+
{entry->off, 0,
707+
LFS_FROM_MEM, {.mem = data}, entry->d.nlen}
684708
}, 2);
685709
lfs_entry_fromle32(&entry->d);
686710
if (err) {
@@ -720,7 +744,8 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
720744

721745
// shift out the entry
722746
int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){
723-
{entry->off, lfs_entry_size(entry), NULL, 0},
747+
{entry->off, lfs_entry_size(entry),
748+
LFS_FROM_MEM, {.mem = NULL}, 0},
724749
}, 1);
725750
if (err) {
726751
return err;
@@ -2153,7 +2178,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
21532178
for (int i = 0; i < 2; i++) {
21542179
err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){
21552180
{sizeof(superdir.d), sizeof(superblock.d),
2156-
&superblock.d, sizeof(superblock.d)}
2181+
LFS_FROM_MEM, {.mem = &superblock.d}, sizeof(superblock.d)}
21572182
}, 1);
21582183
if (err && err != LFS_ERR_CORRUPT) {
21592184
return err;

0 commit comments

Comments
 (0)