@@ -489,8 +489,8 @@ struct lfs_region {
489
489
LFS_FROM_DISK ,
490
490
} source ;
491
491
492
- lfs_off_t oldoff ;
493
- lfs_size_t oldlen ;
492
+ lfs_off_t off ;
493
+ lfs_ssize_t diff ;
494
494
union {
495
495
struct {
496
496
const void * data ;
@@ -500,20 +500,20 @@ struct lfs_region {
500
500
lfs_off_t off ;
501
501
} d ;
502
502
} u ;
503
- lfs_size_t newlen ;
503
+ lfs_size_t len ;
504
504
505
505
struct lfs_region * next ;
506
506
};
507
507
508
508
static int lfs_dir_commit (lfs_t * lfs , lfs_dir_t * dir ,
509
- struct lfs_region * region ) {
509
+ struct lfs_region * regions ) {
510
510
// increment revision count
511
511
dir -> d .rev += 1 ;
512
512
513
513
// keep pairs in order such that pair[0] is most recent
514
514
lfs_pairswap (dir -> pair );
515
- for (struct lfs_region * r = region ; r ; r = r -> next ) {
516
- dir -> d .size += r -> newlen - r -> oldlen ;
515
+ for (struct lfs_region * r = regions ; r ; r = r -> next ) {
516
+ dir -> d .size += r -> diff ;
517
517
}
518
518
519
519
const lfs_block_t oldpair [2 ] = {dir -> pair [0 ], dir -> pair [1 ]};
@@ -541,19 +541,19 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
541
541
return err ;
542
542
}
543
543
544
- struct lfs_region * r = region ;
544
+ struct lfs_region * r = regions ;
545
545
int j = 0 ;
546
546
lfs_off_t oldoff = sizeof (dir -> d );
547
547
lfs_off_t newoff = sizeof (dir -> d );
548
548
while (newoff < (0x7fffffff & dir -> d .size )- 4 ) {
549
- while (r && r -> oldoff == oldoff && r -> newlen == j ) {
550
- oldoff += r -> oldlen ;
549
+ while (r && r -> off == oldoff && r -> len == j ) {
550
+ oldoff += r -> len - r -> diff ;
551
551
r = r -> next ;
552
552
j = 0 ;
553
553
}
554
554
555
555
uint8_t data ;
556
- if (r && r -> oldoff == oldoff ) {
556
+ if (r && r -> off == oldoff ) {
557
557
if (r -> source == LFS_FROM_DISK ) {
558
558
err = lfs_bd_read (lfs , r -> u .d .block ,
559
559
r -> u .d .off + j , & data , 1 );
@@ -660,37 +660,21 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
660
660
return 0 ;
661
661
}
662
662
663
- static int lfs_dir_update (lfs_t * lfs , lfs_dir_t * dir ,
664
- lfs_entry_t * entry , const void * data ) {
665
- lfs_entry_tole32 (& entry -> d );
666
- int err = lfs_dir_commit (lfs , dir ,
667
- & (struct lfs_region ){
668
- LFS_FROM_MEM , entry -> off , sizeof (entry -> d ),
669
- {.m .data = & entry -> d }, sizeof (entry -> d ),
670
- data ?
671
- & (struct lfs_region ){
672
- LFS_FROM_MEM , entry -> off + sizeof (entry -> d ), entry -> d .nlen ,
673
- {.m .data = data }, entry -> d .nlen }
674
- : NULL });
675
- lfs_entry_fromle32 (& entry -> d );
676
- return err ;
677
- }
678
-
679
- static int lfs_dir_append_ (lfs_t * lfs , lfs_dir_t * dir ,
680
- lfs_entry_t * entry , struct lfs_region * region ) {
663
+ static int lfs_dir_append (lfs_t * lfs , lfs_dir_t * dir ,
664
+ lfs_entry_t * entry , struct lfs_region * regions ) {
681
665
// check if we fit, if top bit is set we do not and move on
682
666
while (true) {
683
667
if (dir -> d .size + lfs_entry_size (entry ) <= lfs -> cfg -> block_size ) {
684
668
entry -> off = dir -> d .size - 4 ;
685
- for (struct lfs_region * r = region ; r ; r = r -> next ) {
686
- r -> oldoff += entry -> off ;
669
+ for (struct lfs_region * r = regions ; r ; r = r -> next ) {
670
+ r -> off += entry -> off ;
687
671
}
688
672
689
673
lfs_entry_tole32 (& entry -> d );
690
674
int err = lfs_dir_commit (lfs , dir ,
691
675
& (struct lfs_region ){
692
- LFS_FROM_MEM , entry -> off , 0 ,
693
- {.m .data = & entry -> d }, 4 , region });
676
+ LFS_FROM_MEM , entry -> off , +4 ,
677
+ {.m .data = & entry -> d }, 4 , regions });
694
678
lfs_entry_fromle32 (& entry -> d );
695
679
return err ;
696
680
}
@@ -706,11 +690,15 @@ static int lfs_dir_append_(lfs_t *lfs, lfs_dir_t *dir,
706
690
dir -> d .tail [0 ] = olddir .d .tail [0 ];
707
691
dir -> d .tail [1 ] = olddir .d .tail [1 ];
708
692
entry -> off = dir -> d .size - 4 ;
693
+ for (struct lfs_region * r = regions ; r ; r = r -> next ) {
694
+ r -> off += entry -> off ;
695
+ }
696
+
709
697
lfs_entry_tole32 (& entry -> d );
710
698
err = lfs_dir_commit (lfs , dir ,
711
699
& (struct lfs_region ){
712
- LFS_FROM_MEM , entry -> off , 0 ,
713
- {.m .data = & entry -> d }, 4 , region });
700
+ LFS_FROM_MEM , entry -> off , +4 ,
701
+ {.m .data = & entry -> d }, 4 , regions });
714
702
lfs_entry_fromle32 (& entry -> d );
715
703
if (err ) {
716
704
return err ;
@@ -729,60 +717,95 @@ static int lfs_dir_append_(lfs_t *lfs, lfs_dir_t *dir,
729
717
}
730
718
}
731
719
732
- static int lfs_dir_append (lfs_t * lfs , lfs_dir_t * dir ,
733
- lfs_entry_t * entry , const void * data ) {
734
- // check if we fit, if top bit is set we do not and move on
735
- while (true) {
736
- if (dir -> d .size + lfs_entry_size (entry ) <= lfs -> cfg -> block_size ) {
737
- entry -> off = dir -> d .size - 4 ;
720
+ static int lfs_dir_update (lfs_t * lfs , lfs_dir_t * dir ,
721
+ lfs_entry_t * entry , struct lfs_region * regions ) {
722
+ lfs_off_t oldoff = entry -> off ;
723
+ lfs_ssize_t diff = 0 ;
724
+ lfs_size_t len = 0 ;
725
+ struct lfs_region * * tail = & regions ;
726
+ for (struct lfs_region * r = regions ; r ; r = r -> next ) {
727
+ diff += r -> diff ;
728
+ len += r -> len ;
729
+ tail = & r -> next ;
730
+ }
738
731
739
- lfs_entry_tole32 (& entry -> d );
740
- int err = lfs_dir_commit (lfs , dir ,
741
- & (struct lfs_region ){
742
- LFS_FROM_MEM , entry -> off , 0 ,
743
- {.m .data = & entry -> d }, sizeof (entry -> d ),
744
- & (struct lfs_region ){
745
- LFS_FROM_MEM , entry -> off , 0 ,
746
- {.m .data = data }, entry -> d .nlen }});
747
- lfs_entry_fromle32 (& entry -> d );
748
- return err ;
732
+ // do we still fit?
733
+ if ((0x7fffffff & dir -> d .size ) + diff <= lfs -> cfg -> block_size ) {
734
+ for (struct lfs_region * r = regions ; r ; r = r -> next ) {
735
+ r -> off += entry -> off ;
749
736
}
750
737
751
- // we need to allocate a new dir block
752
- if (!(0x80000000 & dir -> d .size )) {
753
- lfs_dir_t olddir = * dir ;
754
- int err = lfs_dir_alloc (lfs , dir );
755
- if (err ) {
756
- return err ;
757
- }
738
+ lfs_entry_tole32 (& entry -> d );
739
+ int err = lfs_dir_commit (lfs , dir ,
740
+ & (struct lfs_region ){
741
+ LFS_FROM_MEM , entry -> off , 0 ,
742
+ {.m .data = & entry -> d }, sizeof (entry -> d ), regions });
743
+ lfs_entry_fromle32 (& entry -> d );
744
+ if (err ) {
745
+ return err ;
746
+ }
747
+ } else {
748
+ lfs_dir_t olddir = * dir ;
758
749
759
- dir -> d .tail [0 ] = olddir .d .tail [0 ];
760
- dir -> d .tail [1 ] = olddir .d .tail [1 ];
761
- entry -> off = dir -> d .size - 4 ;
762
- lfs_entry_tole32 (& entry -> d );
763
- err = lfs_dir_commit (lfs , dir ,
764
- & (struct lfs_region ){
765
- LFS_FROM_MEM , entry -> off , 0 ,
766
- {.m .data = & entry -> d }, sizeof (entry -> d ),
767
- & (struct lfs_region ){
768
- LFS_FROM_MEM , entry -> off , 0 ,
769
- {.m .data = data }, entry -> d .nlen }});
770
- lfs_entry_fromle32 (& entry -> d );
771
- if (err ) {
772
- return err ;
773
- }
750
+ // mark as moving
751
+ entry -> d .type |= LFS_STRUCT_MOVED ;
752
+ int err = lfs_dir_commit (lfs , & olddir ,
753
+ & (struct lfs_region ){
754
+ LFS_FROM_MEM , oldoff , 0 ,
755
+ {.m .data = & entry -> d .type }, 1 });
756
+ if (err ) {
757
+ return err ;
758
+ }
774
759
775
- olddir .d .size |= 0x80000000 ;
776
- olddir .d .tail [0 ] = dir -> pair [0 ];
777
- olddir .d .tail [1 ] = dir -> pair [1 ];
778
- return lfs_dir_commit (lfs , & olddir , NULL );
760
+ // append updated entry
761
+ entry -> d .type &= LFS_STRUCT_MOVED ;
762
+ lfs_size_t prefix = regions -> off ;
763
+ lfs_size_t suffix = lfs_entry_size (entry ) - len - 4 ;
764
+ for (struct lfs_region * r = regions ; r ; r = r -> next ) {
765
+ r -> off = 0 ;
766
+ r -> diff = r -> len ;
779
767
}
780
768
781
- int err = lfs_dir_fetch (lfs , dir , dir -> d .tail );
769
+ regions = & (struct lfs_region ){
770
+ LFS_FROM_DISK , 0 , + prefix ,
771
+ {.d .block = olddir .pair [0 ], .d .off = entry -> off },
772
+ prefix , regions };
773
+ * tail = & (struct lfs_region ){
774
+ LFS_FROM_DISK , 0 , + suffix ,
775
+ {.d .block = olddir .pair [0 ], .d .off = entry -> off + prefix + len },
776
+ suffix };
777
+
778
+ // remove old entry
779
+ err = lfs_dir_commit (lfs , & olddir ,
780
+ & (struct lfs_region ){
781
+ LFS_FROM_MEM , oldoff , - (lfs_entry_size (entry ) - diff ),
782
+ {.m .data = NULL }, 0 });
782
783
if (err ) {
783
784
return err ;
784
785
}
785
786
}
787
+
788
+ // shift over any files/directories that are affected
789
+ for (lfs_file_t * f = lfs -> files ; f ; f = f -> next ) {
790
+ if (lfs_paircmp (f -> pair , dir -> pair ) == 0 ) {
791
+ if (f -> poff == oldoff ) {
792
+ f -> poff = entry -> off ;
793
+ } else if (f -> poff > entry -> off ) {
794
+ f -> poff += diff ;
795
+ }
796
+ }
797
+ }
798
+
799
+ for (lfs_dir_t * d = lfs -> dirs ; d ; d = d -> next ) {
800
+ if (lfs_paircmp (d -> pair , dir -> pair ) == 0 ) {
801
+ if (d -> off > entry -> off ) {
802
+ d -> off += diff ;
803
+ d -> pos += diff ;
804
+ }
805
+ }
806
+ }
807
+
808
+ return 0 ;
786
809
}
787
810
788
811
static int lfs_dir_remove (lfs_t * lfs , lfs_dir_t * dir , lfs_entry_t * entry ) {
@@ -805,7 +828,7 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
805
828
806
829
// shift out the entry
807
830
int err = lfs_dir_commit (lfs , dir , & (struct lfs_region ){
808
- LFS_FROM_MEM , entry -> off , lfs_entry_size (entry ),
831
+ LFS_FROM_MEM , entry -> off , - lfs_entry_size (entry ),
809
832
{.m .data = NULL }, 0 });
810
833
if (err ) {
811
834
return err ;
@@ -1026,12 +1049,12 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
1026
1049
cwd .d .tail [0 ] = dir .pair [0 ];
1027
1050
cwd .d .tail [1 ] = dir .pair [1 ];
1028
1051
1029
- err = lfs_dir_append_ (lfs , & cwd , & entry ,
1052
+ err = lfs_dir_append (lfs , & cwd , & entry ,
1030
1053
& (struct lfs_region ){
1031
- LFS_FROM_MEM , 0 , 0 ,
1032
- {.m .data = (uint8_t * )& entry .d + 4 }, sizeof (entry .d ) - 4 ,
1054
+ LFS_FROM_MEM , 0 , + ( sizeof ( entry . d ) - 4 ) ,
1055
+ {.m .data = (uint8_t * )& entry .d + 4 }, sizeof (entry .d )- 4 ,
1033
1056
& (struct lfs_region ){
1034
- LFS_FROM_MEM , 0 , 0 ,
1057
+ LFS_FROM_MEM , 0 , + entry . d . nlen ,
1035
1058
{.m .data = path }, entry .d .nlen }});
1036
1059
if (err ) {
1037
1060
return err ;
@@ -1416,12 +1439,12 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
1416
1439
entry .d .nlen = strlen (path );
1417
1440
entry .d .u .file .head = 0xffffffff ;
1418
1441
entry .d .u .file .size = 0 ;
1419
- err = lfs_dir_append_ (lfs , & cwd , & entry ,
1442
+ err = lfs_dir_append (lfs , & cwd , & entry ,
1420
1443
& (struct lfs_region ){
1421
- LFS_FROM_MEM , 0 , 0 ,
1422
- {.m .data = (uint8_t * )& entry .d + 4 }, sizeof (entry .d ) - 4 ,
1444
+ LFS_FROM_MEM , 0 , + ( sizeof ( entry . d ) - 4 ) ,
1445
+ {.m .data = (uint8_t * )& entry .d + 4 }, sizeof (entry .d )- 4 ,
1423
1446
& (struct lfs_region ){
1424
- LFS_FROM_MEM , 0 , 0 ,
1447
+ LFS_FROM_MEM , 0 , + entry . d . nlen ,
1425
1448
{.m .data = path }, entry .d .nlen }});
1426
1449
if (err ) {
1427
1450
return err ;
@@ -1638,7 +1661,10 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
1638
1661
entry .d .u .file .head = file -> head ;
1639
1662
entry .d .u .file .size = file -> size ;
1640
1663
1641
- err = lfs_dir_update (lfs , & cwd , & entry , NULL );
1664
+ err = lfs_dir_update (lfs , & cwd , & entry ,
1665
+ & (struct lfs_region ){
1666
+ LFS_FROM_MEM , 0 , 0 ,
1667
+ {.m .data = (const uint8_t * )& entry .d + 4 }, sizeof (entry .d )- 4 });
1642
1668
if (err ) {
1643
1669
return err ;
1644
1670
}
@@ -2077,17 +2103,25 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
2077
2103
newentry .d .nlen = strlen (newpath );
2078
2104
2079
2105
if (prevexists ) {
2080
- err = lfs_dir_update (lfs , & newcwd , & newentry , newpath );
2106
+ err = lfs_dir_update (lfs , & newcwd , & newentry ,
2107
+ & (struct lfs_region ){
2108
+ LFS_FROM_MEM , 0 , 0 ,
2109
+ {.m .data = (const uint8_t * )& newentry .d + 4 },
2110
+ sizeof (newentry .d )- 4 ,
2111
+ & (struct lfs_region ){
2112
+ LFS_FROM_MEM , sizeof (newentry .d )- 4 , 0 ,
2113
+ {.m .data = newpath }, newentry .d .nlen }});
2081
2114
if (err ) {
2082
2115
return err ;
2083
2116
}
2084
2117
} else {
2085
- err = lfs_dir_append_ (lfs , & newcwd , & newentry ,
2118
+ err = lfs_dir_append (lfs , & newcwd , & newentry ,
2086
2119
& (struct lfs_region ){
2087
- LFS_FROM_MEM , 0 , 0 ,
2088
- {.m .data = (uint8_t * )& newentry .d + 4 }, sizeof (newentry .d ) - 4 ,
2120
+ LFS_FROM_MEM , 0 , + (sizeof (newentry .d )- 4 ),
2121
+ {.m .data = (const uint8_t * )& newentry .d + 4 },
2122
+ sizeof (newentry .d )- 4 ,
2089
2123
& (struct lfs_region ){
2090
- LFS_FROM_MEM , 0 , 0 ,
2124
+ LFS_FROM_MEM , 0 , + newentry . d . nlen ,
2091
2125
{.m .data = newpath }, newentry .d .nlen }});
2092
2126
if (err ) {
2093
2127
return err ;
@@ -2255,7 +2289,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
2255
2289
bool valid = false;
2256
2290
for (int i = 0 ; i < 2 ; i ++ ) {
2257
2291
err = lfs_dir_commit (lfs , & superdir , & (struct lfs_region ){
2258
- LFS_FROM_MEM , sizeof (superdir .d ), sizeof ( superblock . d ) ,
2292
+ LFS_FROM_MEM , sizeof (superdir .d ), 0 ,
2259
2293
{.m .data = & superblock .d }, sizeof (superblock .d )});
2260
2294
if (err && err != LFS_ERR_CORRUPT ) {
2261
2295
return err ;
@@ -2520,7 +2554,10 @@ static int lfs_relocate(lfs_t *lfs,
2520
2554
entry .d .u .dir [0 ] = newpair [0 ];
2521
2555
entry .d .u .dir [1 ] = newpair [1 ];
2522
2556
2523
- int err = lfs_dir_update (lfs , & parent , & entry , NULL );
2557
+ int err = lfs_dir_update (lfs , & parent , & entry ,
2558
+ & (struct lfs_region ){
2559
+ LFS_FROM_MEM , 0 , 0 ,
2560
+ {.m .data = (const uint8_t * )& entry .d + 4 }, sizeof (entry .d )- 4 });
2524
2561
if (err ) {
2525
2562
return err ;
2526
2563
}
0 commit comments