Skip to content

Commit 160299d

Browse files
committed
Initial commit of progress, minimal formatting niave free list
1 parent 02156cb commit 160299d

File tree

5 files changed

+344
-7
lines changed

5 files changed

+344
-7
lines changed

emubd/lfs_emubd.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// Block device emulated on existing filesystem
1919
lfs_error_t lfs_emubd_create(lfs_emubd_t *emu, const char *path) {
2020
memset(&emu->info, 0, sizeof(emu->info));
21+
memset(&emu->stats, 0, sizeof(emu->stats));
2122

2223
// Allocate buffer for creating children files
2324
size_t pathlen = strlen(path);
@@ -64,8 +65,8 @@ lfs_error_t lfs_emubd_read(lfs_emubd_t *emu, uint8_t *buffer,
6465
return -EINVAL;
6566
}
6667

67-
// Default to some arbitrary value for debugging
68-
memset(buffer, 0xcc, size);
68+
// Zero out buffer for debugging
69+
memset(buffer, 0, size);
6970

7071
// Iterate over blocks until enough data is read
7172
while (size > 0) {
@@ -100,6 +101,7 @@ lfs_error_t lfs_emubd_read(lfs_emubd_t *emu, uint8_t *buffer,
100101
off = 0;
101102
}
102103

104+
emu->stats.read_count += 1;
103105
return 0;
104106
}
105107

@@ -148,6 +150,7 @@ lfs_error_t lfs_emubd_write(lfs_emubd_t *emu, const uint8_t *buffer,
148150
off = 0;
149151
}
150152

153+
emu->stats.write_count += 1;
151154
return 0;
152155
}
153156

@@ -175,6 +178,7 @@ lfs_error_t lfs_emubd_erase(lfs_emubd_t *emu,
175178
off = 0;
176179
}
177180

181+
emu->stats.erase_count += 1;
178182
return 0;
179183
}
180184

@@ -188,6 +192,11 @@ lfs_error_t lfs_emubd_info(lfs_emubd_t *emu, struct lfs_bd_info *info) {
188192
return 0;
189193
}
190194

195+
lfs_error_t lfs_emubd_stats(lfs_emubd_t *emu, struct lfs_bd_stats *stats) {
196+
*stats = emu->stats;
197+
return 0;
198+
}
199+
191200

192201
// Wrappers for void*s
193202
static lfs_error_t lfs_emubd_bd_read(void *bd, uint8_t *buffer,

emubd/lfs_emubd.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,19 @@
1111
#include "lfs_bd.h"
1212

1313

14+
// Stats for debugging and optimization
15+
struct lfs_bd_stats {
16+
lfs_lword_t read_count;
17+
lfs_lword_t write_count;
18+
lfs_lword_t erase_count;
19+
};
20+
1421
// The emu bd state
1522
typedef struct lfs_emubd {
1623
char *path;
1724
char *child;
1825
struct lfs_bd_info info;
26+
struct lfs_bd_stats stats;
1927
} lfs_emubd_t;
2028

2129

@@ -50,6 +58,11 @@ lfs_error_t lfs_emubd_sync(lfs_emubd_t *bd);
5058
// Any unknown information may be left unmodified
5159
lfs_error_t lfs_emubd_info(lfs_emubd_t *bd, struct lfs_bd_info *info);
5260

61+
// Get stats of operations on the block device
62+
//
63+
// Used for debugging and optimizations
64+
lfs_error_t lfs_emubd_stats(lfs_emubd_t *bd, struct lfs_bd_stats *stats);
65+
5366
// Block device operations
5467
extern const struct lfs_bd_ops lfs_emubd_ops;
5568

lfs.c

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
/*
2+
* The little filesystem
3+
*
4+
* Copyright (c) 2017 Christopher Haster
5+
* Distributed under the MIT license
6+
*/
7+
#include "lfs.h"
8+
9+
#include <string.h>
10+
#include <stdbool.h>
11+
12+
13+
static uint32_t lfs_crc(const uint8_t *data, lfs_size_t size, uint32_t crc) {
14+
static const uint32_t rtable[16] = {
15+
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
16+
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
17+
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
18+
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
19+
};
20+
21+
for (lfs_size_t i = 0; i < size; i++) {
22+
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];
23+
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];
24+
}
25+
26+
return crc;
27+
}
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));
32+
33+
lfs->bd = bd;
34+
lfs->ops = ops;
35+
36+
lfs_error_t err = lfs->ops->info(lfs->bd, &lfs->info);
37+
if (err) {
38+
return err;
39+
}
40+
41+
return 0;
42+
}
43+
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;
51+
}
52+
}
53+
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+
}
62+
}
63+
64+
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);
84+
if (err) {
85+
return err;
86+
}
87+
ilookback -= irem;
88+
isize -= irem;
89+
}
90+
}
91+
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;
97+
}
98+
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;
106+
}
107+
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+
}
116+
117+
if (lfs->free.off == lfs->info.erase_size || !lfs->free.head) {
118+
lfs_ino_t nhead = 0;
119+
lfs_error_t err = lfs_alloc(lfs, &nhead);
120+
if (err) {
121+
return err;
122+
}
123+
124+
if (lfs->free.off == lfs->info.erase_size) {
125+
err = lfs->ops->write(lfs->bd, (void*)&lfs->free.head, nhead, 0, 4);
126+
if (err) {
127+
return err;
128+
}
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+
138+
err = lfs->ops->write(lfs->bd, (void*)&ino,
139+
nhead, i, 4);
140+
if (err) {
141+
return err;
142+
}
143+
}
144+
}
145+
146+
lfs->free.head = nhead;
147+
lfs->free.off = 4;
148+
}
149+
150+
lfs_error_t err = lfs->ops->write(lfs->bd, (void*)&ino,
151+
lfs->free.head, lfs->free.off, 4);
152+
if (err) {
153+
return err;
154+
}
155+
156+
lfs->free.off += 4;
157+
lfs->free.rev[1] += 1;
158+
return 0;
159+
}
160+
161+
lfs_error_t lfs_format(lfs_t *lfs) {
162+
struct lfs_bd_info info;
163+
lfs_error_t err = lfs->ops->info(lfs->bd, &info);
164+
if (err) {
165+
return err;
166+
}
167+
168+
err = lfs->ops->erase(lfs->bd, 0, 0, info.erase_size);
169+
if (err) {
170+
return err;
171+
}
172+
173+
// TODO erase what could be misinterpreted (pairs of blocks)
174+
175+
{ // 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;
181+
182+
lfs_size_t block_count = lfs->info.total_size / lfs->info.erase_size;
183+
for (lfs_ino_t i = 4; i < block_count; i++) {
184+
lfs_error_t err = lfs_free(lfs, i);
185+
if (err) {
186+
return err;
187+
}
188+
}
189+
}
190+
191+
{
192+
// Write root directory
193+
struct __attribute__((packed)) {
194+
lfs_word_t rev;
195+
lfs_size_t len;
196+
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};
201+
err = lfs->ops->write(lfs->bd, (void*)&header, 2, 0, sizeof(header));
202+
if (err) {
203+
return err;
204+
}
205+
206+
uint32_t crc = lfs_crc((void*)&header, sizeof(header), 0xffffffff);
207+
208+
for (lfs_size_t i = sizeof(header); i < info.erase_size-4; i += 4) {
209+
uint32_t data;
210+
err = lfs->ops->read(lfs->bd, (void*)&data, 2, i, 4);
211+
if (err) {
212+
return err;
213+
}
214+
215+
crc = lfs_crc((void*)&data, 4, crc);
216+
}
217+
218+
err = lfs->ops->write(lfs->bd, (void*)&crc, 2, info.erase_size-4, 4);
219+
if (err) {
220+
return err;
221+
}
222+
}
223+
224+
{
225+
// Write superblock
226+
struct __attribute__((packed)) {
227+
lfs_word_t rev;
228+
lfs_word_t len;
229+
lfs_word_t tail[2];
230+
lfs_word_t free_head;
231+
lfs_word_t free_end;
232+
lfs_ino_t free_ino;
233+
char magic[4];
234+
struct lfs_bd_info info;
235+
} header = {1, 0, {2, 3}, 0, 0, 0, {"lfs"}, info};
236+
err = lfs->ops->write(lfs->bd, (void*)&header, 0, 0, sizeof(header));
237+
if (err) {
238+
return err;
239+
}
240+
241+
uint32_t crc = lfs_crc((void*)&header, sizeof(header), 0xffffffff);
242+
243+
for (lfs_size_t i = sizeof(header); i < info.erase_size-4; i += 4) {
244+
uint32_t data;
245+
err = lfs->ops->read(lfs->bd, (void*)&data, 0, i, 4);
246+
if (err) {
247+
return err;
248+
}
249+
250+
crc = lfs_crc((void*)&data, 4, crc);
251+
}
252+
253+
err = lfs->ops->write(lfs->bd, (void*)&crc, 0, info.erase_size-4, 4);
254+
if (err) {
255+
return err;
256+
}
257+
}
258+
259+
260+
// Sanity check
261+
uint32_t crc = 0xffffffff;
262+
for (lfs_size_t i = 0; i < info.erase_size; i += 4) {
263+
uint32_t data;
264+
err = lfs->ops->read(lfs->bd, (void*)&data, 0, i, 4);
265+
if (err) {
266+
return err;
267+
}
268+
269+
crc = lfs_crc((void*)&data, 4, crc);
270+
}
271+
272+
uint32_t data;
273+
err = lfs->ops->read(lfs->bd, (void*)&data, 0, info.erase_size-4, 4);
274+
if (err) {
275+
return err;
276+
}
277+
278+
return crc;
279+
}
280+

0 commit comments

Comments
 (0)