Cherry-picked upstream out-of-order emubd testing
More information upstream (f2a6f45,fc2aa33,7873d81), but this adds LFS_EMUBD_POWERLOS_OOO for testing out-of-order block devices that require sync to be called for things to serialize. It's a simple implementation, just reverts the first write since last sync on powerloss, but gets the job done. Cherry-picking these changes required reverting emubd's scratch buffer, but carrying around an extra ~block_size of memory isn't a big deal here.
This commit is contained in:
+139
-34
@@ -116,28 +116,34 @@ int lfs_emubd_createcfg(const struct lfs_config *cfg, const char *path,
|
|||||||
lfs_emubd_t *bd = cfg->context;
|
lfs_emubd_t *bd = cfg->context;
|
||||||
bd->cfg = bdcfg;
|
bd->cfg = bdcfg;
|
||||||
|
|
||||||
// allocate our block array, all blocks start as uninitialized
|
|
||||||
bd->blocks = malloc(cfg->block_count * sizeof(lfs_emubd_block_t*));
|
|
||||||
if (!bd->blocks) {
|
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_createcfg -> %d", LFS_ERR_NOMEM);
|
|
||||||
return LFS_ERR_NOMEM;
|
|
||||||
}
|
|
||||||
memset(bd->blocks, 0, cfg->block_count * sizeof(lfs_emubd_block_t*));
|
|
||||||
|
|
||||||
// setup testing things
|
// setup testing things
|
||||||
|
bd->blocks = NULL;
|
||||||
bd->readed = 0;
|
bd->readed = 0;
|
||||||
bd->proged = 0;
|
bd->proged = 0;
|
||||||
bd->erased = 0;
|
bd->erased = 0;
|
||||||
bd->power_cycles = bd->cfg->power_cycles;
|
bd->power_cycles = bd->cfg->power_cycles;
|
||||||
|
bd->ooo_block = -1;
|
||||||
|
bd->ooo_data = NULL;
|
||||||
bd->disk = NULL;
|
bd->disk = NULL;
|
||||||
|
|
||||||
|
// allocate our block array, all blocks start as uninitialized
|
||||||
|
bd->blocks = malloc(cfg->block_count * sizeof(lfs_emubd_block_t*));
|
||||||
|
int err;
|
||||||
|
if (!bd->blocks) {
|
||||||
|
err = LFS_ERR_NOMEM;
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
memset(bd->blocks, 0, cfg->block_count * sizeof(lfs_emubd_block_t*));
|
||||||
|
|
||||||
if (bd->cfg->disk_path) {
|
if (bd->cfg->disk_path) {
|
||||||
bd->disk = malloc(sizeof(lfs_emubd_disk_t));
|
bd->disk = malloc(sizeof(lfs_emubd_disk_t));
|
||||||
if (!bd->disk) {
|
if (!bd->disk) {
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_createcfg -> %d", LFS_ERR_NOMEM);
|
err = LFS_ERR_NOMEM;
|
||||||
return LFS_ERR_NOMEM;
|
goto failed;
|
||||||
}
|
}
|
||||||
bd->disk->rc = 1;
|
bd->disk->rc = 1;
|
||||||
|
bd->disk->fd = -1;
|
||||||
|
bd->disk->scratch = NULL;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
bd->disk->fd = open(bd->cfg->disk_path,
|
bd->disk->fd = open(bd->cfg->disk_path,
|
||||||
@@ -147,37 +153,47 @@ int lfs_emubd_createcfg(const struct lfs_config *cfg, const char *path,
|
|||||||
O_RDWR | O_CREAT, 0666);
|
O_RDWR | O_CREAT, 0666);
|
||||||
#endif
|
#endif
|
||||||
if (bd->disk->fd < 0) {
|
if (bd->disk->fd < 0) {
|
||||||
int err = -errno;
|
err = -errno;
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_create -> %d", err);
|
goto failed;
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// go ahead and erase all of the disk, otherwise the file will not
|
bd->disk->scratch = malloc(cfg->block_size);
|
||||||
// match our internal representation
|
if (!bd->disk->scratch) {
|
||||||
uint8_t *scratch = malloc(cfg->block_size);
|
err = LFS_ERR_NOMEM;
|
||||||
if (!scratch) {
|
goto failed;
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_createcfg -> %d", LFS_ERR_NOMEM);
|
|
||||||
return LFS_ERR_NOMEM;
|
|
||||||
}
|
}
|
||||||
memset(scratch,
|
memset(bd->disk->scratch,
|
||||||
(bd->cfg->erase_value != -1) ? bd->cfg->erase_value : 0,
|
(bd->cfg->erase_value != -1) ? bd->cfg->erase_value : 0,
|
||||||
cfg->block_size);
|
cfg->block_size);
|
||||||
|
|
||||||
|
// go ahead and erase all of the disk, otherwise the file will not
|
||||||
|
// match our internal representation
|
||||||
for (size_t i = 0; i < cfg->block_count; i++) {
|
for (size_t i = 0; i < cfg->block_count; i++) {
|
||||||
ssize_t res = write(bd->disk->fd, scratch, cfg->block_size);
|
ssize_t res = write(bd->disk->fd,
|
||||||
|
bd->disk->scratch,
|
||||||
|
cfg->block_size);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
int err = -errno;
|
err = -errno;
|
||||||
free(scratch);
|
goto failed;
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_create -> %d", err);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(scratch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_createcfg -> %d", 0);
|
LFS_EMUBD_TRACE("lfs_emubd_createcfg -> %d", 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
failed:;
|
||||||
|
LFS_EMUBD_TRACE("lfs_emubd_createcfg -> %d", err);
|
||||||
|
// clean up memory
|
||||||
|
free(bd->blocks);
|
||||||
|
if (bd->disk) {
|
||||||
|
if (bd->disk->fd != -1) {
|
||||||
|
close(bd->disk->fd);
|
||||||
|
}
|
||||||
|
free(bd->disk->scratch);
|
||||||
|
free(bd->disk);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lfs_emubd_create(const struct lfs_config *cfg, const char *path) {
|
int lfs_emubd_create(const struct lfs_config *cfg, const char *path) {
|
||||||
@@ -208,10 +224,12 @@ int lfs_emubd_destroy(const struct lfs_config *cfg) {
|
|||||||
free(bd->blocks);
|
free(bd->blocks);
|
||||||
|
|
||||||
// clean up other resources
|
// clean up other resources
|
||||||
|
lfs_emubd_decblock(bd->ooo_data);
|
||||||
if (bd->disk) {
|
if (bd->disk) {
|
||||||
bd->disk->rc -= 1;
|
bd->disk->rc -= 1;
|
||||||
if (bd->disk->rc == 0) {
|
if (bd->disk->rc == 0) {
|
||||||
close(bd->disk->fd);
|
close(bd->disk->fd);
|
||||||
|
free(bd->disk->scratch);
|
||||||
free(bd->disk);
|
free(bd->disk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,6 +239,71 @@ int lfs_emubd_destroy(const struct lfs_config *cfg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// powerloss hook
|
||||||
|
static int lfs_emubd_powerloss(const struct lfs_config *cfg) {
|
||||||
|
lfs_emubd_t *bd = cfg->context;
|
||||||
|
|
||||||
|
// emulate out-of-order writes?
|
||||||
|
lfs_emubd_block_t *ooo_data = NULL;
|
||||||
|
if (bd->cfg->powerloss_behavior == LFS_EMUBD_POWERLOSS_OOO
|
||||||
|
&& bd->ooo_block != -1) {
|
||||||
|
// since writes between syncs are allowed to be out-of-order, it
|
||||||
|
// shouldn't hurt to restore the first write on powerloss, right?
|
||||||
|
ooo_data = bd->blocks[bd->ooo_block];
|
||||||
|
bd->blocks[bd->ooo_block] = lfs_emubd_incblock(bd->ooo_data);
|
||||||
|
|
||||||
|
// mirror to disk file?
|
||||||
|
if (bd->disk) {
|
||||||
|
off_t res1 = lseek(bd->disk->fd,
|
||||||
|
(off_t)bd->ooo_block*cfg->block_size,
|
||||||
|
SEEK_SET);
|
||||||
|
if (res1 < 0) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t res2 = write(bd->disk->fd,
|
||||||
|
(bd->blocks[bd->ooo_block])
|
||||||
|
? bd->blocks[bd->ooo_block]->data
|
||||||
|
: bd->disk->scratch,
|
||||||
|
cfg->block_size);
|
||||||
|
if (res2 < 0) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// simulate power loss
|
||||||
|
bd->cfg->powerloss_cb(bd->cfg->powerloss_data);
|
||||||
|
|
||||||
|
// if we continue, undo out-of-order write emulation
|
||||||
|
if (bd->cfg->powerloss_behavior == LFS_EMUBD_POWERLOSS_OOO
|
||||||
|
&& bd->ooo_block != -1) {
|
||||||
|
lfs_emubd_decblock(bd->blocks[bd->ooo_block]);
|
||||||
|
bd->blocks[bd->ooo_block] = ooo_data;
|
||||||
|
|
||||||
|
// mirror to disk file?
|
||||||
|
if (bd->disk) {
|
||||||
|
off_t res1 = lseek(bd->disk->fd,
|
||||||
|
(off_t)bd->ooo_block*cfg->block_size,
|
||||||
|
SEEK_SET);
|
||||||
|
if (res1 < 0) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t res2 = write(bd->disk->fd,
|
||||||
|
(bd->blocks[bd->ooo_block])
|
||||||
|
? bd->blocks[bd->ooo_block]->data
|
||||||
|
: bd->disk->scratch,
|
||||||
|
cfg->block_size);
|
||||||
|
if (res2 < 0) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// block device API
|
// block device API
|
||||||
|
|
||||||
@@ -356,8 +439,11 @@ int lfs_emubd_prog(const struct lfs_config *cfg, lfs_block_t block,
|
|||||||
if (bd->power_cycles > 0) {
|
if (bd->power_cycles > 0) {
|
||||||
bd->power_cycles -= 1;
|
bd->power_cycles -= 1;
|
||||||
if (bd->power_cycles == 0) {
|
if (bd->power_cycles == 0) {
|
||||||
// simulate power loss
|
int err = lfs_emubd_powerloss(cfg);
|
||||||
bd->cfg->powerloss_cb(bd->cfg->powerloss_data);
|
if (err) {
|
||||||
|
LFS_EMUBD_TRACE("lfs_emubd_prog -> %d", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,10 +459,17 @@ int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
|||||||
// check if erase is valid
|
// check if erase is valid
|
||||||
LFS_ASSERT(block < cfg->block_count);
|
LFS_ASSERT(block < cfg->block_count);
|
||||||
|
|
||||||
|
// emulate out-of-order writes? save first write
|
||||||
|
if (bd->cfg->powerloss_behavior == LFS_EMUBD_POWERLOSS_OOO
|
||||||
|
&& bd->ooo_block == -1) {
|
||||||
|
bd->ooo_block = block;
|
||||||
|
bd->ooo_data = lfs_emubd_incblock(bd->blocks[block]);
|
||||||
|
}
|
||||||
|
|
||||||
// get the block
|
// get the block
|
||||||
lfs_emubd_block_t *b = lfs_emubd_mutblock(cfg, &bd->blocks[block]);
|
lfs_emubd_block_t *b = lfs_emubd_mutblock(cfg, &bd->blocks[block]);
|
||||||
if (!b) {
|
if (!b) {
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_prog -> %d", LFS_ERR_NOMEM);
|
LFS_EMUBD_TRACE("lfs_emubd_erase -> %d", LFS_ERR_NOMEM);
|
||||||
return LFS_ERR_NOMEM;
|
return LFS_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,8 +533,11 @@ int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
|||||||
if (bd->power_cycles > 0) {
|
if (bd->power_cycles > 0) {
|
||||||
bd->power_cycles -= 1;
|
bd->power_cycles -= 1;
|
||||||
if (bd->power_cycles == 0) {
|
if (bd->power_cycles == 0) {
|
||||||
// simulate power loss
|
int err = lfs_emubd_powerloss(cfg);
|
||||||
bd->cfg->powerloss_cb(bd->cfg->powerloss_data);
|
if (err) {
|
||||||
|
LFS_EMUBD_TRACE("lfs_emubd_erase -> %d", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,14 +547,21 @@ int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
|||||||
|
|
||||||
int lfs_emubd_sync(const struct lfs_config *cfg) {
|
int lfs_emubd_sync(const struct lfs_config *cfg) {
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_sync(%p)", (void*)cfg);
|
LFS_EMUBD_TRACE("lfs_emubd_sync(%p)", (void*)cfg);
|
||||||
|
lfs_emubd_t *bd = cfg->context;
|
||||||
|
|
||||||
// do nothing
|
// emulate out-of-order writes? reset first write, writes
|
||||||
(void)cfg;
|
// cannot be out-of-order across sync
|
||||||
|
if (bd->cfg->powerloss_behavior == LFS_EMUBD_POWERLOSS_OOO) {
|
||||||
|
lfs_emubd_decblock(bd->ooo_data);
|
||||||
|
bd->ooo_block = -1;
|
||||||
|
bd->ooo_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_sync -> %d", 0);
|
LFS_EMUBD_TRACE("lfs_emubd_sync -> %d", 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Additional extended API for driving test features ///
|
/// Additional extended API for driving test features ///
|
||||||
|
|
||||||
static int lfs_emubd_rawcksum(const struct lfs_config *cfg,
|
static int lfs_emubd_rawcksum(const struct lfs_config *cfg,
|
||||||
@@ -643,6 +746,8 @@ int lfs_emubd_copy(const struct lfs_config *cfg, lfs_emubd_t *copy) {
|
|||||||
copy->proged = bd->proged;
|
copy->proged = bd->proged;
|
||||||
copy->erased = bd->erased;
|
copy->erased = bd->erased;
|
||||||
copy->power_cycles = bd->power_cycles;
|
copy->power_cycles = bd->power_cycles;
|
||||||
|
copy->ooo_block = bd->ooo_block;
|
||||||
|
copy->ooo_data = lfs_emubd_incblock(bd->ooo_data);
|
||||||
copy->disk = bd->disk;
|
copy->disk = bd->disk;
|
||||||
if (copy->disk) {
|
if (copy->disk) {
|
||||||
copy->disk->rc += 1;
|
copy->disk->rc += 1;
|
||||||
|
|||||||
+10
-6
@@ -36,17 +36,18 @@ extern "C"
|
|||||||
// Not that read-noop is not allowed. Read _must_ return a consistent (but
|
// Not that read-noop is not allowed. Read _must_ return a consistent (but
|
||||||
// may be arbitrary) value on every read.
|
// may be arbitrary) value on every read.
|
||||||
typedef enum lfs_emubd_badblock_behavior {
|
typedef enum lfs_emubd_badblock_behavior {
|
||||||
LFS_EMUBD_BADBLOCK_PROGERROR,
|
LFS_EMUBD_BADBLOCK_PROGERROR = 0, // Error on prog
|
||||||
LFS_EMUBD_BADBLOCK_ERASEERROR,
|
LFS_EMUBD_BADBLOCK_ERASEERROR = 1, // Error on erase
|
||||||
LFS_EMUBD_BADBLOCK_READERROR,
|
LFS_EMUBD_BADBLOCK_READERROR = 2, // Error on read
|
||||||
LFS_EMUBD_BADBLOCK_PROGNOOP,
|
LFS_EMUBD_BADBLOCK_PROGNOOP = 3, // Prog does nothing silently
|
||||||
LFS_EMUBD_BADBLOCK_ERASENOOP,
|
LFS_EMUBD_BADBLOCK_ERASENOOP = 4, // Erase does nothing silently
|
||||||
} lfs_emubd_badblock_behavior_t;
|
} lfs_emubd_badblock_behavior_t;
|
||||||
|
|
||||||
// Mode determining how power-loss behaves during testing. For now this
|
// Mode determining how power-loss behaves during testing. For now this
|
||||||
// only supports a noop behavior, leaving the data on-disk untouched.
|
// only supports a noop behavior, leaving the data on-disk untouched.
|
||||||
typedef enum lfs_emubd_powerloss_behavior {
|
typedef enum lfs_emubd_powerloss_behavior {
|
||||||
LFS_EMUBD_POWERLOSS_NOOP,
|
LFS_EMUBD_POWERLOSS_NOOP = 0, // Progs are atomic
|
||||||
|
LFS_EMUBD_POWERLOSS_OOO = 1, // Blocks are written out-of-order
|
||||||
} lfs_emubd_powerloss_behavior_t;
|
} lfs_emubd_powerloss_behavior_t;
|
||||||
|
|
||||||
// Type for measuring read/program/erase operations
|
// Type for measuring read/program/erase operations
|
||||||
@@ -126,6 +127,7 @@ typedef struct lfs_emubd_block {
|
|||||||
typedef struct lfs_emubd_disk {
|
typedef struct lfs_emubd_disk {
|
||||||
uint32_t rc;
|
uint32_t rc;
|
||||||
int fd;
|
int fd;
|
||||||
|
uint8_t *scratch;
|
||||||
} lfs_emubd_disk_t;
|
} lfs_emubd_disk_t;
|
||||||
|
|
||||||
// emubd state
|
// emubd state
|
||||||
@@ -138,6 +140,8 @@ typedef struct lfs_emubd {
|
|||||||
lfs_emubd_io_t proged;
|
lfs_emubd_io_t proged;
|
||||||
lfs_emubd_io_t erased;
|
lfs_emubd_io_t erased;
|
||||||
lfs_emubd_powercycles_t power_cycles;
|
lfs_emubd_powercycles_t power_cycles;
|
||||||
|
lfs_ssize_t ooo_block;
|
||||||
|
lfs_emubd_block_t *ooo_data;
|
||||||
lfs_emubd_disk_t *disk;
|
lfs_emubd_disk_t *disk;
|
||||||
|
|
||||||
const struct lfs_emubd_config *cfg;
|
const struct lfs_emubd_config *cfg;
|
||||||
|
|||||||
@@ -157,7 +157,8 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size);
|
|||||||
#define BENCH_BDCFG \
|
#define BENCH_BDCFG \
|
||||||
.erase_value = ERASE_VALUE, \
|
.erase_value = ERASE_VALUE, \
|
||||||
.erase_cycles = ERASE_CYCLES, \
|
.erase_cycles = ERASE_CYCLES, \
|
||||||
.badblock_behavior = BADBLOCK_BEHAVIOR,
|
.badblock_behavior = BADBLOCK_BEHAVIOR, \
|
||||||
|
.powerloss_behavior = POWERLOSS_BEHAVIOR,
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1379,7 +1379,6 @@ static void run_powerloss_linear(
|
|||||||
.power_cycles = (TEST_PLS < powerloss->cycle_count)
|
.power_cycles = (TEST_PLS < powerloss->cycle_count)
|
||||||
? TEST_PLS+1
|
? TEST_PLS+1
|
||||||
: 0,
|
: 0,
|
||||||
.powerloss_behavior = POWERLOSS_BEHAVIOR,
|
|
||||||
.powerloss_cb = powerloss_longjmp,
|
.powerloss_cb = powerloss_longjmp,
|
||||||
.powerloss_data = &powerloss_jmp,
|
.powerloss_data = &powerloss_jmp,
|
||||||
TEST_BDCFG
|
TEST_BDCFG
|
||||||
@@ -1457,7 +1456,6 @@ static void run_powerloss_log(
|
|||||||
.power_cycles = (TEST_PLS < powerloss->cycle_count)
|
.power_cycles = (TEST_PLS < powerloss->cycle_count)
|
||||||
? 1 << TEST_PLS
|
? 1 << TEST_PLS
|
||||||
: 0,
|
: 0,
|
||||||
.powerloss_behavior = POWERLOSS_BEHAVIOR,
|
|
||||||
.powerloss_cb = powerloss_longjmp,
|
.powerloss_cb = powerloss_longjmp,
|
||||||
.powerloss_data = &powerloss_jmp,
|
.powerloss_data = &powerloss_jmp,
|
||||||
TEST_BDCFG
|
TEST_BDCFG
|
||||||
@@ -1535,7 +1533,6 @@ static void run_powerloss_cycles(
|
|||||||
.power_cycles = (TEST_PLS < powerloss->cycle_count)
|
.power_cycles = (TEST_PLS < powerloss->cycle_count)
|
||||||
? powerloss->cycles[TEST_PLS]
|
? powerloss->cycles[TEST_PLS]
|
||||||
: 0,
|
: 0,
|
||||||
.powerloss_behavior = POWERLOSS_BEHAVIOR,
|
|
||||||
.powerloss_cb = powerloss_longjmp,
|
.powerloss_cb = powerloss_longjmp,
|
||||||
.powerloss_data = &powerloss_jmp,
|
.powerloss_data = &powerloss_jmp,
|
||||||
TEST_BDCFG
|
TEST_BDCFG
|
||||||
@@ -1708,7 +1705,6 @@ static void run_powerloss_exhaustive(
|
|||||||
.read_sleep = test_read_sleep,
|
.read_sleep = test_read_sleep,
|
||||||
.prog_sleep = test_prog_sleep,
|
.prog_sleep = test_prog_sleep,
|
||||||
.erase_sleep = test_erase_sleep,
|
.erase_sleep = test_erase_sleep,
|
||||||
.powerloss_behavior = POWERLOSS_BEHAVIOR,
|
|
||||||
.powerloss_cb = powerloss_exhaustive_branch,
|
.powerloss_cb = powerloss_exhaustive_branch,
|
||||||
.powerloss_data = NULL,
|
.powerloss_data = NULL,
|
||||||
TEST_BDCFG
|
TEST_BDCFG
|
||||||
|
|||||||
@@ -142,7 +142,8 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size);
|
|||||||
#define TEST_BDCFG \
|
#define TEST_BDCFG \
|
||||||
.erase_value = ERASE_VALUE, \
|
.erase_value = ERASE_VALUE, \
|
||||||
.erase_cycles = ERASE_CYCLES, \
|
.erase_cycles = ERASE_CYCLES, \
|
||||||
.badblock_behavior = BADBLOCK_BEHAVIOR,
|
.badblock_behavior = BADBLOCK_BEHAVIOR, \
|
||||||
|
.powerloss_behavior = POWERLOSS_BEHAVIOR,
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user