summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2010-07-29 15:52:54 -0500
committerDavid Teigland <teigland@redhat.com>2010-07-29 15:52:54 -0500
commit7c28d3c824e37de3f4833e3a09648d5a86f42866 (patch)
tree0787524576e4e8a5e83ba6f752b2a14435e2c745
parent44c98e33bf8fc14d744c7989a7257fc710e0867c (diff)
downloaddct-stuff-7c28d3c824e37de3f4833e3a09648d5a86f42866.tar.gz
dct-stuff-7c28d3c824e37de3f4833e3a09648d5a86f42866.tar.xz
dct-stuff-7c28d3c824e37de3f4833e3a09648d5a86f42866.zip
dlm_klock: new test
kernel module that acquires dlm locks Signed-off-by: David Teigland <teigland@redhat.com>
-rw-r--r--dlm/dlm_klock/Kbuild2
-rw-r--r--dlm/dlm_klock/Makefile6
-rw-r--r--dlm/dlm_klock/build.sh4
-rw-r--r--dlm/dlm_klock/dlm_klock.c372
4 files changed, 384 insertions, 0 deletions
diff --git a/dlm/dlm_klock/Kbuild b/dlm/dlm_klock/Kbuild
new file mode 100644
index 0000000..b9df5a5
--- /dev/null
+++ b/dlm/dlm_klock/Kbuild
@@ -0,0 +1,2 @@
+obj-m := dlm_klock.o
+
diff --git a/dlm/dlm_klock/Makefile b/dlm/dlm_klock/Makefile
new file mode 100644
index 0000000..018691f
--- /dev/null
+++ b/dlm/dlm_klock/Makefile
@@ -0,0 +1,6 @@
+
+KERNELDIR := /lib/modules/`uname -r`/build
+
+all::
+ $(MAKE) -C $(KERNELDIR) M=`pwd` $@
+
diff --git a/dlm/dlm_klock/build.sh b/dlm/dlm_klock/build.sh
new file mode 100644
index 0000000..1639c75
--- /dev/null
+++ b/dlm/dlm_klock/build.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+make -C /lib/modules/`uname -r`/build M=`pwd`
+
diff --git a/dlm/dlm_klock/dlm_klock.c b/dlm/dlm_klock/dlm_klock.c
new file mode 100644
index 0000000..a7b533f
--- /dev/null
+++ b/dlm/dlm_klock/dlm_klock.c
@@ -0,0 +1,372 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/file.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/jiffies.h>
+
+#include <linux/dlm.h>
+
+static struct proc_dir_entry *proc_dir = NULL;
+static char ls_name[32];
+static dlm_lockspace_t *ls;
+static struct dlm_lksb lksb;
+static wait_queue_head_t wq;
+static int ast_done;
+
+/*
+ * To test time of remote locks:
+ *
+ * node1:
+ * insmod dlm_klock
+ * echo "1" > /proc/dlm_klock/join
+ * echo "3" > /proc/dlm_klock/lock
+ *
+ * node2:
+ * insmod dlm_klock
+ * echo "1" > /proc/dlm_klock/join
+ * echo "1000" > /proc/dlm_klock/loop
+ *
+ * To test time of local locks:
+ *
+ * node1:
+ * insmod dlm_klock
+ * echo "1" > /proc/dlm_klock/join
+ * echo "1000" > /proc/dlm_klock/loop
+ */
+
+static int wait_done(void)
+{
+ return ast_done;
+}
+
+static void bastfn(void *arg, int mode)
+{
+ printk("bast %d\n", mode);
+}
+
+static void astfn(void *arg)
+{
+ ast_done = 1;
+ wake_up(&wq);
+}
+
+static int lock(int mode)
+{
+ int rv;
+
+ memset(&lksb, 0, sizeof(lksb));
+
+ rv = dlm_lock(ls, mode, &lksb, 0,
+ "klock", 5, 0, astfn, &lksb, bastfn);
+
+ if (rv < 0) {
+ printk("dlm_lock mode %d error %d\n", mode, rv);
+ return rv;
+ }
+
+ wait_event(wq, wait_done());
+ ast_done = 0;
+
+ if (lksb.sb_status != 0) {
+ printk("dlm_lock mode %d status %d\n", mode, lksb.sb_status);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int convert(int mode)
+{
+ int rv;
+
+ rv = dlm_lock(ls, mode, &lksb, DLM_LKF_CONVERT,
+ "klock", 5, 0, astfn, &lksb, bastfn);
+
+ if (rv < 0) {
+ printk("dlm_lock convert mode %d error %d\n", mode, rv);
+ return rv;
+ }
+
+ wait_event(wq, wait_done());
+ ast_done = 0;
+
+ if (lksb.sb_status != 0) {
+ printk("dlm_lock convert mode %d status %d\n", mode, lksb.sb_status);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void unlock(void)
+{
+ int rv;
+
+ rv = dlm_unlock(ls, lksb.sb_lkid, 0, &lksb, &lksb);
+ if (rv < 0) {
+ printk("dlm_unlock %x error %d\n", lksb.sb_lkid, rv);
+ return;
+ }
+
+ wait_event(wq, wait_done());
+ ast_done = 0;
+
+ if (lksb.sb_status != -DLM_EUNLOCK)
+ printk("dlm_unlock status %d\n", lksb.sb_status);
+}
+
+static int loop_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ unsigned long t1, t2, t3, t4;
+ char str[32];
+ int num, i, rv;
+
+ if (!ls)
+ return -1;
+
+ memset(str, 0, sizeof(str));
+
+ if (copy_from_user(str, buffer, count))
+ return -EFAULT;
+ num = (int)simple_strtol(str, NULL, 0);
+
+ printk("loop %d begin\n", num);
+
+ t1 = jiffies;
+
+ rv = lock(DLM_LOCK_NL);
+ if (rv < 0)
+ return -1;
+ printk("lock id %x\n", lksb.sb_lkid);
+
+ t2 = jiffies;
+
+ for (i = 0; i < num; i++) {
+ rv = convert(DLM_LOCK_PR);
+ if (rv < 0)
+ break;
+
+ rv = convert(DLM_LOCK_NL);
+ if (rv < 0)
+ break;
+ }
+
+ t3 = jiffies;
+
+ unlock();
+
+ t4 = jiffies;
+
+ printk("loop %d i %d\n", num, i);
+ printk("jiffies t1 %lu t2 %lu t3 %lu t4 %lu\n", t1, t2, t3, t4);
+ printk("ms lock %u loop %u unlock %u total %u\n",
+ jiffies_to_msecs(t2 - t1),
+ jiffies_to_msecs(t3 - t2),
+ jiffies_to_msecs(t4 - t3),
+ jiffies_to_msecs(t4 - t1));
+
+ return count;
+}
+
+static int lock_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char str[8];
+ int mode;
+
+ if (!ls)
+ return -1;
+
+ memset(str, 0, sizeof(str));
+
+ if (copy_from_user(str, buffer, count))
+ return -EFAULT;
+ mode = (int)simple_strtol(str, NULL, 0);
+
+ lock(mode);
+
+ return count;
+}
+
+static int unlock_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ if (!ls)
+ return -1;
+
+ unlock();
+ return count;
+}
+
+
+static int join_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int rv, i;
+
+ if (ls)
+ return -EBUSY;
+
+ /*
+ if (copy_from_user(ls_name, buffer, count))
+ return -EFAULT;
+
+ memset(ls_name, 0, sizeof(ls_name));
+
+ for (i = 0; i < strlen(ls_name); i++) {
+ if (ls_name[i] == '\n') {
+ ls_name[i] = '\0';
+ break;
+ }
+ }
+ */
+
+#ifdef RHEL4
+ rv = dlm_new_lockspace("klock", 5, &ls, DLM_LSF_NOTIMERS);
+#else
+ rv = dlm_new_lockspace("klock", 5, &ls, DLM_LSFL_FS, 32);
+#endif
+ if (rv < 0)
+ printk("dlm join error %d\n", rv);
+ return count;
+}
+
+static int leave_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char str[40];
+ int rv;
+
+ if (!ls)
+ return -EINVAL;
+
+ memset(str, 0, sizeof(str));
+
+ if (copy_from_user(str, buffer, count))
+ return -EFAULT;
+
+ rv = dlm_release_lockspace(ls, 2);
+ if (rv < 0)
+ return rv;
+
+ ls = NULL;
+ return count;
+}
+
+static void create_proc_entries(void)
+{
+ struct proc_dir_entry *p, *join, *leave, *loop, *lock, *unlock;
+
+ p = join = leave = loop = lock = unlock = NULL;
+
+ proc_dir = proc_mkdir("dlm_klock", 0);
+ if (!proc_dir)
+ return;
+ proc_dir->owner = THIS_MODULE;
+
+ p = create_proc_entry("join", 0666, proc_dir);
+ if (!p)
+ goto out;
+ p->owner = THIS_MODULE;
+ p->write_proc = join_write;
+ join = p;
+
+ p = create_proc_entry("leave", 0666, proc_dir);
+ if (!p)
+ goto out;
+ p->owner = THIS_MODULE;
+ p->write_proc = leave_write;
+ leave = p;
+
+ p = create_proc_entry("loop", 0666, proc_dir);
+ if (!p)
+ goto out;
+ p->owner = THIS_MODULE;
+ p->write_proc = loop_write;
+ loop = p;
+
+ p = create_proc_entry("lock", 0666, proc_dir);
+ if (!p)
+ goto out;
+ p->owner = THIS_MODULE;
+ p->write_proc = lock_write;
+ lock = p;
+
+ p = create_proc_entry("unlock", 0666, proc_dir);
+ if (!p)
+ goto out;
+ p->owner = THIS_MODULE;
+ p->write_proc = unlock_write;
+ unlock = p;
+
+ return;
+
+ out:
+ if (join)
+ remove_proc_entry("join", proc_dir);
+ if (leave)
+ remove_proc_entry("leave", proc_dir);
+ if (loop)
+ remove_proc_entry("loop", proc_dir);
+ if (lock)
+ remove_proc_entry("lock", proc_dir);
+ if (unlock)
+ remove_proc_entry("unlock", proc_dir);
+
+ remove_proc_entry("dlm_klock", NULL);
+ proc_dir = NULL;
+}
+
+static void remove_proc_entries(void)
+{
+ if (proc_dir) {
+ remove_proc_entry("join", proc_dir);
+ remove_proc_entry("leave", proc_dir);
+ remove_proc_entry("loop", proc_dir);
+ remove_proc_entry("lock", proc_dir);
+ remove_proc_entry("unlock", proc_dir);
+ proc_dir = NULL;
+ }
+}
+
+int __init init_klock(void)
+{
+#ifdef RHEL4
+ int rv;
+
+ rv = dlm_init();
+ if (rv < 0)
+ return rv;
+#endif
+ init_waitqueue_head(&wq);
+
+ create_proc_entries();
+
+ printk("dlm_klock (built %s %s) installed\n", __DATE__, __TIME__);
+ return 0;
+}
+
+void __exit exit_klock(void)
+{
+#ifdef RHEL4
+ dlm_release();
+#endif
+ remove_proc_entries();
+}
+
+module_init(init_klock);
+module_exit(exit_klock);
+
+MODULE_DESCRIPTION("DLM kernel locking test");
+MODULE_LICENSE("GPL");
+