tests/devcount.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+)
New commits: commit fb9e1c158a684e3e5946cd0ab8e6c9aaef65b6cf Author: David Teigland teigland@redhat.com Date: Fri Apr 1 15:44:27 2011 -0500
devcount: add relock test
in progress, designed to test inquire+reacquire
diff --git a/tests/devcount.c b/tests/devcount.c index d7eeef0..1ddbd84 100644 --- a/tests/devcount.c +++ b/tests/devcount.c @@ -325,6 +325,202 @@ static int do_count(int argc, char *argv[]) }
/* + * Test inquire and acquire with version + * + * lock: + * acquire (no lver) + * if fail + * goto lock; + * else + * goto run; + * + * relock: + * acquire with saved lver + * if fail (others may acquire in lock:) + * sigkill pid; + * goto lock; + * else + * sigcont pid; + * goto run; + * + * run: + * run rw for a while + * inquire pid + * save lver + * sigstop pid + * release ALL + * goto relock + * + */ + +static int do_relock(int argc, char *argv[]) +{ + char *av[COUNT_ARGS+1]; + struct sanlk_lockspace lockspace; + struct sanlk_resource *res, *res_inq; + int i, j, pid, rv, sock, len, status; + int res_count; + uint32_t parent_pid = getpid(); + uint64_t lver; + char *state; + + if (argc < LOCK_ARGS) + return -1; + + count_offset = 0; + + strcpy(lock_path, argv[2]); + strcpy(count_path, argv[4]); + our_hostid = atoi(argv[7]); + + len = sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk); + res = malloc(len); + memset(res, 0, len); + strcpy(res->lockspace_name, "devcount"); + snprintf(res->name, SANLK_NAME_LEN, "resource%s", count_path); + res->name[SANLK_NAME_LEN-1] = '\0'; + res->num_disks = 1; + strncpy(res->disks[0].path, lock_path, SANLK_PATH_LEN); + res->disks[0].path[SANLK_PATH_LEN-1] = '\0'; + res->disks[0].offset = 1024000; + + printf("%d lock_disk %s count_disk %s our_hostid %d\n", + parent_pid, lock_path, count_path, our_hostid); + + memset(&lockspace, 0, sizeof(lockspace)); + strcpy(lockspace.name, "devcount"); + strcpy(lockspace.host_id_disk.path, lock_path); + lockspace.host_id_disk.offset = lock_offset; + lockspace.host_id = our_hostid; + + rv = sanlock_add_lockspace(&lockspace, 0); + if (rv < 0) { + printf("%d sanlock_add_lockspace error %d\n", parent_pid, rv); + exit(EXIT_FAILURE); + } + printf("%d sanlock_add_lockspace done\n", parent_pid); + + /* + * argv[0] = devcount + * argv[1] = relock + * argv[2] = <lock_disk> + * argv[3] = rw + * start copying at argv[3] + */ + + j = 0; + memset(av, 0, sizeof(char *) * COUNT_ARGS+1); + + av[j++] = strdup(argv[0]); + for (i = 3; i < LOCK_ARGS; i++) + av[j++] = strdup(argv[i]); + + while (1) { + pid = fork(); + if (!pid) { + int child_pid = getpid(); + + printf("\n"); + + sock = sanlock_register(); + if (sock < 0) { + printf("%d sanlock_register error %d\n", + child_pid, sock); + exit(-1); + } + + res->flags = 0; + res->lver = 0; + + rv = sanlock_acquire(sock, -1, 0, 1, &res, NULL); + if (rv < 0) { + printf("%d sanlock_acquire error %d\n", + child_pid, rv); + /* all hosts are trying to acquire so we + expect this to acquire only sometimes; + TODO: exit with an error for some rv's */ + exit(0); + } + printf("%d sanlock_acquire done\n", child_pid); + + execv(av[0], av); + perror("execv devcount problem"); + exit(EXIT_FAILURE); + } + + run_more: + /* let the child run for 10 seconds before stopping it */ + + for (i = 0; i < 10; i++) { + rv = waitpid(pid, &status, WNOHANG); + if (rv == pid) + break; + sleep(1); + } + + /* we expect child to exit when it fails go acquire the lock + because it's held by someone else, or rw run time is up */ + + if (rv == pid) { + sleep(rand_int(0, 1)); + continue; + } + + rv = sanlock_inquire(-1, pid, 0, &res_count, &state); + if (rv < 0) { + /* FIXME: if child exited this should just continue */ + printf("sanlock_inquire error %d\n", rv); + goto fail; + } + rv = sanlock_str_to_res(state, &res_inq); + if (rv < 0) { + printf("sanlock_str_to_res error %d %s\n", rv, state); + goto fail; + } + lver = res_inq->lver; + free(res_inq); + free(state); + + kill(pid, SIGSTOP); + + rv = sanlock_release(-1, pid, SANLK_REL_ALL, 0, NULL); + if (rv < 0) { + printf("sanlock_release error %d\n", rv); + goto fail; + } + + /* give a chance to someone else to acquire the lock in here */ + usleep(1000000); + + res->flags = SANLK_RES_LVER; + res->lver = lver; + + rv = sanlock_acquire(-1, pid, 0, 1, &res, NULL); + if (!rv) { + /* we got the lock back in the same version */ + + printf("%d sanlock_acquire %llu done\n", parent_pid, + (unsigned long long)lver); + + kill(pid, SIGCONT); + goto run_more; + } + + /* someone got the lock between our release and reacquire */ + + printf("%d sanlock_acquire %llu error %d\n", parent_pid, + (unsigned long long)lver, rv); + + kill(pid, SIGKILL); + sleep(rand_int(0, 1)); + } + + fail: + printf("test failed...\n"); + sleep(1000000); +} + +/* * devcount lock <lock_disk> rw <count_disk> <sec1> <sec2> <hostid> * sanlock add_lockspace -s devcount:<hostid>:<lock_disk>:0 * devcount rw <count_disk> <sec1> <sec2> <hostid> @@ -880,6 +1076,9 @@ int main(int argc, char *argv[]) else if (!strcmp(argv[1], "lock")) rv = do_lock(argc, argv);
+ else if (!strcmp(argv[1], "relock")) + rv = do_relock(argc, argv); + #if 0 else if (!strcmp(argv[1], "migrate")) rv = do_migrate(argc, argv); @@ -910,6 +1109,11 @@ int main(int argc, char *argv[]) printf(" sanlock add_lockspace -s devcount:<hostid>:<lock_disk>:0\n"); printf(" loop around fork, sanlock_acquire, exec devcount rw\n"); printf("\n"); + printf("devcount relock <lock_disk> rw <count_disk> <sec1> <sec2> <hostid>\n"); + printf(" sanlock add_lockspace -s devcount:<hostid>:<lock_disk>:0\n"); + printf(" loop around fork, sanlock_acquire, exec devcount rw\n"); + printf(" sigstop child, inquire, release, re-acquire, sigcont|sigkill\n"); + printf("\n"); printf("devcount rw <count_disk> <sec1> <sec2> <hostid>\n"); printf(" rw: read count for sec1, looking for writes, then write for sec2\n"); printf(" wr: write count for sec1, then read for sec2, looking for writes\n");
sanlock-devel@lists.fedorahosted.org