mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-08 18:54:21 +01:00
Merge 'Add short writes to unreliable-libc' from FamHaggs
Add short writes in the faulty_libc As @PThorpe92 stated in #3209, this should be implemented here instead of the memory io in the simulator. Running this in the stress test I caught a logic bug in the try_pwritev_raw I will create a pr for that small fix. I will close #3209 in favor of this pr. Closes #3569
This commit is contained in:
@@ -7,12 +7,16 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static double probabilities[] = {
|
||||
[ENOSPC] = 0.01,
|
||||
[EIO] = 0.01,
|
||||
};
|
||||
|
||||
static double short_write_probability = 0.05; // 5% chance of a short write
|
||||
|
||||
static bool chance(double probability)
|
||||
{
|
||||
double event = drand48();
|
||||
@@ -37,6 +41,13 @@ ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
|
||||
if (libc_pwrite == NULL) {
|
||||
libc_pwrite = dlsym(RTLD_NEXT, "pwrite");
|
||||
}
|
||||
|
||||
if (count > 1 && chance(short_write_probability)) {
|
||||
size_t short_count = 1 + (lrand48() % (count - 1));
|
||||
printf("%s: injecting fault SHORT WRITE (requesting %zu instead of %zu)\n", __func__, short_count, count);
|
||||
return libc_pwrite(fd, buf, short_count, offset);
|
||||
}
|
||||
|
||||
if (inject_fault(ENOSPC)) {
|
||||
printf("%s: injecting fault NOSPC\n", __func__);
|
||||
return -1;
|
||||
@@ -55,6 +66,72 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
|
||||
if (libc_pwritev == NULL) {
|
||||
libc_pwritev = dlsym(RTLD_NEXT, "pwritev");
|
||||
}
|
||||
|
||||
/* If no vectors or invalid count, forward directly. */
|
||||
if (iov == NULL || iovcnt <= 0) {
|
||||
return libc_pwritev(fd, iov, iovcnt, offset);
|
||||
}
|
||||
|
||||
if (iovcnt > 0 && chance(short_write_probability)) {
|
||||
struct iovec iov_copy[iovcnt];
|
||||
memcpy(iov_copy, iov, sizeof(struct iovec) * iovcnt);
|
||||
|
||||
/* Compute total bytes requested (guarding against overflow). */
|
||||
size_t total = 0;
|
||||
for (int i = 0; i < iovcnt; ++i) {
|
||||
size_t len = iov_copy[i].iov_len;
|
||||
if (len > 0 && total > SIZE_MAX - len) {
|
||||
total = SIZE_MAX;
|
||||
break;
|
||||
}
|
||||
total += len;
|
||||
}
|
||||
|
||||
/* Only meaningful to short-write if total > 1. */
|
||||
if (total > 1) {
|
||||
/* Choose cutoff in [1, total-1] */
|
||||
size_t cutoff = 1 + (size_t)(lrand48() % (total - 1));
|
||||
size_t remaining = cutoff;
|
||||
|
||||
/* Walk iov_copy and reduce lengths to exactly match cutoff.
|
||||
* After the cutoff is satisfied, following iov entries will be set to 0 length.
|
||||
*/
|
||||
for (int i = 0; i < iovcnt; ++i) {
|
||||
size_t len = iov_copy[i].iov_len;
|
||||
if (len == 0) {
|
||||
/* keep zero-length entries as zero, they do not consume remaining */
|
||||
continue;
|
||||
}
|
||||
if (remaining == 0) {
|
||||
/* drop the rest */
|
||||
iov_copy[i].iov_len = 0;
|
||||
continue;
|
||||
}
|
||||
if (len <= remaining) {
|
||||
/* fully include this iovec */
|
||||
remaining -= len;
|
||||
/* keep iov_copy[i].iov_len as-is */
|
||||
} else {
|
||||
/* partial include: shorten this iovec to remaining */
|
||||
iov_copy[i].iov_len = remaining;
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute new iovcnt to avoid passing trailing zero-length iovecs */
|
||||
int new_iovcnt = iovcnt;
|
||||
while (new_iovcnt > 0 && iov_copy[new_iovcnt - 1].iov_len == 0) {
|
||||
new_iovcnt--;
|
||||
}
|
||||
/* Defensive: cutoff >= 1 so new_iovcnt should be > 0; This should always be true*/
|
||||
if (new_iovcnt > 0) {
|
||||
printf("%s: injecting fault SHORT WRITE cutoff=%zu of %zu (new_iovcnt=%d)\n",
|
||||
__func__, cutoff, total, new_iovcnt);
|
||||
return libc_pwritev(fd, iov_copy, new_iovcnt, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inject_fault(ENOSPC)) {
|
||||
printf("%s: injecting fault NOSPC\n", __func__);
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user