storage/stream/flash: Failed write of reminder rewinds buffer offset
The stream_flash_buffered_write, when invoked to do flush write, will attempt to write the tail bytes from the buffer, filling the required minimal write block size with erase value bytes; after write it rewinds the buffer offset, bytes_written, by number of the "filler bytes". Doe to lack of return code processing from flash_sync call, two things would happen to context in case of failure: 1) the ctx->bytes_written would be rewind pass the value it had before function call as it gets decremented by "filler bytes" even if write failed; 2) the ctx->buf_bytes offset would be accounting for added "filler bytes" which should not be counted as data in buffer. Proper processing of return code has been added to remove effects described above. Unit tests have been expended to cover the scenarios. Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
This commit is contained in:
parent
07107f92c7
commit
32451230e2
2 changed files with 29 additions and 1 deletions
|
@ -161,7 +161,11 @@ int stream_flash_buffered_write(struct stream_flash_ctx *ctx, const uint8_t *dat
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = flash_sync(ctx);
|
rc = flash_sync(ctx);
|
||||||
ctx->bytes_written -= fill_length;
|
if (rc == 0) {
|
||||||
|
ctx->bytes_written -= fill_length;
|
||||||
|
} else {
|
||||||
|
ctx->buf_bytes -= fill_length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -280,6 +280,11 @@ static int fake_write(const struct device *dev, off_t off, const void *data, siz
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bad_write(const struct device *dev, off_t off, const void *data, size_t len)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static void test_stream_flash_buffered_write_callback(void)
|
static void test_stream_flash_buffered_write_callback(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -338,6 +343,25 @@ static void test_stream_flash_buffered_write_callback(void)
|
||||||
zassert_equal(rc, -EINVAL, "expected failure from flash_sync", rc);
|
zassert_equal(rc, -EINVAL, "expected failure from flash_sync", rc);
|
||||||
zassert_equal(ctx.buf_bytes, BUF_LEN, "Expected bytes to be left in buffer");
|
zassert_equal(ctx.buf_bytes, BUF_LEN, "Expected bytes to be left in buffer");
|
||||||
|
|
||||||
|
/* Pretend flashed context and attempt write write block - 1 bytes to trigger unaligned
|
||||||
|
* write; the write needs to fail so that we could check that context does not get modified.
|
||||||
|
*/
|
||||||
|
fake_api.write = bad_write;
|
||||||
|
bad_ctx.callback = NULL;
|
||||||
|
bad_ctx.buf_bytes = 0;
|
||||||
|
cmp_ctx = bad_ctx;
|
||||||
|
size_t wblock = flash_get_write_block_size(ctx.fdev);
|
||||||
|
size_t tow = (wblock == 1) ? 1 : wblock - 1;
|
||||||
|
|
||||||
|
rc = stream_flash_buffered_write(&bad_ctx, write_buf, tow, true);
|
||||||
|
zassert_equal(rc, -EINVAL, "expected failure from flash_sync", rc);
|
||||||
|
zassert_equal(cmp_ctx.bytes_written, bad_ctx.bytes_written,
|
||||||
|
"Expected bytes_written not modified");
|
||||||
|
/* The write failed but bytes have already been added to buffer and buffer offset
|
||||||
|
* increased.
|
||||||
|
*/
|
||||||
|
zassert_equal(bad_ctx.buf_bytes, cmp_ctx.buf_bytes + tow,
|
||||||
|
"Expected %d bytes added to buffer", tow);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_stream_flash_flush(void)
|
static void test_stream_flash_flush(void)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue