cmogstored.git  about / heads / tags
alternative mogstored implementation for MogileFS
blob a80d5879507442434fd36d9a74c94a3f2f11d96b 2402 bytes (raw)
$ git show HEAD:test/pwrite-wrap.c	# shows this blob on the CLI

 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
 
/*
 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
 */
/*
 * 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"
};

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);
	}
}

git clone https://yhbt.net/cmogstored.git