runners: Adopted compile-time optional kiwibd as emubd alternative
kiwibd has been used extensively in external benchmarks, it makes sense to make it the default bd for the bench runner: - test_runner - defaults to emubd - more testing features - bench_runner - defaults to kiwibd - lighter-weight disks The benefit of kiwibd is the disk is just one big blob of RAM, so basically no overhead. This is important when benchmarking on multi-GiB disks. emubd is much heavy, but as a tradeoff can do quite a bit more: bad-block simulation, wear simulation, snapshotting, etc. --- In theory the bd used by each runner can be controlled at compile-time by defining -DBENCH_EMUBD, etc, but I have a feeling no one will ever use this.
This commit is contained in:
@@ -61,10 +61,12 @@
|
||||
BENCH_DEFINE(PROGGED_TIMING, 1484 )
|
||||
BENCH_DEFINE(ERASED_TIMING, 0 )
|
||||
#endif
|
||||
#ifndef BENCH_KIWIBD
|
||||
BENCH_DEFINE(ERASE_CYCLES, 0 )
|
||||
BENCH_DEFINE(BADBLOCK_BEHAVIOR, LFS3_EMUBD_BADBLOCK_PROGERROR )
|
||||
BENCH_DEFINE(POWERLOSS_BEHAVIOR, LFS3_EMUBD_POWERLOSS_ATOMIC )
|
||||
BENCH_DEFINE(EMUBD_SEED, 0 )
|
||||
BENCH_DEFINE(BD_SEED, 0 )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -107,9 +109,11 @@
|
||||
BENCH_BDCFG(readed_timing, READED_TIMING )
|
||||
BENCH_BDCFG(progged_timing, PROGGED_TIMING )
|
||||
BENCH_BDCFG(erased_timing, ERASED_TIMING )
|
||||
#ifndef BENCH_KIWIBD
|
||||
BENCH_BDCFG(erase_cycles, ERASE_CYCLES )
|
||||
BENCH_BDCFG(badblock_behavior, BADBLOCK_BEHAVIOR )
|
||||
BENCH_BDCFG(powerloss_behavior, POWERLOSS_BEHAVIOR )
|
||||
BENCH_BDCFG(seed, EMUBD_SEED )
|
||||
BENCH_BDCFG(seed, BD_SEED )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
+115
-27
@@ -9,7 +9,6 @@
|
||||
#endif
|
||||
|
||||
#include "runners/bench_runner.h"
|
||||
#include "bd/lfs3_emubd.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
@@ -22,6 +21,21 @@
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
// some common types
|
||||
#ifndef BENCH_KIWIBD
|
||||
typedef lfs3_emubd_io_t bench_io_t;
|
||||
typedef lfs3_emubd_sio_t bench_sio_t;
|
||||
typedef lfs3_emubd_ns_t bench_ns_t;
|
||||
typedef lfs3_emubd_sns_t bench_sns_t;
|
||||
#else
|
||||
typedef lfs3_kiwibd_io_t bench_io_t;
|
||||
typedef lfs3_kiwibd_sio_t bench_sio_t;
|
||||
typedef lfs3_kiwibd_ns_t bench_ns_t;
|
||||
typedef lfs3_kiwibd_sns_t bench_sns_t;
|
||||
#endif
|
||||
|
||||
|
||||
// some helpers
|
||||
@@ -436,9 +450,9 @@ FILE *bench_trace_file = NULL;
|
||||
uint32_t bench_trace_cycles = 0;
|
||||
uint64_t bench_trace_time = 0;
|
||||
uint64_t bench_trace_open_time = 0;
|
||||
lfs3_emubd_ns_t bench_read_sleep = 0.0;
|
||||
lfs3_emubd_ns_t bench_prog_sleep = 0.0;
|
||||
lfs3_emubd_ns_t bench_erase_sleep = 0.0;
|
||||
bench_ns_t bench_read_sleep = 0.0;
|
||||
bench_ns_t bench_prog_sleep = 0.0;
|
||||
bench_ns_t bench_erase_sleep = 0.0;
|
||||
|
||||
// this determines both the backtrace buffer and the trace printf buffer, if
|
||||
// trace ends up interleaved or truncated this may need to be increased
|
||||
@@ -603,13 +617,13 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size) {
|
||||
// bench recording state
|
||||
typedef struct bench_record {
|
||||
const char *probe;
|
||||
lfs3_emubd_io_t last_reads;
|
||||
lfs3_emubd_io_t last_progs;
|
||||
lfs3_emubd_io_t last_erases;
|
||||
lfs3_emubd_io_t last_readed;
|
||||
lfs3_emubd_io_t last_progged;
|
||||
lfs3_emubd_io_t last_erased;
|
||||
lfs3_emubd_ns_t last_simtime;
|
||||
bench_io_t last_reads;
|
||||
bench_io_t last_progs;
|
||||
bench_io_t last_erases;
|
||||
bench_io_t last_readed;
|
||||
bench_io_t last_progged;
|
||||
bench_io_t last_erased;
|
||||
bench_ns_t last_simtime;
|
||||
} bench_record_t;
|
||||
|
||||
static struct lfs3_cfg *bench_cfg = NULL;
|
||||
@@ -625,20 +639,37 @@ void bench_reset(struct lfs3_cfg *cfg) {
|
||||
void bench_start(const char *probe) {
|
||||
// measure current read/prog/erase
|
||||
assert(bench_cfg);
|
||||
lfs3_emubd_sio_t reads = lfs3_emubd_reads(bench_cfg);
|
||||
#ifndef BENCH_KIWIBD
|
||||
bench_sio_t reads = lfs3_emubd_reads(bench_cfg);
|
||||
assert(reads >= 0);
|
||||
lfs3_emubd_sio_t progs = lfs3_emubd_progs(bench_cfg);
|
||||
bench_sio_t progs = lfs3_emubd_progs(bench_cfg);
|
||||
assert(progs >= 0);
|
||||
lfs3_emubd_sio_t erases = lfs3_emubd_erases(bench_cfg);
|
||||
bench_sio_t erases = lfs3_emubd_erases(bench_cfg);
|
||||
assert(erases >= 0);
|
||||
lfs3_emubd_sio_t readed = lfs3_emubd_readed(bench_cfg);
|
||||
bench_sio_t readed = lfs3_emubd_readed(bench_cfg);
|
||||
assert(readed >= 0);
|
||||
lfs3_emubd_sio_t progged = lfs3_emubd_progged(bench_cfg);
|
||||
bench_sio_t progged = lfs3_emubd_progged(bench_cfg);
|
||||
assert(progged >= 0);
|
||||
lfs3_emubd_sio_t erased = lfs3_emubd_erased(bench_cfg);
|
||||
bench_sio_t erased = lfs3_emubd_erased(bench_cfg);
|
||||
assert(erased >= 0);
|
||||
// note this can error if no timings provided
|
||||
lfs3_emubd_sns_t simtime = lfs3_emubd_simtime(bench_cfg);
|
||||
bench_sns_t simtime = lfs3_emubd_simtime(bench_cfg);
|
||||
#else
|
||||
bench_sio_t reads = lfs3_kiwibd_reads(bench_cfg);
|
||||
assert(reads >= 0);
|
||||
bench_sio_t progs = lfs3_kiwibd_progs(bench_cfg);
|
||||
assert(progs >= 0);
|
||||
bench_sio_t erases = lfs3_kiwibd_erases(bench_cfg);
|
||||
assert(erases >= 0);
|
||||
bench_sio_t readed = lfs3_kiwibd_readed(bench_cfg);
|
||||
assert(readed >= 0);
|
||||
bench_sio_t progged = lfs3_kiwibd_progged(bench_cfg);
|
||||
assert(progged >= 0);
|
||||
bench_sio_t erased = lfs3_kiwibd_erased(bench_cfg);
|
||||
assert(erased >= 0);
|
||||
// note this can error if no timings provided
|
||||
bench_sns_t simtime = lfs3_kiwibd_simtime(bench_cfg);
|
||||
#endif
|
||||
|
||||
// allocate a new record
|
||||
bench_record_t *record = mappend(
|
||||
@@ -659,20 +690,37 @@ void bench_start(const char *probe) {
|
||||
void bench_stop(const char *probe, uintmax_t n) {
|
||||
// measure current read/prog/erase
|
||||
assert(bench_cfg);
|
||||
lfs3_emubd_sio_t reads = lfs3_emubd_reads(bench_cfg);
|
||||
#ifndef BENCH_KIWIBD
|
||||
bench_sio_t reads = lfs3_emubd_reads(bench_cfg);
|
||||
assert(reads >= 0);
|
||||
lfs3_emubd_sio_t progs = lfs3_emubd_progs(bench_cfg);
|
||||
bench_sio_t progs = lfs3_emubd_progs(bench_cfg);
|
||||
assert(progs >= 0);
|
||||
lfs3_emubd_sio_t erases = lfs3_emubd_erases(bench_cfg);
|
||||
bench_sio_t erases = lfs3_emubd_erases(bench_cfg);
|
||||
assert(erases >= 0);
|
||||
lfs3_emubd_sio_t readed = lfs3_emubd_readed(bench_cfg);
|
||||
bench_sio_t readed = lfs3_emubd_readed(bench_cfg);
|
||||
assert(readed >= 0);
|
||||
lfs3_emubd_sio_t progged = lfs3_emubd_progged(bench_cfg);
|
||||
bench_sio_t progged = lfs3_emubd_progged(bench_cfg);
|
||||
assert(progged >= 0);
|
||||
lfs3_emubd_sio_t erased = lfs3_emubd_erased(bench_cfg);
|
||||
bench_sio_t erased = lfs3_emubd_erased(bench_cfg);
|
||||
assert(erased >= 0);
|
||||
// note this can error if no timings provided
|
||||
lfs3_emubd_sns_t simtime = lfs3_emubd_simtime(bench_cfg);
|
||||
bench_sns_t simtime = lfs3_emubd_simtime(bench_cfg);
|
||||
#else
|
||||
bench_sio_t reads = lfs3_kiwibd_reads(bench_cfg);
|
||||
assert(reads >= 0);
|
||||
bench_sio_t progs = lfs3_kiwibd_progs(bench_cfg);
|
||||
assert(progs >= 0);
|
||||
bench_sio_t erases = lfs3_kiwibd_erases(bench_cfg);
|
||||
assert(erases >= 0);
|
||||
bench_sio_t readed = lfs3_kiwibd_readed(bench_cfg);
|
||||
assert(readed >= 0);
|
||||
bench_sio_t progged = lfs3_kiwibd_progged(bench_cfg);
|
||||
assert(progged >= 0);
|
||||
bench_sio_t erased = lfs3_kiwibd_erased(bench_cfg);
|
||||
assert(erased >= 0);
|
||||
// note this can error if no timings provided
|
||||
bench_sns_t simtime = lfs3_kiwibd_simtime(bench_cfg);
|
||||
#endif
|
||||
|
||||
// find our record
|
||||
for (size_t i = 0; i < bench_record_count; i++) {
|
||||
@@ -1383,20 +1431,33 @@ void perm_run(
|
||||
}
|
||||
|
||||
// create block device and configuration
|
||||
#ifndef BENCH_KIWIBD
|
||||
lfs3_emubd_t bd;
|
||||
#else
|
||||
lfs3_kiwibd_t bd;
|
||||
#endif
|
||||
|
||||
struct lfs3_cfg cfg = {
|
||||
.context = &bd,
|
||||
#ifndef BENCH_KIWIBD
|
||||
.read = lfs3_emubd_read,
|
||||
.prog = lfs3_emubd_prog,
|
||||
.erase = lfs3_emubd_erase,
|
||||
.sync = lfs3_emubd_sync,
|
||||
#else
|
||||
.read = lfs3_kiwibd_read,
|
||||
.prog = lfs3_kiwibd_prog,
|
||||
.erase = lfs3_kiwibd_erase,
|
||||
.sync = lfs3_kiwibd_sync,
|
||||
#endif
|
||||
#define BENCH_CFG(k, v) \
|
||||
.k = v,
|
||||
#include "bench_defines.h"
|
||||
#undef BENCH_CFG
|
||||
};
|
||||
|
||||
// using emubd?
|
||||
#ifndef BENCH_KIWIBD
|
||||
struct lfs3_emubd_cfg bdcfg = {
|
||||
.read_sleep = bench_read_sleep,
|
||||
.prog_sleep = bench_prog_sleep,
|
||||
@@ -1409,10 +1470,29 @@ void perm_run(
|
||||
|
||||
int err = lfs3_emubd_createcfg(&cfg, bench_disk_path, &bdcfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not create block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not create emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// using kiwibd?
|
||||
#else
|
||||
struct lfs3_kiwibd_cfg bdcfg = {
|
||||
.read_sleep = bench_read_sleep,
|
||||
.prog_sleep = bench_prog_sleep,
|
||||
.erase_sleep = bench_erase_sleep,
|
||||
#define BENCH_BDCFG(k, v) \
|
||||
.k = v,
|
||||
#include "bench_defines.h"
|
||||
#undef BENCH_CFG
|
||||
};
|
||||
|
||||
int err = lfs3_kiwibd_createcfg(&cfg, bench_disk_path, &bdcfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not create kiwibd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// run the bench
|
||||
bench_reset(&cfg);
|
||||
printf("running ");
|
||||
@@ -1426,11 +1506,19 @@ void perm_run(
|
||||
printf("\n");
|
||||
|
||||
// cleanup
|
||||
#ifndef BENCH_KIWIBD
|
||||
err = lfs3_emubd_destroy(&cfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not destroy block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not destroy emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
err = lfs3_kiwibd_destroy(&cfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not destroy kiwibd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void run(void) {
|
||||
|
||||
@@ -8,6 +8,23 @@
|
||||
#define BENCH_RUNNER_H
|
||||
|
||||
|
||||
// default to using kiwibd for benches
|
||||
#if !defined(BENCH_EMUBD) && !defined(BENCH_KIWIBD)
|
||||
#define BENCH_KIWIBD
|
||||
#endif
|
||||
|
||||
// ifdef macros for emubd vs kiwibd
|
||||
#ifdef BENCH_EMUBD
|
||||
#define BENCH_IFDEF_EMUBD(a, b) (a)
|
||||
#else
|
||||
#define BENCH_IFDEF_EMUBD(a, b) (b)
|
||||
#endif
|
||||
#ifdef BENCH_KIWIBD
|
||||
#define BENCH_IFDEF_KIWIBD(a, b) (a)
|
||||
#else
|
||||
#define BENCH_IFDEF_KIWIBD(a, b) (b)
|
||||
#endif
|
||||
|
||||
// override LFS3_TRACE
|
||||
void bench_trace(const char *fmt, ...);
|
||||
|
||||
@@ -18,6 +35,7 @@ void bench_trace(const char *fmt, ...);
|
||||
__VA_ARGS__)
|
||||
#define LFS3_TRACE(...) LFS3_TRACE_(__VA_ARGS__, "")
|
||||
#define LFS3_EMUBD_TRACE(...) LFS3_TRACE_(__VA_ARGS__, "")
|
||||
#define LFS3_KIWIBD_TRACE(...) LFS3_TRACE_(__VA_ARGS__, "")
|
||||
|
||||
// BENCH_START/BENCH_STOP macros measure readed/progged/erased bytes
|
||||
// through emubd
|
||||
@@ -36,8 +54,14 @@ void bench_fresult(const char *probe, uintmax_t n, double result);
|
||||
|
||||
|
||||
// note these are indirectly included in any generated files
|
||||
#ifndef BENCH_KIWIBD
|
||||
#include "bd/lfs3_emubd.h"
|
||||
#else
|
||||
#include "bd/lfs3_kiwibd.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// give source a chance to define feature macros
|
||||
#undef _FEATURES_H
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
TEST_DEFINE(CRYSTAL_THRESH, BLOCK_SIZE/8 )
|
||||
TEST_DEFINE(LOOKGBMAP_THRESH, BLOCK_COUNT/4 )
|
||||
TEST_DEFINE(ERASE_VALUE, 0xff )
|
||||
#ifndef TEST_KIWIBD
|
||||
TEST_DEFINE(ERASE_CYCLES, 0 )
|
||||
TEST_DEFINE(BADBLOCK_BEHAVIOR, LFS3_EMUBD_BADBLOCK_PROGERROR )
|
||||
TEST_DEFINE(POWERLOSS_BEHAVIOR, LFS3_EMUBD_POWERLOSS_ATOMIC )
|
||||
TEST_DEFINE(EMUBD_SEED, 0 )
|
||||
TEST_DEFINE(BD_SEED, 0 )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -65,9 +67,11 @@
|
||||
// struct lfs3_*bd_cfg fields
|
||||
#ifdef TEST_BDCFG
|
||||
TEST_BDCFG(erase_value, ERASE_VALUE )
|
||||
#ifndef TEST_KIWIBD
|
||||
TEST_BDCFG(erase_cycles, ERASE_CYCLES )
|
||||
TEST_BDCFG(badblock_behavior, BADBLOCK_BEHAVIOR )
|
||||
TEST_BDCFG(powerloss_behavior, POWERLOSS_BEHAVIOR )
|
||||
TEST_BDCFG(seed, EMUBD_SEED )
|
||||
TEST_BDCFG(seed, BD_SEED )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
+137
-39
@@ -9,7 +9,6 @@
|
||||
#endif
|
||||
|
||||
#include "runners/test_runner.h"
|
||||
#include "bd/lfs3_emubd.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
@@ -22,6 +21,21 @@
|
||||
#include <time.h>
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
// some common types
|
||||
#ifndef TEST_KIWIBD
|
||||
typedef lfs3_emubd_ns_t test_ns_t;
|
||||
typedef lfs3_emubd_sns_t test_sns_t;
|
||||
typedef lfs3_emubd_powercycles_t test_powercycles_t;
|
||||
typedef lfs3_emubd_spowercycles_t test_spowercycles_t;
|
||||
#else
|
||||
typedef lfs3_kiwibd_ns_t test_ns_t;
|
||||
typedef lfs3_kiwibd_sns_t test_sns_t;
|
||||
typedef void test_powercycles_t;
|
||||
typedef void test_spowercycles_t;
|
||||
#endif
|
||||
|
||||
|
||||
// some helpers
|
||||
@@ -117,7 +131,7 @@ typedef struct test_powerloss {
|
||||
const struct test_powerloss *powerloss,
|
||||
const struct test_suite *suite,
|
||||
const struct test_case *case_);
|
||||
const lfs3_emubd_powercycles_t *cycles;
|
||||
const test_powercycles_t *cycles;
|
||||
size_t cycle_count;
|
||||
} test_powerloss_t;
|
||||
|
||||
@@ -447,9 +461,9 @@ FILE *test_trace_file = NULL;
|
||||
uint32_t test_trace_cycles = 0;
|
||||
uint64_t test_trace_time = 0;
|
||||
uint64_t test_trace_open_time = 0;
|
||||
lfs3_emubd_ns_t test_read_sleep = 0.0;
|
||||
lfs3_emubd_ns_t test_prog_sleep = 0.0;
|
||||
lfs3_emubd_ns_t test_erase_sleep = 0.0;
|
||||
test_ns_t test_read_sleep = 0.0;
|
||||
test_ns_t test_prog_sleep = 0.0;
|
||||
test_ns_t test_erase_sleep = 0.0;
|
||||
|
||||
volatile size_t TEST_PLS = 0;
|
||||
|
||||
@@ -620,9 +634,11 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size) {
|
||||
static void perm_printid(
|
||||
const struct test_suite *suite,
|
||||
const struct test_case *case_,
|
||||
const lfs3_emubd_powercycles_t *cycles,
|
||||
const test_powercycles_t *cycles,
|
||||
size_t cycle_count) {
|
||||
(void)suite;
|
||||
(void)cycles;
|
||||
(void)cycle_count;
|
||||
// case[:permutation[:powercycles]]
|
||||
printf("%s:", case_->name);
|
||||
for (size_t d = 0; d < test_define_count; d++) {
|
||||
@@ -633,12 +649,14 @@ static void perm_printid(
|
||||
}
|
||||
|
||||
// only print power-cycles if any occured
|
||||
#ifndef TEST_KIWIBD
|
||||
if (cycle_count) {
|
||||
printf(":");
|
||||
for (size_t i = 0; i < cycle_count; i++) {
|
||||
leb16_print(cycles[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -701,10 +719,12 @@ static void run_powerloss_none(
|
||||
const test_powerloss_t *powerloss,
|
||||
const struct test_suite *suite,
|
||||
const struct test_case *case_);
|
||||
#ifndef TEST_KIWIBD
|
||||
static void run_powerloss_cycles(
|
||||
const test_powerloss_t *powerloss,
|
||||
const struct test_suite *suite,
|
||||
const struct test_case *case_);
|
||||
#endif
|
||||
|
||||
// iterate through permutations in a test case
|
||||
static void case_forperm(
|
||||
@@ -1304,20 +1324,33 @@ static void run_powerloss_none(
|
||||
(void)powerloss;
|
||||
|
||||
// create block device and configuration
|
||||
#ifndef TEST_KIWIBD
|
||||
lfs3_emubd_t bd;
|
||||
#else
|
||||
lfs3_kiwibd_t bd;
|
||||
#endif
|
||||
|
||||
struct lfs3_cfg cfg = {
|
||||
.context = &bd,
|
||||
#ifndef TEST_KIWIBD
|
||||
.read = lfs3_emubd_read,
|
||||
.prog = lfs3_emubd_prog,
|
||||
.erase = lfs3_emubd_erase,
|
||||
.sync = lfs3_emubd_sync,
|
||||
#else
|
||||
.read = lfs3_kiwibd_read,
|
||||
.prog = lfs3_kiwibd_prog,
|
||||
.erase = lfs3_kiwibd_erase,
|
||||
.sync = lfs3_kiwibd_sync,
|
||||
#endif
|
||||
#define TEST_CFG(k, v) \
|
||||
.k = v,
|
||||
#include "test_defines.h"
|
||||
#undef TEST_CFG
|
||||
};
|
||||
|
||||
// using emubd?
|
||||
#ifndef TEST_KIWIBD
|
||||
struct lfs3_emubd_cfg bdcfg = {
|
||||
.read_sleep = test_read_sleep,
|
||||
.prog_sleep = test_prog_sleep,
|
||||
@@ -1330,10 +1363,29 @@ static void run_powerloss_none(
|
||||
|
||||
int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not create block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not create emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// using kiwibd?
|
||||
#else
|
||||
struct lfs3_kiwibd_cfg bdcfg = {
|
||||
.read_sleep = test_read_sleep,
|
||||
.prog_sleep = test_prog_sleep,
|
||||
.erase_sleep = test_erase_sleep,
|
||||
#define TEST_BDCFG(k, v) \
|
||||
.k = v,
|
||||
#include "test_defines.h"
|
||||
#undef TEST_CFG
|
||||
};
|
||||
|
||||
int err = lfs3_kiwibd_createcfg(&cfg, test_disk_path, &bdcfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not create kiwibd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// run the test
|
||||
printf("running ");
|
||||
perm_printid(suite, case_, NULL, 0);
|
||||
@@ -1349,18 +1401,29 @@ static void run_powerloss_none(
|
||||
printf("\n");
|
||||
|
||||
// cleanup
|
||||
#ifndef TEST_KIWIBD
|
||||
err = lfs3_emubd_destroy(&cfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not destroy block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not destroy emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
err = lfs3_kiwibd_destroy(&cfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not destroy kiwibd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef TEST_KIWIBD
|
||||
static void powerloss_longjmp(void *c) {
|
||||
jmp_buf *powerloss_jmp = c;
|
||||
longjmp(*powerloss_jmp, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TEST_KIWIBD
|
||||
static void run_powerloss_linear(
|
||||
const test_powerloss_t *powerloss,
|
||||
const struct test_suite *suite,
|
||||
@@ -1401,7 +1464,7 @@ static void run_powerloss_linear(
|
||||
|
||||
int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not create block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not create emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -1438,11 +1501,13 @@ static void run_powerloss_linear(
|
||||
// cleanup
|
||||
err = lfs3_emubd_destroy(&cfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not destroy block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not destroy emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TEST_KIWIBD
|
||||
static void run_powerloss_log(
|
||||
const test_powerloss_t *powerloss,
|
||||
const struct test_suite *suite,
|
||||
@@ -1483,7 +1548,7 @@ static void run_powerloss_log(
|
||||
|
||||
int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not create block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not create emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -1520,11 +1585,13 @@ static void run_powerloss_log(
|
||||
// cleanup
|
||||
err = lfs3_emubd_destroy(&cfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not destroy block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not destroy emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TEST_KIWIBD
|
||||
static void run_powerloss_cycles(
|
||||
const test_powerloss_t *powerloss,
|
||||
const struct test_suite *suite,
|
||||
@@ -1565,7 +1632,7 @@ static void run_powerloss_cycles(
|
||||
|
||||
int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not create block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not create emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -1601,11 +1668,13 @@ static void run_powerloss_cycles(
|
||||
// cleanup
|
||||
err = lfs3_emubd_destroy(&cfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not destroy block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not destroy emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TEST_KIWIBD
|
||||
struct powerloss_exhaustive_state {
|
||||
struct lfs3_cfg *cfg;
|
||||
|
||||
@@ -1613,13 +1682,17 @@ struct powerloss_exhaustive_state {
|
||||
size_t branch_count;
|
||||
size_t branch_capacity;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef TEST_KIWIBD
|
||||
struct powerloss_exhaustive_cycles {
|
||||
lfs3_emubd_powercycles_t *cycles;
|
||||
test_powercycles_t *cycles;
|
||||
size_t cycle_count;
|
||||
size_t cycle_capacity;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef TEST_KIWIBD
|
||||
static void powerloss_exhaustive_branch(void *c) {
|
||||
struct powerloss_exhaustive_state *state = c;
|
||||
// append to branches
|
||||
@@ -1636,14 +1709,16 @@ static void powerloss_exhaustive_branch(void *c) {
|
||||
// create copy-on-write copy
|
||||
int err = lfs3_emubd_cpy(state->cfg, branch);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: exhaustive: could not create bd copy\n");
|
||||
fprintf(stderr, "error: exhaustive: could not create emubd copy\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// also trigger on next power cycle
|
||||
lfs3_emubd_setpowercycles(state->cfg, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TEST_KIWIBD
|
||||
static void run_powerloss_exhaustive_layer(
|
||||
struct powerloss_exhaustive_cycles *cycles,
|
||||
const struct test_suite *suite,
|
||||
@@ -1673,16 +1748,16 @@ static void run_powerloss_exhaustive_layer(
|
||||
// aggressively clean up memory here to try to keep our memory usage low
|
||||
int err = lfs3_emubd_destroy(cfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not destroy block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not destroy emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// recurse into each branch
|
||||
for (size_t i = 0; i < state.branch_count; i++) {
|
||||
// first push and print the branch
|
||||
lfs3_emubd_powercycles_t *cycle = mappend(
|
||||
test_powercycles_t *cycle = mappend(
|
||||
(void**)&cycles->cycles,
|
||||
sizeof(lfs3_emubd_powercycles_t),
|
||||
sizeof(test_powercycles_t),
|
||||
&cycles->cycle_count,
|
||||
&cycles->cycle_capacity);
|
||||
if (!cycle) {
|
||||
@@ -1708,7 +1783,9 @@ static void run_powerloss_exhaustive_layer(
|
||||
// clean up memory
|
||||
free(state.branches);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TEST_KIWIBD
|
||||
static void run_powerloss_exhaustive(
|
||||
const test_powerloss_t *powerloss,
|
||||
const struct test_suite *suite,
|
||||
@@ -1742,7 +1819,7 @@ static void run_powerloss_exhaustive(
|
||||
|
||||
int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg);
|
||||
if (err) {
|
||||
fprintf(stderr, "error: could not create block device: %d\n", err);
|
||||
fprintf(stderr, "error: could not create emubd: %d\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -1761,33 +1838,44 @@ static void run_powerloss_exhaustive(
|
||||
perm_printid(suite, case_, NULL, 0);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
const test_powerloss_t builtin_powerlosses[] = {
|
||||
{"none", run_powerloss_none, NULL, 0},
|
||||
#ifndef TEST_KIWIBD
|
||||
{"log", run_powerloss_log, NULL, SIZE_MAX},
|
||||
{"linear", run_powerloss_linear, NULL, SIZE_MAX},
|
||||
{"exhaustive", run_powerloss_exhaustive, NULL, SIZE_MAX},
|
||||
#endif
|
||||
{NULL, NULL, NULL, 0},
|
||||
};
|
||||
|
||||
const char *const builtin_powerlosses_help[] = {
|
||||
"Run with no power-losses.",
|
||||
"Run with exponentially-decreasing power-losses.",
|
||||
"Run with linearly-decreasing power-losses.",
|
||||
"Run a all permutations of power-losses, this may take a while.",
|
||||
"Run a all permutations of n power-losses.",
|
||||
"Run a custom comma-separated set of power-losses.",
|
||||
"Run a custom leb16-encoded set of power-losses.",
|
||||
"Run with no powerlosses.",
|
||||
#ifndef TEST_KIWIBD
|
||||
"Run with exponentially-decreasing powerlosses.",
|
||||
"Run with linearly-decreasing powerlosses.",
|
||||
"Run all powerloss permutations, this may take a while.",
|
||||
"Run all permutations of n powerlosses.",
|
||||
"Run custom comma-separated set of powerlosses.",
|
||||
"Run custom leb16-encoded set of powerlosses.",
|
||||
#endif
|
||||
};
|
||||
|
||||
// default to -Pnone,linear, which provides a good heuristic while still
|
||||
// running quickly
|
||||
const test_powerloss_t *test_powerlosses = (const test_powerloss_t[]){
|
||||
{"none", run_powerloss_none, NULL, 0},
|
||||
#ifndef TEST_KIWIBD
|
||||
{"linear", run_powerloss_linear, NULL, SIZE_MAX},
|
||||
#endif
|
||||
};
|
||||
#ifndef TEST_KIWIBD
|
||||
size_t test_powerloss_count = 2;
|
||||
#else
|
||||
size_t test_powerloss_count = 1;
|
||||
#endif
|
||||
|
||||
static void list_powerlosses(void) {
|
||||
// at least size so that names fit
|
||||
@@ -1810,9 +1898,11 @@ static void list_powerlosses(void) {
|
||||
}
|
||||
|
||||
// a couple more options with special parsing
|
||||
printf("%-*s %s\n", name_width, "1,2,3", builtin_powerlosses_help[i+0]);
|
||||
printf("%-*s %s\n", name_width, "{1,2,3}", builtin_powerlosses_help[i+1]);
|
||||
printf("%-*s %s\n", name_width, ":1248g1", builtin_powerlosses_help[i+2]);
|
||||
#ifndef TEST_KIWIBD
|
||||
printf("%-*s %s\n", name_width, "1,2,3", builtin_powerlosses_help[i++]);
|
||||
printf("%-*s %s\n", name_width, "{1,2,3}", builtin_powerlosses_help[i++]);
|
||||
printf("%-*s %s\n", name_width, ":1248g1", builtin_powerlosses_help[i++]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -2263,17 +2353,18 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
// comma-separated permutation
|
||||
#ifndef TEST_KIWIBD
|
||||
if (*optarg == '{') {
|
||||
lfs3_emubd_powercycles_t *cycles = NULL;
|
||||
test_powercycles_t *cycles = NULL;
|
||||
size_t cycle_count = 0;
|
||||
size_t cycle_capacity = 0;
|
||||
|
||||
char *s = optarg + 1;
|
||||
while (true) {
|
||||
parsed = NULL;
|
||||
*(lfs3_emubd_powercycles_t*)mappend(
|
||||
*(test_powercycles_t*)mappend(
|
||||
(void**)&cycles,
|
||||
sizeof(lfs3_emubd_powercycles_t),
|
||||
sizeof(test_powercycles_t),
|
||||
&cycle_count,
|
||||
&cycle_capacity)
|
||||
= strtoumax(s, &parsed, 0);
|
||||
@@ -2298,8 +2389,10 @@ int main(int argc, char **argv) {
|
||||
optarg = s;
|
||||
goto powerloss_next;
|
||||
}
|
||||
#endif
|
||||
|
||||
// leb16-encoded permutation
|
||||
#ifndef TEST_KIWIBD
|
||||
if (*optarg == ':') {
|
||||
// special case for linear power cycles
|
||||
if (optarg[1] == 'x') {
|
||||
@@ -2325,7 +2418,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
// otherwise explicit power cycles
|
||||
} else {
|
||||
lfs3_emubd_powercycles_t *cycles = NULL;
|
||||
test_powercycles_t *cycles = NULL;
|
||||
size_t cycle_count = 0;
|
||||
size_t cycle_capacity = 0;
|
||||
|
||||
@@ -2337,9 +2430,9 @@ int main(int argc, char **argv) {
|
||||
break;
|
||||
}
|
||||
|
||||
*(lfs3_emubd_powercycles_t*)mappend(
|
||||
*(test_powercycles_t*)mappend(
|
||||
(void**)&cycles,
|
||||
sizeof(lfs3_emubd_powercycles_t),
|
||||
sizeof(test_powercycles_t),
|
||||
&cycle_count,
|
||||
&cycle_capacity) = x;
|
||||
s = parsed;
|
||||
@@ -2354,8 +2447,10 @@ int main(int argc, char **argv) {
|
||||
goto powerloss_next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// exhaustive permutations
|
||||
#ifndef TEST_KIWIBD
|
||||
{
|
||||
parsed = NULL;
|
||||
size_t count = strtoumax(optarg, &parsed, 0);
|
||||
@@ -2370,6 +2465,7 @@ int main(int argc, char **argv) {
|
||||
optarg = (char*)parsed;
|
||||
goto powerloss_next;
|
||||
}
|
||||
#endif
|
||||
|
||||
powerloss_unknown:;
|
||||
// unknown scenario?
|
||||
@@ -2580,6 +2676,7 @@ getopt_done:;
|
||||
}
|
||||
|
||||
// special case for linear power cycles
|
||||
#ifndef TEST_KIWIBD
|
||||
if (cycles_ && *cycles_ == 'x') {
|
||||
char *parsed = NULL;
|
||||
size_t cycle_count = leb16_parse(cycles_+1, &parsed);
|
||||
@@ -2618,14 +2715,14 @@ getopt_done:;
|
||||
// otherwise explicit power cycles
|
||||
} else if (cycles_) {
|
||||
// parse power cycles
|
||||
lfs3_emubd_powercycles_t *cycles = NULL;
|
||||
test_powercycles_t *cycles = NULL;
|
||||
size_t cycle_count = 0;
|
||||
size_t cycle_capacity = 0;
|
||||
while (*cycles_ != '\0') {
|
||||
char *parsed = NULL;
|
||||
*(lfs3_emubd_powercycles_t*)mappend(
|
||||
*(test_powercycles_t*)mappend(
|
||||
(void**)&cycles,
|
||||
sizeof(lfs3_emubd_powercycles_t),
|
||||
sizeof(test_powercycles_t),
|
||||
&cycle_count,
|
||||
&cycle_capacity)
|
||||
= leb16_parse(cycles_, &parsed);
|
||||
@@ -2644,6 +2741,7 @@ getopt_done:;
|
||||
cycles,
|
||||
cycle_count};
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// append to identifier list
|
||||
|
||||
@@ -8,6 +8,23 @@
|
||||
#define TEST_RUNNER_H
|
||||
|
||||
|
||||
// default to using emubd for tests
|
||||
#if !defined(TEST_EMUBD) && !defined(TEST_KIWIBD)
|
||||
#define TEST_EMUBD
|
||||
#endif
|
||||
|
||||
// ifdef macros for emubd vs kiwibd
|
||||
#ifdef TEST_EMUBD
|
||||
#define TEST_IFDEF_EMUBD(a, b) (a)
|
||||
#else
|
||||
#define TEST_IFDEF_EMUBD(a, b) (b)
|
||||
#endif
|
||||
#ifdef TEST_KIWIBD
|
||||
#define TEST_IFDEF_KIWIBD(a, b) (a)
|
||||
#else
|
||||
#define TEST_IFDEF_KIWIBD(a, b) (b)
|
||||
#endif
|
||||
|
||||
// override LFS3_TRACE
|
||||
void test_trace(const char *fmt, ...);
|
||||
|
||||
@@ -18,11 +35,18 @@ void test_trace(const char *fmt, ...);
|
||||
__VA_ARGS__)
|
||||
#define LFS3_TRACE(...) LFS3_TRACE_(__VA_ARGS__, "")
|
||||
#define LFS3_EMUBD_TRACE(...) LFS3_TRACE_(__VA_ARGS__, "")
|
||||
#define LFS3_KIWIBD_TRACE(...) LFS3_TRACE_(__VA_ARGS__, "")
|
||||
|
||||
|
||||
// note these are indirectly included in any generated files
|
||||
#ifndef TEST_KIWIBD
|
||||
#include "bd/lfs3_emubd.h"
|
||||
#else
|
||||
#include "bd/lfs3_kiwibd.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// give source a chance to define feature macros
|
||||
#undef _FEATURES_H
|
||||
|
||||
Reference in New Issue
Block a user