Fixed issue in emubd where noop erases start out-of-sync with disk
Because reproducibility is extremely important, emubd always zeros blocks on the first erase, even when erase_value=-1. Well, at least it should be. We were correctly zeroing the blocks in RAM, but if erase_value=-1 we were leaving the disk unzeroed, causing the disk to fall out of sync. Fixed by zeroing disk in lfs_emubd_createcfg, even if erase_value=-1. Also I went ahead and dropped the bd->disk->scratch block. We're already allocating RAM-backed blocks on erase anyways, so keeping scratch around doesn't really gain us anything anymore. Now there is just a temporary allocation in lfs_emubd_createcfg to zero the disk efficiently during initialization.
This commit is contained in:
+20
-27
@@ -138,7 +138,6 @@ int lfs_emubd_createcfg(const struct lfs_config *cfg, const char *path,
|
|||||||
return LFS_ERR_NOMEM;
|
return LFS_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
bd->disk->rc = 1;
|
bd->disk->rc = 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,
|
||||||
@@ -153,31 +152,28 @@ int lfs_emubd_createcfg(const struct lfs_config *cfg, const char *path,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're emulating erase values, we can keep a block around in
|
// go ahead and erase all of the disk, otherwise the file will not
|
||||||
// memory of just the erase state to speed up emulated erases
|
// match our internal representation
|
||||||
if (bd->cfg->erase_value != -1) {
|
uint8_t *scratch = malloc(cfg->block_size);
|
||||||
bd->disk->scratch = malloc(cfg->block_size);
|
if (!scratch) {
|
||||||
if (!bd->disk->scratch) {
|
LFS_EMUBD_TRACE("lfs_emubd_createcfg -> %d", LFS_ERR_NOMEM);
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_createcfg -> %d", LFS_ERR_NOMEM);
|
return 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,
|
cfg->block_size);
|
||||||
cfg->block_size);
|
|
||||||
|
|
||||||
// go ahead and erase all of the disk, otherwise the file will not
|
for (size_t i = 0; i < cfg->block_count; i++) {
|
||||||
// match our internal representation
|
ssize_t res = write(bd->disk->fd, scratch, cfg->block_size);
|
||||||
for (size_t i = 0; i < cfg->block_count; i++) {
|
if (res < 0) {
|
||||||
ssize_t res = write(bd->disk->fd,
|
int err = -errno;
|
||||||
bd->disk->scratch,
|
free(scratch);
|
||||||
cfg->block_size);
|
LFS_EMUBD_TRACE("lfs_emubd_create -> %d", err);
|
||||||
if (res < 0) {
|
return err;
|
||||||
int err = -errno;
|
|
||||||
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);
|
||||||
@@ -216,7 +212,6 @@ int lfs_emubd_destroy(const struct lfs_config *cfg) {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,9 +413,7 @@ int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t res2 = write(bd->disk->fd,
|
ssize_t res2 = write(bd->disk->fd, b->data, cfg->block_size);
|
||||||
bd->disk->scratch,
|
|
||||||
cfg->block_size);
|
|
||||||
if (res2 < 0) {
|
if (res2 < 0) {
|
||||||
int err = -errno;
|
int err = -errno;
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_erase -> %d", err);
|
LFS_EMUBD_TRACE("lfs_emubd_erase -> %d", err);
|
||||||
|
|||||||
+2
-4
@@ -67,9 +67,8 @@ typedef int64_t lfs_emubd_ssleep_t;
|
|||||||
|
|
||||||
// emubd config, this is required for testing
|
// emubd config, this is required for testing
|
||||||
struct lfs_emubd_config {
|
struct lfs_emubd_config {
|
||||||
// 8-bit erase value to use for simulating erases. -1 does not simulate
|
// 8-bit erase value to use for simulating erases. -1 simulates a noop
|
||||||
// erases, which can speed up testing by avoiding the extra block-device
|
// erase, which is faster than simulating a fixed erase value.
|
||||||
// operations to store the erase value.
|
|
||||||
int32_t erase_value;
|
int32_t erase_value;
|
||||||
|
|
||||||
// Number of erase cycles before a block becomes "bad". The exact behavior
|
// Number of erase cycles before a block becomes "bad". The exact behavior
|
||||||
@@ -127,7 +126,6 @@ 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
|
||||||
|
|||||||
Reference in New Issue
Block a user