@@ -26,135 +26,119 @@ static uint32_t lfs_crc(const uint8_t *data, lfs_size_t size, uint32_t crc) {
26
26
return crc ;
27
27
}
28
28
29
- lfs_error_t lfs_create (lfs_t * lfs , lfs_bd_t * bd , const struct lfs_bd_ops * ops ) {
30
- // TODO rm me, for debugging
31
- memset (lfs , 0 , sizeof (lfs_t ));
29
+ static lfs_error_t lfs_alloc (lfs_t * lfs , lfs_ino_t * ino );
30
+ static lfs_error_t lfs_free (lfs_t * lfs , lfs_ino_t ino );
32
31
33
- lfs -> bd = bd ;
34
- lfs -> ops = ops ;
35
32
36
- lfs_error_t err = lfs -> ops -> info (lfs -> bd , & lfs -> info );
37
- if (err ) {
38
- return err ;
39
- }
40
-
41
- return 0 ;
42
- }
33
+ // Next index offset
34
+ static lfs_off_t lfs_inext (lfs_t * lfs , lfs_off_t ioff ) {
35
+ ioff += 1 ;
43
36
44
- static lfs_off_t lfs_calc_irem (lfs_t * lfs , lfs_size_t isize ) {
45
- lfs_size_t icount = lfs -> info .erase_size /4 ;
46
-
47
- if (isize <= icount ) {
48
- return isize ;
49
- } else {
50
- return ((isize - 2 ) % (icount - 1 )) + 1 ;
37
+ lfs_size_t wcount = lfs -> info .erase_size /4 ;
38
+ while (ioff % wcount == 0 ) {
39
+ ioff += lfs_min (lfs_ctz (ioff /wcount + 1 ), wcount - 1 ) + 1 ;
51
40
}
52
- }
53
41
54
- static lfs_off_t lfs_calc_ioff (lfs_t * lfs , lfs_size_t ioff ) {
55
- lfs_size_t icount = lfs -> info .erase_size /4 ;
56
-
57
- if (ioff < icount ) {
58
- return ioff ;
59
- } else {
60
- return ((ioff - 1 ) % (icount - 1 )) + 1 ;
61
- }
42
+ return ioff ;
62
43
}
63
44
45
+ // Find index in index chain given its index offset
64
46
static lfs_error_t lfs_ifind (lfs_t * lfs , lfs_ino_t head ,
65
- lfs_size_t isize , lfs_off_t ioff , lfs_ino_t * ino ) {
66
- if (ioff >= isize ) {
67
- return -15 ;
68
- } else if (isize == 1 ) {
69
- * ino = head ;
70
- return 0 ;
71
- }
72
-
73
- lfs_off_t ilookback = isize - ioff ;
74
- lfs_off_t irealoff = lfs_calc_ioff (lfs , ioff );
75
-
76
- while (true) {
77
- lfs_size_t irem = lfs_calc_irem (lfs , isize );
78
- if (ilookback <= irem ) {
79
- return lfs -> ops -> read (lfs -> bd , (void * )ino ,
80
- head , 4 * irealoff , 4 );
81
- }
82
-
83
- lfs_error_t err = lfs -> ops -> read (lfs -> bd , (void * )& head , head , 0 , 4 );
47
+ lfs_size_t icount , lfs_off_t ioff , lfs_ino_t * ino ) {
48
+ lfs_size_t wcount = lfs -> info .erase_size /4 ;
49
+ lfs_off_t iitarget = ioff / wcount ;
50
+ lfs_off_t iicurrent = (icount - 1 ) / wcount ;
51
+
52
+ while (iitarget != iicurrent ) {
53
+ lfs_size_t skip = lfs_min (
54
+ lfs_min (lfs_ctz (iicurrent + 1 ), wcount - 1 ),
55
+ lfs_npw2 ((iitarget ^ iicurrent )+ 1 )- 1 );
56
+
57
+ lfs_error_t err = lfs -> ops -> read (lfs -> bd , (void * )& head ,
58
+ head , 4 * skip , 4 );
84
59
if (err ) {
85
60
return err ;
86
61
}
87
- ilookback -= irem ;
88
- isize -= irem ;
89
- }
90
- }
91
62
92
- static lfs_error_t lfs_alloc (lfs_t * lfs , lfs_ino_t * ino ) {
93
- lfs_error_t err = lfs_ifind (lfs , lfs -> free .head ,
94
- lfs -> free .rev [1 ], lfs -> free .rev [0 ], ino );
95
- if (err ) {
96
- return err ;
63
+ iicurrent -= 1 << skip ;
97
64
}
98
65
99
- err = lfs -> ops -> erase (lfs -> bd , * ino , 0 , lfs -> info .erase_size );
100
- if (err ) {
101
- return err ;
102
- }
103
-
104
- lfs -> free .rev [0 ] += 1 ;
105
- return 0 ;
66
+ return lfs -> ops -> read (lfs -> bd , (void * )ino , head , 4 * (ioff % wcount ), 4 );
106
67
}
107
68
108
- static lfs_error_t lfs_free (lfs_t * lfs , lfs_ino_t ino ) {
109
- // TODO handle overflow?
110
- if (lfs -> free .rev [1 ] == 0 ) {
111
- lfs -> free .head = ino ;
112
- lfs -> free .rev [1 ]++ ;
113
- lfs -> free .off = lfs -> info .erase_size ;
114
- return 0 ;
115
- }
69
+ // Append index to index chain, updates head and icount
70
+ static lfs_error_t lfs_iappend (lfs_t * lfs , lfs_ino_t * headp ,
71
+ lfs_size_t * icountp , lfs_ino_t ino ) {
72
+ lfs_ino_t head = * headp ;
73
+ lfs_size_t ioff = * icountp - 1 ;
74
+ lfs_size_t wcount = lfs -> info .erase_size /4 ;
116
75
117
- if (lfs -> free .off == lfs -> info .erase_size || !lfs -> free .head ) {
118
- lfs_ino_t nhead = 0 ;
76
+ ioff += 1 ;
77
+
78
+ while (ioff % wcount == 0 ) {
79
+ lfs_ino_t nhead ;
119
80
lfs_error_t err = lfs_alloc (lfs , & nhead );
120
81
if (err ) {
121
82
return err ;
122
83
}
123
84
124
- if (lfs -> free .off == lfs -> info .erase_size ) {
125
- err = lfs -> ops -> write (lfs -> bd , (void * )& lfs -> free .head , nhead , 0 , 4 );
85
+ lfs_off_t skips = lfs_min (lfs_ctz (ioff /wcount + 1 ), wcount - 1 ) + 1 ;
86
+ for (lfs_off_t i = 0 ; i < skips ; i ++ ) {
87
+ err = lfs -> ops -> write (lfs -> bd , (void * )& head , nhead , 4 * i , 4 );
126
88
if (err ) {
127
89
return err ;
128
90
}
129
- } else {
130
- for (lfs_off_t i = 0 ; i < lfs -> free .off ; i += 4 ) {
131
- lfs_ino_t ino ;
132
- lfs_error_t err = lfs -> ops -> read (lfs -> bd , (void * )& ino ,
133
- lfs -> free .phead , i , 4 );
134
- if (err ) {
135
- return err ;
136
- }
137
91
138
- err = lfs -> ops -> write ( lfs -> bd , ( void * ) & ino ,
139
- nhead , i , 4 );
92
+ if ( head && i != skips - 1 ) {
93
+ err = lfs -> ops -> read ( lfs -> bd , ( void * ) & head , head , 4 * i , 4 );
140
94
if (err ) {
141
95
return err ;
142
96
}
143
97
}
144
98
}
145
99
146
- lfs -> free . head = nhead ;
147
- lfs -> free . off = 4 ;
100
+ ioff += skips ;
101
+ head = nhead ;
148
102
}
149
103
150
104
lfs_error_t err = lfs -> ops -> write (lfs -> bd , (void * )& ino ,
151
- lfs -> free .head , lfs -> free .off , 4 );
105
+ head , 4 * (ioff % wcount ), 4 );
106
+ if (err ) {
107
+ return err ;
108
+ }
109
+
110
+ * headp = head ;
111
+ * icountp = ioff + 1 ;
112
+ return 0 ;
113
+ }
114
+
115
+ // Memory managment
116
+ static lfs_error_t lfs_alloc (lfs_t * lfs , lfs_ino_t * ino ) {
117
+ lfs_error_t err = lfs_ifind (lfs , lfs -> free .head ,
118
+ lfs -> free .icount , lfs -> free .ioff , ino );
152
119
if (err ) {
153
120
return err ;
154
121
}
155
122
156
- lfs -> free .off += 4 ;
157
- lfs -> free .rev [1 ] += 1 ;
123
+ lfs -> free .ioff = lfs_inext (lfs , lfs -> free .ioff );
124
+
125
+ return lfs -> ops -> erase (lfs -> bd , * ino , 0 , lfs -> info .erase_size );
126
+ }
127
+
128
+ static lfs_error_t lfs_free (lfs_t * lfs , lfs_ino_t ino ) {
129
+ return lfs_iappend (lfs , & lfs -> free .head , & lfs -> free .icount , ino );
130
+ }
131
+
132
+ // Little filesystem operations
133
+ lfs_error_t lfs_create (lfs_t * lfs , lfs_bd_t * bd , const struct lfs_bd_ops * ops ) {
134
+ lfs -> bd = bd ;
135
+ lfs -> ops = ops ;
136
+
137
+ lfs_error_t err = lfs -> ops -> info (lfs -> bd , & lfs -> info );
138
+ if (err ) {
139
+ return err ;
140
+ }
141
+
158
142
return 0 ;
159
143
}
160
144
@@ -165,22 +149,21 @@ lfs_error_t lfs_format(lfs_t *lfs) {
165
149
return err ;
166
150
}
167
151
168
- err = lfs -> ops -> erase (lfs -> bd , 0 , 0 , info .erase_size );
152
+ err = lfs -> ops -> erase (lfs -> bd , 0 , 0 , 5 * info .erase_size );
169
153
if (err ) {
170
154
return err ;
171
155
}
172
156
173
- // TODO erase what could be misinterpreted (pairs of blocks)
157
+ // TODO make sure that erase clobbered blocks
174
158
175
159
{ // Create free list
176
- lfs -> free .rev [0 ] = 0 ;
177
- lfs -> free .rev [1 ] = 0 ;
178
- lfs -> free .phead = 0 ;
179
- lfs -> free .head = 0 ;
180
- lfs -> free .off = 0 ;
160
+ lfs -> free .head = 4 ;
161
+ lfs -> free .ioff = 1 ;
162
+ lfs -> free .icount = 1 ;
163
+ lfs -> free .rev = 1 ;
181
164
182
165
lfs_size_t block_count = lfs -> info .total_size / lfs -> info .erase_size ;
183
- for (lfs_ino_t i = 4 ; i < block_count ; i ++ ) {
166
+ for (lfs_ino_t i = 5 ; i < block_count ; i ++ ) {
184
167
lfs_error_t err = lfs_free (lfs , i );
185
168
if (err ) {
186
169
return err ;
@@ -194,10 +177,8 @@ lfs_error_t lfs_format(lfs_t *lfs) {
194
177
lfs_word_t rev ;
195
178
lfs_size_t len ;
196
179
lfs_ino_t tail [2 ];
197
- lfs_word_t free_rev [2 ];
198
- lfs_ino_t free_ino ;
199
- } header = {1 , 0 , {0 , 0 },
200
- {lfs -> free .rev [0 ], lfs -> free .rev [1 ]}, lfs -> free .head };
180
+ struct lfs_free_list free ;
181
+ } header = {1 , 0 , {0 , 0 }, lfs -> free };
201
182
err = lfs -> ops -> write (lfs -> bd , (void * )& header , 2 , 0 , sizeof (header ));
202
183
if (err ) {
203
184
return err ;
@@ -227,12 +208,10 @@ lfs_error_t lfs_format(lfs_t *lfs) {
227
208
lfs_word_t rev ;
228
209
lfs_word_t len ;
229
210
lfs_word_t tail [2 ];
230
- lfs_word_t free_head ;
231
- lfs_word_t free_end ;
232
- lfs_ino_t free_ino ;
211
+ struct lfs_free_list free ;
233
212
char magic [4 ];
234
213
struct lfs_bd_info info ;
235
- } header = {1 , 0 , {2 , 3 }, 0 , 0 , 0 , {"lfs" }, info };
214
+ } header = {1 , 0 , {2 , 3 }, { 0 } , {"lfs" }, info };
236
215
err = lfs -> ops -> write (lfs -> bd , (void * )& header , 0 , 0 , sizeof (header ));
237
216
if (err ) {
238
217
return err ;
0 commit comments