summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2010-04-06 13:59:09 -0500
committerDavid Teigland <teigland@redhat.com>2010-04-06 13:59:09 -0500
commit2cd320665a8f5920e5d09b59744239169d1be78d (patch)
tree611c8830841edade179332848f713ed433729ecf
parent9f2d0e1f6615d44c1e7a5ca9b65f6c23d2ac1368 (diff)
downloaddct-stuff-2cd320665a8f5920e5d09b59744239169d1be78d.tar.gz
dct-stuff-2cd320665a8f5920e5d09b59744239169d1be78d.tar.xz
dct-stuff-2cd320665a8f5920e5d09b59744239169d1be78d.zip
add new dlm and fs tests
Signed-off-by: David Teigland <teigland@redhat.com>
-rw-r--r--dlm/dlm_load.c794
-rw-r--r--fs/alternate.c137
-rw-r--r--fs/lock_load.c329
-rwxr-xr-xfs/make_panic162
4 files changed, 1422 insertions, 0 deletions
diff --git a/dlm/dlm_load.c b/dlm/dlm_load.c
new file mode 100644
index 0000000..d54f414
--- /dev/null
+++ b/dlm/dlm_load.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright (c) 2010 David Teigland
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <syslog.h>
+#include <sys/time.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+#include "libdlm.h"
+
+#define LKM_IVMODE -1
+
+#define MAX_CLIENTS 4
+#define MAX_LOCKS 32
+#define MAX_RESOURCES 32
+
+static dlm_lshandle_t *dh;
+static int libdlm_fd;
+static uint32_t iterations = 0;
+static int maxn = MAX_LOCKS;
+static int maxr = MAX_RESOURCES;
+static int openclose = 0;
+static int quiet = 0;
+static int timewarn = 0;
+static uint64_t our_xid = 0;
+static uint32_t ast_count = 0;
+
+struct client {
+ int fd;
+ char type[32];
+};
+
+static int client_size = MAX_CLIENTS;
+static struct client client[MAX_CLIENTS];
+static struct pollfd pollfd[MAX_CLIENTS];
+
+enum {
+ Op_request = 1,
+ Op_convert,
+ Op_unlock,
+ Op_cancel,
+};
+
+struct lk {
+ int id;
+ int locked_stable;
+ int unlocked_stable;
+ int wait_request;
+ int wait_convert;
+ int wait_unlock;
+ int wait_cancel;
+ int rqmode;
+ int grmode;
+ int lastop;
+ int last_status;
+ int bast;
+ time_t wait_start;
+ struct dlm_lksb lksb;
+};
+
+static struct lk *locks;
+
+#define log_debug(fmt, args...) \
+do { \
+ if (!quiet) \
+ printf(fmt "\n", ##args); \
+} while (0)
+
+#define log_error(fmt, args...) \
+do { \
+ printf("ERROR " fmt "\n", ##args); \
+ exit(-1); \
+} while (0)
+
+static int rand_int(int a, int b)
+{
+ return a + (int) (((float)(b - a + 1)) * random() / (RAND_MAX+1.0));
+}
+
+static const char *status_str(int status)
+{
+ static char sts_str[8];
+
+ switch (status) {
+ case 0:
+ return "0 ";
+ case EUNLOCK:
+ return "EUNLOCK";
+ case ECANCEL:
+ return "ECANCEL";
+ case EAGAIN:
+ return "EAGAIN ";
+ case EBUSY:
+ return "EBUSY ";
+ case ETIMEDOUT:
+ return "ETIMEDO";
+ case EDEADLK:
+ return "EDEADLK";
+ default:
+ snprintf(sts_str, 8, "%8x", status);
+ return sts_str;
+ }
+}
+
+static const char *op_str(int op)
+{
+ switch (op) {
+ case Op_request:
+ return "request";
+ case Op_convert:
+ return "convert";
+ case Op_unlock:
+ return "unlock";
+ case Op_cancel:
+ return "cancel";
+ default:
+ return "unknown";
+ }
+}
+
+static struct lk *get_lock(int i)
+{
+ if (i < 0)
+ return NULL;
+ if (i >= maxn)
+ return NULL;
+ return &locks[i];
+}
+
+static void dump(void)
+{
+ struct lk *lk;
+ int i;
+
+ for (i = 0; i < maxn; i++) {
+ lk = get_lock(i);
+ log_debug("lk %03u id %08x wait r%d c%d u%d c%d lastop %s gr %d rq %d\n",
+ i,
+ lk->lksb.sb_lkid,
+ lk->wait_request,
+ lk->wait_convert,
+ lk->wait_unlock,
+ lk->wait_cancel,
+ op_str(lk->lastop),
+ lk->grmode,
+ lk->rqmode);
+ }
+}
+
+static void bastfn(void *arg)
+{
+ struct lk *lk = arg;
+ lk->bast = 1;
+
+ ast_count++;
+
+ log_debug("lk %03u bast %04u", lk->id, ast_count);
+}
+
+static void astfn(void *arg)
+{
+ struct lk *lk = arg;
+ int status = lk->lksb.sb_status;
+ int i = lk->id;
+
+ ast_count++;
+
+ log_debug("lk %03u cast %04u %s %08x "
+ "wait r%d c%d u%d c%d "
+ "gr %2d rq %2d last %s",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop));
+
+ switch (status) {
+ case 0:
+ case EAGAIN:
+ if (lk->wait_request || lk->wait_convert) {
+ if (lk->wait_request && (status == EAGAIN)) {
+ lk->locked_stable = 0;
+ lk->unlocked_stable = 1;
+ } else {
+ lk->locked_stable = 1;
+ lk->unlocked_stable = 0;
+ }
+
+ lk->wait_request = 0;
+ lk->wait_convert = 0;
+
+ if (!status) {
+ lk->grmode = lk->rqmode;
+ lk->rqmode = LKM_IVMODE;
+ } else {
+ lk->rqmode = LKM_IVMODE;
+ }
+ } else {
+ /* wait state error */
+ log_error("lk %03u cast %04u %s %08x "
+ "wait r%d c%d u%d c%d "
+ "gr %2d rq %2d last %s wait state error 1",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop));
+ }
+
+ if (lk->wait_cancel) {
+ lk->wait_cancel = 0;
+ }
+
+ if (lk->wait_unlock) {
+ /* wait state error */
+ log_error("lk %03u cast %04u %s %08x "
+ "wait r%d c%d u%d c%d "
+ "gr %2d rq %2d last %s wait state error 2",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop));
+ }
+ break;
+
+ case EUNLOCK:
+ if (lk->wait_unlock) {
+ lk->locked_stable = 0;
+ lk->unlocked_stable = 1;
+
+ lk->wait_unlock = 0;
+
+ lk->grmode = LKM_IVMODE;
+ lk->bast = 0;
+ } else {
+ /* wait state error */
+ log_error("lk %03u cast %04u %s %08x "
+ "wait r%d c%d u%d c%d "
+ "gr %2d rq %2d last %s wait state error 3",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop));
+ }
+
+ if (lk->wait_request || lk->wait_convert || lk->wait_cancel) {
+ /* wait state error */
+ log_error("lk %03u cast %04u %s %08x "
+ "wait r%d c%d u%d c%d "
+ "gr %2d rq %2d last %s wait state error 4",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop));
+ }
+ break;
+
+ case ECANCEL:
+ if (lk->wait_cancel) {
+ if (lk->grmode > LKM_IVMODE) {
+ lk->locked_stable = 1;
+ lk->unlocked_stable = 0;
+ } else {
+ lk->locked_stable = 0;
+ lk->unlocked_stable = 1;
+ }
+
+ lk->wait_cancel = 0;
+
+ lk->rqmode = LKM_IVMODE;
+ } else {
+ /* wait state error */
+ log_error("lk %03u cast %04u %s %08x "
+ "wait r%d c%d u%d c%d "
+ "gr %2d rq %2d last %s wait state error 5",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop));
+ }
+
+ if (lk->wait_request || lk->wait_convert) {
+ lk->wait_request = 0;
+ lk->wait_convert = 0;
+ }
+
+ if (lk->wait_unlock) {
+ /* wait state error */
+ log_error("lk %03u cast %04u %s %08x "
+ "wait r%d c%d u%d c%d "
+ "gr %2d rq %2d last %s wait state error 6",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop));
+ }
+ break;
+
+ case ETIMEDOUT:
+ log_error("lk %03u cast %04u %s %08x not using timeouts",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid);
+ break;
+
+ case EDEADLK:
+ if (lk->wait_convert) {
+ lk->locked_stable = 1;
+ lk->unlocked_stable = 0;
+
+ lk->wait_convert = 0;
+
+ lk->rqmode = LKM_IVMODE;
+ } else {
+ /* wait state error */
+ log_error("lk %03u cast %04u %s %08x "
+ "wait r%d c%d u%d c%d "
+ "gr %2d rq %2d last %s wait state error 7",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop));
+ }
+
+ if (lk->wait_request || lk->wait_unlock || lk->wait_cancel) {
+ /* wait state error */
+ log_error("lk %03u cast %04u %s %08x "
+ "wait r%d c%d u%d c%d "
+ "gr %2d rq %2d last %s wait state error 8",
+ i, ast_count, status_str(status),
+ lk->lksb.sb_lkid,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop));
+ }
+
+ break;
+
+ default:
+ log_error("lk %03u cast %04u %d %08x error unexpected status",
+ i, ast_count, status, lk->lksb.sb_lkid);
+ };
+}
+
+static int do_request(struct lk *lk, int mode, int noqueue)
+{
+ char name[DLM_RESNAME_MAXLEN];
+ uint64_t *timeout_arg = NULL;
+ uint32_t flags = 0;
+ int i = lk->id;
+ int rv;
+
+ if (noqueue)
+ flags |= LKF_NOQUEUE;
+
+ memset(name, 0, sizeof(name));
+ snprintf(name, sizeof(name), "test%d", (i % maxr));
+
+ log_debug("lk %03u request mode %d noqueue %d", i, mode, noqueue);
+
+ rv = dlm_ls_lockx(dh, mode, &lk->lksb, flags, name, strlen(name), 0,
+ astfn, (void *)lk, bastfn, &our_xid, timeout_arg);
+
+ if (rv) {
+ log_error("lk %03u request errno %d wait r%d c%d u%d c%d lastop %s",
+ i, errno, lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel, op_str(lk->lastop));
+ }
+ return rv;
+}
+
+static int do_convert(struct lk *lk, int mode, int noqueue)
+{
+ char name[DLM_RESNAME_MAXLEN];
+ uint64_t *timeout_arg = NULL;
+ uint32_t flags = LKF_CONVERT;
+ int i = lk->id;
+ int rv;
+
+ if (noqueue)
+ flags |= LKF_NOQUEUE;
+
+ memset(name, 0, sizeof(name));
+ snprintf(name, sizeof(name), "test%d", (i % maxr));
+
+ log_debug("lk %03u convert mode %d noqueue %d", i, mode, noqueue);
+
+ rv = dlm_ls_lockx(dh, mode, &lk->lksb, flags, name, strlen(name), 0,
+ astfn, (void *)lk, bastfn, &our_xid, timeout_arg);
+
+ if (rv) {
+ log_error("lk %03u convert errno %d wait r%d c%d u%d c%d lastop %s",
+ i, errno, lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel, op_str(lk->lastop));
+ }
+ return rv;
+}
+
+static int do_unlock(struct lk *lk)
+{
+ uint32_t lkid = lk->lksb.sb_lkid;
+ uint32_t flags = 0;
+ int i = lk->id;
+ int rv;
+
+ log_debug("lk %03u unlock", i);
+
+ rv = dlm_ls_unlock(dh, lkid, flags, &lk->lksb, lk);
+
+ if (rv) {
+ log_error("lk %03u unlock errno %d wait r%d c%d u%d c%d lastop %s",
+ i, errno, lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel, op_str(lk->lastop));
+ }
+ return rv;
+}
+
+static int do_cancel(struct lk *lk)
+{
+ uint32_t lkid = lk->lksb.sb_lkid;
+ uint32_t flags = LKF_CANCEL;
+ int i = lk->id;
+ int rv;
+
+ log_debug("lk %03u cancel", i);
+
+ rv = dlm_ls_unlock(dh, lkid, flags, &lk->lksb, lk);
+
+ if (rv) {
+ log_error("lk %03u cancel errno %d wait r%d c%d u%d c%d lastop %s",
+ i, errno, lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel, op_str(lk->lastop));
+ }
+ return rv;
+}
+
+static void loop(void)
+{
+ struct lk *lk;
+ uint32_t n = 0;
+ int locknum, noqueue, rqmode, rv;
+
+ while (1) {
+ dlm_dispatch(libdlm_fd);
+
+ n++;
+ if (iterations && n == iterations)
+ break;
+ if (!(n % 10))
+ usleep(200000);
+
+ locknum = rand_int(0, maxn - 1);
+ noqueue = rand_int(0, 1);
+ rqmode = rand_int(0, LKM_EXMODE);
+
+ lk = get_lock(locknum);
+ if (!lk)
+ continue;
+
+ if (lk->unlocked_stable) {
+ rv = do_request(lk, rqmode, noqueue);
+ if (!rv) {
+ lk->lastop = Op_request;
+ lk->rqmode = rqmode;
+ lk->wait_start = time(NULL);
+
+ lk->wait_request = 1;
+ lk->locked_stable = 0;
+ lk->unlocked_stable = 0;
+ }
+ continue;
+ }
+
+ if (lk->locked_stable && lk->bast) {
+ if (rand_int(0, 1)) {
+ rv = do_convert(lk, LKM_NLMODE, 0);
+ if (!rv) {
+ lk->lastop = Op_convert;
+ lk->rqmode = LKM_NLMODE;
+ lk->bast = 0;
+ lk->wait_start = time(NULL);
+
+ lk->wait_convert = 1;
+ lk->locked_stable = 0;
+ lk->unlocked_stable = 0;
+ }
+ } else {
+ rv = do_unlock(lk);
+ if (!rv) {
+ lk->lastop = Op_unlock;
+ lk->rqmode = LKM_IVMODE;
+ lk->bast = 0;
+
+ lk->wait_unlock = 1;
+ lk->locked_stable = 0;
+ lk->unlocked_stable = 0;
+ }
+ }
+ continue;
+ }
+
+ if (lk->locked_stable) {
+ if (rand_int(0, 1)) {
+ rv = do_convert(lk, rqmode, noqueue);
+ if (!rv) {
+ lk->lastop = Op_convert;
+ lk->rqmode = rqmode;
+ lk->wait_start = time(NULL);
+
+ lk->wait_convert = 1;
+ lk->locked_stable = 0;
+ lk->unlocked_stable = 0;
+ }
+ } else {
+ rv = do_unlock(lk);
+ if (!rv) {
+ lk->lastop = Op_unlock;
+ lk->rqmode = LKM_IVMODE;
+
+ lk->wait_unlock = 1;
+ lk->locked_stable = 0;
+ lk->unlocked_stable = 0;
+ }
+ }
+ continue;
+ }
+
+ if ((lk->wait_request || lk->wait_convert) && !lk->wait_cancel) {
+ if (time(NULL) - lk->wait_start > 2) {
+ rv = do_cancel(lk);
+ if (!rv) {
+ lk->lastop = Op_cancel;
+
+ lk->wait_cancel = 1;
+ lk->locked_stable = 0;
+ lk->unlocked_stable = 0;
+ }
+ }
+ }
+
+ log_debug("lk %03u busy locked %d unlocked %d "
+ "wait r%d c%d u%d c%d",
+ lk->id, lk->locked_stable, lk->unlocked_stable,
+ lk->wait_request, lk->wait_convert,
+ lk->wait_unlock, lk->wait_cancel);
+ }
+}
+
+static int client_add(int fd, int *maxi)
+{
+ int i;
+
+ for (i = 0; i < client_size; i++) {
+ if (client[i].fd == -1) {
+ client[i].fd = fd;
+ pollfd[i].fd = fd;
+ pollfd[i].events = POLLIN;
+ if (i > *maxi)
+ *maxi = i;
+ log_debug("client %d fd %d added", i, fd);
+ return i;
+ }
+ }
+ log_error("client add failed");
+ return -1;
+}
+
+static void client_dead(int ci)
+{
+ log_debug("client %d fd %d dead", ci, client[ci].fd);
+ close(client[ci].fd);
+ client[ci].fd = -1;
+ pollfd[ci].fd = -1;
+}
+
+static void client_init(void)
+{
+ int i;
+
+ for (i = 0; i < client_size; i++)
+ client[i].fd = -1;
+}
+
+static void print_usage(void)
+{
+ printf("Options:\n");
+ printf("\n");
+ printf(" -n The number of locks to work with, default %d\n", MAX_LOCKS);
+ printf(" -r The number of resources to work with, default %d\n", MAX_RESOURCES);
+ printf(" -i Iterations in looping stress test, default 0 is no limit\n");
+ printf(" -o Open/close existing lockspace\n");
+ printf(" -q Quiet output, only print errors\n");
+}
+
+static void decode_arguments(int argc, char **argv)
+{
+ int cont = 1;
+ int optchar;
+
+ while (cont) {
+ optchar = getopt(argc, argv, "n:r:i:qoh");
+
+ switch (optchar) {
+
+ case 'n':
+ maxn = atoi(optarg);
+ break;
+
+ case 'r':
+ maxr = atoi(optarg);
+ break;
+
+ case 'i':
+ iterations = atoi(optarg);
+ break;
+
+ case 'o':
+ openclose = 1;
+ break;
+
+ case 'q':
+ quiet = 1;
+ break;
+
+ case 'h':
+ print_usage();
+ exit(EXIT_SUCCESS);
+ break;
+
+ case 'V':
+ printf("%s (built %s %s)\n", argv[0], __DATE__, __TIME__);
+ exit(EXIT_SUCCESS);
+ break;
+
+ case ':':
+ case '?':
+ fprintf(stderr, "Please use '-h' for usage.\n");
+ exit(EXIT_FAILURE);
+ break;
+
+ case EOF:
+ cont = 0;
+ break;
+
+ default:
+ fprintf(stderr, "unknown option: %c\n", optchar);
+ exit(EXIT_FAILURE);
+ break;
+ };
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ uint32_t major, minor, patch;
+ struct lk *lk;
+ int i, rv, maxi = 0, quit = 0;
+
+ srandom(time(NULL));
+
+ decode_arguments(argc, argv);
+
+ if (maxn < maxr) {
+ log_error("number of resources must be >= number of locks");
+ return -1;
+ }
+ if (maxn % maxr) {
+ log_error("number of locks must be multiple of number of resources");
+ return -1;
+ }
+
+ log_debug("maxn = %d", maxn);
+ log_debug("maxr = %d", maxr);
+ log_debug("locks per resource = %d", maxn / maxr);
+
+ client_init();
+
+ locks = malloc(maxn * sizeof(struct lk));
+ if (!locks) {
+ log_error("no mem for %d locks", maxn);
+ return 0;
+ }
+ memset(locks, 0, sizeof(*locks));
+
+ lk = locks;
+ for (i = 0; i < maxn; i++) {
+ lk->id = i;
+ lk->grmode = -1;
+ lk->rqmode = -1;
+ lk->unlocked_stable = 1;
+ lk++;
+ }
+
+ rv = dlm_kernel_version(&major, &minor, &patch);
+ if (rv < 0) {
+ log_error("can't detect dlm in kernel %d", errno);
+ return -1;
+ }
+ log_debug("dlm kernel version: %u.%u.%u", major, minor, patch);
+ dlm_library_version(&major, &minor, &patch);
+ log_debug("dlm library version: %u.%u.%u", major, minor, patch);
+
+ if (openclose) {
+ log_debug("dlm_open_lockspace...");
+
+ dh = dlm_open_lockspace("test");
+ if (!dh) {
+ log_error("dlm_open_lockspace error %lu %d",
+ (unsigned long)dh, errno);
+ return -ENOTCONN;
+ }
+ } else {
+ log_debug("dlm_new_lockspace...");
+
+ dh = dlm_new_lockspace("test", 0600,
+ timewarn ? DLM_LSFL_TIMEWARN : 0);
+ if (!dh) {
+ log_error("dlm_new_lockspace error %lu %d",
+ (unsigned long)dh, errno);
+ return -ENOTCONN;
+ }
+ }
+
+ rv = dlm_ls_get_fd(dh);
+ if (rv < 0) {
+ log_error("dlm_ls_get_fd error %d %d", rv, errno);
+ dlm_release_lockspace("test", dh, 1);
+ return rv;
+ }
+ libdlm_fd = rv;
+
+ client_add(libdlm_fd, &maxi);
+
+ loop();
+
+ if (openclose) {
+ log_debug("dlm_close_lockspace");
+
+ rv = dlm_close_lockspace(dh);
+ if (rv < 0)
+ log_error("dlm_close_lockspace error %d %d",
+ rv, errno);
+ } else {
+ log_debug("dlm_release_lockspace");
+
+ rv = dlm_release_lockspace("test", dh, 1);
+ if (rv < 0)
+ log_error("dlm_release_lockspace error %d %d",
+ rv, errno);
+ }
+
+ return 0;
+}
+
diff --git a/fs/alternate.c b/fs/alternate.c
new file mode 100644
index 0000000..942f3b9
--- /dev/null
+++ b/fs/alternate.c
@@ -0,0 +1,137 @@
+/******************************************************************************
+*******************************************************************************
+**
+** Copyright 2001 Sistina Software, Inc.
+**
+** This is free software released under the GNU General Public License.
+** There is no warranty for this software. See the file COPYING for
+** details.
+**
+*******************************************************************************
+******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define die(fmt, args...) \
+{ \
+ fprintf(stderr, "%s: ", prog_name); \
+ fprintf(stderr, fmt, ##args); \
+ exit(EXIT_FAILURE); \
+}
+
+#define do_lseek(fd, off) \
+{ \
+ if (lseek((fd), (off), SEEK_SET) != (off)) \
+ die("bad seek: %s on line %d of file %s\n", \
+ strerror(errno),__LINE__, __FILE__); \
+}
+
+#define do_read(fd, buff, len) \
+{ \
+ if (read((fd), (buff), (len)) != (len)) \
+ die("bad read: %s on line %d of file %s\n", \
+ strerror(errno), __LINE__, __FILE__); \
+}
+
+#define do_write(fd, buff, len) \
+{ \
+ if (write((fd), (buff), (len)) != (len)) \
+ die("bad write: %s on line %d of file %s\n", \
+ strerror(errno), __LINE__, __FILE__); \
+}
+
+#define BLOCK_SIZE (512)
+
+char *prog_name;
+
+unsigned int wait;
+unsigned int delay = 0;
+
+int main(int argc, char *argv[])
+{
+ int cont = 1;
+ int optchar;
+ int fd;
+ char *filename;
+ char buf[BLOCK_SIZE];
+ unsigned long long offset;
+ unsigned long long num, last_num = 0;
+ unsigned int id, clients;
+ unsigned long long skip = 0;
+ unsigned int iterations = 0;
+ unsigned int delay = 0;
+
+ prog_name = argv[0];
+
+ while (cont) {
+ optchar = getopt(argc, argv, "i:s:");
+ switch (optchar) {
+ case 'i':
+ iterations = atoi(optarg);
+ break;
+ case 's':
+ delay = atoi(optarg);
+ break;
+ case 'h':
+ die("[-i iterations] [-s usleep] filename offset id clients\n");
+ case EOF:
+ cont = 0;
+ break;
+ }
+ }
+
+ if (argc - optind < 4)
+ die("[-i iterations] [-s usleep] filename offset id clients\n");
+
+ filename = argv[optind];
+ offset = atoll(argv[optind + 1]);
+ id = atoi(argv[optind + 2]);
+ clients = atoi(argv[optind + 3]);
+
+ fd = open(filename, O_RDWR | O_CREAT, 0644);
+ if (fd < 0)
+ die("can't open file %s: %s\n", argv[1], strerror(errno));
+
+ for (;;) {
+ do_lseek(fd, offset);
+
+ do_read(fd, buf, BLOCK_SIZE);
+
+ num = atoll(buf);
+ if (num % clients == id) {
+ num++;
+ sprintf(buf, "%llu\n", num);
+ printf("%llu %llu\n", num, skip);
+
+ if (last_num && last_num + clients != num)
+ die("bad\n");
+
+ do_lseek(fd, offset);
+
+ do_write(fd, buf, BLOCK_SIZE);
+
+ if (iterations && num >= iterations)
+ break;
+
+ last_num = num;
+ skip = 0;
+ } else {
+ skip++;
+ }
+
+ if (delay)
+ usleep(delay);
+ }
+
+ close(fd);
+
+ exit(EXIT_SUCCESS);
+}
+
diff --git a/fs/lock_load.c b/fs/lock_load.c
new file mode 100644
index 0000000..79c449f
--- /dev/null
+++ b/fs/lock_load.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2009 David Teigland
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define die(fmt, args...) \
+{ \
+ fprintf(stderr, "%s: ", prog_name); \
+ fprintf(stderr, fmt, ##args); \
+ exit(EXIT_FAILURE); \
+}
+
+#define MAX_FILES 1000
+int fda[MAX_FILES];
+unsigned int inodea[MAX_FILES];
+
+int do_create;
+int use_flock;
+int use_plock;
+int filecount;
+int iterations;
+int our_pid;
+char *prog_name;
+int blocking;
+int delay = 10; /* milliseconds */
+
+void read_flock(int fd)
+{
+ int error;
+ int mode = LOCK_SH;
+
+ if (!blocking)
+ mode |= LOCK_NB;
+
+ error = flock(fd, mode);
+ if (error < 0) {
+ printf("%d read lock failed %d errno %d\n",
+ our_pid, error, errno);
+ }
+}
+
+void write_flock(int fd)
+{
+ int error;
+ int mode = LOCK_EX;
+
+ if (!blocking)
+ mode |= LOCK_NB;
+
+ error = flock(fd, mode);
+ if (error < 0) {
+ printf("%d write lock failed %d errno %d\n",
+ our_pid, error, errno);
+ }
+}
+
+void unlock_flock(int fd)
+{
+ int error;
+
+ error = flock(fd, LOCK_UN);
+ if (error < 0) {
+ printf("%d unlock failed %d errno %d\n",
+ our_pid, error, errno);
+ }
+}
+
+int do_plock(int fd, int offset, int len, int type)
+{
+ struct flock lock;
+ int action;
+
+ lock.l_type = type;
+ lock.l_start = offset;
+ lock.l_whence = SEEK_SET;
+ lock.l_len = len;
+
+ if (blocking)
+ action = F_SETLKW;
+ else
+ action = F_SETLK;
+
+ return fcntl(fd, action, &lock);
+}
+
+int rand_int(int a, int b)
+{
+ return a + (int) (((float)(b - a + 1)) * random() / (RAND_MAX+1.0));
+}
+
+void rand_range(int *offset, int *len)
+{
+ switch (rand_int(0, 2)) {
+ case 0:
+ *offset = 0;
+ *len = 10;
+ return;
+ case 1:
+ *offset = 0;
+ *len = 5;
+ return;
+ case 2:
+ *offset = 5;
+ *len = 5;
+ return;
+ }
+}
+
+static uint64_t dt_usec(struct timeval *start, struct timeval *stop)
+{
+ uint64_t dt;
+
+ dt = stop->tv_sec - start->tv_sec;
+ dt *= 1000000;
+ dt += stop->tv_usec - start->tv_usec;
+ return dt;
+}
+
+void loop_plock(void)
+{
+ struct timeval t1, t2;
+ int i, fdi, fd, offset, len, rv;
+
+ for (i = 0;; i++) {
+
+ fdi = rand_int(0, filecount-1);
+ fd = fda[fdi];
+
+ rand_range(&offset, &len);
+
+ switch (rand_int(0, 2)) {
+ case 0:
+ gettimeofday(&t1, NULL);
+ rv = do_plock(fd, offset, len, F_UNLCK);
+ gettimeofday(&t2, NULL);
+
+ printf("%06d file%04d ino %04x U %02d-%02d pid %d err %02d sec %.6f\n",
+ i, fdi, inodea[fdi], offset, offset+len-1, our_pid,
+ rv ? errno : 0, 1.e-6 * dt_usec(&t1, &t2));
+ break;
+
+ case 1:
+ gettimeofday(&t1, NULL);
+ rv = do_plock(fd, offset, len, F_RDLCK);
+ gettimeofday(&t2, NULL);
+
+ printf("%06d file%04d ino %04x R %02d-%02d pid %d err %02d sec %.6f\n",
+ i, fdi, inodea[fdi], offset, offset+len-1, our_pid,
+ rv ? errno : 0, 1.e-6 * dt_usec(&t1, &t2));
+
+ break;
+ case 2:
+ gettimeofday(&t1, NULL);
+ rv = do_plock(fd, offset, len, F_WRLCK);
+ gettimeofday(&t2, NULL);
+
+ printf("%06d file%04d ino %04x W %02d-%02d pid %d err %02d sec %.6f\n",
+ i, fdi, inodea[fdi], offset, offset+len-1, our_pid,
+ rv ? errno : 0, 1.e-6 * dt_usec(&t1, &t2));
+ break;
+ }
+
+ if (iterations && i == iterations)
+ break;
+
+ if (delay)
+ usleep(delay * 1000);
+ }
+}
+
+void loop_flock(void)
+{
+ return;
+}
+
+int open_all_files(void)
+{
+ int i, fd;
+ struct stat st;
+ char path[64];
+
+ for (i = 0; i < filecount; i++) {
+ memset(path, 0, sizeof(path));
+ sprintf(path, "file%04u", i);
+
+ fd = open(path, O_RDWR | O_CREAT, 0644);
+ if (fd < 0)
+ die("can't open file %s\n", strerror(errno));
+ fda[i] = fd;
+
+ memset(&st, 0, sizeof(st));
+ fstat(fd, &st);
+ inodea[i] = (unsigned int)st.st_ino;
+ }
+}
+
+void close_all_files(void)
+{
+ int i;
+
+ for (i = 0; i < filecount; i++)
+ close(fda[i]);
+}
+
+void print_usage(void)
+{
+ fprintf(stderr, "lock_load\n");
+ fprintf(stderr, " -i <n> iterations (default 0, no limit)\n");
+ fprintf(stderr, " -n <n> number of files (default 100)\n");
+ fprintf(stderr, " -c only create files\n");
+ fprintf(stderr, " -f use flock\n");
+ fprintf(stderr, " -p use plock (default)\n");
+ fprintf(stderr, " -d <ms> millisecond delay between each op (default 10)\n");
+ fprintf(stderr, " -b use blocking locks (default non-blocking)\n");
+ fprintf(stderr, " (warning: can easily deadlock)\n");
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char *argv[])
+{
+ int cont = 1;
+ int optchar;
+
+ do_create = 0;
+ use_flock = 0;
+ use_plock = 1;
+ filecount = 100;
+ iterations = 0;
+ blocking = 0;
+ delay = 10;
+
+ while (cont) {
+ optchar = getopt(argc, argv, "cfpn:i:d:bh");
+
+ switch (optchar) {
+ case 'c':
+ do_create = 1;
+ break;
+
+ case 'f':
+ use_flock = 1;
+ break;
+
+ case 'p':
+ use_plock = 1;
+ break;
+
+ case 'n':
+ filecount = atoi(optarg);
+ break;
+
+ case 'i':
+ iterations = atoi(optarg);
+ break;
+
+ case 'd':
+ delay = atoi(optarg);
+ break;
+
+ case 'b':
+ blocking = 1;
+ break;
+
+
+ case EOF:
+ cont = 0;
+ break;
+
+ case 'h':
+ default:
+ print_usage();
+ break;
+ };
+ }
+
+ srandom(time(NULL));
+ prog_name = argv[0];
+ our_pid = getpid();
+
+ if (filecount > MAX_FILES) {
+ fprintf(stderr, "max files is %d\n", MAX_FILES);
+ return -1;
+ }
+
+ if (do_create) {
+ open_all_files();
+ close_all_files();
+ return 0;
+ }
+
+ open_all_files();
+
+ if (use_flock)
+ loop_flock();
+ else if (use_plock)
+ loop_plock();
+ else
+ fprintf(stderr, "use -f or -p for flock or plock\n");
+
+ close_all_files();
+
+ return 0;
+}
+
diff --git a/fs/make_panic b/fs/make_panic
new file mode 100755
index 0000000..fd27fb8
--- /dev/null
+++ b/fs/make_panic
@@ -0,0 +1,162 @@
+#!/usr/bin/perl
+
+#############################################################
+#############################################################
+##
+## Copyright 2001 Sistina Software Inc.
+##
+## This is free software released under the GNU General
+## Public License. There is no warranty for this
+## software. See the file COPYING for details.
+##
+#############################################################
+#############################################################
+
+use Getopt::Std;
+
+exit(1) unless getopts('s:f:e:hdqr:l:');
+
+if (defined $opt_h)
+{
+ print << "EndHelp";
+Usage: make_panic [OPTION]
+ -e <iterations> number of iterations, infinite if not defined
+ -f <forks> number of processes to fork
+ -h help
+ -s <seed> seed for random number generator
+ -d drop seed so you could use it next time
+ -q Don't print out the status updates. (slient)
+ -r Number of directories
+ -l Number of files
+EndHelp
+
+ exit(0);
+}
+
+
+if (defined $opt_f)
+{
+ $opt_f = 1 if $opt_f <=0;
+ while (--$opt_f)
+ {
+ if ($pid = fork())
+ {
+ #parent
+ }
+ elsif (defined $pid)
+ {
+ last;
+ }
+ else
+ {
+ die "Fork error $!";
+ }
+ }
+}
+
+if(defined $opt_s)
+{
+ $seed = $opt_s;
+}
+else
+{
+ $seed = time ^ $$;
+}
+if(defined($opt_d))
+{
+ system("echo $seed > /make_panic_seed.$$");
+}
+srand($seed);
+
+if (defined $opt_r)
+{
+ $dirs = $opt_r;
+}
+else
+{
+ $dirs = 50;
+}
+
+if (defined $opt_l)
+{
+ $files = $opt_l;
+}
+else
+{
+ $files = 1000;
+}
+
+
+for ($x = 0; $x < $dirs; $x++)
+{
+ mkdir(sprintf("dir%.10u", $x), 0755);
+}
+
+$last = time();
+$ops_at_last_tick = 0;
+
+while ( (defined $opt_e)?($opt_e-- > 0):1 )
+{
+ $v = int(rand(6));
+
+ $x = int(rand($dirs));
+ $y = int(rand($files));
+ $file = sprintf("dir%.10u/file%.10u", $x, $y);
+
+ if ($v == 0)
+ {
+ open(DATAFILE, ">> $file") || die;
+ close(DATAFILE);
+ }
+ elsif ($v == 1 || $v == 2)
+ {
+ $z = int(rand(1000000000));
+ if (open(DATAFILE, "+< $file"))
+ {
+ seek(DATAFILE, $z, 0);
+ print DATAFILE "$z\n";
+ close(DATAFILE);
+ }
+ }
+ elsif ($v == 3 || $v == 4)
+ {
+ $z = int(rand(1000000000));
+ if (open(DATAFILE, "< $file"))
+ {
+ seek(DATAFILE, -100, 2);
+ read(DATAFILE, $tmp, 100) == 100;
+ close(DATAFILE);
+ }
+ }
+ elsif ($v == 5)
+ {
+ unlink "$file";
+ }
+
+
+ $ops++;
+# if ($ops % 250 == 0)
+# {
+# $new = time();
+# $last-- if ($new == $last);
+# $rate = 250 / ($new - $last);
+# $pretty_rate = sprintf("%.2f", $rate);
+# $last = $new;
+# }
+
+ $new = time();
+
+ if ($new != $last) {
+ $rate = ($ops - $ops_at_last_tick) / ($new - $last);
+ $pretty_rate = sprintf("%.2f", $rate);
+ $ops_at_last_tick = $ops;
+ $last = $new;
+ }
+
+ if( ! defined $opt_q ) {
+ print "$ops:$v: $pretty_rate\n";
+ }
+}
+
+
+