diff --git a/emubd/lfs_emubd.c b/emubd/lfs_emubd.c index 682ad92..de63057 100644 --- a/emubd/lfs_emubd.c +++ b/emubd/lfs_emubd.c @@ -19,6 +19,40 @@ #include +// Emulated block device utils +static inline void lfs_emubd_tole32(lfs_emubd_t *emu) { + emu->cfg.read_size = lfs_tole32(emu->cfg.read_size); + emu->cfg.prog_size = lfs_tole32(emu->cfg.prog_size); + emu->cfg.block_size = lfs_tole32(emu->cfg.block_size); + emu->cfg.block_count = lfs_tole32(emu->cfg.block_count); + + emu->stats.read_count = lfs_tole32(emu->stats.read_count); + emu->stats.prog_count = lfs_tole32(emu->stats.prog_count); + emu->stats.erase_count = lfs_tole32(emu->stats.erase_count); + + for (int i = 0; i < sizeof(emu->history.blocks) / + sizeof(emu->history.blocks[0]); i++) { + emu->history.blocks[i] = lfs_tole32(emu->history.blocks[i]); + } +} + +static inline void lfs_emubd_fromle32(lfs_emubd_t *emu) { + emu->cfg.read_size = lfs_fromle32(emu->cfg.read_size); + emu->cfg.prog_size = lfs_fromle32(emu->cfg.prog_size); + emu->cfg.block_size = lfs_fromle32(emu->cfg.block_size); + emu->cfg.block_count = lfs_fromle32(emu->cfg.block_count); + + emu->stats.read_count = lfs_fromle32(emu->stats.read_count); + emu->stats.prog_count = lfs_fromle32(emu->stats.prog_count); + emu->stats.erase_count = lfs_fromle32(emu->stats.erase_count); + + for (int i = 0; i < sizeof(emu->history.blocks) / + sizeof(emu->history.blocks[0]); i++) { + emu->history.blocks[i] = lfs_fromle32(emu->history.blocks[i]); + } +} + + // Block device emulated on existing filesystem int lfs_emubd_create(const struct lfs_config *cfg, const char *path) { lfs_emubd_t *emu = cfg->context; @@ -46,20 +80,39 @@ int lfs_emubd_create(const struct lfs_config *cfg, const char *path) { } // Load stats to continue incrementing - snprintf(emu->child, LFS_NAME_MAX, "stats"); + snprintf(emu->child, LFS_NAME_MAX, ".stats"); FILE *f = fopen(emu->path, "r"); if (!f) { - return -errno; + memset(&emu->stats, 0, sizeof(emu->stats)); + } else { + size_t res = fread(&emu->stats, sizeof(emu->stats), 1, f); + lfs_emubd_fromle32(emu); + if (res < 1) { + return -errno; + } + + err = fclose(f); + if (err) { + return -errno; + } } - size_t res = fread(&emu->stats, sizeof(emu->stats), 1, f); - if (res < 1) { - return -errno; - } + // Load history + snprintf(emu->child, LFS_NAME_MAX, ".history"); + f = fopen(emu->path, "r"); + if (!f) { + memset(&emu->history, 0, sizeof(emu->history)); + } else { + size_t res = fread(&emu->history, sizeof(emu->history), 1, f); + lfs_emubd_fromle32(emu); + if (res < 1) { + return -errno; + } - err = fclose(f); - if (err) { - return -errno; + err = fclose(f); + if (err) { + return -errno; + } } return 0; @@ -161,6 +214,13 @@ int lfs_emubd_prog(const struct lfs_config *cfg, lfs_block_t block, return -errno; } + // update history and stats + if (block != emu->history.blocks[0]) { + memcpy(&emu->history.blocks[1], &emu->history.blocks[0], + sizeof(emu->history) - sizeof(emu->history.blocks[0])); + emu->history.blocks[0] = block; + } + emu->stats.prog_count += 1; return 0; } @@ -206,13 +266,15 @@ int lfs_emubd_sync(const struct lfs_config *cfg) { lfs_emubd_t *emu = cfg->context; // Just write out info/stats for later lookup - snprintf(emu->child, LFS_NAME_MAX, "config"); + snprintf(emu->child, LFS_NAME_MAX, ".config"); FILE *f = fopen(emu->path, "w"); if (!f) { return -errno; } + lfs_emubd_tole32(emu); size_t res = fwrite(&emu->cfg, sizeof(emu->cfg), 1, f); + lfs_emubd_fromle32(emu); if (res < 1) { return -errno; } @@ -222,13 +284,33 @@ int lfs_emubd_sync(const struct lfs_config *cfg) { return -errno; } - snprintf(emu->child, LFS_NAME_MAX, "stats"); + snprintf(emu->child, LFS_NAME_MAX, ".stats"); f = fopen(emu->path, "w"); if (!f) { return -errno; } + lfs_emubd_tole32(emu); res = fwrite(&emu->stats, sizeof(emu->stats), 1, f); + lfs_emubd_fromle32(emu); + if (res < 1) { + return -errno; + } + + err = fclose(f); + if (err) { + return -errno; + } + + snprintf(emu->child, LFS_NAME_MAX, ".history"); + f = fopen(emu->path, "w"); + if (!f) { + return -errno; + } + + lfs_emubd_tole32(emu); + res = fwrite(&emu->history, sizeof(emu->history), 1, f); + lfs_emubd_fromle32(emu); if (res < 1) { return -errno; } diff --git a/emubd/lfs_emubd.h b/emubd/lfs_emubd.h index 0fd4387..64afa3e 100644 --- a/emubd/lfs_emubd.h +++ b/emubd/lfs_emubd.h @@ -45,6 +45,10 @@ typedef struct lfs_emubd { uint64_t erase_count; } stats; + struct { + lfs_block_t blocks[4]; + } history; + struct { uint32_t read_size; uint32_t prog_size; diff --git a/lfs.c b/lfs.c index 2df9253..f112386 100644 --- a/lfs.c +++ b/lfs.c @@ -879,6 +879,8 @@ static int32_t lfs_dir_fetchmatch(lfs_t *lfs, dir->tail[1] = temptail[1]; dir->split = tempsplit; dir->locals = templocals; + + lfs->seed ^= crc; crc = 0xffffffff; } else { err = lfs_bd_crc32(lfs, dir->pair[0], @@ -2874,6 +2876,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { lfs->root[0] = 0xffffffff; lfs->root[1] = 0xffffffff; lfs->mlist = NULL; + lfs->seed = 0; lfs->globals.s.movepair[0] = 0xffffffff; lfs->globals.s.movepair[1] = 0xffffffff; lfs->globals.s.moveid = 0x3ff; @@ -2962,12 +2965,6 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { return err; } - // setup free lookahead - lfs->free.off = 0; - lfs->free.size = 0; - lfs->free.i = 0; - lfs_alloc_ack(lfs); - // load superblock lfs_mdir_t root; err = lfs_dir_fetch(lfs, &root, (const lfs_block_t[2]){0, 1}); @@ -3065,6 +3062,12 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { lfs->globals.s.moveid); } + // setup free lookahead + lfs->free.off = lfs->seed % lfs->cfg->block_size; + lfs->free.size = 0; + lfs->free.i = 0; + lfs_alloc_ack(lfs); + return 0; cleanup: diff --git a/lfs.h b/lfs.h index dfafb5b..f2672ac 100644 --- a/lfs.h +++ b/lfs.h @@ -382,6 +382,7 @@ typedef struct lfs { lfs_block_t root[2]; lfs_mlist_t *mlist; + uint32_t seed; lfs_global_t globals; lfs_global_t locals; diff --git a/tests/corrupt.py b/tests/corrupt.py index 76f07ce..5e2a9a3 100755 --- a/tests/corrupt.py +++ b/tests/corrupt.py @@ -3,37 +3,41 @@ import struct import sys import os +import argparse -def main(*paths): - # find most recent block - file = None - rev = None - for path in paths: - try: - nfile = open(path, 'r+b') - nrev, = struct.unpack('> 22 + id = (tag & 0x003ff000) >> 12 + size = (tag & 0x00000fff) >> 0 + + data = file.read(size) + if type == 0x0f0: + crc = binascii.crc32(data[:4], crc) + else: + crc = binascii.crc32(data, crc) + + print '%04x: %08x %-14s %3s %3d %-23s %-8s' % ( + off, tag, + typeof(type) + (' bad!' if type == 0x0f0 and ~crc else ''), + id if id != 0x3ff else '.', size, + ' '.join('%02x' % ord(c) for c in data[:8]), + ''.join(c if c >= ' ' and c <= '~' else '.' for c in data[:8])) + + off += tag & 0xfff + if type == 0x0f0: + crc = 0 + +if __name__ == "__main__": + import sys + main(*sys.argv[1:]) diff --git a/tests/stats.py b/tests/stats.py index 2ba1fb6..ab21b59 100755 --- a/tests/stats.py +++ b/tests/stats.py @@ -7,7 +7,7 @@ import os import re def main(): - with open('blocks/config') as file: + with open('blocks/.config') as file: s = struct.unpack(' 0; lfs_unmount(&lfs) => 0; TEST -tests/corrupt.py blocks/{4,5} +tests/corrupt.py -n 1 tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; lfs_dir_open(&lfs, &dir[0], "b") => 0; @@ -86,8 +86,7 @@ tests/test.py << TEST lfs_rename(&lfs, "c/hello", "d/hello") => 0; lfs_unmount(&lfs) => 0; TEST -tests/corrupt.py blocks/{6,7} -tests/corrupt.py blocks/{8,9} +tests/corrupt.py -n 2 tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; lfs_dir_open(&lfs, &dir[0], "c") => 0; @@ -166,7 +165,7 @@ tests/test.py << TEST lfs_rename(&lfs, "b/hi", "c/hi") => 0; lfs_unmount(&lfs) => 0; TEST -tests/corrupt.py blocks/{4,5} +tests/corrupt.py -n 1 tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; lfs_dir_open(&lfs, &dir[0], "b") => 0; @@ -193,8 +192,7 @@ tests/test.py << TEST lfs_rename(&lfs, "c/hi", "d/hi") => 0; lfs_unmount(&lfs) => 0; TEST -tests/corrupt.py blocks/{6,7} -tests/corrupt.py blocks/{8,9} +tests/corrupt.py -n 2 tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; lfs_dir_open(&lfs, &dir[0], "c") => 0; diff --git a/tests/test_orphan.sh b/tests/test_orphan.sh index e66e592..9c2cb7b 100755 --- a/tests/test_orphan.sh +++ b/tests/test_orphan.sh @@ -17,7 +17,7 @@ tests/test.py << TEST TEST # corrupt most recent commit, this should be the update to the previous # linked-list entry and should orphan the child -tests/corrupt.py blocks/{6,7} +tests/corrupt.py tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0;