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:
Christopher Haster
2024-05-01 15:03:38 -05:00
parent b122a50b6c
commit 5fbf073bfb
2 changed files with 22 additions and 31 deletions
+11 -18
View File
@@ -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(bd->disk->scratch, memset(scratch,
bd->cfg->erase_value, (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, ssize_t res = write(bd->disk->fd, scratch, cfg->block_size);
bd->disk->scratch,
cfg->block_size);
if (res < 0) { if (res < 0) {
int err = -errno; int err = -errno;
free(scratch);
LFS_EMUBD_TRACE("lfs_emubd_create -> %d", err); LFS_EMUBD_TRACE("lfs_emubd_create -> %d", err);
return 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
View File
@@ -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