Skip to content

Commit 03b262b

Browse files
committed
Separated out version of dir remove/append for non-entries
This allows updates to directories without needing to allocate an entry struct for every call.
1 parent 362b0bb commit 03b262b

File tree

1 file changed

+91
-86
lines changed

1 file changed

+91
-86
lines changed

lfs.c

Lines changed: 91 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -677,15 +677,14 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
677677
return 0;
678678
}
679679

680-
static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
681-
lfs_entry_t *entry, struct lfs_region *regions) {
680+
static int lfs_dir_append_(lfs_t *lfs, lfs_dir_t *dir,
681+
lfs_off_t *off, lfs_size_t size, struct lfs_region *regions) {
682682
// check if we fit, if top bit is set we do not and move on
683683
while (true) {
684-
if ((0x7fffffff & dir->d.size) + lfs_entry_size(entry)
685-
<= lfs->cfg->block_size) {
686-
entry->off = dir->d.size - 4;
684+
if ((0x7fffffff & dir->d.size) + size <= lfs->cfg->block_size) {
685+
*off = dir->d.size - 4;
687686
for (struct lfs_region *r = regions; r; r = r->next) {
688-
r->off += entry->off;
687+
r->off += *off;
689688
}
690689

691690
return lfs_dir_commit(lfs, dir, regions);
@@ -701,9 +700,9 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
701700

702701
dir->d.tail[0] = olddir.d.tail[0];
703702
dir->d.tail[1] = olddir.d.tail[1];
704-
entry->off = dir->d.size - 4;
703+
*off = dir->d.size - 4;
705704
for (struct lfs_region *r = regions; r; r = r->next) {
706-
r->off += entry->off;
705+
r->off += *off;
707706
}
708707

709708
err = lfs_dir_commit(lfs, dir, regions);
@@ -724,9 +723,70 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
724723
}
725724
}
726725

726+
static int lfs_dir_remove_(lfs_t *lfs, lfs_dir_t *dir,
727+
lfs_off_t off, lfs_size_t size) {
728+
// check if we should just drop the directory block
729+
if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + size) {
730+
lfs_dir_t pdir;
731+
int res = lfs_pred(lfs, dir->pair, &pdir);
732+
if (res < 0) {
733+
return res;
734+
}
735+
736+
if (pdir.d.size & 0x80000000) {
737+
pdir.d.size &= dir->d.size | 0x7fffffff;
738+
pdir.d.tail[0] = dir->d.tail[0];
739+
pdir.d.tail[1] = dir->d.tail[1];
740+
return lfs_dir_commit(lfs, &pdir, NULL);
741+
}
742+
}
743+
744+
// shift out the entry
745+
int err = lfs_dir_commit(lfs, dir,
746+
&(struct lfs_region){
747+
off, -size,
748+
lfs_commit_mem, NULL, 0});
749+
if (err) {
750+
return err;
751+
}
752+
753+
// shift over any files/directories that are affected
754+
for (lfs_file_t *f = lfs->files; f; f = f->next) {
755+
if (lfs_paircmp(f->pair, dir->pair) == 0) {
756+
if (f->poff == off) {
757+
f->pair[0] = 0xffffffff;
758+
f->pair[1] = 0xffffffff;
759+
} else if (f->poff > off) {
760+
f->poff -= size;
761+
}
762+
}
763+
}
764+
765+
for (lfs_dir_t *d = lfs->dirs; d; d = d->next) {
766+
if (lfs_paircmp(d->pair, dir->pair) == 0) {
767+
if (d->off > off) {
768+
d->off -= size;
769+
d->pos -= size;
770+
}
771+
}
772+
}
773+
774+
return 0;
775+
}
776+
777+
static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
778+
lfs_entry_t *entry, struct lfs_region *regions) {
779+
return lfs_dir_append_(lfs, dir,
780+
&entry->off, lfs_entry_size(entry), regions);
781+
}
782+
783+
static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
784+
return lfs_dir_remove_(lfs, dir,
785+
entry->off, lfs_entry_size(entry));
786+
}
787+
727788
static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
728789
lfs_entry_t *entry, struct lfs_region *regions) {
729-
lfs_off_t oldoff = entry->off; // <- TODO rm me?
730790
lfs_ssize_t diff = 0;
731791
for (struct lfs_region *r = regions; r; r = r->next) {
732792
diff += r->diff;
@@ -742,6 +802,24 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
742802
if (err) {
743803
return err;
744804
}
805+
806+
// shift over any files/directories that are affected
807+
for (lfs_file_t *f = lfs->files; f; f = f->next) {
808+
if (lfs_paircmp(f->pair, dir->pair) == 0) {
809+
if (f->poff > entry->off) {
810+
f->poff += diff;
811+
}
812+
}
813+
}
814+
815+
for (lfs_dir_t *d = lfs->dirs; d; d = d->next) {
816+
if (lfs_paircmp(d->pair, dir->pair) == 0) {
817+
if (d->off > entry->off) {
818+
d->off += diff;
819+
d->pos += diff;
820+
}
821+
}
822+
}
745823
} else {
746824
lfs_dir_t olddir = *dir;
747825
lfs_off_t oldoff = entry->off;
@@ -756,9 +834,9 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
756834
if (err) {
757835
return err;
758836
}
837+
entry->d.type &= LFS_STRUCT_MOVED;
759838

760839
// append updated entry
761-
entry->d.type &= LFS_STRUCT_MOVED;
762840
err = lfs_dir_append(lfs, dir, entry,
763841
&(struct lfs_region){
764842
0, +lfs_entry_size(entry),
@@ -769,86 +847,13 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
769847
}
770848

771849
// remove old entry
772-
err = lfs_dir_commit(lfs, &olddir,
773-
&(struct lfs_region){
774-
oldoff, -oldsize,
775-
lfs_commit_mem, NULL, 0});
850+
err = lfs_dir_remove_(lfs, dir, oldoff, oldsize);
776851
if (err) {
777852
return err;
778853
}
779-
}
780854

781-
// TODO move to dir_commit?
782-
// TODO this doesn't work...
783-
// shift over any files/directories that are affected
784-
for (lfs_file_t *f = lfs->files; f; f = f->next) {
785-
if (lfs_paircmp(f->pair, dir->pair) == 0) {
786-
if (f->poff == oldoff) {
787-
f->poff = entry->off;
788-
} else if (f->poff > entry->off) {
789-
f->poff += diff;
790-
}
791-
}
792-
}
793-
794-
for (lfs_dir_t *d = lfs->dirs; d; d = d->next) {
795-
if (lfs_paircmp(d->pair, dir->pair) == 0) {
796-
if (d->off > entry->off) {
797-
d->off += diff;
798-
d->pos += diff;
799-
}
800-
}
801-
}
802-
803-
return 0;
804-
}
805-
806-
static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
807-
// check if we should just drop the directory block
808-
if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4
809-
+ lfs_entry_size(entry)) {
810-
lfs_dir_t pdir;
811-
int res = lfs_pred(lfs, dir->pair, &pdir);
812-
if (res < 0) {
813-
return res;
814-
}
815-
816-
if (pdir.d.size & 0x80000000) {
817-
pdir.d.size &= dir->d.size | 0x7fffffff;
818-
pdir.d.tail[0] = dir->d.tail[0];
819-
pdir.d.tail[1] = dir->d.tail[1];
820-
return lfs_dir_commit(lfs, &pdir, NULL);
821-
}
822-
}
823-
824-
// shift out the entry
825-
int err = lfs_dir_commit(lfs, dir,
826-
&(struct lfs_region){
827-
entry->off, -lfs_entry_size(entry),
828-
lfs_commit_mem, NULL, 0});
829-
if (err) {
830-
return err;
831-
}
832-
833-
// shift over any files/directories that are affected
834-
for (lfs_file_t *f = lfs->files; f; f = f->next) {
835-
if (lfs_paircmp(f->pair, dir->pair) == 0) {
836-
if (f->poff == entry->off) {
837-
f->pair[0] = 0xffffffff;
838-
f->pair[1] = 0xffffffff;
839-
} else if (f->poff > entry->off) {
840-
f->poff -= lfs_entry_size(entry);
841-
}
842-
}
843-
}
844-
845-
for (lfs_dir_t *d = lfs->dirs; d; d = d->next) {
846-
if (lfs_paircmp(d->pair, dir->pair) == 0) {
847-
if (d->off > entry->off) {
848-
d->off -= lfs_entry_size(entry);
849-
d->pos -= lfs_entry_size(entry);
850-
}
851-
}
855+
// TODO remove file under file?
856+
// TODO need to shift entries?
852857
}
853858

854859
return 0;

0 commit comments

Comments
 (0)