ia64/xen-unstable

view tools/xenstore/xs_crashme.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents b3a255e88810
children
line source
1 /* Code which randomly corrupts bits going to the daemon.
2 Copyright (C) 2005 Rusty Russell IBM Corporation
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 #include <stdbool.h>
19 #include <stdio.h>
20 #include <sys/types.h>
21 #include <stdarg.h>
22 #include <string.h>
23 #include <sys/time.h>
24 #include "xs.h"
25 #include "talloc.h"
26 #include <errno.h>
28 #define XSTEST
29 #define RAND_FREQ 128 /* One char in 32 is corrupted. */
31 /* jhash.h: Jenkins hash support.
32 *
33 * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
34 *
35 * http://burtleburtle.net/bob/hash/
36 *
37 * These are the credits from Bob's sources:
38 *
39 * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
40 * hash(), hash2(), hash3, and mix() are externally useful functions.
41 * Routines to test the hash are included if SELF_TEST is defined.
42 * You can use this free for any purpose. It has no warranty.
43 *
44 * Copyright (C) 2003 David S. Miller (davem@redhat.com)
45 *
46 * I've modified Bob's hash to be useful in the Linux kernel, and
47 * any bugs present are surely my fault. -DaveM
48 */
50 /* NOTE: Arguments are modified. */
51 #define __jhash_mix(a, b, c) \
52 { \
53 a -= b; a -= c; a ^= (c>>13); \
54 b -= c; b -= a; b ^= (a<<8); \
55 c -= a; c -= b; c ^= (b>>13); \
56 a -= b; a -= c; a ^= (c>>12); \
57 b -= c; b -= a; b ^= (a<<16); \
58 c -= a; c -= b; c ^= (b>>5); \
59 a -= b; a -= c; a ^= (c>>3); \
60 b -= c; b -= a; b ^= (a<<10); \
61 c -= a; c -= b; c ^= (b>>15); \
62 }
64 /* The golden ration: an arbitrary value */
65 #define JHASH_GOLDEN_RATIO 0x9e3779b9
67 /* The most generic version, hashes an arbitrary sequence
68 * of bytes. No alignment or length assumptions are made about
69 * the input key.
70 */
71 static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
72 {
73 uint32_t a, b, c, len;
74 const uint8_t *k = key;
76 len = length;
77 a = b = JHASH_GOLDEN_RATIO;
78 c = initval;
80 while (len >= 12) {
81 a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24));
82 b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24));
83 c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24));
85 __jhash_mix(a,b,c);
87 k += 12;
88 len -= 12;
89 }
91 c += length;
92 switch (len) {
93 case 11: c += ((uint32_t)k[10]<<24);
94 case 10: c += ((uint32_t)k[9]<<16);
95 case 9 : c += ((uint32_t)k[8]<<8);
96 case 8 : b += ((uint32_t)k[7]<<24);
97 case 7 : b += ((uint32_t)k[6]<<16);
98 case 6 : b += ((uint32_t)k[5]<<8);
99 case 5 : b += k[4];
100 case 4 : a += ((uint32_t)k[3]<<24);
101 case 3 : a += ((uint32_t)k[2]<<16);
102 case 2 : a += ((uint32_t)k[1]<<8);
103 case 1 : a += k[0];
104 };
106 __jhash_mix(a,b,c);
108 return c;
109 }
111 /* A special optimized version that handles 1 or more of uint32_ts.
112 * The length parameter here is the number of uint32_ts in the key.
113 */
114 static inline uint32_t jhash2(uint32_t *k, uint32_t length, uint32_t initval)
115 {
116 uint32_t a, b, c, len;
118 a = b = JHASH_GOLDEN_RATIO;
119 c = initval;
120 len = length;
122 while (len >= 3) {
123 a += k[0];
124 b += k[1];
125 c += k[2];
126 __jhash_mix(a, b, c);
127 k += 3; len -= 3;
128 }
130 c += length * 4;
132 switch (len) {
133 case 2 : b += k[1];
134 case 1 : a += k[0];
135 };
137 __jhash_mix(a,b,c);
139 return c;
140 }
143 /* A special ultra-optimized versions that knows they are hashing exactly
144 * 3, 2 or 1 word(s).
145 *
146 * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
147 * done at the end is not done here.
148 */
149 static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval)
150 {
151 a += JHASH_GOLDEN_RATIO;
152 b += JHASH_GOLDEN_RATIO;
153 c += initval;
155 __jhash_mix(a, b, c);
157 return c;
158 }
160 static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval)
161 {
162 return jhash_3words(a, b, 0, initval);
163 }
165 static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
166 {
167 return jhash_3words(a, 0, 0, initval);
168 }
170 static unsigned int get_randomness(int *state)
171 {
172 return jhash_1word((*state)++, *state * 1103515243);
173 }
175 static int state;
177 /* Lengthening headers is pointless: other end will just wait for more
178 * data and timeout. We merely shorten the length. */
179 static void corrupt_header(char *output, const struct xsd_sockmsg *msg,
180 unsigned int *next_bit)
181 {
182 struct xsd_sockmsg newmsg = *msg;
184 while (*next_bit < sizeof(*msg)) {
185 if (newmsg.len)
186 newmsg.len = get_randomness(&state) % newmsg.len;
187 *next_bit += get_randomness(&state) % RAND_FREQ;
188 }
189 memcpy(output, &newmsg, sizeof(newmsg));
190 }
192 #define read_all_choice read_all
193 static bool write_all_choice(int fd, const void *data, unsigned int len)
194 {
195 char corrupt_data[len];
196 bool ret;
197 static unsigned int next_bit;
199 if (len == sizeof(struct xsd_sockmsg)
200 && ((unsigned long)data % __alignof__(struct xsd_sockmsg)) == 0)
201 corrupt_header(corrupt_data, data, &next_bit);
202 else {
203 memcpy(corrupt_data, data, len);
204 while (next_bit < len * CHAR_BIT) {
205 corrupt_data[next_bit/CHAR_BIT]
206 ^= (1 << (next_bit%CHAR_BIT));
207 next_bit += get_randomness(&state) % RAND_FREQ;
208 }
209 }
211 ret = xs_write_all(fd, corrupt_data, len);
212 next_bit -= len * CHAR_BIT;
213 return ret;
214 }
216 #include "xs.c"
218 static char *random_path(void)
219 {
220 unsigned int i;
221 char *ret = NULL;
223 if (get_randomness(&state) % 20 == 0)
224 return talloc_strdup(NULL, "/");
226 for (i = 0; i < 1 || (get_randomness(&state) % 2); i++) {
227 ret = talloc_asprintf_append(ret, "/%i",
228 get_randomness(&state) % 15);
229 }
230 return ret;
231 }
233 /* Do the next operation, return the results. */
234 static void do_next_op(struct xs_handle *h, bool verbose)
235 {
236 char *name;
237 unsigned int num;
239 if (verbose)
240 printf("State %i: ", state);
242 name = random_path();
243 switch (get_randomness(&state) % 9) {
244 case 0:
245 if (verbose)
246 printf("DIR %s\n", name);
247 free(xs_directory(h, name, &num));
248 break;
249 case 1:
250 if (verbose)
251 printf("READ %s\n", name);
252 free(xs_read(h, name, &num));
253 break;
254 case 2: {
255 char *contents = talloc_asprintf(NULL, "%i",
256 get_randomness(&state));
257 unsigned int len = get_randomness(&state)%(strlen(contents)+1);
258 if (verbose)
259 printf("WRITE %s %.*s\n", name, len, contents);
260 xs_write(h, name, contents, len);
261 break;
262 }
263 case 3:
264 if (verbose)
265 printf("MKDIR %s\n", name);
266 xs_mkdir(h, name);
267 break;
268 case 4:
269 if (verbose)
270 printf("RM %s\n", name);
271 xs_rm(h, name);
272 break;
273 case 5:
274 if (verbose)
275 printf("GETPERMS %s\n", name);
276 free(xs_get_permissions(h, name, &num));
277 break;
278 case 6: {
279 unsigned int i, num = get_randomness(&state)%8;
280 struct xs_permissions perms[num];
282 if (verbose)
283 printf("SETPERMS %s: ", name);
284 for (i = 0; i < num; i++) {
285 perms[i].id = get_randomness(&state)%8;
286 perms[i].perms = get_randomness(&state)%4;
287 if (verbose)
288 printf("%i%c ", perms[i].id,
289 perms[i].perms == XS_PERM_WRITE ? 'W'
290 : perms[i].perms == XS_PERM_READ ? 'R'
291 : perms[i].perms ==
292 (XS_PERM_READ|XS_PERM_WRITE) ? 'B'
293 : 'N');
294 }
295 if (verbose)
296 printf("\n");
297 xs_set_permissions(h, name, perms, num);
298 break;
299 }
300 case 7: {
301 if (verbose)
302 printf("START %s\n", name);
303 xs_transaction_start(h);
304 break;
305 }
306 case 8: {
307 bool abort = (get_randomness(&state) % 2);
309 if (verbose)
310 printf("STOP %s\n", abort ? "ABORT" : "COMMIT");
311 xs_transaction_end(h, abort);
312 break;
313 }
314 default:
315 barf("Impossible randomness");
316 }
317 }
319 static struct xs_handle *h;
320 static void alarmed(int sig __attribute__((unused)))
321 {
322 /* We force close on timeout. */
323 close(h->fd);
324 }
326 static int start_daemon(void)
327 {
328 int fds[2];
329 int daemon_pid;
331 /* Start daemon. */
332 pipe(fds);
333 if ((daemon_pid = fork())) {
334 /* Child writes PID when its ready: we wait for that. */
335 char buffer[20];
336 close(fds[1]);
337 if (read(fds[0], buffer, sizeof(buffer)) < 0)
338 barf("Failed to summon daemon");
339 close(fds[0]);
340 return daemon_pid;
341 } else {
342 dup2(fds[1], STDOUT_FILENO);
343 close(fds[0]);
344 #if 1
345 execlp("valgrind", "valgrind", "--log-file=/tmp/xs_crashme.vglog", "-q", "./xenstored_test", "--output-pid",
346 "--no-fork", "--trace-file=/tmp/trace", NULL);
347 #else
348 execlp("./xenstored_test", "xenstored_test", "--output-pid",
349 "--no-fork", NULL);
350 #endif
351 exit(1);
352 }
353 }
356 int main(int argc, char **argv)
357 {
358 unsigned int i;
359 int pid;
361 if (argc != 3 && argc != 4)
362 barf("Usage: xs_crashme <iterations> <seed> [pid]");
364 if (argc == 3)
365 pid = start_daemon();
366 else
367 pid = atoi(argv[3]);
369 state = atoi(argv[2]);
370 h = xs_daemon_open();
371 if (!h)
372 barf_perror("Opening connection to daemon");
373 signal(SIGALRM, alarmed);
374 for (i = 0; i < (unsigned)atoi(argv[1]); i++) {
375 alarm(1);
376 do_next_op(h, false);
377 if (i % (atoi(argv[1]) / 72 ?: 1) == 0) {
378 printf(".");
379 fflush(stdout);
380 }
381 if (kill(pid, 0) != 0)
382 barf_perror("Pinging daemon on iteration %i", i);
383 if (h->fd < 0) {
384 xs_daemon_close(h);
385 h = xs_daemon_open();
386 if (!h)
387 barf_perror("Connecting on iteration %i", i);
388 }
389 }
390 kill(pid, SIGTERM);
391 return 0;
392 }