9
9
10
10
#include <string.h>
11
11
#include <stdbool.h>
12
+ #include <stdlib.h>
12
13
13
14
14
15
/// Block device operations ///
16
+ static int lfs_bd_flush (lfs_t * lfs ) {
17
+ if (lfs -> pcache .off != -1 ) {
18
+ int err = lfs -> cfg -> prog (lfs -> cfg , lfs -> pcache .block ,
19
+ lfs -> pcache .off , lfs -> cfg -> prog_size ,
20
+ lfs -> pcache .buffer );
21
+ if (err ) {
22
+ return err ;
23
+ }
24
+
25
+ lfs -> pcache .off = -1 ;
26
+ }
27
+
28
+ return 0 ;
29
+ }
30
+
15
31
static int lfs_bd_read (lfs_t * lfs , lfs_block_t block ,
16
32
lfs_off_t off , lfs_size_t size , void * buffer ) {
17
- return lfs -> cfg -> read (lfs -> cfg , block , off , size , buffer );
33
+ uint8_t * data = buffer ;
34
+
35
+ // flush overlapping programs
36
+ while (size > 0 ) {
37
+ if (block == lfs -> pcache .block && off >= lfs -> pcache .off &&
38
+ off < lfs -> pcache .off + lfs -> cfg -> prog_size ) {
39
+ // is already in cache?
40
+ lfs_size_t diff = lfs_min (size ,
41
+ lfs -> cfg -> prog_size - (off - lfs -> pcache .off ));
42
+ memcpy (data , & lfs -> pcache .buffer [off - lfs -> pcache .off ], diff );
43
+
44
+ data += diff ;
45
+ off += diff ;
46
+ size -= diff ;
47
+ continue ;
48
+ } else if (block == lfs -> rcache .block && off >= lfs -> rcache .off &&
49
+ off < lfs -> rcache .off + lfs -> cfg -> read_size ) {
50
+ // is already in cache?
51
+ lfs_size_t diff = lfs_min (size ,
52
+ lfs -> cfg -> read_size - (off - lfs -> rcache .off ));
53
+ memcpy (data , & lfs -> rcache .buffer [off - lfs -> rcache .off ], diff );
54
+
55
+ data += diff ;
56
+ off += diff ;
57
+ size -= diff ;
58
+ continue ;
59
+ }
60
+
61
+ // write out pending programs
62
+ int err = lfs_bd_flush (lfs );
63
+ if (err ) {
64
+ return err ;
65
+ }
66
+
67
+ if (off % lfs -> cfg -> read_size == 0 &&
68
+ size >= lfs -> cfg -> read_size ) {
69
+ // bypass cache?
70
+ lfs_size_t diff = size - (size % lfs -> cfg -> read_size );
71
+ int err = lfs -> cfg -> read (lfs -> cfg , block , off , diff , data );
72
+ if (err ) {
73
+ return err ;
74
+ }
75
+
76
+ data += diff ;
77
+ off += diff ;
78
+ size -= diff ;
79
+ continue ;
80
+ }
81
+
82
+ // load to cache, first condition can no longer fail
83
+ lfs -> rcache .block = block ;
84
+ lfs -> rcache .off = off - (off % lfs -> cfg -> read_size );
85
+ // TODO remove reading, should be unnecessary
86
+ err = lfs -> cfg -> read (lfs -> cfg , lfs -> rcache .block ,
87
+ lfs -> rcache .off , lfs -> cfg -> read_size ,
88
+ lfs -> rcache .buffer );
89
+ if (err ) {
90
+ return err ;
91
+ }
92
+ }
93
+
94
+ return 0 ;
18
95
}
19
96
20
97
static int lfs_bd_prog (lfs_t * lfs , lfs_block_t block ,
21
98
lfs_off_t off , lfs_size_t size , const void * buffer ) {
22
- return lfs -> cfg -> prog (lfs -> cfg , block , off , size , buffer );
99
+ const uint8_t * data = buffer ;
100
+
101
+ if (block == lfs -> rcache .block ) {
102
+ // invalidate read cache
103
+ lfs -> rcache .off = -1 ;
104
+ }
105
+
106
+ while (size > 0 ) {
107
+ if (block == lfs -> pcache .block && off >= lfs -> pcache .off &&
108
+ off < lfs -> pcache .off + lfs -> cfg -> prog_size ) {
109
+ // is already in cache?
110
+ lfs_size_t diff = lfs_min (size ,
111
+ lfs -> cfg -> prog_size - (off - lfs -> pcache .off ));
112
+ memcpy (& lfs -> pcache .buffer [off - lfs -> pcache .off ], data , diff );
113
+
114
+ data += diff ;
115
+ off += diff ;
116
+ size -= diff ;
117
+ continue ;
118
+ }
119
+
120
+ // write out pending programs
121
+ int err = lfs_bd_flush (lfs );
122
+ if (err ) {
123
+ return err ;
124
+ }
125
+
126
+ if (off % lfs -> cfg -> prog_size == 0 &&
127
+ size >= lfs -> cfg -> prog_size ) {
128
+ // bypass cache?
129
+ lfs_size_t diff = size - (size % lfs -> cfg -> prog_size );
130
+ int err = lfs -> cfg -> prog (lfs -> cfg , block , off , diff , data );
131
+ if (err ) {
132
+ return err ;
133
+ }
134
+
135
+ data += diff ;
136
+ off += diff ;
137
+ size -= diff ;
138
+ continue ;
139
+ }
140
+
141
+ // prepare cache, first condition can no longer fail
142
+ lfs -> pcache .block = block ;
143
+ lfs -> pcache .off = off - (off % lfs -> cfg -> prog_size );
144
+ err = lfs -> cfg -> read (lfs -> cfg , lfs -> pcache .block ,
145
+ lfs -> pcache .off , lfs -> cfg -> prog_size ,
146
+ lfs -> pcache .buffer );
147
+ if (err ) {
148
+ return err ;
149
+ }
150
+ }
151
+
152
+ return 0 ;
23
153
}
24
154
25
155
static int lfs_bd_erase (lfs_t * lfs , lfs_block_t block ) {
26
156
return lfs -> cfg -> erase (lfs -> cfg , block );
27
157
}
28
158
29
159
static int lfs_bd_sync (lfs_t * lfs ) {
160
+ int err = lfs_bd_flush (lfs );
161
+ if (err ) {
162
+ return err ;
163
+ }
164
+
30
165
return lfs -> cfg -> sync (lfs -> cfg );
31
166
}
32
167
@@ -41,11 +176,9 @@ static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block,
41
176
return err ;
42
177
}
43
178
44
- if (c != * data ) {
179
+ if (c != data [ i ] ) {
45
180
return false;
46
181
}
47
-
48
- data += 1 ;
49
182
}
50
183
51
184
return true;
@@ -452,13 +585,13 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
452
585
}
453
586
454
587
while (off < lfs -> cfg -> block_size - 4 ) {
455
- uint8_t data ;
456
- int err = lfs_bd_read (lfs , dir -> pair [0 ], off , 1 , & data );
588
+ uint8_t data = 0xff ;
589
+ crc = lfs_crc (crc , 1 , & data );
590
+ err = lfs_bd_prog (lfs , dir -> pair [0 ], off , 1 , & data );
457
591
if (err ) {
458
592
return err ;
459
593
}
460
594
461
- crc = lfs_crc (crc , 1 , & data );
462
595
off += 1 ;
463
596
}
464
597
@@ -512,13 +645,14 @@ static int lfs_dir_shift(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
512
645
}
513
646
514
647
while (woff < lfs -> cfg -> block_size - 4 ) {
515
- uint8_t data ;
516
- int err = lfs_bd_read (lfs , dir -> pair [0 ], woff , 1 , & data );
648
+ uint8_t data = 0xff ;
649
+ crc = lfs_crc (crc , 1 , & data );
650
+ err = lfs_bd_prog (lfs , dir -> pair [0 ], woff , 1 , & data );
517
651
if (err ) {
518
652
return err ;
519
653
}
520
654
521
- crc = lfs_crc ( crc , 1 , & data );
655
+
522
656
woff += 1 ;
523
657
}
524
658
@@ -618,6 +752,7 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
618
752
}
619
753
620
754
dir -> off = sizeof (dir -> d );
755
+ continue ;
621
756
}
622
757
623
758
int err = lfs_bd_read (lfs , dir -> pair [0 ], dir -> off ,
@@ -986,17 +1121,59 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
986
1121
987
1122
988
1123
/// Generic filesystem operations ///
989
- int lfs_format (lfs_t * lfs , const struct lfs_config * config ) {
990
- lfs -> cfg = config ;
1124
+ static int lfs_init (lfs_t * lfs , const struct lfs_config * cfg ) {
1125
+ lfs -> cfg = cfg ;
991
1126
lfs -> words = lfs -> cfg -> block_size / sizeof (uint32_t );
1127
+ lfs -> rcache .off = -1 ;
1128
+ lfs -> pcache .off = -1 ;
1129
+
1130
+ if (lfs -> cfg -> read_buffer ) {
1131
+ lfs -> rcache .buffer = lfs -> cfg -> read_buffer ;
1132
+ } else {
1133
+ lfs -> rcache .buffer = malloc (lfs -> cfg -> read_size );
1134
+ if (!lfs -> rcache .buffer ) {
1135
+ return LFS_ERROR_NO_MEM ;
1136
+ }
1137
+ }
1138
+
1139
+ if (lfs -> cfg -> prog_buffer ) {
1140
+ lfs -> pcache .buffer = lfs -> cfg -> prog_buffer ;
1141
+ } else {
1142
+ lfs -> pcache .buffer = malloc (lfs -> cfg -> prog_size );
1143
+ if (!lfs -> pcache .buffer ) {
1144
+ return LFS_ERROR_NO_MEM ;
1145
+ }
1146
+ }
1147
+
1148
+ return 0 ;
1149
+ }
1150
+
1151
+ static int lfs_deinit (lfs_t * lfs ) {
1152
+ // Free allocated memory
1153
+ if (!lfs -> cfg -> read_buffer ) {
1154
+ free (lfs -> rcache .buffer );
1155
+ }
1156
+
1157
+ if (!lfs -> cfg -> prog_buffer ) {
1158
+ free (lfs -> pcache .buffer );
1159
+ }
1160
+
1161
+ return 0 ;
1162
+ }
1163
+
1164
+ int lfs_format (lfs_t * lfs , const struct lfs_config * cfg ) {
1165
+ int err = lfs_init (lfs , cfg );
1166
+ if (err ) {
1167
+ return err ;
1168
+ }
992
1169
993
1170
// Create free list
994
1171
lfs -> free .begin = 0 ;
995
1172
lfs -> free .end = lfs -> cfg -> block_count - 1 ;
996
1173
997
1174
// Create superblock dir
998
1175
lfs_dir_t superdir ;
999
- int err = lfs_dir_alloc (lfs , & superdir );
1176
+ err = lfs_dir_alloc (lfs , & superdir );
1000
1177
if (err ) {
1001
1178
return err ;
1002
1179
}
@@ -1044,16 +1221,23 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config) {
1044
1221
}
1045
1222
1046
1223
// sanity check that fetch works
1047
- return lfs_dir_fetch (lfs , & superdir , (const lfs_block_t [2 ]){0 , 1 });
1224
+ err = lfs_dir_fetch (lfs , & superdir , (const lfs_block_t [2 ]){0 , 1 });
1225
+ if (err ) {
1226
+ return err ;
1227
+ }
1228
+
1229
+ return lfs_deinit (lfs );
1048
1230
}
1049
1231
1050
- int lfs_mount (lfs_t * lfs , const struct lfs_config * config ) {
1051
- lfs -> cfg = config ;
1052
- lfs -> words = lfs -> cfg -> block_size / sizeof (uint32_t );
1232
+ int lfs_mount (lfs_t * lfs , const struct lfs_config * cfg ) {
1233
+ int err = lfs_init (lfs , cfg );
1234
+ if (err ) {
1235
+ return err ;
1236
+ }
1053
1237
1054
1238
lfs_dir_t dir ;
1055
1239
lfs_superblock_t superblock ;
1056
- int err = lfs_dir_fetch (lfs , & dir , (const lfs_block_t [2 ]){0 , 1 });
1240
+ err = lfs_dir_fetch (lfs , & dir , (const lfs_block_t [2 ]){0 , 1 });
1057
1241
if (!err ) {
1058
1242
err = lfs_bd_read (lfs , dir .pair [0 ],
1059
1243
sizeof (dir .d ), sizeof (superblock .d ), & superblock .d );
@@ -1078,8 +1262,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *config) {
1078
1262
}
1079
1263
1080
1264
int lfs_unmount (lfs_t * lfs ) {
1081
- // Do nothing for now
1082
- return 0 ;
1265
+ return lfs_deinit (lfs );
1083
1266
}
1084
1267
1085
1268
int lfs_traverse (lfs_t * lfs , int (* cb )(void * , lfs_block_t ), void * data ) {
0 commit comments