[Cluster-devel] cluster/dlm/tests/usertest dlmtest2.c
teigland at sourceware.org
teigland at sourceware.org
Tue Feb 27 18:55:53 UTC 2007
CVSROOT: /cvs/cluster
Module name: cluster
Changes by: teigland at sourceware.org 2007-02-27 18:55:52
Modified files:
dlm/tests/usertest: dlmtest2.c
Log message:
lots of changes, biggest is new "stress" test
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/dlm/tests/usertest/dlmtest2.c.diff?cvsroot=cluster&r1=1.4&r2=1.5
--- cluster/dlm/tests/usertest/dlmtest2.c 2007/01/04 20:34:18 1.4
+++ cluster/dlm/tests/usertest/dlmtest2.c 2007/02/27 18:55:52 1.5
@@ -30,12 +30,28 @@
#include "libdlm.h"
+#define MAX_CLIENTS 4
+#define MAX_LOCKS 16
+
static dlm_lshandle_t *dh;
static int libdlm_fd;
static int noqueue = 1;
-
-#define MAX_CLIENTS 4
-#define LOCKS 16
+static int quiet = 1;
+static int verbose = 0;
+static int bast_cb;
+static int maxn = MAX_LOCKS;
+
+#define log_print(fmt, args...) \
+do { \
+ if (!quiet) \
+ printf(fmt , ##args); \
+} while (0)
+
+#define log_verbose(fmt, args...) \
+do { \
+ if (verbose) \
+ printf(fmt , ##args); \
+} while (0)
struct client {
int fd;
@@ -46,278 +62,256 @@
static struct client client[MAX_CLIENTS];
static struct pollfd pollfd[MAX_CLIENTS];
+enum {
+ Op_lock = 1,
+ Op_unlock,
+ Op_unlockf,
+ Op_cancel,
+};
+
struct lk {
int id;
int rqmode;
int grmode;
int wait_ast;
+ int lastop;
+ int last_status;
+ int bast;
struct dlm_lksb lksb;
};
-struct lk locks[LOCKS];
-struct lk *locks_flood;
-int locks_flood_n;
-int locks_flood_ast_done;
+struct lk *locks;
void unlock(int i);
+void unlockf(int i);
-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;
- printf("client %d fd %d added\n", i, fd);
- return i;
- }
- }
- printf("client add failed\n");
- return -1;
+int rand_int(int a, int b)
+{
+ return a + (int) (((float)(b - a + 1)) * random() / (RAND_MAX+1.0));
}
-static void client_dead(int ci)
+char *status_str(int status)
{
- printf("client %d fd %d dead\n", ci, client[ci].fd);
- close(client[ci].fd);
- client[ci].fd = -1;
- pollfd[ci].fd = -1;
+ 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 ";
+ default:
+ snprintf(sts_str, 8, "%8x", status);
+ return sts_str;
+ }
}
-static void client_init(void)
-{
- int i;
+char *op_str(int op)
+{
+ switch (op) {
+ case Op_lock:
+ return "lock";
+ case Op_unlock:
+ return "unlock";
+ case Op_unlockf:
+ return "unlockf";
+ case Op_cancel:
+ return "cancel";
+ default:
+ return "unknown";
+ }
+}
- for (i = 0; i < client_size; i++)
- client[i].fd = -1;
+struct lk *get_lock(int i)
+{
+ if (i < 0)
+ return NULL;
+ if (i >= maxn)
+ return NULL;
+ return &locks[i];
}
-void dump(void)
+int all_unlocks_done(void)
{
+ struct lk *lk;
int i;
- for (i = 0; i < LOCKS; i++) {
- printf("x %d lkid %x grmode %d rqmode %d wait_ast %d\n", i,
- locks[i].lksb.sb_lkid,
- locks[i].grmode,
- locks[i].rqmode,
- locks[i].wait_ast);
+ for (i = 0; i < maxn; i++) {
+ lk = get_lock(i);
+ if (lk->grmode == -1 && !lk->wait_ast)
+ continue;
+ return 0;
}
+ return 1;
}
-void dump_flood(void)
+void dump(void)
{
struct lk *lk;
int i;
- if (!locks_flood_n) {
- printf("no current locks_flood\n");
- return;
- }
-
- for (i = 0; i < locks_flood_n; i++) {
- lk = &locks_flood[i];
- printf("x %d lkid %x grmode %d rqmode %d wait_ast %d\n", i,
+ for (i = 0; i < maxn; i++) {
+ lk = get_lock(i);
+ printf("x %2d lkid %06x gr %2d rq %2d wait_ast %d last op %s\t%s\n",
+ i,
lk->lksb.sb_lkid,
lk->grmode,
lk->rqmode,
- lk->wait_ast);
+ lk->wait_ast,
+ op_str(lk->lastop),
+ status_str(lk->last_status));
}
}
void bastfn(void *arg)
{
struct lk *lk = arg;
-
- printf("bast %d\n", lk->id);
-
- unlock(lk->id);
+ lk->bast = 1;
+ bast_cb = 1;
}
-void astfn(void *arg)
+void do_bast(struct lk *lk)
{
- struct lk *lk = arg;
- int i = lk->id;
+ int skip = 0;
- printf("ast %d sb_lkid %x sb_status %x\n", i, lk->lksb.sb_lkid,
- lk->lksb.sb_status);
-
- if (!lk->wait_ast) {
- printf("not waiting for ast\n");
- exit(-1);
+ if (lk->lastop == Op_unlock || lk->lastop == Op_unlockf) {
+ skip = 1;
+ }
+ if (!lk->lksb.sb_lkid) {
+ skip = 1;
}
- lk->wait_ast = 0;
+ if (skip)
+ printf(" bast: skip %3d\t%x\n", lk->id, lk->lksb.sb_lkid);
+ else {
+ printf(" bast: unlockf %3d\t%x\n", lk->id, lk->lksb.sb_lkid);
+ unlockf(lk->id);
+ lk->lastop = Op_unlockf;
+ }
+ lk->bast = 0;
+}
- if (lk->lksb.sb_status == EUNLOCK) {
- memset(&locks[i].lksb, 0, sizeof(struct dlm_lksb));
- locks[i].grmode = -1;
- } else if (lk->lksb.sb_status == EAGAIN) {
- if (locks[i].grmode == -1)
- memset(&locks[i].lksb, 0, sizeof(struct dlm_lksb));
- } else {
- if (lk->lksb.sb_status != 0) {
- printf("unknown sb_status\n");
- exit(-1);
- }
+void do_bast_unlocks(void)
+{
+ struct lk *lk;
+ int i;
- locks[i].grmode = locks[i].rqmode;
+ for (i = 0; i < maxn; i++) {
+ lk = get_lock(i);
+ if (lk->bast)
+ do_bast(lk);
}
-
- locks[i].rqmode = -1;
+ bast_cb = 0;
}
-void bastfn_flood(void *arg)
+void process_libdlm(void)
{
- struct lk *lk = arg;
- printf("bastfn_flood %d\n", lk->id);
+ dlm_dispatch(libdlm_fd);
+ if (bast_cb)
+ do_bast_unlocks();
}
-void astfn_flood(void *arg)
+void astfn(void *arg)
{
struct lk *lk = arg;
- int i = lk->id, unlock = 0;
+ int i = lk->id;
if (!lk->wait_ast) {
- printf("lk %d not waiting for ast\n", lk->id);
- exit(-1);
+ printf(" ast: %s %3d\t%x: !wait_ast gr %d rq %d last op %s %s\n",
+ status_str(lk->lksb.sb_status), i, lk->lksb.sb_lkid,
+ lk->grmode, lk->rqmode,
+ op_str(lk->lastop), status_str(lk->last_status));
}
- lk->wait_ast = 0;
+ log_print(" ast: %s %3d\t%x\n",
+ status_str(lk->lksb.sb_status), i, lk->lksb.sb_lkid);
+
+ lk->last_status = lk->lksb.sb_status;
if (lk->lksb.sb_status == EUNLOCK) {
memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
lk->grmode = -1;
- unlock = 1;
- } else if (lk->lksb.sb_status == EAGAIN) {
- if (lk->grmode == -1)
- memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
- } else {
- if (lk->lksb.sb_status != 0) {
- printf("lk %d unknown sb_status %d\n", lk->id,
- lk->lksb.sb_status);
- exit(-1);
- }
+ lk->wait_ast = 0;
- lk->grmode = lk->rqmode;
- }
-
- lk->rqmode = -1;
- locks_flood_ast_done++;
-
- if (locks_flood_ast_done == locks_flood_n) {
- printf("astfn_flood all %d done\n", locks_flood_n);
- if (unlock) {
- free(locks_flood);
- locks_flood = NULL;
- locks_flood_n = 0;
+ } else if (lk->lksb.sb_status == ECANCEL) {
+ if (lk->grmode == -1) {
+ memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
+ lk->wait_ast = 0;
+ } else {
+ if (lk->lastop != Op_unlock && lk->lastop != Op_unlockf)
+ lk->wait_ast = 0;
}
- }
-}
-void astfn_flood_unlock(void *arg)
-{
- struct lk *lk = arg;
- int i = lk->id, unlock = 0, rv;
-
- if (!lk->wait_ast) {
- printf("lk %d not waiting for ast\n", lk->id);
- exit(-1);
- }
-
- lk->wait_ast = 0;
-
- if (lk->lksb.sb_status == EUNLOCK) {
- memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
- lk->grmode = -1;
- lk->rqmode = -1;
- unlock = 1;
- locks_flood_ast_done++;
} else if (lk->lksb.sb_status == EAGAIN) {
- if (lk->grmode == -1)
+ if (lk->grmode == -1) {
memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
- lk->rqmode = -1;
+ lk->wait_ast = 0;
+ } else {
+ if (lk->lastop != Op_unlockf)
+ lk->wait_ast = 0;
+ }
+
} else {
if (lk->lksb.sb_status != 0) {
- printf("lk %d unknown sb_status %d\n", lk->id,
- lk->lksb.sb_status);
+ printf("unknown sb_status %x\n", lk->lksb.sb_status);
exit(-1);
}
- /* lock completed, now unlock it immediately */
+ if (lk->lastop != Op_unlockf)
+ lk->wait_ast = 0;
lk->grmode = lk->rqmode;
- lk->rqmode = -1;
-
- rv = dlm_ls_unlock(dh, lk->lksb.sb_lkid, 0, &lk->lksb,
- (void *)lk);
- if (!rv) {
- lk->wait_ast = 1;
- lk->rqmode = -1;
- } else {
- char input[32];
- printf("astfn_flood_unlock: dlm_ls_unlock: %d rv %d "
- "errno %d\n", i, rv, errno);
- printf("press X to exit, D to dispatch, "
- "other to continue\n");
- fgets(input, 32, stdin);
- if (input[0] == 'X')
- exit(-1);
- else if (input[0] == 'D')
- dlm_dispatch(libdlm_fd);
- }
}
- if (locks_flood_ast_done == locks_flood_n) {
- printf("astfn_flood_unlock all %d unlocked\n", locks_flood_n);
- if (unlock) {
- free(locks_flood);
- locks_flood = NULL;
- locks_flood_n = 0;
- }
- }
-}
-
-void process_libdlm(void)
-{
- dlm_dispatch(libdlm_fd);
+ lk->rqmode = -1;
}
void lock(int i, int mode)
{
char name[DLM_RESNAME_MAXLEN];
+ struct lk *lk;
int flags = 0;
int rv;
- if (i < 0 || i >= LOCKS)
+ lk = get_lock(i);
+ if (!lk)
return;
if (noqueue)
flags |= LKF_NOQUEUE;
- if (locks[i].lksb.sb_lkid)
+ if (lk->lksb.sb_lkid)
flags |= LKF_CONVERT;
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "test%d", i);
- printf("dlm_ls_lock: %d grmode %d rqmode %d flags %x lkid %x %s\n",
- i, locks[i].grmode, mode, flags, locks[i].lksb.sb_lkid, name);
+ log_verbose("lock: %d grmode %d rqmode %d flags %x lkid %x %s\n",
+ i, lk->grmode, mode, flags, lk->lksb.sb_lkid, name);
- rv = dlm_ls_lock(dh, mode, &locks[i].lksb, flags,
- name, strlen(name), 0, astfn, (void *) &locks[i],
- bastfn, NULL);
+ rv = dlm_ls_lock(dh, mode, &lk->lksb, flags, name, strlen(name), 0,
+ astfn, (void *) lk, bastfn, NULL);
if (!rv) {
- locks[i].wait_ast = 1;
- locks[i].rqmode = mode;
+ lk->wait_ast = 1;
+ lk->rqmode = mode;
+ } else if (rv == -1 && errno == EBUSY) {
+ printf(" : lock %3d\t%x: EBUSY gr %d rq %d wait_ast %d\n",
+ i, lk->lksb.sb_lkid, lk->grmode, lk->rqmode, lk->wait_ast);
+ } else {
+ printf(" : lock %3d\t%x: errno %d gr %d rq %d wait_ast %d\n",
+ i, lk->lksb.sb_lkid, errno, lk->grmode, lk->rqmode, lk->wait_ast);
}
- printf("dlm_ls_lock: %d rv %d sb_lkid %x sb_status %x\n",
- i, rv, locks[i].lksb.sb_lkid, locks[i].lksb.sb_status);
+ log_verbose("lock: %d rv %d sb_lkid %x sb_status %x\n",
+ i, rv, lk->lksb.sb_lkid, lk->lksb.sb_status);
+
+ lk->lastop = Op_lock;
}
void lock_sync(int i, int mode)
@@ -325,35 +319,37 @@
char name[DLM_RESNAME_MAXLEN];
int flags = 0;
int rv;
+ struct lk *lk;
- if (i < 0 || i >= LOCKS)
+ lk = get_lock(i);
+ if (!lk)
return;
if (noqueue)
flags |= LKF_NOQUEUE;
- if (locks[i].lksb.sb_lkid)
+ if (lk->lksb.sb_lkid)
flags |= LKF_CONVERT;
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "test%d", i);
- printf("dlm_ls_lock_wait: %d rqmode %d flags %x lkid %x %s\n",
- i, mode, flags, locks[i].lksb.sb_lkid, name);
+ log_verbose("lock_sync: %d rqmode %d flags %x lkid %x %s\n",
+ i, mode, flags, lk->lksb.sb_lkid, name);
- rv = dlm_ls_lock_wait(dh, mode, &locks[i].lksb, flags,
- name, strlen(name), 0, (void *) &locks[i],
+ rv = dlm_ls_lock_wait(dh, mode, &lk->lksb, flags,
+ name, strlen(name), 0, (void *) lk,
bastfn, NULL);
- printf("dlm_ls_lock_wait: %d rv %d sb_lkid %x sb_status %x\n",
- i, rv, locks[i].lksb.sb_lkid, locks[i].lksb.sb_status);
+ log_verbose("lock_sync: %d rv %d sb_lkid %x sb_status %x\n",
+ i, rv, lk->lksb.sb_lkid, lk->lksb.sb_status);
if (!rv) {
- locks[i].grmode = mode;
- locks[i].rqmode = -1;
+ lk->grmode = mode;
+ lk->rqmode = -1;
} else if (rv == EAGAIN) {
- if (locks[i].grmode == -1)
- memset(&locks[i].lksb, 0, sizeof(struct dlm_lksb));
+ if (lk->grmode == -1)
+ memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
} else {
printf("unknown rv %d\n", rv);
exit(-1);
@@ -364,275 +360,271 @@
{
int i;
- for (i = 0; i < LOCKS; i++)
+ for (i = 0; i < maxn; i++)
lock(i, mode);
}
-void lock_flood(int n, int mode)
+void _unlock(int i, uint32_t flags)
{
struct lk *lk;
- char name[DLM_RESNAME_MAXLEN];
- int flags = 0, rv, i;
-
- if (noqueue)
- flags |= LKF_NOQUEUE;
-
- if (locks_flood) {
- printf("unlock_flood required before another lock_flood\n");
- return;
- }
-
- locks_flood = malloc(n * sizeof(struct lk));
- if (!locks_flood) {
- printf("no mem for %d locks\n", n);
- return;
- }
- locks_flood_n = n;
- locks_flood_ast_done = 0;
- memset(locks_flood, 0, sizeof(*locks_flood));
-
- for (i = 0; i < n; i++) {
- memset(name, 0, sizeof(name));
- snprintf(name, sizeof(name), "testflood%d", i);
- lk = &locks_flood[i];
-
- rv = dlm_ls_lock(dh, mode, &lk->lksb, flags,
- name, strlen(name), 0, astfn_flood, (void *) lk,
- bastfn_flood, NULL);
- if (!rv) {
- lk->wait_ast = 1;
- lk->rqmode = mode;
- }
- }
-}
-
-void unlock(int i)
-{
uint32_t lkid;
int rv;
- if (i < 0 || i >= LOCKS)
+ lk = get_lock(i);
+ if (!lk)
return;
- lkid = locks[i].lksb.sb_lkid;
- if (!lkid) {
- printf("unlock %d skip zero lkid\n", i);
+ lkid = lk->lksb.sb_lkid;
+ if (!lkid)
return;
- }
- printf("dlm_ls_unlock: %d lkid %x\n", i, lkid);
+ log_verbose("unlock: %d lkid %x flags %x\n", i, lkid, flags);
- rv = dlm_ls_unlock(dh, lkid, 0, &locks[i].lksb, &locks[i]);
+ rv = dlm_ls_unlock(dh, lkid, flags, &lk->lksb, lk);
if (!rv) {
- locks[i].wait_ast = 1;
- locks[i].rqmode = -1;
- printf("dlm_ls_unlock: %d\n", i);
+ lk->wait_ast = 1;
+ } else if (rv == -1 && errno == EBUSY) {
+ printf("unlock: EBUSY %d %x flags %x gr %d rq %d wait_ast %d\n",
+ i, lk->lksb.sb_lkid, flags, lk->grmode, lk->rqmode, lk->wait_ast);
} else {
+ printf("unlock: error %d %x flags %x rv %d errno %d gr %d rq %d wait_ast %d\n",
+ i, lk->lksb.sb_lkid, flags, rv, errno, lk->grmode, lk->rqmode,
+ lk->wait_ast);
+#if 0
char input[32];
- printf("dlm_ls_unlock: %d rv %d errno %d\n", i, rv, errno);
- dump();
printf("press X to exit, D to dispatch, other to continue\n");
fgets(input, 32, stdin);
if (input[0] == 'X')
exit(-1);
else if (input[0] == 'D')
dlm_dispatch(libdlm_fd);
+#endif
}
}
+void unlock(int i)
+{
+ struct lk *lk = get_lock(i);
+ _unlock(i, 0);
+ lk->rqmode = -1;
+ lk->lastop = Op_unlock;
+}
+
+void unlockf(int i)
+{
+ struct lk *lk = get_lock(i);
+ _unlock(i, LKF_FORCEUNLOCK);
+ lk->rqmode = -1;
+ lk->lastop = Op_unlockf;
+}
+
+void cancel(int i)
+{
+ struct lk *lk = get_lock(i);
+ _unlock(i, LKF_CANCEL);
+ lk->lastop = Op_cancel;
+}
+
void unlock_sync(int i)
{
uint32_t lkid;
int rv;
+ struct lk *lk;
- if (i < 0 || i >= LOCKS)
+ lk = get_lock(i);
+ if (!lk)
return;
- lkid = locks[i].lksb.sb_lkid;
+ lkid = lk->lksb.sb_lkid;
if (!lkid) {
- printf("unlock %d skip zero lkid\n", i);
+ log_print("unlock %d skip zero lkid\n", i);
return;
}
- printf("dlm_ls_unlock_wait: %d lkid %x\n", i, lkid);
+ log_verbose("unlock_sync: %d lkid %x\n", i, lkid);
- rv = dlm_ls_unlock_wait(dh, lkid, 0, &locks[i].lksb);
+ rv = dlm_ls_unlock_wait(dh, lkid, 0, &lk->lksb);
- printf("dlm_ls_unlock_wait: %d rv %d sb_status %x\n", i, rv,
- locks[i].lksb.sb_status);
+ log_verbose("unlock_sync: %d rv %d sb_status %x\n", i, rv,
+ lk->lksb.sb_status);
- memset(&locks[i].lksb, 0, sizeof(struct dlm_lksb));
- locks[i].grmode = -1;
- locks[i].rqmode = -1;
+ memset(&lk->lksb, 0, sizeof(struct dlm_lksb));
+ lk->grmode = -1;
+ lk->rqmode = -1;
}
void unlock_all(void)
{
+ struct lk *lk;
int i;
- for (i = 0; i < LOCKS; i++)
+ for (i = 0; i < maxn; i++) {
+ lk = get_lock(i);
unlock(i);
+ lk->lastop = Op_unlock;
+ }
}
-void unlock_flood(void)
+void stress(int num)
{
+ int i, o, op, skip;
+ unsigned int n, skips, lock_ops, unlock_ops, unlockf_ops, cancel_ops;
struct lk *lk;
- uint32_t lkid;
- int rv, i;
- if (!locks_flood)
- return;
+ n = skips = lock_ops = unlock_ops = unlockf_ops = cancel_ops = 0;
- if (locks_flood_ast_done != locks_flood_n)
- printf("warning: locks_flood_ast_done %d locks_flood_n %d\n",
- locks_flood_ast_done, locks_flood_n);
+ while (1) {
+ process_libdlm();
- locks_flood_ast_done = 0;
+ if (++n == num)
+ break;
- for (i = 0; i < locks_flood_n; i++) {
- lk = &locks_flood[i];
- lkid = lk->lksb.sb_lkid;
- if (!lkid) {
- printf("unlock_flood %d skip zero lkid\n", i);
+ i = rand_int(0, maxn-1);
+ lk = get_lock(i);
+ if (!lk)
continue;
- }
- rv = dlm_ls_unlock(dh, lkid, 0, &lk->lksb, (void *)lk);
- if (!rv) {
- lk->wait_ast = 1;
- lk->rqmode = -1;
- } else {
- char input[32];
- printf("flood: dlm_ls_unlock: %d rv %d errno %d\n",
- i, rv, errno);
- printf("press X to exit, D to dispatch, "
- "other to continue\n");
- fgets(input, 32, stdin);
- if (input[0] == 'X')
- exit(-1);
- else if (input[0] == 'D')
- dlm_dispatch(libdlm_fd);
+ o = rand_int(0, 5);
+ switch (o) {
+ case 0:
+ case 1:
+ case 2:
+ op = Op_lock;
+ break;
+ case 3:
+ op = Op_unlock;
+ break;
+ case 4:
+ op = Op_unlockf;
+ break;
+ case 5:
+ op = Op_cancel;
+ break;
}
- }
-}
-void flood(int n, int mode)
-{
- struct lk *lk;
- char name[DLM_RESNAME_MAXLEN];
- int flags = 0, rv, i;
+ skip = 0;
- if (noqueue)
- flags |= LKF_NOQUEUE;
+ switch (op) {
+ case Op_lock:
+ if (lk->wait_ast) {
+ skip = 1;
+ break;
+ }
- if (locks_flood) {
- printf("unlock_flood required first\n");
- return;
- }
+ noqueue = !!o;
- locks_flood = malloc(n * sizeof(struct lk));
- if (!locks_flood) {
- printf("no mem for %d locks\n", n);
- return;
- }
- locks_flood_n = n;
- locks_flood_ast_done = 0;
- memset(locks_flood, 0, sizeof(*locks_flood));
+ lock(i, rand_int(0, 5));
+ lock_ops++;
+ printf("%8u: lock %3d\t%x\n", n, i, lk->lksb.sb_lkid);
+ break;
- for (i = 0; i < n; i++) {
- memset(name, 0, sizeof(name));
- snprintf(name, sizeof(name), "testflood%d", i);
- lk = &locks_flood[i];
+ case Op_unlock:
+ if (lk->wait_ast) {
+ skip = 1;
+ break;
+ }
+ if (lk->lastop == Op_unlock || lk->lastop == Op_unlockf) {
+ skip = 1;
+ break;
+ }
+ if (!lk->lksb.sb_lkid) {
+ skip = 1;
+ break;
+ }
- rv = dlm_ls_lock(dh, mode, &lk->lksb, flags,
- name, strlen(name), 0, astfn_flood_unlock, (void *) lk,
- bastfn_flood, NULL);
- if (!rv) {
- lk->wait_ast = 1;
- lk->rqmode = mode;
- }
- }
-}
+ unlock(i);
+ unlock_ops++;
+ printf("%8u: unlock %3d\t%x\n", n, i, lk->lksb.sb_lkid);
+ break;
-void loop(int i, int num)
-{
- int n;
+ case Op_unlockf:
+ if (lk->lastop == Op_unlock || lk->lastop == Op_unlockf) {
+ skip = 1;
+ break;
+ }
+ if (!lk->lksb.sb_lkid) {
+ skip = 1;
+ break;
+ }
- for (n = 0; n < num; n++) {
- lock(i, LKM_PRMODE);
- dlm_dispatch(libdlm_fd);
- unlock(i);
- dlm_dispatch(libdlm_fd);
- /*
- lock_sync(i, LKM_PRMODE);
- unlock_sync(i);
- */
- }
-}
+ unlockf(i);
+ unlockf_ops++;
+ printf("%8u: unlockf %3d\t%x\n", n, i, lk->lksb.sb_lkid);
+ break;
-int rand_int(int a, int b)
-{
- return a + (int) (((float)(b - a + 1)) * random() / (RAND_MAX+1.0));
-}
+ case Op_cancel:
+ if (!lk->wait_ast) {
+ skip = 1;
+ break;
+ }
+ if (lk->lastop > Op_lock) {
+ skip = 1;
+ break;
+ }
-void hammer(int num)
-{
- int n, i, busy = 0, lock_ops = 0, unlock_ops = 0;
+ cancel(i);
+ cancel_ops++;
+ printf("%8u: cancel %3d\t%x\n", n, i, lk->lksb.sb_lkid);
+ break;
+ }
- while (1) {
- dlm_dispatch(libdlm_fd);
+ if (skip)
+ skips++;
+ }
- i = rand_int(0, LOCKS-1);
+ printf("skip %d lock %d unlock %d unlockf %d cancel %d\n",
+ skips, lock_ops, unlock_ops, unlockf_ops, cancel_ops);
+}
- if (locks[i].wait_ast) {
- busy++;
- continue;
- }
+static int client_add(int fd, int *maxi)
+{
+ int i;
- if (locks[i].grmode == -1) {
- lock(i, rand_int(0, 5));
- lock_ops++;
- } else {
- unlock(i);
- unlock_ops++;
+ 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;
+ printf("client %d fd %d added\n", i, fd);
+ return i;
}
-
- if (++n == num)
- break;
}
+ printf("client add failed\n");
+ return -1;
+}
- printf("hammer: locks %d unlocks %d busy %d\n",
- lock_ops, unlock_ops, busy);
-
- unlock_all();;
+static void client_dead(int ci)
+{
+ printf("client %d fd %d dead\n", ci, client[ci].fd);
+ close(client[ci].fd);
+ client[ci].fd = -1;
+ pollfd[ci].fd = -1;
}
-int all_unlocks_done(void)
+static void client_init(void)
{
int i;
- for (i = 0; i < LOCKS; i++) {
- if (locks[i].grmode == -1 && !locks[i].wait_ast)
- continue;
- return 0;
- }
- return 1;
+ for (i = 0; i < client_size; i++)
+ client[i].fd = -1;
}
+
void process_command(int *quit)
{
char inbuf[132];
char cmd[32];
- int x = 0, y = 0;
+ int x = 0, y = 0, z = 0;
fgets(inbuf, sizeof(inbuf), stdin);
- sscanf(inbuf, "%s %d %d", cmd, &x, &y);
+ sscanf(inbuf, "%s %d %d", cmd, &x, &y, &z);
if (!strncmp(cmd, "EXIT", 4)) {
*quit = 1;
unlock_all();
- unlock_flood();
return;
}
@@ -651,6 +643,16 @@
return;
}
+ if (!strncmp(cmd, "unlockf", 7) && strlen(cmd) == 7) {
+ unlockf(x);
+ return;
+ }
+
+ if (!strncmp(cmd, "cancel", 6) && strlen(cmd) == 6) {
+ cancel(x);
+ return;
+ }
+
if (!strncmp(cmd, "lock_sync", 9) && strlen(cmd) == 9) {
lock_sync(x, y);
return;
@@ -673,22 +675,20 @@
exit(0);
}
- if (!strncmp(cmd, "lock_flood", 10) && strlen(cmd) == 10) {
- lock_flood(x, y);
+ if (!strncmp(cmd, "lock-cancel", 11) && strlen(cmd) == 11) {
+ lock(x, y);
+ /* usleep(1000 * z); */
+ cancel(x);
return;
}
- if (!strncmp(cmd, "unlock_flood", 12) && strlen(cmd) == 12) {
- unlock_flood();
+ if (!strncmp(cmd, "lock-unlockf", 12) && strlen(cmd) == 12) {
+ lock(x, y);
+ /* usleep(1000 * z); */
+ unlockf(x);
return;
}
- if (!strncmp(cmd, "unlock_flood-kill", 17) && strlen(cmd) == 17) {
- unlock_flood();
- printf("process exiting\n");
- exit(0);
- }
-
if (!strncmp(cmd, "ex", 2)) {
lock(x, LKM_EXMODE);
return;
@@ -699,71 +699,84 @@
return;
}
- if (!strncmp(cmd, "flood", 5)) {
- flood(x, y);
+ if (!strncmp(cmd, "hold", 4) && strlen(cmd) == 4) {
+ lock_all(LKM_PRMODE);
return;
}
- if (!strncmp(cmd, "hold", 4)) {
+ if (!strncmp(cmd, "hold-kill", 9) && strlen(cmd) == 9) {
lock_all(LKM_PRMODE);
- return;
+ exit(0);
}
- if (!strncmp(cmd, "release", 6)) {
+ if (!strncmp(cmd, "release", 7) && strlen(cmd) == 7) {
unlock_all();
return;
}
+ if (!strncmp(cmd, "release-kill", 12) && strlen(cmd) == 12) {
+ unlock_all();
+ exit(0);
+ }
+
if (!strncmp(cmd, "dump", 4) && strlen(cmd) == 4) {
dump();
return;
}
- if (!strncmp(cmd, "dump_flood", 10) && strlen(cmd) == 10) {
- dump_flood();
+ if (!strncmp(cmd, "stress", 6)) {
+ stress(x);
return;
}
- if (!strncmp(cmd, "loop", 4)) {
- loop(x, y);
+ if (!strncmp(cmd, "noqueue", 7)) {
+ noqueue = !noqueue;
+ printf("noqueue is %s\n", noqueue ? "on" : "off");
return;
}
- if (!strncmp(cmd, "hammer", 6)) {
- hammer(x);
+ if (!strncmp(cmd, "quiet", 5)) {
+ quiet = !quiet;
+ printf("quiet is %d\n", quiet);
return;
}
- if (!strncmp(cmd, "noqueue", 7)) {
- noqueue = !noqueue;
- printf("noqueue is %s\n", noqueue ? "on" : "off");
+ if (!strncmp(cmd, "verbose", 7)) {
+ verbose = !verbose;
+ printf("verbose is %d\n", verbose);
return;
}
if (!strncmp(cmd, "help", 4)) {
printf("Usage:\n");
- printf("MAX locks is %d (x of 0 to %d)\n", LOCKS, LOCKS-1);
+ printf("max locks is %d (x of 0 to %d)\n", maxn, maxn-1);
printf("EXIT - exit program after unlocking any held locks\n");
printf("kill - exit program without unlocking any locks\n");
printf("lock x mode - request/convert lock on resource x\n");
printf("unlock x - unlock lock on resource x\n");
+ printf("unlockf x - force unlock lock on resource x\n");
+ printf("cancel x - cancel lock on resource x\n");
printf("lock_sync x mode - synchronous version of lock\n");
printf("unlock_sync x - synchronous version of unlock\n");
- printf("lock-kill x mode - request/convert lock on resource x, then exit\n");
- printf("unlock-kill x - unlock lock on resource x, then exit\n");
- printf("lock_flood n mode - request n locks (in flood namespace)\n");
- printf("unlock_flood - unlock all from lock_flood\n");
- printf("unlock_flood-kill - unlock all from lock_flood and exit\n");
printf("ex x - equivalent to: lock x 5\n");
printf("pr x - equivalent to: lock x 3\n");
- printf("flood n mode - request n locks, unlock each as it completes\n");
- printf("hold - for x in 0 to MAX, lock x 3\n");
- printf("release - for x in 0 to MAX, unlock x\n");
+ printf("hold - for x in 0 to max, lock x 3\n");
+ printf("release - for x in 0 to max, unlock x\n");
+ printf("stress n - loop doing random lock/unlock/unlockf/cancel on all locks, n times\n");
printf("dump - show info for all resources\n");
- printf("dump_flood - show info for all flood resources\n");
- printf("loop x n - lock_sync x PR / unlock_sync x, n times\n");
- printf("hammer n - loop doing random lock/unlock on all locks, n times\n");
- printf("noqueue - toggle NOQUEUE flag for all requests\n");
+ printf("noqueue - toggle NOQUEUE flag for all requests\n");
+ printf("quiet - toggle quiet flag\n");
+ printf("verbose - toggle verbose flag\n");
+
+ printf("\ncombined operations\n");
+ printf("hold-kill - hold; kill\n");
+ printf("release-kill - release; kill\n");
+ printf("lock-kill x mode - lock; kill\n");
+ printf("unlock-kill x - unlock; kill\n");
+ printf("lock-cancel x mode msec - lock; sleep; cancel\n");
+ printf("lock-unlockf x mode msec - lock; sleep; unlockf\n");
+ printf("lock-cancel-kill x mode msec - lock; sleep; cancel; kill\n");
+ printf("lock-unlockf-kill x mode msec - lock; sleep; unlockf; kill\n");
return;
}
@@ -772,15 +785,28 @@
int main(int argc, char *argv[])
{
+ struct lk *lk;
int i, rv, maxi = 0, quit = 0;
+ if (argc > 1)
+ maxn = atoi(argv[1]);
+ printf("maxn = %d\n", maxn);
+
client_init();
- memset(&locks, 0, sizeof(locks));
- for (i = 0; i < LOCKS; i++) {
- locks[i].id = i;
- locks[i].grmode = -1;
- locks[i].rqmode = -1;
+ locks = malloc(maxn * sizeof(struct lk));
+ if (!locks) {
+ printf("no mem for %d locks\n", maxn);
+ return;
+ }
+ memset(locks, 0, sizeof(*locks));
+
+ lk = locks;
+ for (i = 0; i < maxn; i++) {
+ lk->id = i;
+ lk->grmode = -1;
+ lk->rqmode = -1;
+ lk++;
}
printf("Joining test lockspace...\n");
More information about the Cluster-devel
mailing list