#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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");