1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
| | /*
* Copyright (C) 2012-2015 all contributors <cmogstored-public@bogomips.org>
* License: GPLv3 or later (see COPYING for details)
*/
/*
* fault injection wrapper for pwrite
*/
#include "cmogstored.h"
#include "iov_str.h"
#include <poll.h>
#include <sys/uio.h>
static sig_atomic_t pwrite_wrap_flags;
static int pwrite_slow_msec = 5000;
#define PWRITE_WRAP_NONE (0)
#define PWRITE_WRAP_SLOW (1)
#define PWRITE_WRAP_PARTIAL (1 << 1)
#define PWRITE_WRAP_ENOSPC (1 << 2)
#define PWRITE_WRAP_MAX 4
static const char * const pwrite_wrap_names[] = {
"none", "slow", "partial", "enospc"
};
#define EMIT(s) write(STDERR_FILENO, (s), sizeof(s)-1)
/* test/pwrite_wrap.rb depends on the following line */
static const char msg[] = "pwrite fault injection\n";
int __real_pwrite(int fd, void *buf, size_t count, off_t offset);
int __wrap_pwrite(int fd, void *buf, size_t count, off_t offset)
{
if (pwrite_wrap_flags & PWRITE_WRAP_SLOW) {
poll(NULL, 0, pwrite_slow_msec);
}
if ((pwrite_wrap_flags & PWRITE_WRAP_PARTIAL) && (count > 0))
count--;
if (pwrite_wrap_flags & PWRITE_WRAP_ENOSPC) {
errno = ENOSPC;
return -1;
}
return __real_pwrite(fd, buf, count, offset);
}
static void set_wrap_pwrite(int signum)
{
static sig_atomic_t pwrite_wrap_knob = 0;
struct iovec vec[3];
union { const char *in; void *out; } name;
switch (signum) {
case SIGVTALRM:
pwrite_wrap_knob = (pwrite_wrap_knob + 1) % PWRITE_WRAP_MAX;
IOV_STR(&vec[0], "knob set: ");
break;
case SIGTTIN:
pwrite_wrap_flags |= pwrite_wrap_knob;
IOV_STR(&vec[0], "flag set: ");
break;
case SIGTTOU:
pwrite_wrap_flags ^= pwrite_wrap_knob;
IOV_STR(&vec[0], "flag clr: ");
break;
default: assert(0 && "unknown signal caught");
}
name.in = pwrite_wrap_names[pwrite_wrap_knob];
vec[1].iov_base = name.out;
vec[1].iov_len = strlen(name.in);
IOV_STR(&vec[2], "\n");
writev(STDERR_FILENO, vec, 3);
}
__attribute__((constructor)) void pwrite_wrap_init(void)
{
struct sigaction sa;
const char slow_env[] = "PWRITE_WRAP_SLOW_MSEC";
const char *msec = getenv(slow_env);
memset(&sa, 0, sizeof(struct sigaction));
CHECK(int, 0, sigemptyset(&sa.sa_mask) );
sa.sa_handler = set_wrap_pwrite;
CHECK(int, 0, sigaction(SIGVTALRM, &sa, NULL));
CHECK(int, 0, sigaction(SIGTTIN, &sa, NULL));
CHECK(int, 0, sigaction(SIGTTOU, &sa, NULL));
if (msec) {
char *end;
unsigned long v = strtoul(msec, &end, 10);
if (*end || v > INT_MAX)
die("Invalid %s=%s", slow_env, msec);
pwrite_slow_msec = v;
fprintf(stderr, "set %s=%d\n", slow_env, pwrite_slow_msec);
}
}
|