tests/devcount-dmsetup | 28 ++++++
tests/devcount.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 231 insertions(+), 3 deletions(-)
New commits:
commit 1ee905695cc9053412fe58aca267e1f0cd69f0fe
Author: David Teigland <teigland(a)redhat.com>
Date: Tue Apr 26 16:15:53 2011 -0500
devcount: add expire test
forces host_id renewals to expire using dmsetup
diff --git a/tests/devcount-dmsetup b/tests/devcount-dmsetup
new file mode 100755
index 0000000..0a92f76
--- /dev/null
+++ b/tests/devcount-dmsetup
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+if [ $# -le 1 ]; then
+ echo "num $#"
+ echo ""
+ echo "devcount-dmsetup save <dev>"
+ echo ""
+ echo "devcount-dmsetup error <dev>"
+ echo ""
+ echo "devcount-dmsetup linear <dev>"
+ echo ""
+fi
+
+cmd=$1
+dev=$2
+
+if [ "$cmd" == "save" ]; then
+ rm -f /tmp/table-linear.txt
+ rm -f /tmp/table-error.txt
+ dmsetup table $dev > /tmp/table-linear.txt
+ sed "s/linear/error/" /tmp/table-linear.txt > /tmp/table-error.txt
+ exit 0
+fi
+
+dmsetup suspend $dev
+dmsetup load $dev /tmp/table-$cmd.txt
+dmsetup resume $dev
+
diff --git a/tests/devcount.c b/tests/devcount.c
index 4ad389f..fc7a1fb 100644
--- a/tests/devcount.c
+++ b/tests/devcount.c
@@ -380,7 +380,7 @@ static int do_count(int argc, char *argv[])
if (write_seconds && (our_we->time - start >= write_seconds))
break;
- if (check_pause(pause_fd)) {
+ if (!(writes % 64) && check_pause(pause_fd)) {
print_our_we(count_path, our_pid, writes, our_we, "pause");
fprintf(stderr, "we_are_paused\n");
raise(SIGSTOP);
@@ -436,7 +436,7 @@ static int do_count(int argc, char *argv[])
return -1;
}
-static void add_lockspace(void)
+static int add_lockspace(void)
{
int rv;
@@ -446,7 +446,11 @@ static void add_lockspace(void)
lockspace.host_id = our_hostid;
rv = sanlock_add_lockspace(&lockspace, 0);
- printf("%d sanlock_add_lockspace %d\n", getpid(), rv);
+
+ log_debug("%s p %d sanlock_add_lockspace %d",
+ lock_path, getpid(), rv);
+
+ return rv;
}
/*
@@ -641,6 +645,7 @@ static int do_relock(int argc, char *argv[])
kill_child:
kill_pid(pid);
+ log_debug("%s p %d killed c %d", count_path, parent_pid, pid);
dead_child:
close(c2p[0]);
close(c2p[1]);
@@ -1126,6 +1131,7 @@ static int do_migrate(int argc, char *argv[])
write_migrate_incoming(state); /* to dest */
kill_pid(pid);
+ log_debug("%s p %d killed c %d", count_path, parent_pid, pid);
close(c2p[0]);
close(c2p[1]);
free(state);
@@ -1137,6 +1143,195 @@ static int do_migrate(int argc, char *argv[])
return -1;
}
+/*
+ * dmsetup table /dev/bull/lock1 > /tmp/table-linear.txt
+ * sed "s/linear/error/" /tmp/table-linear.txt > /tmp/table-error.txt
+ *
+ * dmsetup suspend /dev/bull/lock1
+ * dmsetup load /dev/bull/lock1 /tmp/table-error.txt
+ * dmsetup resume /dev/bull/lock1
+ *
+ * dmsetup suspend /dev/bull/lock1
+ * dmsetup load /dev/bull/lock1 /tmp/table-linear.txt
+ * dmsetup resume /dev/bull/lock1
+ */
+
+static void dmsetup_save_lock_disk(void)
+{
+ char cmd[128];
+ sprintf(cmd, "./devcount-dmsetup save %s", lock_path);
+ system(cmd);
+}
+
+static void dmsetup_error_lock_disk(void)
+{
+ char cmd[128];
+ sprintf(cmd, "./devcount-dmsetup error %s", lock_path);
+ system(cmd);
+}
+
+static void dmsetup_linear_lock_disk(void)
+{
+ char cmd[128];
+ sprintf(cmd, "./devcount-dmsetup linear %s", lock_path);
+ system(cmd);
+}
+
+int do_expire(int argc, char *argv[])
+{
+ char *av[COUNT_ARGS+1];
+ struct sanlk_resource *res;
+ uint32_t parent_pid = getpid();
+ int i, j, pid, rv, sock, len, status;
+ int c2p[2];
+ char result[5];
+
+ if (argc < LOCK_ARGS)
+ return -1;
+
+ count_offset = 0;
+
+ strcpy(lock_path, argv[2]);
+ strcpy(count_path, argv[4]);
+ our_hostid = atoi(argv[7]);
+
+ dmsetup_save_lock_disk();
+
+ add_lockspace();
+
+ len = sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk);
+ res = malloc(len);
+ memset(res, 0, len);
+ strcpy(res->lockspace_name, lockspace.name);
+ 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;
+
+ /*
+ * argv[0] = devcount
+ * argv[1] = expire
+ * argv[2] = <lock_disk>
+ * argv[3] = rw
+ * start copying at argv[3]
+ */
+
+ j = 0;
+ av[j++] = strdup(argv[0]);
+ for (i = 3; i < LOCK_ARGS; i++)
+ av[j++] = strdup(argv[i]);
+ av[j] = NULL;
+
+ while (1) {
+ pipe(c2p);
+
+ pid = fork();
+ if (!pid) {
+ int child_pid = getpid();
+
+ sock = sanlock_register();
+ if (sock < 0) {
+ log_error("%s c %d sanlock_register error %d",
+ count_path, child_pid, sock);
+ exit(-1);
+ }
+
+ /* this acquire can take up to 90 seconds waiting for
+ the host_id of the owner to time out */
+
+ log_debug("%s c %d sanlock_acquire begin",
+ count_path, child_pid);
+
+ rv = sanlock_acquire(sock, -1, 0, 1, &res, NULL);
+ if (rv < 0) {
+ log_debug("%s c %d sanlock_acquire error %d",
+ count_path, 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 */
+
+ write(c2p[1], "fail", 4);
+ close(c2p[0]);
+ close(c2p[1]);
+ exit(0);
+ }
+ log_debug("%s c %d sanlock_acquire done",
+ count_path, child_pid);
+
+ write(c2p[1], "good", 4);
+ close(c2p[0]);
+ close(c2p[1]);
+ execv(av[0], av);
+ perror("execv devcount problem");
+ exit(EXIT_FAILURE);
+ }
+
+ memset(&result, 0, sizeof(result));
+ read(c2p[0], &result, 4);
+ close(c2p[0]);
+ close(c2p[1]);
+
+ if (strstr(result, "fail")) {
+ /* we expect child to exit when it fails to acquire the
+ lock because it's held by someone else */
+ waitpid(pid, &status, 0);
+ goto dead_child;
+ }
+
+ /* this test should be run with sec2 set to some large value
+ that won't run out before sanlock daemon kills rw */
+
+ sleep(rand_int(6, 100));
+
+ dmsetup_error_lock_disk();
+ log_debug("%s p %d disable %s", count_path, parent_pid, lock_path);
+
+ /* sanlock daemon kills pid when the renewals fail; after the
+ kill it will try to release the resource lease, which will
+ also fail if the resource lease is on the same disk as the
+ host_id lease. Other nodes trying to get pid's resource
+ lease are watching our host_id for 90 seconds, after which
+ they will take pid's resource lease. If the resource lease
+ is on a different disk, the daemon will be able to release
+ it after the kill, and another node will be able to take it
+ immediately after that, without watching our host_id for 90
+ seconds */
+
+ /* other nodes can't rely on the daemon being able to kill rw,
+ so they need to wait 90 seconds to ensure that the watchdog
+ has killed the host before taking pid's resource lease.
+ In a different test, have the daemon kill fail, causing rw
+ to continue running until the watchdog fires, after which
+ another host will take pid's resource lease */
+
+ waitpid(pid, &status, 0);
+ log_debug("%s p %d waitpid c %d done", count_path, parent_pid, pid);
+
+ sleep(rand_int(0, 3));
+
+ dmsetup_linear_lock_disk();
+ log_debug("%s p %d enable %s", count_path, parent_pid, lock_path);
+
+ log_debug("%s p %d sanlock_add_lockspace begin",
+ lock_path, parent_pid);
+ while (1) {
+ sleep(1);
+ rv = add_lockspace();
+ if (!rv)
+ break;
+ }
+ dead_child:
+ sleep(rand_int(0, 1));
+ }
+
+ printf("test failed...\n");
+ sleep(1000000);
+ return -1;
+}
+
/*
* devcount init <lock_disk> <count_disk>
* sanlock direct init -n 8 -s devcount:0:<lock_disk>:0
@@ -1248,6 +1443,9 @@ int main(int argc, char *argv[])
else if (!strcmp(argv[1], "migrate"))
rv = do_migrate(argc, argv);
+ else if (!strcmp(argv[1], "expire"))
+ rv = do_expire(argc, argv);
+
if (!rv)
return 0;
@@ -1281,10 +1479,12 @@ int main(int argc, char *argv[])
printf("devcount wrap <lock_disk> rw <count_disk> <sec1>
<sec2> <hostid>\n");
printf(" sanlock add_lockspace -s
devcount:<hostid>:<lock_disk>:0\n");
printf(" sanlock_acquire, exec devcount rw\n");
+ printf("\n");
printf("devcount migrate <lock_disk> rw <count_disk> <sec1>
<sec2> <hostid> <max_hostid>\n");
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 expire <lock_disk> rw <count_disk> <sec1>
<sec2> <hostid>\n");
printf("\n");
return -1;
}