dlm: master - libdlm: move files

David Teigland teigland at fedoraproject.org
Fri Sep 30 21:57:40 UTC 2011


Gitweb:        http://git.fedorahosted.org/git/dlm.git?p=dlm.git;a=commitdiff;h=b440452a8a553e1b3df2a92144077ba4459688fc
Commit:        b440452a8a553e1b3df2a92144077ba4459688fc
Parent:        8d03f2e225d3a2109def78ddf9c7bed13575ea2e
Author:        David Teigland <teigland at redhat.com>
AuthorDate:    Fri Sep 30 16:48:57 2011 -0500
Committer:     David Teigland <teigland at redhat.com>
CommitterDate: Fri Sep 30 16:54:07 2011 -0500

libdlm: move files

and new Makefile

Signed-off-by: David Teigland <teigland at redhat.com>
---
 dlm/libdlm/51-dlm.rules            |    5 -
 dlm/libdlm/libdlm.c                | 1487 ------------------------------------
 dlm/libdlm/libdlm.h                |  275 -------
 dlm/libdlm/libdlm_internal.h       |    9 -
 dlm/man/dlm_cleanup.3              |    1 -
 dlm/man/dlm_close_lockspace.3      |    1 -
 dlm/man/dlm_create_lockspace.3     |   94 ---
 dlm/man/dlm_dispatch.3             |    1 -
 dlm/man/dlm_get_fd.3               |    1 -
 dlm/man/dlm_lock.3                 |  239 ------
 dlm/man/dlm_lock_wait.3            |    1 -
 dlm/man/dlm_ls_lock.3              |    1 -
 dlm/man/dlm_ls_lock_wait.3         |    1 -
 dlm/man/dlm_ls_lockx.3             |    1 -
 dlm/man/dlm_ls_pthread_init.3      |    1 -
 dlm/man/dlm_ls_unlock.3            |    1 -
 dlm/man/dlm_ls_unlock_wait.3       |    1 -
 dlm/man/dlm_new_lockspace.3        |    1 -
 dlm/man/dlm_open_lockspace.3       |    1 -
 dlm/man/dlm_pthread_init.3         |    1 -
 dlm/man/dlm_release_lockspace.3    |    1 -
 dlm/man/dlm_unlock.3               |   94 ---
 dlm/man/dlm_unlock_wait.3          |    1 -
 dlm/man/libdlm.3                   |  105 ---
 libdlm/51-dlm.rules                |    5 +
 libdlm/Makefile                    |  117 +++
 libdlm/libdlm.c                    | 1485 +++++++++++++++++++++++++++++++++++
 libdlm/libdlm.h                    |  275 +++++++
 libdlm/libdlm_internal.h           |    9 +
 libdlm/man/dlm_cleanup.3           |    1 +
 libdlm/man/dlm_close_lockspace.3   |    1 +
 libdlm/man/dlm_create_lockspace.3  |   94 +++
 libdlm/man/dlm_dispatch.3          |    1 +
 libdlm/man/dlm_get_fd.3            |    1 +
 libdlm/man/dlm_lock.3              |  239 ++++++
 libdlm/man/dlm_lock_wait.3         |    1 +
 libdlm/man/dlm_ls_lock.3           |    1 +
 libdlm/man/dlm_ls_lock_wait.3      |    1 +
 libdlm/man/dlm_ls_lockx.3          |    1 +
 libdlm/man/dlm_ls_pthread_init.3   |    1 +
 libdlm/man/dlm_ls_unlock.3         |    1 +
 libdlm/man/dlm_ls_unlock_wait.3    |    1 +
 libdlm/man/dlm_new_lockspace.3     |    1 +
 libdlm/man/dlm_open_lockspace.3    |    1 +
 libdlm/man/dlm_pthread_init.3      |    1 +
 libdlm/man/dlm_release_lockspace.3 |    1 +
 libdlm/man/dlm_unlock.3            |   94 +++
 libdlm/man/dlm_unlock_wait.3       |    1 +
 libdlm/man/libdlm.3                |  105 +++
 49 files changed, 2439 insertions(+), 2324 deletions(-)

diff --git a/dlm/libdlm/51-dlm.rules b/dlm/libdlm/51-dlm.rules
deleted file mode 100644
index f71e79d..0000000
--- a/dlm/libdlm/51-dlm.rules
+++ /dev/null
@@ -1,5 +0,0 @@
-KERNEL=="dlm-control", NAME="misc/dlm-control", MODE="0666"
-KERNEL=="dlm-monitor", NAME="misc/dlm-monitor", MODE="0666"
-KERNEL=="dlm_default", NAME="misc/dlm_default", MODE="0666"
-KERNEL=="dlm_*", NAME="misc/%k", MODE="0660"
-
diff --git a/dlm/libdlm/libdlm.c b/dlm/libdlm/libdlm.c
deleted file mode 100644
index 823bb84..0000000
--- a/dlm/libdlm/libdlm.c
+++ /dev/null
@@ -1,1487 +0,0 @@
-#include "clusterautoconfig.h"
-
-#ifdef _REENTRANT
-#include <pthread.h>
-#endif
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <linux/major.h>
-#ifdef HAVE_SELINUX
-#include <selinux/selinux.h>
-#endif
-#include <linux/types.h>
-#include <linux/dlm.h>
-#define BUILDING_LIBDLM
-#include "libdlm.h"
-#include <linux/dlm_device.h>
-
-#define MISC_PREFIX		"/dev/misc/"
-#define DLM_PREFIX		"dlm_"
-#define DLM_MISC_PREFIX		MISC_PREFIX DLM_PREFIX
-#define DLM_CONTROL_NAME	"dlm-control"
-#define DLM_CONTROL_PATH	MISC_PREFIX DLM_CONTROL_NAME
-#define DEFAULT_LOCKSPACE	"default"
-
-/*
- * V5 of the dlm_device.h kernel/user interface structs
- */
-
-struct dlm_lock_params_v5 {
-	__u8 mode;
-	__u8 namelen;
-	__u16 flags;
-	__u32 lkid;
-	__u32 parent;
-	void *castparam;
-	void *castaddr;
-	void *bastparam;
-	void *bastaddr;
-	struct dlm_lksb *lksb;
-	char lvb[DLM_USER_LVB_LEN];
-	char name[0];
-};
-
-struct dlm_write_request_v5 {
-	__u32 version[3];
-	__u8 cmd;
-	__u8 is64bit;
-	__u8 unused[2];
-
-	union  {
-		struct dlm_lock_params_v5 lock;
-		struct dlm_lspace_params lspace;
-	} i;
-};
-
-struct dlm_lock_result_v5 {
-	__u32 length;
-	void *user_astaddr;
-	void *user_astparam;
-	struct dlm_lksb *user_lksb;
-	struct dlm_lksb lksb;
-	__u8 bast_mode;
-	__u8 unused[3];
-	/* Offsets may be zero if no data is present */
-	__u32 lvb_offset;
-};
-
-
-/*
- * One of these per lockspace in use by the application
- */
-
-struct dlm_ls_info {
-    int fd;
-#ifdef _REENTRANT
-    pthread_t tid;
-#else
-    int tid;
-#endif
-};
-
-/*
- * The default lockspace.
- * I've resisted putting locking around this as the user should be
- * "sensible" and only do lockspace operations either in the
- * main thread or ... carefully...
- */
-
-static struct dlm_ls_info *default_ls = NULL;
-static int control_fd = -1;
-static struct dlm_device_version kernel_version;
-static int kernel_version_detected = 0;
-
-
-static int release_lockspace(uint32_t minor, uint32_t flags);
-
-
-static void ls_dev_name(const char *lsname, char *devname, int devlen)
-{
-	snprintf(devname, devlen, DLM_MISC_PREFIX "%s", lsname);
-}
-
-static void dummy_ast_routine(void *arg)
-{
-}
-
-#ifdef _REENTRANT
-/* Used for the synchronous and "simplified, synchronous" API routines */
-struct lock_wait
-{
-    pthread_cond_t  cond;
-    pthread_mutex_t mutex;
-    struct dlm_lksb lksb;
-};
-
-static void sync_ast_routine(void *arg)
-{
-    struct lock_wait *lwait = arg;
-
-    pthread_mutex_lock(&lwait->mutex);
-    pthread_cond_signal(&lwait->cond);
-    pthread_mutex_unlock(&lwait->mutex);
-}
-
-/* lock_resource & unlock_resource
- * are the simplified, synchronous API.
- * Aways uses the default lockspace.
- */
-int lock_resource(const char *resource, int mode, int flags, int *lockid)
-{
-    int status;
-    struct lock_wait lwait;
-
-    if (default_ls == NULL)
-    {
-	if (dlm_pthread_init())
-	{
-	    return -1;
-	}
-    }
-
-    if (!lockid)
-    {
-	errno = EINVAL;
-	return -1;
-    }
-
-    /* Conversions need the lockid in the LKSB */
-    if (flags & LKF_CONVERT)
-	lwait.lksb.sb_lkid = *lockid;
-
-    pthread_cond_init(&lwait.cond, NULL);
-    pthread_mutex_init(&lwait.mutex, NULL);
-    pthread_mutex_lock(&lwait.mutex);
-
-    status = dlm_lock(mode,
-		      &lwait.lksb,
-		      flags,
-		      resource,
-		      strlen(resource),
-		      0,
-		      sync_ast_routine,
-		      &lwait,
-		      NULL,
-		      NULL);
-    if (status)
-	return status;
-
-    /* Wait for it to complete */
-    pthread_cond_wait(&lwait.cond, &lwait.mutex);
-    pthread_mutex_unlock(&lwait.mutex);
-
-    *lockid = lwait.lksb.sb_lkid;
-
-    errno = lwait.lksb.sb_status;
-    if (lwait.lksb.sb_status)
-	return -1;
-    else
-	return 0;
-}
-
-
-int unlock_resource(int lockid)
-{
-    int status;
-    struct lock_wait lwait;
-
-    if (default_ls == NULL)
-    {
-	errno = -ENOTCONN;
-	return -1;
-    }
-
-    pthread_cond_init(&lwait.cond, NULL);
-    pthread_mutex_init(&lwait.mutex, NULL);
-    pthread_mutex_lock(&lwait.mutex);
-
-    status = dlm_unlock(lockid, 0, &lwait.lksb, &lwait);
-
-    if (status)
-	return status;
-
-    /* Wait for it to complete */
-    pthread_cond_wait(&lwait.cond, &lwait.mutex);
-    pthread_mutex_unlock(&lwait.mutex);
-
-    errno = lwait.lksb.sb_status;
-    if (lwait.lksb.sb_status != DLM_EUNLOCK)
-	return -1;
-    else
-	return 0;
-}
-
-/* Tidy up threads after a lockspace is closed */
-static int ls_pthread_cleanup(struct dlm_ls_info *lsinfo)
-{
-    int status = 0;
-    int fd;
-
-    /* Must close the fd after the thread has finished */
-    fd = lsinfo->fd;
-    if (lsinfo->tid)
-    {
-	status = pthread_cancel(lsinfo->tid);
-	if (!status)
-	    pthread_join(lsinfo->tid, NULL);
-    }
-    if (!status)
-    {
-	free(lsinfo);
-	close(fd);
-    }
-
-    return status;
-}
-
-/* Cleanup default lockspace */
-int dlm_pthread_cleanup(void)
-{
-    struct dlm_ls_info *lsinfo = default_ls;
-
-    /* Protect users from their own stupidity */
-    if (!lsinfo)
-	return 0;
-
-    default_ls = NULL;
-
-    return ls_pthread_cleanup(lsinfo);
-}
-#else
-
-/* Non-pthread version of cleanup */
-static int ls_pthread_cleanup(struct dlm_ls_info *lsinfo)
-{
-    close(lsinfo->fd);
-    free(lsinfo);
-    return 0;
-}
-#endif
-
-
-static void set_version_v5(struct dlm_write_request_v5 *req)
-{
-	req->version[0] = kernel_version.version[0];
-	req->version[1] = kernel_version.version[1];
-	req->version[2] = kernel_version.version[2];
-	if (sizeof(long) == sizeof(long long))
-		req->is64bit = 1;
-	else
-		req->is64bit = 0;
-}
-
-static void set_version_v6(struct dlm_write_request *req)
-{
-	req->version[0] = kernel_version.version[0];
-	req->version[1] = kernel_version.version[1];
-	req->version[2] = kernel_version.version[2];
-	if (sizeof(long) == sizeof(long long))
-		req->is64bit = 1;
-	else
-		req->is64bit = 0;
-}
-
-static int open_default_lockspace(void)
-{
-	if (!default_ls) {
-		dlm_lshandle_t ls;
-
-		/* This isn't the race it looks, create_lockspace will
-		 * do the right thing if the lockspace has already been
-		 * created.
-		 */
-
-		ls = dlm_open_lockspace(DEFAULT_LOCKSPACE);
-		if (!ls)
-			ls = dlm_create_lockspace(DEFAULT_LOCKSPACE, 0600);
-		if (!ls)
-			return -1;
-
-		default_ls = (struct dlm_ls_info *)ls;
-	}
-	return 0;
-}
-
-static void detect_kernel_version(void)
-{
-	struct dlm_device_version v;
-	int rv;
-
-	rv = read(control_fd, &v, sizeof(struct dlm_device_version));
-	if (rv < 0) {
-		kernel_version.version[0] = 5;
-		kernel_version.version[1] = 0;
-		kernel_version.version[2] = 0;
-	} else {
-		kernel_version.version[0] = v.version[0];
-		kernel_version.version[1] = v.version[1];
-		kernel_version.version[2] = v.version[2];
-	}
-
-	kernel_version_detected = 1;
-}
-
-static int find_control_minor(int *minor)
-{
-	FILE *f;
-	char name[256];
-	int found = 0, m = 0;
-
-	f = fopen("/proc/misc", "r");
-	if (!f)
-		return -1;
-
-	while (!feof(f)) {
-		if (fscanf(f, "%d %s", &m, name) != 2)
-			continue;
-		if (strcmp(name, DLM_CONTROL_NAME))
-			continue;
-		found = 1;
-		break;
-	}
-	fclose(f);
-
-	if (found) {
-		*minor = m;
-		return 0;
-	}
-	return -1;
-}
-
-static int open_control_device(void)
-{
-	struct stat st;
-	int i, rv, minor, found = 0;
-
-	if (control_fd > -1)
-		goto out;
-
-	rv = find_control_minor(&minor);
-	if (rv < 0)
-		return -1;
-
-	/* wait for udev to create the device */
-
-	for (i = 0; i < 10; i++) {
-		if (stat(DLM_CONTROL_PATH, &st) == 0 &&
-		    minor(st.st_rdev) == minor) {
-			found = 1;
-			break;
-		}
-		sleep(1);
-		continue;
-	}
-
-	if (!found)
-		return -1;
-
-	control_fd = open(DLM_CONTROL_PATH, O_RDWR);
-	if (control_fd == -1)
-		return -1;
-
- out:
-	fcntl(control_fd, F_SETFD, 1);
-
-	if (!kernel_version_detected)
-		detect_kernel_version();
-	return 0;
-}
-
-/* the max number of characters in a sysfs device name, not including \0 */
-#define MAX_SYSFS_NAME 19
-
-static int find_udev_device(const char *lockspace, int minor, char *udev_path)
-{
-	char basename[PATH_MAX];
-	char tmp_path[PATH_MAX];
-	DIR *d;
-	struct dirent *de;
-	struct stat st;
-	size_t basename_len;
-	int i;
-
-	ls_dev_name(lockspace, udev_path, PATH_MAX);
-	snprintf(basename, PATH_MAX, DLM_PREFIX "%s", lockspace);
-	basename_len = strlen(basename);
-
-	for (i = 0; i < 10; i++) {
-
-		/* look for a device with the full name */
-
-		if (stat(udev_path, &st) == 0 && minor(st.st_rdev) == minor)
-			return 0;
-
-		if (basename_len < MAX_SYSFS_NAME) {
-			sleep(1);
-			continue;
-		}
-
-		/* look for a device with a truncated name */
-
-		d = opendir(MISC_PREFIX);
-		while ((de = readdir(d))) {
-			if (de->d_name[0] == '.')
-				continue;
-			if (strlen(de->d_name) < MAX_SYSFS_NAME)
-				continue;
-			if (strncmp(de->d_name, basename, MAX_SYSFS_NAME))
-				continue;
-			snprintf(tmp_path, PATH_MAX, MISC_PREFIX "%s",
-				 de->d_name);
-			if (stat(tmp_path, &st))
-				continue;
-			if (minor(st.st_rdev) != minor)
-				continue;
-
-			/* truncated name */
-			strncpy(udev_path, tmp_path, PATH_MAX);
-			closedir(d);
-			return 0;
-		}
-		closedir(d);
-		sleep(1);
-	}
-
-	return -1;
-}
-
-/*
- * do_dlm_dispatch()
- * Read an ast from the kernel.
- */
-
-static int do_dlm_dispatch_v5(int fd)
-{
-	char resultbuf[sizeof(struct dlm_lock_result_v5) + DLM_USER_LVB_LEN];
-	struct dlm_lock_result_v5 *result = (struct dlm_lock_result_v5 *)resultbuf;
-	char *fullresult = NULL;
-	int status;
-	void (*astaddr)(void *astarg);
-
-	status = read(fd, result, sizeof(resultbuf));
-	if (status <= 0)
-		return -1;
-
-	/* This shouldn't happen any more, can probably be removed */
-
-	if (result->length != status) {
-		int newstat;
-
-		fullresult = malloc(result->length);
-		if (!fullresult)
-			return -1;
-
-		newstat = read(fd, (struct dlm_lock_result_v5 *)fullresult,
-			       result->length);
-
-		/* If it read OK then use the new data. otherwise we can
-		   still deliver the AST, it just might not have all the
-		   info in it...hmmm */
-
-		if (newstat == result->length)
-			result = (struct dlm_lock_result_v5 *)fullresult;
-	} else {
-		fullresult = resultbuf;
-	}
-
-
-	/* Copy lksb to user's buffer - except the LVB ptr */
-	memcpy(result->user_lksb, &result->lksb,
-	       sizeof(struct dlm_lksb) - sizeof(char*));
-
-	/* Flip the status. Kernel space likes negative return codes,
-	   userspace positive ones */
-	result->user_lksb->sb_status = -result->user_lksb->sb_status;
-
-	/* Copy optional items */
-	if (result->lvb_offset)
-		memcpy(result->user_lksb->sb_lvbptr,
-		       fullresult + result->lvb_offset, DLM_LVB_LEN);
-
-	/* Call AST */
-	if (result->user_astaddr) {
-		astaddr = result->user_astaddr;
-		astaddr(result->user_astparam);
-	}
-
-	if (fullresult != resultbuf)
-		free(fullresult);
-
-	return 0;
-}
-
-static int do_dlm_dispatch_v6(int fd)
-{
-	char resultbuf[sizeof(struct dlm_lock_result) + DLM_USER_LVB_LEN];
-	struct dlm_lock_result *result = (struct dlm_lock_result *)resultbuf;
-	int status;
-	void (*astaddr)(void *astarg);
-
-	status = read(fd, result, sizeof(resultbuf));
-	if (status <= 0)
-		return -1;
-
-	/* Copy lksb to user's buffer - except the LVB ptr */
-	memcpy(result->user_lksb, &result->lksb,
-	       sizeof(struct dlm_lksb) - sizeof(char*));
-
-	/* Copy lvb to user's buffer */
-	if (result->lvb_offset)
-		memcpy(result->user_lksb->sb_lvbptr,
-		       (char *)result + result->lvb_offset, DLM_LVB_LEN);
-
-	result->user_lksb->sb_status = -result->user_lksb->sb_status;
-
-	if (result->user_astaddr) {
-		astaddr = result->user_astaddr;
-		astaddr(result->user_astparam);
-	}
-
-	return 0;
-}
-
-static int do_dlm_dispatch(int fd)
-{
-	if (kernel_version.version[0] == 5)
-		return do_dlm_dispatch_v5(fd);
-	else
-		return do_dlm_dispatch_v6(fd);
-}
-
-
-/*
- * sync_write()
- * Helper routine which supports the synchronous DLM calls. This
- * writes a parameter block down to the DLM and waits for the
- * operation to complete. This hides the different completion mechanism
- * used when called from the main thread or the DLM 'AST' thread.
- */
-
-#ifdef _REENTRANT
-
-static int sync_write_v5(struct dlm_ls_info *lsinfo,
-			 struct dlm_write_request_v5 *req, int len)
-{
-	struct lock_wait lwait;
-	int status;
-
-	if (pthread_self() == lsinfo->tid) {
-		/* This is the DLM worker thread, don't use lwait to sync */
-		req->i.lock.castaddr  = dummy_ast_routine;
-		req->i.lock.castparam = NULL;
-
-		status = write(lsinfo->fd, req, len);
-		if (status < 0)
-			return -1;
-
-		while (req->i.lock.lksb->sb_status == EINPROG) {
-			do_dlm_dispatch_v5(lsinfo->fd);
-		}
-	} else {
-		pthread_cond_init(&lwait.cond, NULL);
-		pthread_mutex_init(&lwait.mutex, NULL);
-		pthread_mutex_lock(&lwait.mutex);
-
-		req->i.lock.castaddr  = sync_ast_routine;
-		req->i.lock.castparam = &lwait;
-
-		status = write(lsinfo->fd, req, len);
-		if (status < 0)
-			return -1;
-
-		pthread_cond_wait(&lwait.cond, &lwait.mutex);
-		pthread_mutex_unlock(&lwait.mutex);
-	}
-
-	return status; /* lock status is in the lksb */
-}
-
-static int sync_write_v6(struct dlm_ls_info *lsinfo,
-			 struct dlm_write_request *req, int len)
-{
-	struct lock_wait lwait;
-	int status;
-
-	if (pthread_self() == lsinfo->tid) {
-		/* This is the DLM worker thread, don't use lwait to sync */
-		req->i.lock.castaddr  = dummy_ast_routine;
-		req->i.lock.castparam = NULL;
-
-		status = write(lsinfo->fd, req, len);
-		if (status < 0)
-			return -1;
-
-		while (req->i.lock.lksb->sb_status == EINPROG) {
-			do_dlm_dispatch_v6(lsinfo->fd);
-		}
-	} else {
-		pthread_cond_init(&lwait.cond, NULL);
-		pthread_mutex_init(&lwait.mutex, NULL);
-		pthread_mutex_lock(&lwait.mutex);
-
-		req->i.lock.castaddr  = sync_ast_routine;
-		req->i.lock.castparam = &lwait;
-
-		status = write(lsinfo->fd, req, len);
-		if (status < 0)
-			return -1;
-
-		pthread_cond_wait(&lwait.cond, &lwait.mutex);
-		pthread_mutex_unlock(&lwait.mutex);
-	}
-
-	return status; /* lock status is in the lksb */
-}
-
-#else /* _REENTRANT */
-
-static int sync_write_v5(struct dlm_ls_info *lsinfo,
-			 struct dlm_write_request_v5 *req, int len)
-{
-	int status;
-
-	req->i.lock.castaddr  = dummy_ast_routine;
-	req->i.lock.castparam = NULL;
-
-	status = write(lsinfo->fd, req, len);
-	if (status < 0)
-		return -1;
-
-	while (req->i.lock.lksb->sb_status == EINPROG) {
-		do_dlm_dispatch_v5(lsinfo->fd);
-	}
-
-	errno = req->i.lock.lksb->sb_status;
-	if (errno && errno != EUNLOCK)
-		return -1;
-	return 0;
-}
-
-static int sync_write_v6(struct dlm_ls_info *lsinfo,
-			 struct dlm_write_request *req, int len)
-{
-	int status;
-
-	req->i.lock.castaddr  = dummy_ast_routine;
-	req->i.lock.castparam = NULL;
-
-	status = write(lsinfo->fd, req, len);
-	if (status < 0)
-		return -1;
-
-	while (req->i.lock.lksb->sb_status == EINPROG) {
-		do_dlm_dispatch_v6(lsinfo->fd);
-	}
-
-	errno = req->i.lock.lksb->sb_status;
-	if (errno && errno != EUNLOCK)
-		return -1;
-	return 0;
-}
-
-#endif /* _REENTRANT */
-
-
-/*
- * Lock
- * All the ways to request/convert a lock
- */
-
-static int ls_lock_v5(dlm_lshandle_t ls,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,
-		void (*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg))
-{
-	char parambuf[sizeof(struct dlm_write_request_v5) + DLM_RESNAME_MAXLEN];
-	struct dlm_write_request_v5 *req = (struct dlm_write_request_v5 *)parambuf;
-	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-	int status;
-	int len;
-
-	memset(req, 0, sizeof(*req));
-	set_version_v5(req);
-
-	req->cmd = DLM_USER_LOCK;
-	req->i.lock.mode = mode;
-	req->i.lock.flags = (flags & ~LKF_WAIT);
-	req->i.lock.lkid = lksb->sb_lkid;
-	req->i.lock.parent = parent;
-	req->i.lock.lksb = lksb;
-	req->i.lock.castaddr = astaddr;
-	req->i.lock.bastaddr = bastaddr;
-	req->i.lock.castparam = astarg;	/* same comp and blocking ast arg */
-	req->i.lock.bastparam = astarg;
-
-	if (flags & LKF_CONVERT) {
-		req->i.lock.namelen = 0;
-	} else {
-		if (namelen > DLM_RESNAME_MAXLEN) {
-			errno = EINVAL;
-			return -1;
-		}
-		req->i.lock.namelen = namelen;
-		memcpy(req->i.lock.name, name, namelen);
-	}
-
-	if (flags & LKF_VALBLK) {
-		memcpy(req->i.lock.lvb, lksb->sb_lvbptr, DLM_LVB_LEN);
-	}
-
-	len = sizeof(struct dlm_write_request_v5) + namelen;
-	lksb->sb_status = EINPROG;
-
-	if (flags & LKF_WAIT)
-		status = sync_write_v5(lsinfo, req, len);
-	else
-		status = write(lsinfo->fd, req, len);
-
-	if (status < 0)
-		return -1;
-
-	/*
-	 * the lock id is the return value from the write on the device
-	 */
-
-	if (status > 0)
-		lksb->sb_lkid = status;
-	return 0;
-}
-
-static int ls_lock_v6(dlm_lshandle_t ls,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,
-		void (*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg),
-		uint64_t *xid,
-		uint64_t *timeout)
-{
-	char parambuf[sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN];
-	struct dlm_write_request *req = (struct dlm_write_request *)parambuf;
-	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-	int status;
-	int len;
-
-	memset(req, 0, sizeof(*req));
-	set_version_v6(req);
-
-	req->cmd = DLM_USER_LOCK;
-	req->i.lock.mode = mode;
-	req->i.lock.flags = (flags & ~LKF_WAIT);
-	req->i.lock.lkid = lksb->sb_lkid;
-	req->i.lock.parent = parent;
-	req->i.lock.lksb = lksb;
-	req->i.lock.castaddr = astaddr;
-	req->i.lock.bastaddr = bastaddr;
-	req->i.lock.castparam = astarg;	/* same comp and blocking ast arg */
-	req->i.lock.bastparam = astarg;
-
-	if (xid)
-		req->i.lock.xid = *xid;
-	if (timeout)
-		req->i.lock.timeout = *timeout;
-
-	if (flags & LKF_CONVERT) {
-		req->i.lock.namelen = 0;
-	} else {
-		if (namelen > DLM_RESNAME_MAXLEN) {
-			errno = EINVAL;
-			return -1;
-		}
-		req->i.lock.namelen = namelen;
-		memcpy(req->i.lock.name, name, namelen);
-	}
-
-	if (flags & LKF_VALBLK) {
-		memcpy(req->i.lock.lvb, lksb->sb_lvbptr, DLM_LVB_LEN);
-	}
-
-	len = sizeof(struct dlm_write_request) + namelen;
-	lksb->sb_status = EINPROG;
-
-	if (flags & LKF_WAIT)
-		status = sync_write_v6(lsinfo, req, len);
-	else
-		status = write(lsinfo->fd, req, len);
-
-	if (status < 0)
-		return -1;
-
-	/*
-	 * the lock id is the return value from the write on the device
-	 */
-
-	if (status > 0)
-		lksb->sb_lkid = status;
-	return 0;
-}
-
-static int ls_lock(dlm_lshandle_t ls,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,
-		void (*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg),
-		void *range)
-{
-	/* no support for range locks */
-	if (range) {
-		errno = ENOSYS;
-		return -1;
-	}
-
-	if (flags & LKF_VALBLK && !lksb->sb_lvbptr) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (kernel_version.version[0] == 5)
-		return ls_lock_v5(ls, mode, lksb, flags, name, namelen, parent,
-				  astaddr, astarg, bastaddr);
-	else
-		return ls_lock_v6(ls, mode, lksb, flags, name, namelen, parent,
-				  astaddr, astarg, bastaddr, NULL, NULL);
-}
-
-/*
- * Extended async locking in own lockspace
- */
-int dlm_ls_lockx(dlm_lshandle_t ls,
-		 uint32_t mode,
-		 struct dlm_lksb *lksb,
-		 uint32_t flags,
-		 const void *name,
-		 unsigned int namelen,
-		 uint32_t parent,
-		 void (*astaddr) (void *astarg),
-		 void *astarg,
-		 void (*bastaddr) (void *astarg),
-		 uint64_t *xid,
-		 uint64_t *timeout)
-{
-	if (kernel_version.version[0] < 6) {
-		errno = ENOSYS;
-		return -1;
-	}
-
-	return ls_lock_v6(ls, mode, lksb, flags, name, namelen, parent,
-			  astaddr, astarg, bastaddr, xid, timeout);
-}
-
-/*
- * Async locking in own lockspace
- */
-int dlm_ls_lock(dlm_lshandle_t ls,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,
-		void (*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg),
-		void *range)
-{
-	return ls_lock(ls, mode, lksb, flags, name, namelen, parent,
-		       astaddr, astarg, bastaddr, range);
-}
-
-/*
- * Sync locking in own lockspace
- */
-int dlm_ls_lock_wait(dlm_lshandle_t ls,
-		     uint32_t mode,
-		     struct dlm_lksb *lksb,
-		     uint32_t flags,
-		     const void *name,
-		     unsigned int namelen,
-		     uint32_t parent,
-		     void *bastarg,
-		     void (*bastaddr) (void *bastarg),
-		     void *range)
-{
-	return ls_lock(ls, mode, lksb, flags | LKF_WAIT, name, namelen, parent,
-		       NULL, bastarg, bastaddr, range);
-}
-
-/*
- * Async locking in the default lockspace
- */
-int dlm_lock(uint32_t mode,
-	     struct dlm_lksb *lksb,
-	     uint32_t flags,
-	     const void *name,
-	     unsigned int namelen,
-	     uint32_t parent,
-	     void (*astaddr) (void *astarg),
-	     void *astarg,
-	     void (*bastaddr) (void *astarg),
-	     void *range)
-{
-	if (open_default_lockspace())
-		return -1;
-
-	return ls_lock(default_ls, mode, lksb, flags, name, namelen, parent,
-		       astaddr, astarg, bastaddr, range);
-}
-
-/*
- * Sync locking in the default lockspace
- */
-int dlm_lock_wait(uint32_t mode,
-		     struct dlm_lksb *lksb,
-		     uint32_t flags,
-		     const void *name,
-		     unsigned int namelen,
-		     uint32_t parent,
-		     void *bastarg,
-		     void (*bastaddr) (void *bastarg),
-		     void *range)
-{
-	if (open_default_lockspace())
-		return -1;
-
-	return ls_lock(default_ls, mode, lksb, flags | LKF_WAIT, name, namelen,
-		       parent, NULL, bastarg, bastaddr, range);
-}
-
-
-/*
- * Unlock
- * All the ways to unlock/cancel a lock
- */
-
-static int ls_unlock_v5(struct dlm_ls_info *lsinfo, uint32_t lkid,
-			uint32_t flags, struct dlm_lksb *lksb, void *astarg)
-{
-	struct dlm_write_request_v5 req;
-
-	set_version_v5(&req);
-	req.cmd = DLM_USER_UNLOCK;
-	req.i.lock.lkid = lkid;
-	req.i.lock.flags = (flags & ~LKF_WAIT);
-	req.i.lock.lksb  = lksb;
-	req.i.lock.castparam = astarg;
-	/* DLM_USER_UNLOCK will default to existing completion AST */
-	req.i.lock.castaddr = 0;
-	lksb->sb_status = EINPROG;
-
-	if (flags & LKF_WAIT)
-		return sync_write_v5(lsinfo, &req, sizeof(req));
-	else
-		return write(lsinfo->fd, &req, sizeof(req));
-}
-
-static int ls_unlock_v6(struct dlm_ls_info *lsinfo, uint32_t lkid,
-			uint32_t flags, struct dlm_lksb *lksb, void *astarg)
-{
-	struct dlm_write_request req;
-
-	set_version_v6(&req);
-	req.cmd = DLM_USER_UNLOCK;
-	req.i.lock.lkid = lkid;
-	req.i.lock.flags = (flags & ~LKF_WAIT);
-	req.i.lock.lksb  = lksb;
-	req.i.lock.namelen = 0;
-	req.i.lock.castparam = astarg;
-	/* DLM_USER_UNLOCK will default to existing completion AST */
-	req.i.lock.castaddr = 0;
-	lksb->sb_status = EINPROG;
-
-	if (flags & LKF_WAIT)
-		return sync_write_v6(lsinfo, &req, sizeof(req));
-	else
-		return write(lsinfo->fd, &req, sizeof(req));
-}
-
-int dlm_ls_unlock(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags,
-		  struct dlm_lksb *lksb, void *astarg)
-{
-	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-	int status;
-
-	if (ls == NULL) {
-		errno = ENOTCONN;
-		return -1;
-	}
-
-	if (!lkid) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (kernel_version.version[0] == 5)
-		status = ls_unlock_v5(lsinfo, lkid, flags, lksb, astarg);
-	else
-		status = ls_unlock_v6(lsinfo, lkid, flags, lksb, astarg);
-
-	if (status < 0)
-		return -1;
-	return 0;
-}
-
-int dlm_ls_unlock_wait(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags,
-		       struct dlm_lksb *lksb)
-{
-	return dlm_ls_unlock(ls, lkid, flags | LKF_WAIT, lksb, NULL);
-}
-
-int dlm_unlock_wait(uint32_t lkid, uint32_t flags, struct dlm_lksb *lksb)
-{
-	return dlm_ls_unlock_wait(default_ls, lkid, flags | LKF_WAIT, lksb);
-}
-
-int dlm_unlock(uint32_t lkid, uint32_t flags, struct dlm_lksb *lksb,
-	       void *astarg)
-{
-	return dlm_ls_unlock(default_ls, lkid, flags, lksb, astarg);
-}
-
-int dlm_ls_deadlock_cancel(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags)
-{
-	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-	struct dlm_write_request req;
-
-	if (kernel_version.version[0] < 6) {
-		errno = ENOSYS;
-		return -1;
-	}
-
-	if (ls == NULL) {
-		errno = ENOTCONN;
-		return -1;
-	}
-
-	if (!lkid) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	set_version_v6(&req);
-	req.cmd = DLM_USER_DEADLOCK;
-	req.i.lock.lkid = lkid;
-	req.i.lock.flags = flags;
-
-	return write(lsinfo->fd, &req, sizeof(req));
-}
-
-
-/*
- * Purge
- * Clear away orphan locks
- */
-
-int dlm_ls_purge(dlm_lshandle_t ls, int nodeid, int pid)
-{
-	struct dlm_write_request req;
-	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-	int status;
-
-	if (kernel_version.version[0] < 6) {
-		errno = ENOSYS;
-		return -1;
-	}
-
-	if (ls == NULL) {
-		errno = ENOTCONN;
-		return -1;
-	}
-
-	set_version_v6(&req);
-	req.cmd = DLM_USER_PURGE;
-	req.i.purge.nodeid = nodeid;
-	req.i.purge.pid = pid;
-
-	status = write(lsinfo->fd, &req, sizeof(req));
-
-	if (status < 0)
-		return -1;
-	return 0;
-}
-
-
-/* These two routines for for users that want to
- * do their own fd handling.
- * This allows a non-threaded app to use the DLM.
- */
-int dlm_get_fd(void)
-{
-    if (default_ls)
-    {
-	return default_ls->fd;
-    }
-    else
-    {
-	if (open_default_lockspace())
-	    return -1;
-	else
-	    return default_ls->fd;
-    }
-}
-
-int dlm_dispatch(int fd)
-{
-    int status;
-    int fdflags;
-
-    fdflags = fcntl(fd, F_GETFL, 0);
-    fcntl(fd, F_SETFL,  fdflags | O_NONBLOCK);
-    do
-    {
-	status = do_dlm_dispatch(fd);
-    } while (status == 0);
-
-    /* EAGAIN is not an error */
-    if (status < 0 && errno == EAGAIN)
-	status = 0;
-
-    fcntl(fd, F_SETFL, fdflags);
-    return status;
-}
-
-/* Converts a lockspace handle into a file descriptor */
-int dlm_ls_get_fd(dlm_lshandle_t lockspace)
-{
-    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)lockspace;
-
-    return lsinfo->fd;
-}
-
-#ifdef _REENTRANT
-static void *dlm_recv_thread(void *lsinfo)
-{
-	struct dlm_ls_info *lsi = lsinfo;
-
-	for (;;)
-		do_dlm_dispatch(lsi->fd);
-
-	return NULL;
-}
-
-/* Multi-threaded callers normally use this */
-int dlm_pthread_init(void)
-{
-    if (open_default_lockspace())
-	return -1;
-
-    if (default_ls->tid)
-    {
-	errno = EEXIST;
-	return -1;
-    }
-
-    if (pthread_create(&default_ls->tid, NULL, dlm_recv_thread, default_ls))
-    {
-	int saved_errno = errno;
-	close(default_ls->fd);
-	free(default_ls);
-	default_ls = NULL;
-	errno = saved_errno;
-	return -1;
-    }
-    return 0;
-}
-
-/* And same, for those with their own lockspace */
-int dlm_ls_pthread_init(dlm_lshandle_t ls)
-{
-    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-
-    if (lsinfo->tid)
-    {
-	errno = EEXIST;
-	return -1;
-    }
-
-    return pthread_create(&lsinfo->tid, NULL, dlm_recv_thread, (void *)ls);
-}
-#endif
-
-/*
- * Lockspace manipulation functions
- * Privileged users (checked by the kernel) can create/release lockspaces
- */
-
-static int create_lockspace_v5(const char *name, uint32_t flags)
-{
-	char reqbuf[sizeof(struct dlm_write_request_v5) + DLM_LOCKSPACE_LEN];
-	struct dlm_write_request_v5 *req = (struct dlm_write_request_v5 *)reqbuf;
-	int namelen = strlen(name);
-	int minor;
-
-	memset(reqbuf, 0, sizeof(reqbuf));
-	set_version_v5(req);
-
-	req->cmd = DLM_USER_CREATE_LOCKSPACE;
-	req->i.lspace.flags = flags;
-
-	if (namelen > DLM_LOCKSPACE_LEN) {
-		errno = EINVAL;
-		return -1;
-	}
-	memcpy(req->i.lspace.name, name, namelen);
-
-	minor = write(control_fd, req, sizeof(*req) + namelen);
-
-	return minor;
-}
-
-static int create_lockspace_v6(const char *name, uint32_t flags)
-{
-	char reqbuf[sizeof(struct dlm_write_request) + DLM_LOCKSPACE_LEN];
-	struct dlm_write_request *req = (struct dlm_write_request *)reqbuf;
-	int namelen = strlen(name);
-	int minor;
-
-	memset(reqbuf, 0, sizeof(reqbuf));
-	set_version_v6(req);
-
-	req->cmd = DLM_USER_CREATE_LOCKSPACE;
-	req->i.lspace.flags = flags;
-
-	if (namelen > DLM_LOCKSPACE_LEN) {
-		errno = EINVAL;
-		return -1;
-	}
-	memcpy(req->i.lspace.name, name, namelen);
-
-	minor = write(control_fd, req, sizeof(*req) + namelen);
-
-	return minor;
-}
-
-static dlm_lshandle_t create_lockspace(const char *name, mode_t mode,
-				       uint32_t flags)
-{
-	char dev_path[PATH_MAX];
-	char udev_path[PATH_MAX];
-	struct dlm_ls_info *newls;
-	int error, saved_errno, minor;
-
-	/* We use the control device for creating lockspaces. */
-	if (open_control_device())
-		return NULL;
-
-	newls = malloc(sizeof(struct dlm_ls_info));
-	if (!newls)
-		return NULL;
-
-	ls_dev_name(name, dev_path, sizeof(dev_path));
-
-	if (kernel_version.version[0] == 5)
-		minor = create_lockspace_v5(name, flags);
-	else
-		minor = create_lockspace_v6(name, flags);
-
-	if (minor < 0)
-		goto fail;
-
-	/* Wait for udev to create the device; the device it creates may
-	   have a truncated name due to the sysfs device name limit. */
-	   
-	error = find_udev_device(name, minor, udev_path);
-	if (error)
-		goto fail;
-
-	/* If the symlink already exists, find_udev_device() will return
-	   it and we'll skip this. */
-
-	if (strcmp(dev_path, udev_path)) {
-		error = symlink(udev_path, dev_path);
-		if (error)
-			goto fail;
-	}
-
-	/* Open it and return the struct as a handle */
-
-	newls->fd = open(dev_path, O_RDWR);
-	if (newls->fd == -1)
-		goto fail;
-	if (mode)
-		fchmod(newls->fd, mode);
-	newls->tid = 0;
-	fcntl(newls->fd, F_SETFD, 1);
-	return (dlm_lshandle_t)newls;
-
- fail:
-	saved_errno = errno;
-	free(newls);
-	errno = saved_errno;
-	return NULL;
-}
-
-dlm_lshandle_t dlm_new_lockspace(const char *name, mode_t mode, uint32_t flags)
-{
-	return create_lockspace(name, mode, flags);
-}
-
-dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode)
-{
-	return create_lockspace(name, mode, 0);
-}
-
-static int release_lockspace_v5(uint32_t minor, uint32_t flags)
-{
-	struct dlm_write_request_v5 req;
-
-	set_version_v5(&req);
-	req.cmd = DLM_USER_REMOVE_LOCKSPACE;
-	req.i.lspace.minor = minor;
-	req.i.lspace.flags = flags;
-
-	return write(control_fd, &req, sizeof(req));
-}
-
-static int release_lockspace_v6(uint32_t minor, uint32_t flags)
-{
-	struct dlm_write_request req;
-
-	set_version_v6(&req);
-	req.cmd = DLM_USER_REMOVE_LOCKSPACE;
-	req.i.lspace.minor = minor;
-	req.i.lspace.flags = flags;
-
-	return write(control_fd, &req, sizeof(req));
-}
-
-static int release_lockspace(uint32_t minor, uint32_t flags)
-{
-	if (kernel_version.version[0] == 5)
-		return release_lockspace_v5(minor, flags);
-	else
-		return release_lockspace_v6(minor, flags);
-}
-
-int dlm_release_lockspace(const char *name, dlm_lshandle_t ls, int force)
-{
-	char dev_path[PATH_MAX];
-	struct stat st;
-	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-	uint32_t flags = 0;
-	int fd, is_symlink = 0;
-
-	ls_dev_name(name, dev_path, sizeof(dev_path));
-	if (!lstat(dev_path, &st) && S_ISLNK(st.st_mode))
-		is_symlink = 1;
-
-	/* We need the minor number */
-	if (fstat(lsinfo->fd, &st))
-		return -1;
-
-	/* Close the lockspace first if it's in use */
-	ls_pthread_cleanup(lsinfo);
-
-	if (open_control_device())
-		return -1;
-
-	if (force)
-		flags = DLM_USER_LSFLG_FORCEFREE;
-
-	release_lockspace(minor(st.st_rdev), flags);
-
-	if (!is_symlink)
-		return 0;
-
-	/* The following open is used to detect if our release was the last.
-	   It will fail if our release was the last, because either:
-	   . udev has already removed the truncated sysfs device name (ENOENT)
-	   . the misc device has been deregistered in the kernel (ENODEV)
-	     (the deregister completes before release returns)
-
-	   So, if the open fails, we know that our release was the last,
-	   udev will be removing the device with the truncated name (if it
-	   hasn't already), and we should remove the symlink. */
-
-	fd = open(dev_path, O_RDWR);
-	if (fd < 0)
-		unlink(dev_path);
-	else
-		close(fd); /* our release was not the last */
-
-	return 0;
-}
-
-/*
- * Normal users just open/close lockspaces
- */
-
-dlm_lshandle_t dlm_open_lockspace(const char *name)
-{
-	char dev_name[PATH_MAX];
-	struct dlm_ls_info *newls;
-	int saved_errno;
-
-	/* Need to detect kernel version */
-	if (open_control_device())
-		return NULL;
-
-	newls = malloc(sizeof(struct dlm_ls_info));
-	if (!newls)
-		return NULL;
-
-	newls->tid = 0;
-	ls_dev_name(name, dev_name, sizeof(dev_name));
-
-	newls->fd = open(dev_name, O_RDWR);
-	saved_errno = errno;
-
-	if (newls->fd == -1) {
-		free(newls);
-		errno = saved_errno;
-		return NULL;
-	}
-	fcntl(newls->fd, F_SETFD, 1);
-	return (dlm_lshandle_t)newls;
-}
-
-int dlm_close_lockspace(dlm_lshandle_t ls)
-{
-	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-
-	ls_pthread_cleanup(lsinfo);
-	return 0;
-}
-
-int dlm_kernel_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
-{
-	if (open_control_device())
-		return -1;
-	*major = kernel_version.version[0];
-	*minor = kernel_version.version[1];
-	*patch = kernel_version.version[2];
-	return 0;
-}
-
-void dlm_library_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
-{
-	*major = DLM_DEVICE_VERSION_MAJOR;
-	*minor = DLM_DEVICE_VERSION_MINOR;
-	*patch = DLM_DEVICE_VERSION_PATCH;
-}
-
diff --git a/dlm/libdlm/libdlm.h b/dlm/libdlm/libdlm.h
deleted file mode 100644
index 17a552c..0000000
--- a/dlm/libdlm/libdlm.h
+++ /dev/null
@@ -1,275 +0,0 @@
-#ifndef __LIBDLM_H
-#define __LIBDLM_H
-
-/*
- * Typedefs for things that are compatible with the kernel but replicated here
- * so that users only need the libdlm include file.  libdlm itself needs the
- * full kernel file so shouldn't use these.
- */
-
-#define DLM_LVB_LEN             32
-
-#ifndef BUILDING_LIBDLM
-
-/*
- * These two lengths are copied from linux/dlmconstants.h
- * They are the max length of a lockspace name and the max length of a
- * resource name.
- */
-
-#define DLM_LOCKSPACE_LEN       64
-#define DLM_RESNAME_MAXLEN      64
-
-struct dlm_lksb {
-	int sb_status;
-	uint32_t sb_lkid;
-	char sb_flags;
-	char *sb_lvbptr;
-};
-
-/* lksb flags */
-#define DLM_SBF_DEMOTED         0x01
-#define DLM_SBF_VALNOTVALID     0x02
-#define DLM_SBF_ALTMODE         0x04
-
-/* dlm_new_lockspace flags */
-#define DLM_LSFL_NODIR          0x00000001
-#define DLM_LSFL_TIMEWARN       0x00000002
-#define DLM_LSFL_FS             0x00000004
-#define DLM_LSFL_NEWEXCL        0x00000008
-
-#endif
-
-
-#if 0
-/* Dummy definition to keep linkages */
-struct dlm_queryinfo;
-#endif
-
-extern int dlm_kernel_version(uint32_t *maj, uint32_t *min, uint32_t *patch);
-extern void dlm_library_version(uint32_t *maj, uint32_t *min, uint32_t *patch);
-
-
-/*
- * Using the default lockspace
- *
- * lock_resource() - simple sync request or convert (requires pthreads)
- * unlock_resource() - simple sync unlock (requires pthreads)
- * dlm_lock() - async request or convert
- * dlm_unlock() - async unlock or cancel
- * dlm_lock_wait() - sync request or convert
- * dlm_unlock_wait() - sync unlock or cancel
- */
-
-#ifdef _REENTRANT
-extern int lock_resource(const char *resource, int mode, int flags, int *lockid);
-extern int unlock_resource(int lockid);
-#endif
-
-extern int dlm_lock(uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,			/* unusued */
-		void (*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg),
-		void *range);				/* unused */
-
-extern int dlm_unlock(uint32_t lkid,
-		uint32_t flags,
-		struct dlm_lksb *lksb,
-		void *astarg);
-
-extern int dlm_lock_wait(uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,			/* unused */
-		void *bastarg,
-		void (*bastaddr) (void *bastarg),
-		void *range);				/* unused */
-
-extern int dlm_unlock_wait(uint32_t lkid,
-		uint32_t flags,
-		struct dlm_lksb *lksb);
-
-
-/* 
- * These two are for users that want to do their own FD handling
- *
- * dlm_get_fd() - returns fd for the default lockspace for polling and dispatch
- * dlm_dispatch() - dispatches pending asts and basts
- */
-
-extern int dlm_get_fd(void);
-extern int dlm_dispatch(int fd);
-
-
-/*
- * Creating your own lockspace
- *
- * dlm_create_lockspace() - create and open a lockspace and return a handle
- *                          to it.  Privileges are required to create/release.
- * dlm_new_lockspace() - same as create but allows flags
- * dlm_open_lockspace() - simply returns a handle for an existing lockspace and
- *                        may be called by ordinary users.
- * dlm_release_lockspace()
- * dlm_close_lockspace()
- * dlm_ls_get_fd()
- *
- * NOTE: that if you dlm_create_lockspace() then dlm_open_lockspace() you will
- * have two open files on the same device. Hardly a major problem but I thought
- * it worth pointing out.
- */
-
-typedef void *dlm_lshandle_t;
-
-extern dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode);
-extern int dlm_release_lockspace(const char *name, dlm_lshandle_t ls,
-		int force);
-extern dlm_lshandle_t dlm_open_lockspace(const char *name);
-extern int dlm_close_lockspace(dlm_lshandle_t ls);
-extern int dlm_ls_get_fd(dlm_lshandle_t ls);
-extern dlm_lshandle_t dlm_new_lockspace(const char *name, mode_t mode,
-		uint32_t flags);
-
-
-/*
- * Using your own lockspace
- *
- * dlm_ls_lock()
- * dlm_ls_lockx()
- * dlm_ls_unlock()
- * dlm_ls_lock_wait()
- * dlm_ls_unlock_wait()
- * dlm_ls_deadlock_cancel()
- * dlm_ls_purge()
- */
-
-extern int dlm_ls_lock(dlm_lshandle_t lockspace,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,			/* unused */
-		void (*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg),
-		void *range);				/* unused */
-
-extern int dlm_ls_lockx(dlm_lshandle_t lockspace,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,			/* unused */
-		void (*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg),
-		uint64_t *xid,
-		uint64_t *timeout);
-
-extern int dlm_ls_unlock(dlm_lshandle_t lockspace,
-		uint32_t lkid,
-		uint32_t flags,
-		struct dlm_lksb *lksb,
-		void *astarg);
-
-extern int dlm_ls_lock_wait(dlm_lshandle_t lockspace,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,			/* unused */
-		void *bastarg,
-		void (*bastaddr) (void *bastarg),
-		void *range);				/* unused */
-
-extern int dlm_ls_unlock_wait(dlm_lshandle_t lockspace,
-		uint32_t lkid,
-		uint32_t flags,
-		struct dlm_lksb *lksb);
-
-extern int dlm_ls_deadlock_cancel(dlm_lshandle_t ls,
-		uint32_t lkid,
-		uint32_t flags);
-
-extern int dlm_ls_purge(dlm_lshandle_t lockspace,
-		int nodeid,
-		int pid);
-
-
-/*
- * For threaded applications
- *
- * dlm_pthread_init()
- * dlm_ls_pthread_init() - call this before any locking operations and the ASTs
- *                         will be delivered in their own thread.
- * dlm_pthread_cleanup() - call the cleanup routine at application exit
- *			   (optional) or, if the locking functions are in a
- *			   shared library that is to be unloaded.
- *
- * dlm_close/release_lockspace() will tidy the threads for a non-default
- * lockspace
- */
-
-#ifdef _REENTRANT
-extern int dlm_pthread_init(void);
-extern int dlm_ls_pthread_init(dlm_lshandle_t lockspace);
-extern int dlm_pthread_cleanup(void);
-#endif
-
-
-/*
- * Lock modes
- */
-
-#define LKM_NLMODE          0           /* null lock */
-#define LKM_CRMODE          1           /* concurrent read */
-#define LKM_CWMODE          2           /* concurrent write */
-#define LKM_PRMODE          3           /* protected read */
-#define LKM_PWMODE          4           /* protected write */
-#define LKM_EXMODE          5           /* exclusive */
-
-
-/*
- * Locking flags - these match the ones in dlm.h
- */
-
-#define LKF_NOQUEUE         0x00000001
-#define LKF_CANCEL          0x00000002
-#define LKF_CONVERT         0x00000004
-#define LKF_VALBLK          0x00000008
-#define LKF_QUECVT          0x00000010
-#define LKF_IVVALBLK        0x00000020
-#define LKF_CONVDEADLK      0x00000040
-#define LKF_PERSISTENT      0x00000080
-#define LKF_NODLCKWT        0x00000100
-#define LKF_NODLCKBLK       0x00000200
-#define LKF_EXPEDITE        0x00000400
-#define LKF_NOQUEUEBAST     0x00000800
-#define LKF_HEADQUE         0x00001000
-#define LKF_NOORDER         0x00002000
-#define LKF_ORPHAN          0x00004000
-#define LKF_ALTPR           0x00008000
-#define LKF_ALTCW           0x00010000
-#define LKF_FORCEUNLOCK     0x00020000
-#define LKF_TIMEOUT         0x00040000
-#define LKF_WAIT            0x80000000  /* Userspace only, for sync API calls */
-
-/*
- * Extra return codes used by the DLM
- */
-
-#define ECANCEL             0x10001
-#define EUNLOCK             0x10002
-#define	EINPROG		    0x10003     /* lock operation is in progress */
-
-#endif
-
diff --git a/dlm/libdlm/libdlm_internal.h b/dlm/libdlm/libdlm_internal.h
deleted file mode 100644
index c8b270e..0000000
--- a/dlm/libdlm/libdlm_internal.h
+++ /dev/null
@@ -1,9 +0,0 @@
-
-/* Needed before we include the kernel libdlm header */
-#define __user
-typedef uint8_t __u8;
-typedef uint16_t __u16;
-typedef uint32_t __u32;
-#define BUILDING_LIBDLM
-
-
diff --git a/dlm/man/dlm_cleanup.3 b/dlm/man/dlm_cleanup.3
deleted file mode 100644
index db4a9cf..0000000
--- a/dlm/man/dlm_cleanup.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/libdlm.3
diff --git a/dlm/man/dlm_close_lockspace.3 b/dlm/man/dlm_close_lockspace.3
deleted file mode 100644
index e5db408..0000000
--- a/dlm/man/dlm_close_lockspace.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_create_lockspace.3
diff --git a/dlm/man/dlm_create_lockspace.3 b/dlm/man/dlm_create_lockspace.3
deleted file mode 100644
index 3879e85..0000000
--- a/dlm/man/dlm_create_lockspace.3
+++ /dev/null
@@ -1,94 +0,0 @@
-.TH DLM_CREATE_LOCKSPACE 3 "July 5, 2007" "libdlm functions"
-.SH NAME
-dlm_create_lockspace, dlm_open_lockspace, dlm_close_lockspace, dlm_release_lockspace \- manipulate DLM lockspaces
-.SH SYNOPSIS
-.nf
- #include <libdlm.h>
-
-dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode);
-dlm_lshandle_t dlm_new_lockspace(const char *name, mode_t mode,
-                                 uint32_t flags);
-dlm_lshandle_t dlm_open_lockspace(const char *name);
-int dlm_close_lockspace(dlm_lshandle_t ls);
-int dlm_release_lockspace(const char *name, dlm_lshandle_t ls,
-                          int force);
-
-.fi
-.SH DESCRIPTION
-The DLM allows locks to be partitioned into "lockspaces", and these can be manipulated by userspace calls. It is possible (though not recommended) for an application to have multiple lockspaces open at one time. 
-
-Many of the DLM calls work on the "default" lockspace, which should be fine for most users. The calls with _ls_ in them allow you to isolate your application from all others running in the cluster. Remember, lockspaces are a cluster-wide resource, so if you create a lockspace called "myls" it will share locks with a lockspace called "myls" on all nodes. These calls allow users to create & remove lockspaces, and users to connect to existing lockspace to store their locks there.
-.PP
-.SS
-dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode);
-.br
-This creates a lockspace called <name> and the mode of the file user to access it will be <mode> (subject to umask as usual). The lockspace must not already exist on this node, if it does -1 will be returned and errno will be set to EEXIST. If you really want to use this lockspace you can then use dlm_open_lockspace() below. The name is the name of a misc device that will be created in /dev/misc.
-.br
-On success a handle to the lockspace is returned, which can be used to pass into subsequent dlm_ls_lock/unlock calls. Make no assumptions as to the content of this handle as it's content may change in future.
-.br
-The caller must have CAP_SYSADMIN privileges to do this operation.
-.PP
-Return codes:
-0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
-.nf
-EINVAL          An invalid parameter was passed to the call
-ENOMEM          A (kernel) memory allocation failed
-EEXIST          The lockspace already exists
-EPERM           Process does not have capability to create lockspaces
-ENOSYS          A fatal error occurred initializing the DLM
-Any error returned by the open() system call
-.fi
-.SS
-int dlm_new_lockspace(const char *name, mode_t mode, uint32_t flags)
-.PP
-Performs the same function as 
-.B dlm_create_lockspace()
-above, but passes some creation flags to the call that affect the lockspace being created. Currently supported flags are:
-.nf
-DLM_LSFL_NODIR    the lockspace should not use a resource directory
-DLM_LSFL_TIMEWARN the dlm should emit warnings over netlink when locks
-                  have been waiting too long; required for deadlock
-                  detection
-.fi
-.SS
-int dlm_release_lockspace(const char *name, dlm_lshandle_t ls, int force)
-.PP
-Deletes a lockspace. If the lockspace still has active locks then -1 will be returned and errno set to EBUSY. Both the lockspace handle /and/ the name must be specified. This call also closes the lockspace and stops the thread associated with the lockspace, if any.
-.br
-Note that other nodes in the cluster may still have locks open on this lockspace. This call only removes the lockspace from the current node.  If the force flag is set then the lockspace will be removed even if another user on this node has active locks in it. Existing users will NOT be notified if you do this, so be careful.
-.br
-The caller must have CAP_SYSADMIN privileges to do this operation.
-.PP
-Return codes:
-0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
-.nf
-EINVAL          An invalid parameter was passed to the call
-EPERM           Process does not have capability to release lockspaces
-EBUSY           The lockspace could not be freed because it still
-                contains locks and force was not set.
-.fi
-
-.SS
-dlm_lshandle_t dlm_open_lockspace(const char *name)
-.PP
-Opens an already existing lockspace and returns a handle to it.
-.PP
-Return codes:
-0 is returned if the call completed successfully. If not, -1 is returned and errno is set to an error returned by the open() system call
-.SS
-int dlm_close_lockspace(dlm_lshandle_t ls)
-.br
-Close the lockspace. Any locks held by this process will be freed. If a thread is associated with this lockspace then it will be stopped.
-.PP
-Return codes:
-0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
-.nf
-EINVAL		lockspace was not a valid lockspace handle
-.fi
-
-
-.SH SEE ALSO
-
-.BR libdlm (3),
-.BR dlm_unlock (3),
-.BR dlm_lock (3),
diff --git a/dlm/man/dlm_dispatch.3 b/dlm/man/dlm_dispatch.3
deleted file mode 100644
index db4a9cf..0000000
--- a/dlm/man/dlm_dispatch.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/libdlm.3
diff --git a/dlm/man/dlm_get_fd.3 b/dlm/man/dlm_get_fd.3
deleted file mode 100644
index db4a9cf..0000000
--- a/dlm/man/dlm_get_fd.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/libdlm.3
diff --git a/dlm/man/dlm_lock.3 b/dlm/man/dlm_lock.3
deleted file mode 100644
index 3c5f8b5..0000000
--- a/dlm/man/dlm_lock.3
+++ /dev/null
@@ -1,239 +0,0 @@
-.TH DLM_LOCK 3 "July 5, 2007" "libdlm functions"
-.SH NAME
-dlm_lock \- acquire or convert a DLM lock
-.SH SYNOPSIS
-.nf
- #include <libdlm.h>
-
-int dlm_lock(uint32_t mode,
-		struct dlm_lksb *lksb,	
-		uint32_t flags,	
-		const void *name,	
-		unsigned int namelen,
-		uint32_t parent,		/* unused */
-		void (*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg),
-		void *range);			/* unused */
-
-int dlm_lock_wait(uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,		/* unused */
-		void *bastarg,
-		void (*bastaddr) (void *bastarg),
-		void *range);			/* unused */
-
-int dlm_ls_lock(dlm_lshandle_t lockspace,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,		/* unused */
-		void (*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg),
-		void *range);			/* unused */
-
-int dlm_ls_lock_wait(dlm_lshandle_t lockspace,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,		/* unusued */
-		void *bastarg,
-		void (*bastaddr) (void *bastarg),
-		void *range);			/* unused */
-
-int dlm_ls_lockx(dlm_lshandle_t lockspace,
-		uint32_t mode,
-		struct dlm_lksb *lksb,
-		uint32_t flags,
-		const void *name,
-		unsigned int namelen,
-		uint32_t parent,		/* unused */
-		(*astaddr) (void *astarg),
-		void *astarg,
-		void (*bastaddr) (void *astarg),
-		uint64_t *xid,
-		uint64_t *timeout);
-
-
-
-.fi
-.SH DESCRIPTION
-dlm_lock and its variants acquire and convert locks in the DLM.
-.PP
-dlm_lock() operations are asynchronous. If the call to dlm_lock returns an error then the operation has failed and the AST routine will not be called. If dlm_lock returns 0 it is still possible that the lock operation will fail. The AST routine will be called when the locking is complete or has failed and the status is returned in the lksb. 
-.B dlm_lock_wait()
-will wait until the lock operation has completed and returns the final completion status.
-.B dlm_ls_lock()
-is the same as 
-.B dlm_lock()
-but takes a lockspace argument. This lockspace must have been previously opened by
-.B dlm_lockspace_open() or
-.B dlm_lockspace_create().
-.PP
-For conversion operations the name and namelen are ignored and the lock ID in the LKSB is used to identify the lock to be converted.
-.PP
-If a lock value block is specified then in general, a grant or a conversion to an equal-level or higher-level lock mode reads the lock value from the resource into the caller's lock value block. When a lock conversion from EX or PW to an equal-level or lower-level lock mode occurs, the contents of the caller's lock value block are written into the resource. If the LVB is invalidated the lksb.sb_flags member will be set to DLM_SBF_VALNOTVALID. Lock values blocks are always 32 bytes long.
-.PP
-If the AST routines or parameter are passed to a conversion operation then they will overwrite those values that were passed to a previous dlm_lock call.
-.PP
-.B mode
-Lock mode to acquire or convert to.
-.nf
-  LKM_NLMODE	NULL Lock
-  LKM_CRMODE	Concurrent read
-  LKM_CWMODE	Concurrent write
-  LKM_PRMODE	Protected read
-  LKM_PWMODE	Protected write
-  LKM_EXMODE	Exclusive
-.fi
-.PP
-.B flags
-Affect the operation of the lock call:
-.nf
-  LKF_NOQUEUE     Don't queue the lock. If it cannot be granted return
-                  -EAGAIN
-  LKF_CONVERT     Convert an existing lock
-  LKF_VALBLK      Lock has a value block
-  LKF_QUECVT      Put conversion to the back of the queue
-  LKF_EXPEDITE    Grant a NL lock immediately regardless of other locks
-                  on the conversion queue
-  LKF_PERSISTENT  Specifies a lock that will not be unlocked when the
-                  process exits; it will become an orphan lock.
-  LKF_CONVDEADLK  Enable internal conversion deadlock resolution where
-                  the lock's granted mode may be set to NL and
-                  DLM_SBF_DEMOTED is returned in lksb.sb_flags.
-  LKF_NODLCKWT    Do not consider this lock when trying to detect
-                  deadlock conditions.
-  LKF_NODLCKBLK   Not implemented
-  LKF_NOQUEUEBAST Send blocking ASTs even for NOQUEUE operations
-  LKF_HEADQUE     Add locks to the head of the convert or waiting queue
-  LKF_NOORDER     Avoid the VMS rules on grant order
-  LKF_ALTPR       If the requested mode can't be granted (generally CW),
-                  try to grant in PR and return DLM_SBF_ALTMODE.
-  LKF_ALTCW       If the requested mode can't be granted (generally PR),
-                  try to grant in CW and return DLM_SBF_ALTMODE.
-  LKF_TIMEOUT     The lock will time out per the timeout arg.
-
-.fi
-.PP
-.B lksb
-Lock Status block
-.br
-This structure contains the returned lock ID, the actual
-status of the lock operation (all lock ops are asynchronous)
-and the value block if LKF_VALBLK is set.
-.PP
-.B name
-.br
-Name of the lock. Can be binary, max 64 bytes. Ignored for lock
-conversions.  (Should be a string to work with debugging tools.)
-.PP
-.B namelen	
-.br
-Length of the above name. Ignored for lock conversions.
-.PP
-.B parent	
-.br
-ID of parent lock or NULL if this is a top-level lock. This is currently unused.
-.PP
-.B ast	
-.br
-Address of AST routine to be called when the lock operation
-completes. The final completion status of the lock will be
-in the lksb. the AST routine must not be NULL.
-.PP		
-.B astargs	
-.br
-Argument to pass to the AST routine (most people pass the lksb
-in here but it can be anything you like.)
-.PP
-.B bast
-.br
-Blocking AST routine. address of a function to call if this 
-lock is blocking another. The function will be called with
-astargs. 
-.PP
-.B range
-.br
-This is unused.
-.PP
-.B xid
-.br
-Optional transaction ID for deadlock detection.
-.PP
-.B timeout
-.br
-Timeout in centiseconds. If it takes longer than this to acquire the lock
-(usually because it is already blocked by another lock), then the AST 
-will trigger with ETIMEDOUT as the status. If the lock operation is a conversion
-then the lock will remain at its current status. If this is a new lock then
-the lock will not exist and any LKB in the lksb will be invalid.  This is
-ignored without the LKF_TIMEOUT flag.
-.PP
-.SS Return values
-0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
-.PP
-.nf
-EINVAL          An invalid parameter was passed to the call (eg bad lock
-                mode or flag)
-ENOMEM          A (kernel) memory allocation failed
-EAGAIN          LKF_NOQUEUE was requested and the lock could not be
-                granted
-EBUSY           The lock is currently being locked or converted
-EFAULT          The userland buffer could not be read/written by the
-                kernel (this indicates a library problem)
-EDEADLOCK       The lock operation is causing a deadlock and has been
-                cancelled. If this was a conversion then the lock is
-                reverted to its previously granted state. If it was a
-                new lock then it has not been granted. (NB Only
-                conversion deadlocks are currently detected)
-.PP
-If an error is returned in the AST, then lksb.sb_status is set to the one of the above values instead of zero.
-.SS Structures
-.nf
-struct dlm_lksb {
-  int      sb_status; /* Final status of lock operation */
-  uint32_t sb_lkid;   /* ID of lock. Returned from dlm_lock()
-                         on first use. Used as input to
-                         dlm_lock() for a conversion operation */
-  char     sb_flags;  /* Completion flags, see above */
-  char     sb_lvbptr; /* Optional pointer to lock value block */
-};
-
-.fi
-.SH EXAMPLE
-.nf
-int status;
-struct dlm_lksb lksb;
-
-status = dlm_lock_wait(LKM_EXMODE,
-                       &lksb,
-                       LKF_NOQUEUE,
-                       "MyLock",
-                       strlen("MyLock"),
-                       0, // Parent,
-                       NULL, // bast arg
-                       NULL, // bast routine,
-                       NULL); // Range
-
-if (status == 0)
-	dlm_unlock_wait(lksb.sb_lkid, 0, &lksb);
-
-.fi
-
-.SH SEE ALSO
-
-.BR libdlm (3),
-.BR dlm_unlock (3),
-.BR dlm_open_lockspace (3),
-.BR dlm_create_lockspace (3),
-.BR dlm_close_lockspace (3),
-.BR dlm_release_lockspace (3)
diff --git a/dlm/man/dlm_lock_wait.3 b/dlm/man/dlm_lock_wait.3
deleted file mode 100644
index a99225c..0000000
--- a/dlm/man/dlm_lock_wait.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_lock.3
diff --git a/dlm/man/dlm_ls_lock.3 b/dlm/man/dlm_ls_lock.3
deleted file mode 100644
index a99225c..0000000
--- a/dlm/man/dlm_ls_lock.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_lock.3
diff --git a/dlm/man/dlm_ls_lock_wait.3 b/dlm/man/dlm_ls_lock_wait.3
deleted file mode 100644
index a99225c..0000000
--- a/dlm/man/dlm_ls_lock_wait.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_lock.3
diff --git a/dlm/man/dlm_ls_lockx.3 b/dlm/man/dlm_ls_lockx.3
deleted file mode 100644
index a99225c..0000000
--- a/dlm/man/dlm_ls_lockx.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_lock.3
diff --git a/dlm/man/dlm_ls_pthread_init.3 b/dlm/man/dlm_ls_pthread_init.3
deleted file mode 100644
index db4a9cf..0000000
--- a/dlm/man/dlm_ls_pthread_init.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/libdlm.3
diff --git a/dlm/man/dlm_ls_unlock.3 b/dlm/man/dlm_ls_unlock.3
deleted file mode 100644
index 91babd2..0000000
--- a/dlm/man/dlm_ls_unlock.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_unlock.3
diff --git a/dlm/man/dlm_ls_unlock_wait.3 b/dlm/man/dlm_ls_unlock_wait.3
deleted file mode 100644
index 91babd2..0000000
--- a/dlm/man/dlm_ls_unlock_wait.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_unlock.3
diff --git a/dlm/man/dlm_new_lockspace.3 b/dlm/man/dlm_new_lockspace.3
deleted file mode 100644
index e5db408..0000000
--- a/dlm/man/dlm_new_lockspace.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_create_lockspace.3
diff --git a/dlm/man/dlm_open_lockspace.3 b/dlm/man/dlm_open_lockspace.3
deleted file mode 100644
index e5db408..0000000
--- a/dlm/man/dlm_open_lockspace.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_create_lockspace.3
diff --git a/dlm/man/dlm_pthread_init.3 b/dlm/man/dlm_pthread_init.3
deleted file mode 100644
index db4a9cf..0000000
--- a/dlm/man/dlm_pthread_init.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/libdlm.3
diff --git a/dlm/man/dlm_release_lockspace.3 b/dlm/man/dlm_release_lockspace.3
deleted file mode 100644
index e5db408..0000000
--- a/dlm/man/dlm_release_lockspace.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_create_lockspace.3
diff --git a/dlm/man/dlm_unlock.3 b/dlm/man/dlm_unlock.3
deleted file mode 100644
index 9023139..0000000
--- a/dlm/man/dlm_unlock.3
+++ /dev/null
@@ -1,94 +0,0 @@
-.TH DLM_UNLOCK 3 "July 5, 2007" "libdlm functions"
-.SH NAME
-dlm_unlock \- unlock a DLM lock
-.SH SYNOPSIS
-.nf
-#include <libdlm.h>
-
-int dlm_unlock(uint32_t lkid,
-               uint32_t flags, struct dlm_lksb *lksb, void *astarg);
-
-int dlm_unlock_wait(uint32_t lkid,
-                    uint32_t flags, struct dlm_lksb *lksb);
-
-.fi
-.SH DESCRIPTION
-.B dlm_unlock()
-unlocks a lock previously acquired by dlm_lock and its variants.
-.PP
-Unless 
-.B dlm_unlock_wait() 
-is used unlocks are also asynchronous. The AST routine is called when the resource is successfully unlocked (see below).
-.PP
-.B lkid
-Lock ID as returned in the lksb
-.PP
-.B flags
-flags affecting the unlock operation:
-.nf
-  LKF_CANCEL       Cancel a pending lock or conversion. 
-                   This returns the lock to it's previously
-                   granted mode (in case of a conversion) or
-                   unlocks it (in case of a waiting lock).
-  LKF_IVVALBLK     Invalidate value block
-  LKF_FORCEUNLOCK  Unlock the lock even if it's waiting.
-.fi
-.PP
-.B lksb
-LKSB to return status and value block information.
-.PP
-.B astarg
-New parameter to be passed to the completion AST.
-The completion AST routine is the
-last completion AST routine specified in a dlm_lock call.
-If dlm_lock_wait() was the last routine to issue a lock, 
-dlm_unlock_wait() must be used to release the lock. If dlm_lock()
-was the last routine to issue a lock then either dlm_unlock()
-or dlm_unlock_wait() may be called.
-.PP
-
-.SS Return values
-0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
-.PP
-.nf
-EINVAL          An invalid parameter was passed to the call (eg bad
-                lock mode or flag)
-EINPROGRESS     The lock is already being unlocked
-EBUSY           The lock is currently being locked or converted
-ENOTEMPTY       An attempt to made to unlock a parent lock that still has
-                child locks.
-ECANCEL         A lock conversion was successfully cancelled
-EUNLOCK         An unlock operation completed successfully
-                (sb_status only)
-EFAULT          The userland buffer could not be read/written by the
-                kernel
-.fi
-If an error is returned in the AST, then lksb.sb_status is set to the one of the above numbers instead of zero.
-.SH EXAMPLE
-.nf
-int status;
-struct dlm_lksb lksb;
-
-status = dlm_lock_wait(LKM_EXMODE,
-                       &lksb,
-                       LKF_NOQUEUE,
-                       "MyLock",
-                       strlen("MyLock"),
-                       0,     // Parent,
-                       NULL,  // bast arg
-                       NULL,  // bast routine,
-                       NULL); // Range
-
-if (status == 0)
-	dlm_unlock_wait(lksb.sb_lkid, 0, &lksb);
-
-.fi
-
-.SH SEE ALSO
-
-.BR libdlm (3),
-.BR dlm_lock (3),
-.BR dlm_open_lockspace (3),
-.BR dlm_create_lockspace (3),
-.BR dlm_close_lockspace (3),
-.BR dlm_release_lockspace (3)
diff --git a/dlm/man/dlm_unlock_wait.3 b/dlm/man/dlm_unlock_wait.3
deleted file mode 100644
index 91babd2..0000000
--- a/dlm/man/dlm_unlock_wait.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/dlm_unlock.3
diff --git a/dlm/man/libdlm.3 b/dlm/man/libdlm.3
deleted file mode 100644
index a020560..0000000
--- a/dlm/man/libdlm.3
+++ /dev/null
@@ -1,105 +0,0 @@
-.TH LIBDLM 3 "July 5, 2007" "libdlm functions"
-.SH NAME
-libdlm \- dlm_get_fd, dlm_dispatch, dlm_pthread_init, dlm_ls_pthread_init, dlm_cleanup
-.SH SYNOPSIS
-.nf
-#include <libdlm.h>
-.nf
-int dlm_pthread_init();
-int dlm_ls_pthread_init(dlm_lshandle_t lockspace);
-int dlm_pthread_cleanup();
-int dlm_get_fd(void);
-int dlm_dispatch(int fd);
-
-link with -ldlm
-.fi
-.SH DESCRIPTION
-libdlm provides the programmatic userspace interface to the Distributed Lock manager. It provides all the calls you need to manipulate locks & lockspaces
-.br
-libdlm can be used in pthread or non-pthread applications. For pthread applications simply call the following function before doing any lock operations. If you're using pthreads, remember to define _REENTRANT at the top of the program or using -D_REENTRANT on the compile line.
-.br
-pthreads is the normal way of using the DLM. This way you simply initialize the DLM's thread and all the AST routines will be delivered in that thread. You just call the dlm_lock() etc routines in the main line of your program.
-.br
-If you don't want to use pthreads or you want to handle the dlm callback ASTs yourself then you can get an FD handle to the DLM device and call 
-.B dlm_dispatch()
-on it whenever it becomes active. That was ASTs will be delivered in the context of the thread/process that called 
-.B dlm_dispatch().
-
-
-.SS int dlm_pthread_init()
-.br
-Creates a thread to receive all lock ASTs. The AST callback function for lock operations will be called in the context of this thread. If there is a potential for local resource access conflicts you must provide your own pthread-based locking in the AST routine.
-.PP
-.SS int dlm_ls_pthread_init(dlm_lshandle_t lockspace)
-.br
-As dlm_pthread_init but initializes a thread for the specified lockspace.
-.PP
-.SS int dlm_pthread_cleanup()
-.br
-Cleans up the default lockspace threads after use. Normally you don't need to call this, but if the locking code is in a dynamically loadable shared library this will probably be necessary.
-.br
-For non-pthread based applications the DLM provides a file descriptor that the program can feed into poll/select. If activity is detected on that FD then a dispatch function should be called:
-.PP
-.SS int dlm_get_fd()
-Returns a file-descriptor for the DLM suitable for passing in to poll() or select().
-.PP
-.SS int dlm_dispatch(int fd)
-.br
-Reads from the DLM and calls any AST routines that may be needed. This routine runs in the context of the caller so no extra locking is needed to protect local resources.
-.PP
-
-
-.SH libdlm_lt
-There also exists a "light" version of the libdlm library called libdlm_lt. This is provided for those applications that do not want to use pthread functions. If you use this library it is important that your application is NOT compiled with -D_REENTRANT or linked with libpthread.
-
-.SH EXAMPLES
-
-Create a lockspace and start a thread to deliver its callbacks:
-.nf
-dlm_lshandle_t ls;
-
-ls = dlm_create_lockspace("myLS", 0660);
-dlm_ls_pthread_init(ls);
-
- ...
-
-status = dlm_ls_lock(ls,
-                     ... );
-
-
-.fi
-.PP
- Using poll(2) to wait for and dispatch ASTs
-.nf
-
-
-static int poll_for_ast(dlm_lshandle_t ls)
-{
-    struct pollfd pfd;
-
-    pfd.fd = dlm_ls_get_fd(ls);
-    pfd.events = POLLIN;
-    while (!ast_called)
-    {
-        if (poll(&pfd, 1, 0) < 0)
-        {
-            perror("poll");
-            return -1;
-        }
-        dlm_dispatch(dlm_ls_get_fd(ls));
-    }
-    ast_called = 0;
-    return 0;
-}
-.fi
-
-
-.SH SEE ALSO
-
-.BR libdlm (3),
-.BR dlm_lock (3),
-.BR dlm_unlock (3),
-.BR dlm_open_lockspace (3),
-.BR dlm_create_lockspace (3),
-.BR dlm_close_lockspace (3),
-.BR dlm_release_lockspace (3)
diff --git a/libdlm/51-dlm.rules b/libdlm/51-dlm.rules
new file mode 100644
index 0000000..f71e79d
--- /dev/null
+++ b/libdlm/51-dlm.rules
@@ -0,0 +1,5 @@
+KERNEL=="dlm-control", NAME="misc/dlm-control", MODE="0666"
+KERNEL=="dlm-monitor", NAME="misc/dlm-monitor", MODE="0666"
+KERNEL=="dlm_default", NAME="misc/dlm_default", MODE="0666"
+KERNEL=="dlm_*", NAME="misc/%k", MODE="0660"
+
diff --git a/libdlm/Makefile b/libdlm/Makefile
new file mode 100644
index 0000000..2b8b6d3
--- /dev/null
+++ b/libdlm/Makefile
@@ -0,0 +1,117 @@
+LIB_NAME = libdlm
+LIB_MAJOR = 3
+LIB_MINOR = 0
+LIB_O = $(LIB_NAME).o
+LIB_SO = $(LIB_NAME).so
+LIB_SMAJOR = $(LIB_SO).$(LIB_MAJOR)
+LIB_TARGET = $(LIB_SO).$(LIB_MAJOR).$(LIB_MINOR)
+
+LLT_NAME = libdlm_lt
+LLT_MAJOR = 3
+LLT_MINOR = 0
+LLT_O = $(LLT_NAME).o
+LLT_SO = $(LLT_NAME).so
+LLT_SMAJOR = $(LLT_SO).$(LLT_MAJOR)
+LLT_TARGET = $(LLT_SO).$(LLT_MAJOR).$(LLT_MINOR)
+
+HDR_TARGET = libdlm.h
+
+MAN_TARGET = \
+	man/dlm_cleanup.3 \
+	man/dlm_close_lockspace.3 \
+	man/dlm_create_lockspace.3 \
+	man/dlm_dispatch.3 \
+	man/dlm_get_fd.3 \
+	man/dlm_lock.3 \
+	man/dlm_lock_wait.3 \
+	man/dlm_ls_lock.3 \
+	man/dlm_ls_lock_wait.3 \
+	man/dlm_ls_lockx.3 \
+	man/dlm_ls_pthread_init.3 \
+	man/dlm_ls_unlock.3 \
+	man/dlm_ls_unlock_wait.3 \
+	man/dlm_new_lockspace.3 \
+	man/dlm_open_lockspace.3 \
+	man/dlm_pthread_init.3 \
+	man/dlm_release_lockspace.3 \
+	man/dlm_unlock.3 \
+	man/dlm_unlock_wait.3 \
+	man/libdlm.3
+
+UDEV_TARGET = 51-dlm.rules
+
+SOURCE = libdlm.c
+
+CFLAGS += -D_GNU_SOURCE -g \
+	-Wall \
+	-Wformat \
+	-Wformat-security \
+	-Wmissing-prototypes \
+	-Wnested-externs \
+	-Wpointer-arith \
+	-Wextra -Wshadow \
+	-Wcast-align \
+	-Wwrite-strings \
+	-Waggregate-return \
+	-Wstrict-prototypes \
+	-Winline \
+	-Wredundant-decls \
+	-Wno-sign-compare \
+	-Wno-unused-parameter \
+	-Wp,-D_FORTIFY_SOURCE=2 \
+	-fexceptions \
+	-fasynchronous-unwind-tables \
+	-fdiagnostics-show-option \
+	-fPIC \
+
+LIB_CFLAGS += $(CFLAGS) -D_REENTRANT
+LLT_CFLAGS += $(CFLAGS)
+
+LDFLAGS += -Wl
+
+LIB_LDFLAGS += $(LDFLAGS) -lpthread
+LLT_LDFLAGS += $(LDFLAGS)
+
+all: $(LIB_TARGET) $(LLT_TARGET)
+
+$(LIB_O): $(SOURCE) 
+	$(CC) $(LIB_CFLAGS) -c -o $@ $<
+
+$(LLT_O): $(SOURCE) 
+	$(CC) $(LLT_CFLAGS) -c -o $@ $<
+
+$(LIB_TARGET): $(LIB_O)
+	$(CC) $(LIB_LDFLAGS) -shared -o $@ -Wl,-soname=$(LIB_SMAJOR) $^
+	ln -sf $(LIB_TARGET) $(LIB_SO)
+	ln -sf $(LIB_TARGET) $(LIB_SMAJOR)
+
+$(LLT_TARGET): $(LLT_O)
+	$(CC) $(LLT_LDFLAGS) -shared -o $@ -Wl,-soname=$(LLT_SMAJOR) $^
+	ln -sf $(LLT_TARGET) $(LLT_SO)
+	ln -sf $(LLT_TARGET) $(LLT_SMAJOR)
+
+clean:
+	rm -f *.o *.so *.so.* *.a
+
+INSTALL=$(shell which install)
+
+DESTDIR=
+LIBDIR=/usr/lib64
+HDRDIR=/usr/include 
+MANDIR=/usr/share/man
+UDEVDIR=/etc/udev/rules.d
+
+.PHONY: install
+install: all
+	$(INSTALL) -d $(DESTDIR)/$(LIBDIR)
+	$(INSTALL) -d $(DESTDIR)/$(HDRDIR)
+	$(INSTALL) -d $(DESTDIR)/$(MANDIR)/man3
+	$(INSTALL) -d $(DESTDIR)/$(UDEVDIR)
+	$(INSTALL) -c -m 755 $(LIB_TARGET) $(DESTDIR)/$(LIBDIR)
+	$(INSTALL) -c -m 755 $(LLT_TARGET) $(DESTDIR)/$(LIBDIR)
+	cp -a $(LIB_SO) $(DESTDIR)/$(LIBDIR)
+	cp -a $(LLT_SO) $(DESTDIR)/$(LIBDIR)
+	$(INSTALL) -c -m 644 $(HDR_TARGET) $(DESTDIR)/$(HDRDIR)
+	$(INSTALL) -m 644 $(MAN_TARGET) $(DESTDIR)/$(MANDIR)/man3/
+	$(INSTALL) -m 644 $(UDEV_TARGET) $(DESTDIR)/$(UDEVDIR)
+
diff --git a/libdlm/libdlm.c b/libdlm/libdlm.c
new file mode 100644
index 0000000..a5157e2
--- /dev/null
+++ b/libdlm/libdlm.c
@@ -0,0 +1,1485 @@
+#ifdef _REENTRANT
+#include <pthread.h>
+#endif
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <linux/major.h>
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#endif
+#include <linux/types.h>
+#include <linux/dlm.h>
+#define BUILDING_LIBDLM
+#include "libdlm.h"
+#include <linux/dlm_device.h>
+
+#define MISC_PREFIX		"/dev/misc/"
+#define DLM_PREFIX		"dlm_"
+#define DLM_MISC_PREFIX		MISC_PREFIX DLM_PREFIX
+#define DLM_CONTROL_NAME	"dlm-control"
+#define DLM_CONTROL_PATH	MISC_PREFIX DLM_CONTROL_NAME
+#define DEFAULT_LOCKSPACE	"default"
+
+/*
+ * V5 of the dlm_device.h kernel/user interface structs
+ */
+
+struct dlm_lock_params_v5 {
+	__u8 mode;
+	__u8 namelen;
+	__u16 flags;
+	__u32 lkid;
+	__u32 parent;
+	void *castparam;
+	void *castaddr;
+	void *bastparam;
+	void *bastaddr;
+	struct dlm_lksb *lksb;
+	char lvb[DLM_USER_LVB_LEN];
+	char name[0];
+};
+
+struct dlm_write_request_v5 {
+	__u32 version[3];
+	__u8 cmd;
+	__u8 is64bit;
+	__u8 unused[2];
+
+	union  {
+		struct dlm_lock_params_v5 lock;
+		struct dlm_lspace_params lspace;
+	} i;
+};
+
+struct dlm_lock_result_v5 {
+	__u32 length;
+	void *user_astaddr;
+	void *user_astparam;
+	struct dlm_lksb *user_lksb;
+	struct dlm_lksb lksb;
+	__u8 bast_mode;
+	__u8 unused[3];
+	/* Offsets may be zero if no data is present */
+	__u32 lvb_offset;
+};
+
+
+/*
+ * One of these per lockspace in use by the application
+ */
+
+struct dlm_ls_info {
+    int fd;
+#ifdef _REENTRANT
+    pthread_t tid;
+#else
+    int tid;
+#endif
+};
+
+/*
+ * The default lockspace.
+ * I've resisted putting locking around this as the user should be
+ * "sensible" and only do lockspace operations either in the
+ * main thread or ... carefully...
+ */
+
+static struct dlm_ls_info *default_ls = NULL;
+static int control_fd = -1;
+static struct dlm_device_version kernel_version;
+static int kernel_version_detected = 0;
+
+
+static int release_lockspace(uint32_t minor, uint32_t flags);
+
+
+static void ls_dev_name(const char *lsname, char *devname, int devlen)
+{
+	snprintf(devname, devlen, DLM_MISC_PREFIX "%s", lsname);
+}
+
+static void dummy_ast_routine(void *arg)
+{
+}
+
+#ifdef _REENTRANT
+/* Used for the synchronous and "simplified, synchronous" API routines */
+struct lock_wait
+{
+    pthread_cond_t  cond;
+    pthread_mutex_t mutex;
+    struct dlm_lksb lksb;
+};
+
+static void sync_ast_routine(void *arg)
+{
+    struct lock_wait *lwait = arg;
+
+    pthread_mutex_lock(&lwait->mutex);
+    pthread_cond_signal(&lwait->cond);
+    pthread_mutex_unlock(&lwait->mutex);
+}
+
+/* lock_resource & unlock_resource
+ * are the simplified, synchronous API.
+ * Aways uses the default lockspace.
+ */
+int lock_resource(const char *resource, int mode, int flags, int *lockid)
+{
+    int status;
+    struct lock_wait lwait;
+
+    if (default_ls == NULL)
+    {
+	if (dlm_pthread_init())
+	{
+	    return -1;
+	}
+    }
+
+    if (!lockid)
+    {
+	errno = EINVAL;
+	return -1;
+    }
+
+    /* Conversions need the lockid in the LKSB */
+    if (flags & LKF_CONVERT)
+	lwait.lksb.sb_lkid = *lockid;
+
+    pthread_cond_init(&lwait.cond, NULL);
+    pthread_mutex_init(&lwait.mutex, NULL);
+    pthread_mutex_lock(&lwait.mutex);
+
+    status = dlm_lock(mode,
+		      &lwait.lksb,
+		      flags,
+		      resource,
+		      strlen(resource),
+		      0,
+		      sync_ast_routine,
+		      &lwait,
+		      NULL,
+		      NULL);
+    if (status)
+	return status;
+
+    /* Wait for it to complete */
+    pthread_cond_wait(&lwait.cond, &lwait.mutex);
+    pthread_mutex_unlock(&lwait.mutex);
+
+    *lockid = lwait.lksb.sb_lkid;
+
+    errno = lwait.lksb.sb_status;
+    if (lwait.lksb.sb_status)
+	return -1;
+    else
+	return 0;
+}
+
+
+int unlock_resource(int lockid)
+{
+    int status;
+    struct lock_wait lwait;
+
+    if (default_ls == NULL)
+    {
+	errno = -ENOTCONN;
+	return -1;
+    }
+
+    pthread_cond_init(&lwait.cond, NULL);
+    pthread_mutex_init(&lwait.mutex, NULL);
+    pthread_mutex_lock(&lwait.mutex);
+
+    status = dlm_unlock(lockid, 0, &lwait.lksb, &lwait);
+
+    if (status)
+	return status;
+
+    /* Wait for it to complete */
+    pthread_cond_wait(&lwait.cond, &lwait.mutex);
+    pthread_mutex_unlock(&lwait.mutex);
+
+    errno = lwait.lksb.sb_status;
+    if (lwait.lksb.sb_status != DLM_EUNLOCK)
+	return -1;
+    else
+	return 0;
+}
+
+/* Tidy up threads after a lockspace is closed */
+static int ls_pthread_cleanup(struct dlm_ls_info *lsinfo)
+{
+    int status = 0;
+    int fd;
+
+    /* Must close the fd after the thread has finished */
+    fd = lsinfo->fd;
+    if (lsinfo->tid)
+    {
+	status = pthread_cancel(lsinfo->tid);
+	if (!status)
+	    pthread_join(lsinfo->tid, NULL);
+    }
+    if (!status)
+    {
+	free(lsinfo);
+	close(fd);
+    }
+
+    return status;
+}
+
+/* Cleanup default lockspace */
+int dlm_pthread_cleanup(void)
+{
+    struct dlm_ls_info *lsinfo = default_ls;
+
+    /* Protect users from their own stupidity */
+    if (!lsinfo)
+	return 0;
+
+    default_ls = NULL;
+
+    return ls_pthread_cleanup(lsinfo);
+}
+#else
+
+/* Non-pthread version of cleanup */
+static int ls_pthread_cleanup(struct dlm_ls_info *lsinfo)
+{
+    close(lsinfo->fd);
+    free(lsinfo);
+    return 0;
+}
+#endif
+
+
+static void set_version_v5(struct dlm_write_request_v5 *req)
+{
+	req->version[0] = kernel_version.version[0];
+	req->version[1] = kernel_version.version[1];
+	req->version[2] = kernel_version.version[2];
+	if (sizeof(long) == sizeof(long long))
+		req->is64bit = 1;
+	else
+		req->is64bit = 0;
+}
+
+static void set_version_v6(struct dlm_write_request *req)
+{
+	req->version[0] = kernel_version.version[0];
+	req->version[1] = kernel_version.version[1];
+	req->version[2] = kernel_version.version[2];
+	if (sizeof(long) == sizeof(long long))
+		req->is64bit = 1;
+	else
+		req->is64bit = 0;
+}
+
+static int open_default_lockspace(void)
+{
+	if (!default_ls) {
+		dlm_lshandle_t ls;
+
+		/* This isn't the race it looks, create_lockspace will
+		 * do the right thing if the lockspace has already been
+		 * created.
+		 */
+
+		ls = dlm_open_lockspace(DEFAULT_LOCKSPACE);
+		if (!ls)
+			ls = dlm_create_lockspace(DEFAULT_LOCKSPACE, 0600);
+		if (!ls)
+			return -1;
+
+		default_ls = (struct dlm_ls_info *)ls;
+	}
+	return 0;
+}
+
+static void detect_kernel_version(void)
+{
+	struct dlm_device_version v;
+	int rv;
+
+	rv = read(control_fd, &v, sizeof(struct dlm_device_version));
+	if (rv < 0) {
+		kernel_version.version[0] = 5;
+		kernel_version.version[1] = 0;
+		kernel_version.version[2] = 0;
+	} else {
+		kernel_version.version[0] = v.version[0];
+		kernel_version.version[1] = v.version[1];
+		kernel_version.version[2] = v.version[2];
+	}
+
+	kernel_version_detected = 1;
+}
+
+static int find_control_minor(int *minor)
+{
+	FILE *f;
+	char name[256];
+	int found = 0, m = 0;
+
+	f = fopen("/proc/misc", "r");
+	if (!f)
+		return -1;
+
+	while (!feof(f)) {
+		if (fscanf(f, "%d %s", &m, name) != 2)
+			continue;
+		if (strcmp(name, DLM_CONTROL_NAME))
+			continue;
+		found = 1;
+		break;
+	}
+	fclose(f);
+
+	if (found) {
+		*minor = m;
+		return 0;
+	}
+	return -1;
+}
+
+static int open_control_device(void)
+{
+	struct stat st;
+	int i, rv, minor, found = 0;
+
+	if (control_fd > -1)
+		goto out;
+
+	rv = find_control_minor(&minor);
+	if (rv < 0)
+		return -1;
+
+	/* wait for udev to create the device */
+
+	for (i = 0; i < 10; i++) {
+		if (stat(DLM_CONTROL_PATH, &st) == 0 &&
+		    minor(st.st_rdev) == minor) {
+			found = 1;
+			break;
+		}
+		sleep(1);
+		continue;
+	}
+
+	if (!found)
+		return -1;
+
+	control_fd = open(DLM_CONTROL_PATH, O_RDWR);
+	if (control_fd == -1)
+		return -1;
+
+ out:
+	fcntl(control_fd, F_SETFD, 1);
+
+	if (!kernel_version_detected)
+		detect_kernel_version();
+	return 0;
+}
+
+/* the max number of characters in a sysfs device name, not including \0 */
+#define MAX_SYSFS_NAME 19
+
+static int find_udev_device(const char *lockspace, int minor, char *udev_path)
+{
+	char bname[PATH_MAX];
+	char tmp_path[PATH_MAX];
+	DIR *d;
+	struct dirent *de;
+	struct stat st;
+	size_t basename_len;
+	int i;
+
+	ls_dev_name(lockspace, udev_path, PATH_MAX);
+	snprintf(bname, PATH_MAX, DLM_PREFIX "%s", lockspace);
+	basename_len = strlen(bname);
+
+	for (i = 0; i < 10; i++) {
+
+		/* look for a device with the full name */
+
+		if (stat(udev_path, &st) == 0 && minor(st.st_rdev) == minor)
+			return 0;
+
+		if (basename_len < MAX_SYSFS_NAME) {
+			sleep(1);
+			continue;
+		}
+
+		/* look for a device with a truncated name */
+
+		d = opendir(MISC_PREFIX);
+		while ((de = readdir(d))) {
+			if (de->d_name[0] == '.')
+				continue;
+			if (strlen(de->d_name) < MAX_SYSFS_NAME)
+				continue;
+			if (strncmp(de->d_name, bname, MAX_SYSFS_NAME))
+				continue;
+			snprintf(tmp_path, PATH_MAX, MISC_PREFIX "%s",
+				 de->d_name);
+			if (stat(tmp_path, &st))
+				continue;
+			if (minor(st.st_rdev) != minor)
+				continue;
+
+			/* truncated name */
+			strncpy(udev_path, tmp_path, PATH_MAX);
+			closedir(d);
+			return 0;
+		}
+		closedir(d);
+		sleep(1);
+	}
+
+	return -1;
+}
+
+/*
+ * do_dlm_dispatch()
+ * Read an ast from the kernel.
+ */
+
+static int do_dlm_dispatch_v5(int fd)
+{
+	char resultbuf[sizeof(struct dlm_lock_result_v5) + DLM_USER_LVB_LEN];
+	struct dlm_lock_result_v5 *result = (struct dlm_lock_result_v5 *)resultbuf;
+	char *fullresult = NULL;
+	int status;
+	void (*astaddr)(void *astarg);
+
+	status = read(fd, result, sizeof(resultbuf));
+	if (status <= 0)
+		return -1;
+
+	/* This shouldn't happen any more, can probably be removed */
+
+	if (result->length != status) {
+		int newstat;
+
+		fullresult = malloc(result->length);
+		if (!fullresult)
+			return -1;
+
+		newstat = read(fd, (struct dlm_lock_result_v5 *)fullresult,
+			       result->length);
+
+		/* If it read OK then use the new data. otherwise we can
+		   still deliver the AST, it just might not have all the
+		   info in it...hmmm */
+
+		if (newstat == result->length)
+			result = (struct dlm_lock_result_v5 *)fullresult;
+	} else {
+		fullresult = resultbuf;
+	}
+
+
+	/* Copy lksb to user's buffer - except the LVB ptr */
+	memcpy(result->user_lksb, &result->lksb,
+	       sizeof(struct dlm_lksb) - sizeof(char*));
+
+	/* Flip the status. Kernel space likes negative return codes,
+	   userspace positive ones */
+	result->user_lksb->sb_status = -result->user_lksb->sb_status;
+
+	/* Copy optional items */
+	if (result->lvb_offset)
+		memcpy(result->user_lksb->sb_lvbptr,
+		       fullresult + result->lvb_offset, DLM_LVB_LEN);
+
+	/* Call AST */
+	if (result->user_astaddr) {
+		astaddr = result->user_astaddr;
+		astaddr(result->user_astparam);
+	}
+
+	if (fullresult != resultbuf)
+		free(fullresult);
+
+	return 0;
+}
+
+static int do_dlm_dispatch_v6(int fd)
+{
+	char resultbuf[sizeof(struct dlm_lock_result) + DLM_USER_LVB_LEN];
+	struct dlm_lock_result *result = (struct dlm_lock_result *)resultbuf;
+	int status;
+	void (*astaddr)(void *astarg);
+
+	status = read(fd, result, sizeof(resultbuf));
+	if (status <= 0)
+		return -1;
+
+	/* Copy lksb to user's buffer - except the LVB ptr */
+	memcpy(result->user_lksb, &result->lksb,
+	       sizeof(struct dlm_lksb) - sizeof(char*));
+
+	/* Copy lvb to user's buffer */
+	if (result->lvb_offset)
+		memcpy(result->user_lksb->sb_lvbptr,
+		       (char *)result + result->lvb_offset, DLM_LVB_LEN);
+
+	result->user_lksb->sb_status = -result->user_lksb->sb_status;
+
+	if (result->user_astaddr) {
+		astaddr = result->user_astaddr;
+		astaddr(result->user_astparam);
+	}
+
+	return 0;
+}
+
+static int do_dlm_dispatch(int fd)
+{
+	if (kernel_version.version[0] == 5)
+		return do_dlm_dispatch_v5(fd);
+	else
+		return do_dlm_dispatch_v6(fd);
+}
+
+
+/*
+ * sync_write()
+ * Helper routine which supports the synchronous DLM calls. This
+ * writes a parameter block down to the DLM and waits for the
+ * operation to complete. This hides the different completion mechanism
+ * used when called from the main thread or the DLM 'AST' thread.
+ */
+
+#ifdef _REENTRANT
+
+static int sync_write_v5(struct dlm_ls_info *lsinfo,
+			 struct dlm_write_request_v5 *req, int len)
+{
+	struct lock_wait lwait;
+	int status;
+
+	if (pthread_self() == lsinfo->tid) {
+		/* This is the DLM worker thread, don't use lwait to sync */
+		req->i.lock.castaddr  = dummy_ast_routine;
+		req->i.lock.castparam = NULL;
+
+		status = write(lsinfo->fd, req, len);
+		if (status < 0)
+			return -1;
+
+		while (req->i.lock.lksb->sb_status == EINPROG) {
+			do_dlm_dispatch_v5(lsinfo->fd);
+		}
+	} else {
+		pthread_cond_init(&lwait.cond, NULL);
+		pthread_mutex_init(&lwait.mutex, NULL);
+		pthread_mutex_lock(&lwait.mutex);
+
+		req->i.lock.castaddr  = sync_ast_routine;
+		req->i.lock.castparam = &lwait;
+
+		status = write(lsinfo->fd, req, len);
+		if (status < 0)
+			return -1;
+
+		pthread_cond_wait(&lwait.cond, &lwait.mutex);
+		pthread_mutex_unlock(&lwait.mutex);
+	}
+
+	return status; /* lock status is in the lksb */
+}
+
+static int sync_write_v6(struct dlm_ls_info *lsinfo,
+			 struct dlm_write_request *req, int len)
+{
+	struct lock_wait lwait;
+	int status;
+
+	if (pthread_self() == lsinfo->tid) {
+		/* This is the DLM worker thread, don't use lwait to sync */
+		req->i.lock.castaddr  = dummy_ast_routine;
+		req->i.lock.castparam = NULL;
+
+		status = write(lsinfo->fd, req, len);
+		if (status < 0)
+			return -1;
+
+		while (req->i.lock.lksb->sb_status == EINPROG) {
+			do_dlm_dispatch_v6(lsinfo->fd);
+		}
+	} else {
+		pthread_cond_init(&lwait.cond, NULL);
+		pthread_mutex_init(&lwait.mutex, NULL);
+		pthread_mutex_lock(&lwait.mutex);
+
+		req->i.lock.castaddr  = sync_ast_routine;
+		req->i.lock.castparam = &lwait;
+
+		status = write(lsinfo->fd, req, len);
+		if (status < 0)
+			return -1;
+
+		pthread_cond_wait(&lwait.cond, &lwait.mutex);
+		pthread_mutex_unlock(&lwait.mutex);
+	}
+
+	return status; /* lock status is in the lksb */
+}
+
+#else /* _REENTRANT */
+
+static int sync_write_v5(struct dlm_ls_info *lsinfo,
+			 struct dlm_write_request_v5 *req, int len)
+{
+	int status;
+
+	req->i.lock.castaddr  = dummy_ast_routine;
+	req->i.lock.castparam = NULL;
+
+	status = write(lsinfo->fd, req, len);
+	if (status < 0)
+		return -1;
+
+	while (req->i.lock.lksb->sb_status == EINPROG) {
+		do_dlm_dispatch_v5(lsinfo->fd);
+	}
+
+	errno = req->i.lock.lksb->sb_status;
+	if (errno && errno != EUNLOCK)
+		return -1;
+	return 0;
+}
+
+static int sync_write_v6(struct dlm_ls_info *lsinfo,
+			 struct dlm_write_request *req, int len)
+{
+	int status;
+
+	req->i.lock.castaddr  = dummy_ast_routine;
+	req->i.lock.castparam = NULL;
+
+	status = write(lsinfo->fd, req, len);
+	if (status < 0)
+		return -1;
+
+	while (req->i.lock.lksb->sb_status == EINPROG) {
+		do_dlm_dispatch_v6(lsinfo->fd);
+	}
+
+	errno = req->i.lock.lksb->sb_status;
+	if (errno && errno != EUNLOCK)
+		return -1;
+	return 0;
+}
+
+#endif /* _REENTRANT */
+
+
+/*
+ * Lock
+ * All the ways to request/convert a lock
+ */
+
+static int ls_lock_v5(dlm_lshandle_t ls,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,
+		void (*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg))
+{
+	char parambuf[sizeof(struct dlm_write_request_v5) + DLM_RESNAME_MAXLEN];
+	struct dlm_write_request_v5 *req = (struct dlm_write_request_v5 *)parambuf;
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+	int status;
+	int len;
+
+	memset(req, 0, sizeof(*req));
+	set_version_v5(req);
+
+	req->cmd = DLM_USER_LOCK;
+	req->i.lock.mode = mode;
+	req->i.lock.flags = (flags & ~LKF_WAIT);
+	req->i.lock.lkid = lksb->sb_lkid;
+	req->i.lock.parent = parent;
+	req->i.lock.lksb = lksb;
+	req->i.lock.castaddr = astaddr;
+	req->i.lock.bastaddr = bastaddr;
+	req->i.lock.castparam = astarg;	/* same comp and blocking ast arg */
+	req->i.lock.bastparam = astarg;
+
+	if (flags & LKF_CONVERT) {
+		req->i.lock.namelen = 0;
+	} else {
+		if (namelen > DLM_RESNAME_MAXLEN) {
+			errno = EINVAL;
+			return -1;
+		}
+		req->i.lock.namelen = namelen;
+		memcpy(req->i.lock.name, name, namelen);
+	}
+
+	if (flags & LKF_VALBLK) {
+		memcpy(req->i.lock.lvb, lksb->sb_lvbptr, DLM_LVB_LEN);
+	}
+
+	len = sizeof(struct dlm_write_request_v5) + namelen;
+	lksb->sb_status = EINPROG;
+
+	if (flags & LKF_WAIT)
+		status = sync_write_v5(lsinfo, req, len);
+	else
+		status = write(lsinfo->fd, req, len);
+
+	if (status < 0)
+		return -1;
+
+	/*
+	 * the lock id is the return value from the write on the device
+	 */
+
+	if (status > 0)
+		lksb->sb_lkid = status;
+	return 0;
+}
+
+static int ls_lock_v6(dlm_lshandle_t ls,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,
+		void (*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg),
+		uint64_t *xid,
+		uint64_t *timeout)
+{
+	char parambuf[sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN];
+	struct dlm_write_request *req = (struct dlm_write_request *)parambuf;
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+	int status;
+	int len;
+
+	memset(req, 0, sizeof(*req));
+	set_version_v6(req);
+
+	req->cmd = DLM_USER_LOCK;
+	req->i.lock.mode = mode;
+	req->i.lock.flags = (flags & ~LKF_WAIT);
+	req->i.lock.lkid = lksb->sb_lkid;
+	req->i.lock.parent = parent;
+	req->i.lock.lksb = lksb;
+	req->i.lock.castaddr = astaddr;
+	req->i.lock.bastaddr = bastaddr;
+	req->i.lock.castparam = astarg;	/* same comp and blocking ast arg */
+	req->i.lock.bastparam = astarg;
+
+	if (xid)
+		req->i.lock.xid = *xid;
+	if (timeout)
+		req->i.lock.timeout = *timeout;
+
+	if (flags & LKF_CONVERT) {
+		req->i.lock.namelen = 0;
+	} else {
+		if (namelen > DLM_RESNAME_MAXLEN) {
+			errno = EINVAL;
+			return -1;
+		}
+		req->i.lock.namelen = namelen;
+		memcpy(req->i.lock.name, name, namelen);
+	}
+
+	if (flags & LKF_VALBLK) {
+		memcpy(req->i.lock.lvb, lksb->sb_lvbptr, DLM_LVB_LEN);
+	}
+
+	len = sizeof(struct dlm_write_request) + namelen;
+	lksb->sb_status = EINPROG;
+
+	if (flags & LKF_WAIT)
+		status = sync_write_v6(lsinfo, req, len);
+	else
+		status = write(lsinfo->fd, req, len);
+
+	if (status < 0)
+		return -1;
+
+	/*
+	 * the lock id is the return value from the write on the device
+	 */
+
+	if (status > 0)
+		lksb->sb_lkid = status;
+	return 0;
+}
+
+static int ls_lock(dlm_lshandle_t ls,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,
+		void (*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg),
+		void *range)
+{
+	/* no support for range locks */
+	if (range) {
+		errno = ENOSYS;
+		return -1;
+	}
+
+	if (flags & LKF_VALBLK && !lksb->sb_lvbptr) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (kernel_version.version[0] == 5)
+		return ls_lock_v5(ls, mode, lksb, flags, name, namelen, parent,
+				  astaddr, astarg, bastaddr);
+	else
+		return ls_lock_v6(ls, mode, lksb, flags, name, namelen, parent,
+				  astaddr, astarg, bastaddr, NULL, NULL);
+}
+
+/*
+ * Extended async locking in own lockspace
+ */
+int dlm_ls_lockx(dlm_lshandle_t ls,
+		 uint32_t mode,
+		 struct dlm_lksb *lksb,
+		 uint32_t flags,
+		 const void *name,
+		 unsigned int namelen,
+		 uint32_t parent,
+		 void (*astaddr) (void *astarg),
+		 void *astarg,
+		 void (*bastaddr) (void *astarg),
+		 uint64_t *xid,
+		 uint64_t *timeout)
+{
+	if (kernel_version.version[0] < 6) {
+		errno = ENOSYS;
+		return -1;
+	}
+
+	return ls_lock_v6(ls, mode, lksb, flags, name, namelen, parent,
+			  astaddr, astarg, bastaddr, xid, timeout);
+}
+
+/*
+ * Async locking in own lockspace
+ */
+int dlm_ls_lock(dlm_lshandle_t ls,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,
+		void (*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg),
+		void *range)
+{
+	return ls_lock(ls, mode, lksb, flags, name, namelen, parent,
+		       astaddr, astarg, bastaddr, range);
+}
+
+/*
+ * Sync locking in own lockspace
+ */
+int dlm_ls_lock_wait(dlm_lshandle_t ls,
+		     uint32_t mode,
+		     struct dlm_lksb *lksb,
+		     uint32_t flags,
+		     const void *name,
+		     unsigned int namelen,
+		     uint32_t parent,
+		     void *bastarg,
+		     void (*bastaddr) (void *bastarg),
+		     void *range)
+{
+	return ls_lock(ls, mode, lksb, flags | LKF_WAIT, name, namelen, parent,
+		       NULL, bastarg, bastaddr, range);
+}
+
+/*
+ * Async locking in the default lockspace
+ */
+int dlm_lock(uint32_t mode,
+	     struct dlm_lksb *lksb,
+	     uint32_t flags,
+	     const void *name,
+	     unsigned int namelen,
+	     uint32_t parent,
+	     void (*astaddr) (void *astarg),
+	     void *astarg,
+	     void (*bastaddr) (void *astarg),
+	     void *range)
+{
+	if (open_default_lockspace())
+		return -1;
+
+	return ls_lock(default_ls, mode, lksb, flags, name, namelen, parent,
+		       astaddr, astarg, bastaddr, range);
+}
+
+/*
+ * Sync locking in the default lockspace
+ */
+int dlm_lock_wait(uint32_t mode,
+		     struct dlm_lksb *lksb,
+		     uint32_t flags,
+		     const void *name,
+		     unsigned int namelen,
+		     uint32_t parent,
+		     void *bastarg,
+		     void (*bastaddr) (void *bastarg),
+		     void *range)
+{
+	if (open_default_lockspace())
+		return -1;
+
+	return ls_lock(default_ls, mode, lksb, flags | LKF_WAIT, name, namelen,
+		       parent, NULL, bastarg, bastaddr, range);
+}
+
+
+/*
+ * Unlock
+ * All the ways to unlock/cancel a lock
+ */
+
+static int ls_unlock_v5(struct dlm_ls_info *lsinfo, uint32_t lkid,
+			uint32_t flags, struct dlm_lksb *lksb, void *astarg)
+{
+	struct dlm_write_request_v5 req;
+
+	set_version_v5(&req);
+	req.cmd = DLM_USER_UNLOCK;
+	req.i.lock.lkid = lkid;
+	req.i.lock.flags = (flags & ~LKF_WAIT);
+	req.i.lock.lksb  = lksb;
+	req.i.lock.castparam = astarg;
+	/* DLM_USER_UNLOCK will default to existing completion AST */
+	req.i.lock.castaddr = 0;
+	lksb->sb_status = EINPROG;
+
+	if (flags & LKF_WAIT)
+		return sync_write_v5(lsinfo, &req, sizeof(req));
+	else
+		return write(lsinfo->fd, &req, sizeof(req));
+}
+
+static int ls_unlock_v6(struct dlm_ls_info *lsinfo, uint32_t lkid,
+			uint32_t flags, struct dlm_lksb *lksb, void *astarg)
+{
+	struct dlm_write_request req;
+
+	set_version_v6(&req);
+	req.cmd = DLM_USER_UNLOCK;
+	req.i.lock.lkid = lkid;
+	req.i.lock.flags = (flags & ~LKF_WAIT);
+	req.i.lock.lksb  = lksb;
+	req.i.lock.namelen = 0;
+	req.i.lock.castparam = astarg;
+	/* DLM_USER_UNLOCK will default to existing completion AST */
+	req.i.lock.castaddr = 0;
+	lksb->sb_status = EINPROG;
+
+	if (flags & LKF_WAIT)
+		return sync_write_v6(lsinfo, &req, sizeof(req));
+	else
+		return write(lsinfo->fd, &req, sizeof(req));
+}
+
+int dlm_ls_unlock(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags,
+		  struct dlm_lksb *lksb, void *astarg)
+{
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+	int status;
+
+	if (ls == NULL) {
+		errno = ENOTCONN;
+		return -1;
+	}
+
+	if (!lkid) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (kernel_version.version[0] == 5)
+		status = ls_unlock_v5(lsinfo, lkid, flags, lksb, astarg);
+	else
+		status = ls_unlock_v6(lsinfo, lkid, flags, lksb, astarg);
+
+	if (status < 0)
+		return -1;
+	return 0;
+}
+
+int dlm_ls_unlock_wait(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags,
+		       struct dlm_lksb *lksb)
+{
+	return dlm_ls_unlock(ls, lkid, flags | LKF_WAIT, lksb, NULL);
+}
+
+int dlm_unlock_wait(uint32_t lkid, uint32_t flags, struct dlm_lksb *lksb)
+{
+	return dlm_ls_unlock_wait(default_ls, lkid, flags | LKF_WAIT, lksb);
+}
+
+int dlm_unlock(uint32_t lkid, uint32_t flags, struct dlm_lksb *lksb,
+	       void *astarg)
+{
+	return dlm_ls_unlock(default_ls, lkid, flags, lksb, astarg);
+}
+
+int dlm_ls_deadlock_cancel(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags)
+{
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+	struct dlm_write_request req;
+
+	if (kernel_version.version[0] < 6) {
+		errno = ENOSYS;
+		return -1;
+	}
+
+	if (ls == NULL) {
+		errno = ENOTCONN;
+		return -1;
+	}
+
+	if (!lkid) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	set_version_v6(&req);
+	req.cmd = DLM_USER_DEADLOCK;
+	req.i.lock.lkid = lkid;
+	req.i.lock.flags = flags;
+
+	return write(lsinfo->fd, &req, sizeof(req));
+}
+
+
+/*
+ * Purge
+ * Clear away orphan locks
+ */
+
+int dlm_ls_purge(dlm_lshandle_t ls, int nodeid, int pid)
+{
+	struct dlm_write_request req;
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+	int status;
+
+	if (kernel_version.version[0] < 6) {
+		errno = ENOSYS;
+		return -1;
+	}
+
+	if (ls == NULL) {
+		errno = ENOTCONN;
+		return -1;
+	}
+
+	set_version_v6(&req);
+	req.cmd = DLM_USER_PURGE;
+	req.i.purge.nodeid = nodeid;
+	req.i.purge.pid = pid;
+
+	status = write(lsinfo->fd, &req, sizeof(req));
+
+	if (status < 0)
+		return -1;
+	return 0;
+}
+
+
+/* These two routines for for users that want to
+ * do their own fd handling.
+ * This allows a non-threaded app to use the DLM.
+ */
+int dlm_get_fd(void)
+{
+    if (default_ls)
+    {
+	return default_ls->fd;
+    }
+    else
+    {
+	if (open_default_lockspace())
+	    return -1;
+	else
+	    return default_ls->fd;
+    }
+}
+
+int dlm_dispatch(int fd)
+{
+    int status;
+    int fdflags;
+
+    fdflags = fcntl(fd, F_GETFL, 0);
+    fcntl(fd, F_SETFL,  fdflags | O_NONBLOCK);
+    do
+    {
+	status = do_dlm_dispatch(fd);
+    } while (status == 0);
+
+    /* EAGAIN is not an error */
+    if (status < 0 && errno == EAGAIN)
+	status = 0;
+
+    fcntl(fd, F_SETFL, fdflags);
+    return status;
+}
+
+/* Converts a lockspace handle into a file descriptor */
+int dlm_ls_get_fd(dlm_lshandle_t lockspace)
+{
+    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)lockspace;
+
+    return lsinfo->fd;
+}
+
+#ifdef _REENTRANT
+static void *dlm_recv_thread(void *lsinfo)
+{
+	struct dlm_ls_info *lsi = lsinfo;
+
+	for (;;)
+		do_dlm_dispatch(lsi->fd);
+
+	return NULL;
+}
+
+/* Multi-threaded callers normally use this */
+int dlm_pthread_init(void)
+{
+    if (open_default_lockspace())
+	return -1;
+
+    if (default_ls->tid)
+    {
+	errno = EEXIST;
+	return -1;
+    }
+
+    if (pthread_create(&default_ls->tid, NULL, dlm_recv_thread, default_ls))
+    {
+	int saved_errno = errno;
+	close(default_ls->fd);
+	free(default_ls);
+	default_ls = NULL;
+	errno = saved_errno;
+	return -1;
+    }
+    return 0;
+}
+
+/* And same, for those with their own lockspace */
+int dlm_ls_pthread_init(dlm_lshandle_t ls)
+{
+    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+
+    if (lsinfo->tid)
+    {
+	errno = EEXIST;
+	return -1;
+    }
+
+    return pthread_create(&lsinfo->tid, NULL, dlm_recv_thread, (void *)ls);
+}
+#endif
+
+/*
+ * Lockspace manipulation functions
+ * Privileged users (checked by the kernel) can create/release lockspaces
+ */
+
+static int create_lockspace_v5(const char *name, uint32_t flags)
+{
+	char reqbuf[sizeof(struct dlm_write_request_v5) + DLM_LOCKSPACE_LEN];
+	struct dlm_write_request_v5 *req = (struct dlm_write_request_v5 *)reqbuf;
+	int namelen = strlen(name);
+	int minor;
+
+	memset(reqbuf, 0, sizeof(reqbuf));
+	set_version_v5(req);
+
+	req->cmd = DLM_USER_CREATE_LOCKSPACE;
+	req->i.lspace.flags = flags;
+
+	if (namelen > DLM_LOCKSPACE_LEN) {
+		errno = EINVAL;
+		return -1;
+	}
+	memcpy(req->i.lspace.name, name, namelen);
+
+	minor = write(control_fd, req, sizeof(*req) + namelen);
+
+	return minor;
+}
+
+static int create_lockspace_v6(const char *name, uint32_t flags)
+{
+	char reqbuf[sizeof(struct dlm_write_request) + DLM_LOCKSPACE_LEN];
+	struct dlm_write_request *req = (struct dlm_write_request *)reqbuf;
+	int namelen = strlen(name);
+	int minor;
+
+	memset(reqbuf, 0, sizeof(reqbuf));
+	set_version_v6(req);
+
+	req->cmd = DLM_USER_CREATE_LOCKSPACE;
+	req->i.lspace.flags = flags;
+
+	if (namelen > DLM_LOCKSPACE_LEN) {
+		errno = EINVAL;
+		return -1;
+	}
+	memcpy(req->i.lspace.name, name, namelen);
+
+	minor = write(control_fd, req, sizeof(*req) + namelen);
+
+	return minor;
+}
+
+static dlm_lshandle_t create_lockspace(const char *name, mode_t mode,
+				       uint32_t flags)
+{
+	char dev_path[PATH_MAX];
+	char udev_path[PATH_MAX];
+	struct dlm_ls_info *newls;
+	int error, saved_errno, minor;
+
+	/* We use the control device for creating lockspaces. */
+	if (open_control_device())
+		return NULL;
+
+	newls = malloc(sizeof(struct dlm_ls_info));
+	if (!newls)
+		return NULL;
+
+	ls_dev_name(name, dev_path, sizeof(dev_path));
+
+	if (kernel_version.version[0] == 5)
+		minor = create_lockspace_v5(name, flags);
+	else
+		minor = create_lockspace_v6(name, flags);
+
+	if (minor < 0)
+		goto fail;
+
+	/* Wait for udev to create the device; the device it creates may
+	   have a truncated name due to the sysfs device name limit. */
+	   
+	error = find_udev_device(name, minor, udev_path);
+	if (error)
+		goto fail;
+
+	/* If the symlink already exists, find_udev_device() will return
+	   it and we'll skip this. */
+
+	if (strcmp(dev_path, udev_path)) {
+		error = symlink(udev_path, dev_path);
+		if (error)
+			goto fail;
+	}
+
+	/* Open it and return the struct as a handle */
+
+	newls->fd = open(dev_path, O_RDWR);
+	if (newls->fd == -1)
+		goto fail;
+	if (mode)
+		fchmod(newls->fd, mode);
+	newls->tid = 0;
+	fcntl(newls->fd, F_SETFD, 1);
+	return (dlm_lshandle_t)newls;
+
+ fail:
+	saved_errno = errno;
+	free(newls);
+	errno = saved_errno;
+	return NULL;
+}
+
+dlm_lshandle_t dlm_new_lockspace(const char *name, mode_t mode, uint32_t flags)
+{
+	return create_lockspace(name, mode, flags);
+}
+
+dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode)
+{
+	return create_lockspace(name, mode, 0);
+}
+
+static int release_lockspace_v5(uint32_t minor, uint32_t flags)
+{
+	struct dlm_write_request_v5 req;
+
+	set_version_v5(&req);
+	req.cmd = DLM_USER_REMOVE_LOCKSPACE;
+	req.i.lspace.minor = minor;
+	req.i.lspace.flags = flags;
+
+	return write(control_fd, &req, sizeof(req));
+}
+
+static int release_lockspace_v6(uint32_t minor, uint32_t flags)
+{
+	struct dlm_write_request req;
+
+	set_version_v6(&req);
+	req.cmd = DLM_USER_REMOVE_LOCKSPACE;
+	req.i.lspace.minor = minor;
+	req.i.lspace.flags = flags;
+
+	return write(control_fd, &req, sizeof(req));
+}
+
+static int release_lockspace(uint32_t minor, uint32_t flags)
+{
+	if (kernel_version.version[0] == 5)
+		return release_lockspace_v5(minor, flags);
+	else
+		return release_lockspace_v6(minor, flags);
+}
+
+int dlm_release_lockspace(const char *name, dlm_lshandle_t ls, int force)
+{
+	char dev_path[PATH_MAX];
+	struct stat st;
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+	uint32_t flags = 0;
+	int fd, is_symlink = 0;
+
+	ls_dev_name(name, dev_path, sizeof(dev_path));
+	if (!lstat(dev_path, &st) && S_ISLNK(st.st_mode))
+		is_symlink = 1;
+
+	/* We need the minor number */
+	if (fstat(lsinfo->fd, &st))
+		return -1;
+
+	/* Close the lockspace first if it's in use */
+	ls_pthread_cleanup(lsinfo);
+
+	if (open_control_device())
+		return -1;
+
+	if (force)
+		flags = DLM_USER_LSFLG_FORCEFREE;
+
+	release_lockspace(minor(st.st_rdev), flags);
+
+	if (!is_symlink)
+		return 0;
+
+	/* The following open is used to detect if our release was the last.
+	   It will fail if our release was the last, because either:
+	   . udev has already removed the truncated sysfs device name (ENOENT)
+	   . the misc device has been deregistered in the kernel (ENODEV)
+	     (the deregister completes before release returns)
+
+	   So, if the open fails, we know that our release was the last,
+	   udev will be removing the device with the truncated name (if it
+	   hasn't already), and we should remove the symlink. */
+
+	fd = open(dev_path, O_RDWR);
+	if (fd < 0)
+		unlink(dev_path);
+	else
+		close(fd); /* our release was not the last */
+
+	return 0;
+}
+
+/*
+ * Normal users just open/close lockspaces
+ */
+
+dlm_lshandle_t dlm_open_lockspace(const char *name)
+{
+	char dev_name[PATH_MAX];
+	struct dlm_ls_info *newls;
+	int saved_errno;
+
+	/* Need to detect kernel version */
+	if (open_control_device())
+		return NULL;
+
+	newls = malloc(sizeof(struct dlm_ls_info));
+	if (!newls)
+		return NULL;
+
+	newls->tid = 0;
+	ls_dev_name(name, dev_name, sizeof(dev_name));
+
+	newls->fd = open(dev_name, O_RDWR);
+	saved_errno = errno;
+
+	if (newls->fd == -1) {
+		free(newls);
+		errno = saved_errno;
+		return NULL;
+	}
+	fcntl(newls->fd, F_SETFD, 1);
+	return (dlm_lshandle_t)newls;
+}
+
+int dlm_close_lockspace(dlm_lshandle_t ls)
+{
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+
+	ls_pthread_cleanup(lsinfo);
+	return 0;
+}
+
+int dlm_kernel_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
+{
+	if (open_control_device())
+		return -1;
+	*major = kernel_version.version[0];
+	*minor = kernel_version.version[1];
+	*patch = kernel_version.version[2];
+	return 0;
+}
+
+void dlm_library_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
+{
+	*major = DLM_DEVICE_VERSION_MAJOR;
+	*minor = DLM_DEVICE_VERSION_MINOR;
+	*patch = DLM_DEVICE_VERSION_PATCH;
+}
+
diff --git a/libdlm/libdlm.h b/libdlm/libdlm.h
new file mode 100644
index 0000000..17a552c
--- /dev/null
+++ b/libdlm/libdlm.h
@@ -0,0 +1,275 @@
+#ifndef __LIBDLM_H
+#define __LIBDLM_H
+
+/*
+ * Typedefs for things that are compatible with the kernel but replicated here
+ * so that users only need the libdlm include file.  libdlm itself needs the
+ * full kernel file so shouldn't use these.
+ */
+
+#define DLM_LVB_LEN             32
+
+#ifndef BUILDING_LIBDLM
+
+/*
+ * These two lengths are copied from linux/dlmconstants.h
+ * They are the max length of a lockspace name and the max length of a
+ * resource name.
+ */
+
+#define DLM_LOCKSPACE_LEN       64
+#define DLM_RESNAME_MAXLEN      64
+
+struct dlm_lksb {
+	int sb_status;
+	uint32_t sb_lkid;
+	char sb_flags;
+	char *sb_lvbptr;
+};
+
+/* lksb flags */
+#define DLM_SBF_DEMOTED         0x01
+#define DLM_SBF_VALNOTVALID     0x02
+#define DLM_SBF_ALTMODE         0x04
+
+/* dlm_new_lockspace flags */
+#define DLM_LSFL_NODIR          0x00000001
+#define DLM_LSFL_TIMEWARN       0x00000002
+#define DLM_LSFL_FS             0x00000004
+#define DLM_LSFL_NEWEXCL        0x00000008
+
+#endif
+
+
+#if 0
+/* Dummy definition to keep linkages */
+struct dlm_queryinfo;
+#endif
+
+extern int dlm_kernel_version(uint32_t *maj, uint32_t *min, uint32_t *patch);
+extern void dlm_library_version(uint32_t *maj, uint32_t *min, uint32_t *patch);
+
+
+/*
+ * Using the default lockspace
+ *
+ * lock_resource() - simple sync request or convert (requires pthreads)
+ * unlock_resource() - simple sync unlock (requires pthreads)
+ * dlm_lock() - async request or convert
+ * dlm_unlock() - async unlock or cancel
+ * dlm_lock_wait() - sync request or convert
+ * dlm_unlock_wait() - sync unlock or cancel
+ */
+
+#ifdef _REENTRANT
+extern int lock_resource(const char *resource, int mode, int flags, int *lockid);
+extern int unlock_resource(int lockid);
+#endif
+
+extern int dlm_lock(uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,			/* unusued */
+		void (*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg),
+		void *range);				/* unused */
+
+extern int dlm_unlock(uint32_t lkid,
+		uint32_t flags,
+		struct dlm_lksb *lksb,
+		void *astarg);
+
+extern int dlm_lock_wait(uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,			/* unused */
+		void *bastarg,
+		void (*bastaddr) (void *bastarg),
+		void *range);				/* unused */
+
+extern int dlm_unlock_wait(uint32_t lkid,
+		uint32_t flags,
+		struct dlm_lksb *lksb);
+
+
+/* 
+ * These two are for users that want to do their own FD handling
+ *
+ * dlm_get_fd() - returns fd for the default lockspace for polling and dispatch
+ * dlm_dispatch() - dispatches pending asts and basts
+ */
+
+extern int dlm_get_fd(void);
+extern int dlm_dispatch(int fd);
+
+
+/*
+ * Creating your own lockspace
+ *
+ * dlm_create_lockspace() - create and open a lockspace and return a handle
+ *                          to it.  Privileges are required to create/release.
+ * dlm_new_lockspace() - same as create but allows flags
+ * dlm_open_lockspace() - simply returns a handle for an existing lockspace and
+ *                        may be called by ordinary users.
+ * dlm_release_lockspace()
+ * dlm_close_lockspace()
+ * dlm_ls_get_fd()
+ *
+ * NOTE: that if you dlm_create_lockspace() then dlm_open_lockspace() you will
+ * have two open files on the same device. Hardly a major problem but I thought
+ * it worth pointing out.
+ */
+
+typedef void *dlm_lshandle_t;
+
+extern dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode);
+extern int dlm_release_lockspace(const char *name, dlm_lshandle_t ls,
+		int force);
+extern dlm_lshandle_t dlm_open_lockspace(const char *name);
+extern int dlm_close_lockspace(dlm_lshandle_t ls);
+extern int dlm_ls_get_fd(dlm_lshandle_t ls);
+extern dlm_lshandle_t dlm_new_lockspace(const char *name, mode_t mode,
+		uint32_t flags);
+
+
+/*
+ * Using your own lockspace
+ *
+ * dlm_ls_lock()
+ * dlm_ls_lockx()
+ * dlm_ls_unlock()
+ * dlm_ls_lock_wait()
+ * dlm_ls_unlock_wait()
+ * dlm_ls_deadlock_cancel()
+ * dlm_ls_purge()
+ */
+
+extern int dlm_ls_lock(dlm_lshandle_t lockspace,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,			/* unused */
+		void (*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg),
+		void *range);				/* unused */
+
+extern int dlm_ls_lockx(dlm_lshandle_t lockspace,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,			/* unused */
+		void (*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg),
+		uint64_t *xid,
+		uint64_t *timeout);
+
+extern int dlm_ls_unlock(dlm_lshandle_t lockspace,
+		uint32_t lkid,
+		uint32_t flags,
+		struct dlm_lksb *lksb,
+		void *astarg);
+
+extern int dlm_ls_lock_wait(dlm_lshandle_t lockspace,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,			/* unused */
+		void *bastarg,
+		void (*bastaddr) (void *bastarg),
+		void *range);				/* unused */
+
+extern int dlm_ls_unlock_wait(dlm_lshandle_t lockspace,
+		uint32_t lkid,
+		uint32_t flags,
+		struct dlm_lksb *lksb);
+
+extern int dlm_ls_deadlock_cancel(dlm_lshandle_t ls,
+		uint32_t lkid,
+		uint32_t flags);
+
+extern int dlm_ls_purge(dlm_lshandle_t lockspace,
+		int nodeid,
+		int pid);
+
+
+/*
+ * For threaded applications
+ *
+ * dlm_pthread_init()
+ * dlm_ls_pthread_init() - call this before any locking operations and the ASTs
+ *                         will be delivered in their own thread.
+ * dlm_pthread_cleanup() - call the cleanup routine at application exit
+ *			   (optional) or, if the locking functions are in a
+ *			   shared library that is to be unloaded.
+ *
+ * dlm_close/release_lockspace() will tidy the threads for a non-default
+ * lockspace
+ */
+
+#ifdef _REENTRANT
+extern int dlm_pthread_init(void);
+extern int dlm_ls_pthread_init(dlm_lshandle_t lockspace);
+extern int dlm_pthread_cleanup(void);
+#endif
+
+
+/*
+ * Lock modes
+ */
+
+#define LKM_NLMODE          0           /* null lock */
+#define LKM_CRMODE          1           /* concurrent read */
+#define LKM_CWMODE          2           /* concurrent write */
+#define LKM_PRMODE          3           /* protected read */
+#define LKM_PWMODE          4           /* protected write */
+#define LKM_EXMODE          5           /* exclusive */
+
+
+/*
+ * Locking flags - these match the ones in dlm.h
+ */
+
+#define LKF_NOQUEUE         0x00000001
+#define LKF_CANCEL          0x00000002
+#define LKF_CONVERT         0x00000004
+#define LKF_VALBLK          0x00000008
+#define LKF_QUECVT          0x00000010
+#define LKF_IVVALBLK        0x00000020
+#define LKF_CONVDEADLK      0x00000040
+#define LKF_PERSISTENT      0x00000080
+#define LKF_NODLCKWT        0x00000100
+#define LKF_NODLCKBLK       0x00000200
+#define LKF_EXPEDITE        0x00000400
+#define LKF_NOQUEUEBAST     0x00000800
+#define LKF_HEADQUE         0x00001000
+#define LKF_NOORDER         0x00002000
+#define LKF_ORPHAN          0x00004000
+#define LKF_ALTPR           0x00008000
+#define LKF_ALTCW           0x00010000
+#define LKF_FORCEUNLOCK     0x00020000
+#define LKF_TIMEOUT         0x00040000
+#define LKF_WAIT            0x80000000  /* Userspace only, for sync API calls */
+
+/*
+ * Extra return codes used by the DLM
+ */
+
+#define ECANCEL             0x10001
+#define EUNLOCK             0x10002
+#define	EINPROG		    0x10003     /* lock operation is in progress */
+
+#endif
+
diff --git a/libdlm/libdlm_internal.h b/libdlm/libdlm_internal.h
new file mode 100644
index 0000000..c8b270e
--- /dev/null
+++ b/libdlm/libdlm_internal.h
@@ -0,0 +1,9 @@
+
+/* Needed before we include the kernel libdlm header */
+#define __user
+typedef uint8_t __u8;
+typedef uint16_t __u16;
+typedef uint32_t __u32;
+#define BUILDING_LIBDLM
+
+
diff --git a/libdlm/man/dlm_cleanup.3 b/libdlm/man/dlm_cleanup.3
new file mode 100644
index 0000000..db4a9cf
--- /dev/null
+++ b/libdlm/man/dlm_cleanup.3
@@ -0,0 +1 @@
+.so man3/libdlm.3
diff --git a/libdlm/man/dlm_close_lockspace.3 b/libdlm/man/dlm_close_lockspace.3
new file mode 100644
index 0000000..e5db408
--- /dev/null
+++ b/libdlm/man/dlm_close_lockspace.3
@@ -0,0 +1 @@
+.so man3/dlm_create_lockspace.3
diff --git a/libdlm/man/dlm_create_lockspace.3 b/libdlm/man/dlm_create_lockspace.3
new file mode 100644
index 0000000..3879e85
--- /dev/null
+++ b/libdlm/man/dlm_create_lockspace.3
@@ -0,0 +1,94 @@
+.TH DLM_CREATE_LOCKSPACE 3 "July 5, 2007" "libdlm functions"
+.SH NAME
+dlm_create_lockspace, dlm_open_lockspace, dlm_close_lockspace, dlm_release_lockspace \- manipulate DLM lockspaces
+.SH SYNOPSIS
+.nf
+ #include <libdlm.h>
+
+dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode);
+dlm_lshandle_t dlm_new_lockspace(const char *name, mode_t mode,
+                                 uint32_t flags);
+dlm_lshandle_t dlm_open_lockspace(const char *name);
+int dlm_close_lockspace(dlm_lshandle_t ls);
+int dlm_release_lockspace(const char *name, dlm_lshandle_t ls,
+                          int force);
+
+.fi
+.SH DESCRIPTION
+The DLM allows locks to be partitioned into "lockspaces", and these can be manipulated by userspace calls. It is possible (though not recommended) for an application to have multiple lockspaces open at one time. 
+
+Many of the DLM calls work on the "default" lockspace, which should be fine for most users. The calls with _ls_ in them allow you to isolate your application from all others running in the cluster. Remember, lockspaces are a cluster-wide resource, so if you create a lockspace called "myls" it will share locks with a lockspace called "myls" on all nodes. These calls allow users to create & remove lockspaces, and users to connect to existing lockspace to store their locks there.
+.PP
+.SS
+dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode);
+.br
+This creates a lockspace called <name> and the mode of the file user to access it will be <mode> (subject to umask as usual). The lockspace must not already exist on this node, if it does -1 will be returned and errno will be set to EEXIST. If you really want to use this lockspace you can then use dlm_open_lockspace() below. The name is the name of a misc device that will be created in /dev/misc.
+.br
+On success a handle to the lockspace is returned, which can be used to pass into subsequent dlm_ls_lock/unlock calls. Make no assumptions as to the content of this handle as it's content may change in future.
+.br
+The caller must have CAP_SYSADMIN privileges to do this operation.
+.PP
+Return codes:
+0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
+.nf
+EINVAL          An invalid parameter was passed to the call
+ENOMEM          A (kernel) memory allocation failed
+EEXIST          The lockspace already exists
+EPERM           Process does not have capability to create lockspaces
+ENOSYS          A fatal error occurred initializing the DLM
+Any error returned by the open() system call
+.fi
+.SS
+int dlm_new_lockspace(const char *name, mode_t mode, uint32_t flags)
+.PP
+Performs the same function as 
+.B dlm_create_lockspace()
+above, but passes some creation flags to the call that affect the lockspace being created. Currently supported flags are:
+.nf
+DLM_LSFL_NODIR    the lockspace should not use a resource directory
+DLM_LSFL_TIMEWARN the dlm should emit warnings over netlink when locks
+                  have been waiting too long; required for deadlock
+                  detection
+.fi
+.SS
+int dlm_release_lockspace(const char *name, dlm_lshandle_t ls, int force)
+.PP
+Deletes a lockspace. If the lockspace still has active locks then -1 will be returned and errno set to EBUSY. Both the lockspace handle /and/ the name must be specified. This call also closes the lockspace and stops the thread associated with the lockspace, if any.
+.br
+Note that other nodes in the cluster may still have locks open on this lockspace. This call only removes the lockspace from the current node.  If the force flag is set then the lockspace will be removed even if another user on this node has active locks in it. Existing users will NOT be notified if you do this, so be careful.
+.br
+The caller must have CAP_SYSADMIN privileges to do this operation.
+.PP
+Return codes:
+0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
+.nf
+EINVAL          An invalid parameter was passed to the call
+EPERM           Process does not have capability to release lockspaces
+EBUSY           The lockspace could not be freed because it still
+                contains locks and force was not set.
+.fi
+
+.SS
+dlm_lshandle_t dlm_open_lockspace(const char *name)
+.PP
+Opens an already existing lockspace and returns a handle to it.
+.PP
+Return codes:
+0 is returned if the call completed successfully. If not, -1 is returned and errno is set to an error returned by the open() system call
+.SS
+int dlm_close_lockspace(dlm_lshandle_t ls)
+.br
+Close the lockspace. Any locks held by this process will be freed. If a thread is associated with this lockspace then it will be stopped.
+.PP
+Return codes:
+0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
+.nf
+EINVAL		lockspace was not a valid lockspace handle
+.fi
+
+
+.SH SEE ALSO
+
+.BR libdlm (3),
+.BR dlm_unlock (3),
+.BR dlm_lock (3),
diff --git a/libdlm/man/dlm_dispatch.3 b/libdlm/man/dlm_dispatch.3
new file mode 100644
index 0000000..db4a9cf
--- /dev/null
+++ b/libdlm/man/dlm_dispatch.3
@@ -0,0 +1 @@
+.so man3/libdlm.3
diff --git a/libdlm/man/dlm_get_fd.3 b/libdlm/man/dlm_get_fd.3
new file mode 100644
index 0000000..db4a9cf
--- /dev/null
+++ b/libdlm/man/dlm_get_fd.3
@@ -0,0 +1 @@
+.so man3/libdlm.3
diff --git a/libdlm/man/dlm_lock.3 b/libdlm/man/dlm_lock.3
new file mode 100644
index 0000000..3c5f8b5
--- /dev/null
+++ b/libdlm/man/dlm_lock.3
@@ -0,0 +1,239 @@
+.TH DLM_LOCK 3 "July 5, 2007" "libdlm functions"
+.SH NAME
+dlm_lock \- acquire or convert a DLM lock
+.SH SYNOPSIS
+.nf
+ #include <libdlm.h>
+
+int dlm_lock(uint32_t mode,
+		struct dlm_lksb *lksb,	
+		uint32_t flags,	
+		const void *name,	
+		unsigned int namelen,
+		uint32_t parent,		/* unused */
+		void (*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg),
+		void *range);			/* unused */
+
+int dlm_lock_wait(uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,		/* unused */
+		void *bastarg,
+		void (*bastaddr) (void *bastarg),
+		void *range);			/* unused */
+
+int dlm_ls_lock(dlm_lshandle_t lockspace,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,		/* unused */
+		void (*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg),
+		void *range);			/* unused */
+
+int dlm_ls_lock_wait(dlm_lshandle_t lockspace,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,		/* unusued */
+		void *bastarg,
+		void (*bastaddr) (void *bastarg),
+		void *range);			/* unused */
+
+int dlm_ls_lockx(dlm_lshandle_t lockspace,
+		uint32_t mode,
+		struct dlm_lksb *lksb,
+		uint32_t flags,
+		const void *name,
+		unsigned int namelen,
+		uint32_t parent,		/* unused */
+		(*astaddr) (void *astarg),
+		void *astarg,
+		void (*bastaddr) (void *astarg),
+		uint64_t *xid,
+		uint64_t *timeout);
+
+
+
+.fi
+.SH DESCRIPTION
+dlm_lock and its variants acquire and convert locks in the DLM.
+.PP
+dlm_lock() operations are asynchronous. If the call to dlm_lock returns an error then the operation has failed and the AST routine will not be called. If dlm_lock returns 0 it is still possible that the lock operation will fail. The AST routine will be called when the locking is complete or has failed and the status is returned in the lksb. 
+.B dlm_lock_wait()
+will wait until the lock operation has completed and returns the final completion status.
+.B dlm_ls_lock()
+is the same as 
+.B dlm_lock()
+but takes a lockspace argument. This lockspace must have been previously opened by
+.B dlm_lockspace_open() or
+.B dlm_lockspace_create().
+.PP
+For conversion operations the name and namelen are ignored and the lock ID in the LKSB is used to identify the lock to be converted.
+.PP
+If a lock value block is specified then in general, a grant or a conversion to an equal-level or higher-level lock mode reads the lock value from the resource into the caller's lock value block. When a lock conversion from EX or PW to an equal-level or lower-level lock mode occurs, the contents of the caller's lock value block are written into the resource. If the LVB is invalidated the lksb.sb_flags member will be set to DLM_SBF_VALNOTVALID. Lock values blocks are always 32 bytes long.
+.PP
+If the AST routines or parameter are passed to a conversion operation then they will overwrite those values that were passed to a previous dlm_lock call.
+.PP
+.B mode
+Lock mode to acquire or convert to.
+.nf
+  LKM_NLMODE	NULL Lock
+  LKM_CRMODE	Concurrent read
+  LKM_CWMODE	Concurrent write
+  LKM_PRMODE	Protected read
+  LKM_PWMODE	Protected write
+  LKM_EXMODE	Exclusive
+.fi
+.PP
+.B flags
+Affect the operation of the lock call:
+.nf
+  LKF_NOQUEUE     Don't queue the lock. If it cannot be granted return
+                  -EAGAIN
+  LKF_CONVERT     Convert an existing lock
+  LKF_VALBLK      Lock has a value block
+  LKF_QUECVT      Put conversion to the back of the queue
+  LKF_EXPEDITE    Grant a NL lock immediately regardless of other locks
+                  on the conversion queue
+  LKF_PERSISTENT  Specifies a lock that will not be unlocked when the
+                  process exits; it will become an orphan lock.
+  LKF_CONVDEADLK  Enable internal conversion deadlock resolution where
+                  the lock's granted mode may be set to NL and
+                  DLM_SBF_DEMOTED is returned in lksb.sb_flags.
+  LKF_NODLCKWT    Do not consider this lock when trying to detect
+                  deadlock conditions.
+  LKF_NODLCKBLK   Not implemented
+  LKF_NOQUEUEBAST Send blocking ASTs even for NOQUEUE operations
+  LKF_HEADQUE     Add locks to the head of the convert or waiting queue
+  LKF_NOORDER     Avoid the VMS rules on grant order
+  LKF_ALTPR       If the requested mode can't be granted (generally CW),
+                  try to grant in PR and return DLM_SBF_ALTMODE.
+  LKF_ALTCW       If the requested mode can't be granted (generally PR),
+                  try to grant in CW and return DLM_SBF_ALTMODE.
+  LKF_TIMEOUT     The lock will time out per the timeout arg.
+
+.fi
+.PP
+.B lksb
+Lock Status block
+.br
+This structure contains the returned lock ID, the actual
+status of the lock operation (all lock ops are asynchronous)
+and the value block if LKF_VALBLK is set.
+.PP
+.B name
+.br
+Name of the lock. Can be binary, max 64 bytes. Ignored for lock
+conversions.  (Should be a string to work with debugging tools.)
+.PP
+.B namelen	
+.br
+Length of the above name. Ignored for lock conversions.
+.PP
+.B parent	
+.br
+ID of parent lock or NULL if this is a top-level lock. This is currently unused.
+.PP
+.B ast	
+.br
+Address of AST routine to be called when the lock operation
+completes. The final completion status of the lock will be
+in the lksb. the AST routine must not be NULL.
+.PP		
+.B astargs	
+.br
+Argument to pass to the AST routine (most people pass the lksb
+in here but it can be anything you like.)
+.PP
+.B bast
+.br
+Blocking AST routine. address of a function to call if this 
+lock is blocking another. The function will be called with
+astargs. 
+.PP
+.B range
+.br
+This is unused.
+.PP
+.B xid
+.br
+Optional transaction ID for deadlock detection.
+.PP
+.B timeout
+.br
+Timeout in centiseconds. If it takes longer than this to acquire the lock
+(usually because it is already blocked by another lock), then the AST 
+will trigger with ETIMEDOUT as the status. If the lock operation is a conversion
+then the lock will remain at its current status. If this is a new lock then
+the lock will not exist and any LKB in the lksb will be invalid.  This is
+ignored without the LKF_TIMEOUT flag.
+.PP
+.SS Return values
+0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
+.PP
+.nf
+EINVAL          An invalid parameter was passed to the call (eg bad lock
+                mode or flag)
+ENOMEM          A (kernel) memory allocation failed
+EAGAIN          LKF_NOQUEUE was requested and the lock could not be
+                granted
+EBUSY           The lock is currently being locked or converted
+EFAULT          The userland buffer could not be read/written by the
+                kernel (this indicates a library problem)
+EDEADLOCK       The lock operation is causing a deadlock and has been
+                cancelled. If this was a conversion then the lock is
+                reverted to its previously granted state. If it was a
+                new lock then it has not been granted. (NB Only
+                conversion deadlocks are currently detected)
+.PP
+If an error is returned in the AST, then lksb.sb_status is set to the one of the above values instead of zero.
+.SS Structures
+.nf
+struct dlm_lksb {
+  int      sb_status; /* Final status of lock operation */
+  uint32_t sb_lkid;   /* ID of lock. Returned from dlm_lock()
+                         on first use. Used as input to
+                         dlm_lock() for a conversion operation */
+  char     sb_flags;  /* Completion flags, see above */
+  char     sb_lvbptr; /* Optional pointer to lock value block */
+};
+
+.fi
+.SH EXAMPLE
+.nf
+int status;
+struct dlm_lksb lksb;
+
+status = dlm_lock_wait(LKM_EXMODE,
+                       &lksb,
+                       LKF_NOQUEUE,
+                       "MyLock",
+                       strlen("MyLock"),
+                       0, // Parent,
+                       NULL, // bast arg
+                       NULL, // bast routine,
+                       NULL); // Range
+
+if (status == 0)
+	dlm_unlock_wait(lksb.sb_lkid, 0, &lksb);
+
+.fi
+
+.SH SEE ALSO
+
+.BR libdlm (3),
+.BR dlm_unlock (3),
+.BR dlm_open_lockspace (3),
+.BR dlm_create_lockspace (3),
+.BR dlm_close_lockspace (3),
+.BR dlm_release_lockspace (3)
diff --git a/libdlm/man/dlm_lock_wait.3 b/libdlm/man/dlm_lock_wait.3
new file mode 100644
index 0000000..a99225c
--- /dev/null
+++ b/libdlm/man/dlm_lock_wait.3
@@ -0,0 +1 @@
+.so man3/dlm_lock.3
diff --git a/libdlm/man/dlm_ls_lock.3 b/libdlm/man/dlm_ls_lock.3
new file mode 100644
index 0000000..a99225c
--- /dev/null
+++ b/libdlm/man/dlm_ls_lock.3
@@ -0,0 +1 @@
+.so man3/dlm_lock.3
diff --git a/libdlm/man/dlm_ls_lock_wait.3 b/libdlm/man/dlm_ls_lock_wait.3
new file mode 100644
index 0000000..a99225c
--- /dev/null
+++ b/libdlm/man/dlm_ls_lock_wait.3
@@ -0,0 +1 @@
+.so man3/dlm_lock.3
diff --git a/libdlm/man/dlm_ls_lockx.3 b/libdlm/man/dlm_ls_lockx.3
new file mode 100644
index 0000000..a99225c
--- /dev/null
+++ b/libdlm/man/dlm_ls_lockx.3
@@ -0,0 +1 @@
+.so man3/dlm_lock.3
diff --git a/libdlm/man/dlm_ls_pthread_init.3 b/libdlm/man/dlm_ls_pthread_init.3
new file mode 100644
index 0000000..db4a9cf
--- /dev/null
+++ b/libdlm/man/dlm_ls_pthread_init.3
@@ -0,0 +1 @@
+.so man3/libdlm.3
diff --git a/libdlm/man/dlm_ls_unlock.3 b/libdlm/man/dlm_ls_unlock.3
new file mode 100644
index 0000000..91babd2
--- /dev/null
+++ b/libdlm/man/dlm_ls_unlock.3
@@ -0,0 +1 @@
+.so man3/dlm_unlock.3
diff --git a/libdlm/man/dlm_ls_unlock_wait.3 b/libdlm/man/dlm_ls_unlock_wait.3
new file mode 100644
index 0000000..91babd2
--- /dev/null
+++ b/libdlm/man/dlm_ls_unlock_wait.3
@@ -0,0 +1 @@
+.so man3/dlm_unlock.3
diff --git a/libdlm/man/dlm_new_lockspace.3 b/libdlm/man/dlm_new_lockspace.3
new file mode 100644
index 0000000..e5db408
--- /dev/null
+++ b/libdlm/man/dlm_new_lockspace.3
@@ -0,0 +1 @@
+.so man3/dlm_create_lockspace.3
diff --git a/libdlm/man/dlm_open_lockspace.3 b/libdlm/man/dlm_open_lockspace.3
new file mode 100644
index 0000000..e5db408
--- /dev/null
+++ b/libdlm/man/dlm_open_lockspace.3
@@ -0,0 +1 @@
+.so man3/dlm_create_lockspace.3
diff --git a/libdlm/man/dlm_pthread_init.3 b/libdlm/man/dlm_pthread_init.3
new file mode 100644
index 0000000..db4a9cf
--- /dev/null
+++ b/libdlm/man/dlm_pthread_init.3
@@ -0,0 +1 @@
+.so man3/libdlm.3
diff --git a/libdlm/man/dlm_release_lockspace.3 b/libdlm/man/dlm_release_lockspace.3
new file mode 100644
index 0000000..e5db408
--- /dev/null
+++ b/libdlm/man/dlm_release_lockspace.3
@@ -0,0 +1 @@
+.so man3/dlm_create_lockspace.3
diff --git a/libdlm/man/dlm_unlock.3 b/libdlm/man/dlm_unlock.3
new file mode 100644
index 0000000..9023139
--- /dev/null
+++ b/libdlm/man/dlm_unlock.3
@@ -0,0 +1,94 @@
+.TH DLM_UNLOCK 3 "July 5, 2007" "libdlm functions"
+.SH NAME
+dlm_unlock \- unlock a DLM lock
+.SH SYNOPSIS
+.nf
+#include <libdlm.h>
+
+int dlm_unlock(uint32_t lkid,
+               uint32_t flags, struct dlm_lksb *lksb, void *astarg);
+
+int dlm_unlock_wait(uint32_t lkid,
+                    uint32_t flags, struct dlm_lksb *lksb);
+
+.fi
+.SH DESCRIPTION
+.B dlm_unlock()
+unlocks a lock previously acquired by dlm_lock and its variants.
+.PP
+Unless 
+.B dlm_unlock_wait() 
+is used unlocks are also asynchronous. The AST routine is called when the resource is successfully unlocked (see below).
+.PP
+.B lkid
+Lock ID as returned in the lksb
+.PP
+.B flags
+flags affecting the unlock operation:
+.nf
+  LKF_CANCEL       Cancel a pending lock or conversion. 
+                   This returns the lock to it's previously
+                   granted mode (in case of a conversion) or
+                   unlocks it (in case of a waiting lock).
+  LKF_IVVALBLK     Invalidate value block
+  LKF_FORCEUNLOCK  Unlock the lock even if it's waiting.
+.fi
+.PP
+.B lksb
+LKSB to return status and value block information.
+.PP
+.B astarg
+New parameter to be passed to the completion AST.
+The completion AST routine is the
+last completion AST routine specified in a dlm_lock call.
+If dlm_lock_wait() was the last routine to issue a lock, 
+dlm_unlock_wait() must be used to release the lock. If dlm_lock()
+was the last routine to issue a lock then either dlm_unlock()
+or dlm_unlock_wait() may be called.
+.PP
+
+.SS Return values
+0 is returned if the call completed successfully. If not, -1 is returned and errno is set to one of the following:
+.PP
+.nf
+EINVAL          An invalid parameter was passed to the call (eg bad
+                lock mode or flag)
+EINPROGRESS     The lock is already being unlocked
+EBUSY           The lock is currently being locked or converted
+ENOTEMPTY       An attempt to made to unlock a parent lock that still has
+                child locks.
+ECANCEL         A lock conversion was successfully cancelled
+EUNLOCK         An unlock operation completed successfully
+                (sb_status only)
+EFAULT          The userland buffer could not be read/written by the
+                kernel
+.fi
+If an error is returned in the AST, then lksb.sb_status is set to the one of the above numbers instead of zero.
+.SH EXAMPLE
+.nf
+int status;
+struct dlm_lksb lksb;
+
+status = dlm_lock_wait(LKM_EXMODE,
+                       &lksb,
+                       LKF_NOQUEUE,
+                       "MyLock",
+                       strlen("MyLock"),
+                       0,     // Parent,
+                       NULL,  // bast arg
+                       NULL,  // bast routine,
+                       NULL); // Range
+
+if (status == 0)
+	dlm_unlock_wait(lksb.sb_lkid, 0, &lksb);
+
+.fi
+
+.SH SEE ALSO
+
+.BR libdlm (3),
+.BR dlm_lock (3),
+.BR dlm_open_lockspace (3),
+.BR dlm_create_lockspace (3),
+.BR dlm_close_lockspace (3),
+.BR dlm_release_lockspace (3)
diff --git a/libdlm/man/dlm_unlock_wait.3 b/libdlm/man/dlm_unlock_wait.3
new file mode 100644
index 0000000..91babd2
--- /dev/null
+++ b/libdlm/man/dlm_unlock_wait.3
@@ -0,0 +1 @@
+.so man3/dlm_unlock.3
diff --git a/libdlm/man/libdlm.3 b/libdlm/man/libdlm.3
new file mode 100644
index 0000000..a020560
--- /dev/null
+++ b/libdlm/man/libdlm.3
@@ -0,0 +1,105 @@
+.TH LIBDLM 3 "July 5, 2007" "libdlm functions"
+.SH NAME
+libdlm \- dlm_get_fd, dlm_dispatch, dlm_pthread_init, dlm_ls_pthread_init, dlm_cleanup
+.SH SYNOPSIS
+.nf
+#include <libdlm.h>
+.nf
+int dlm_pthread_init();
+int dlm_ls_pthread_init(dlm_lshandle_t lockspace);
+int dlm_pthread_cleanup();
+int dlm_get_fd(void);
+int dlm_dispatch(int fd);
+
+link with -ldlm
+.fi
+.SH DESCRIPTION
+libdlm provides the programmatic userspace interface to the Distributed Lock manager. It provides all the calls you need to manipulate locks & lockspaces
+.br
+libdlm can be used in pthread or non-pthread applications. For pthread applications simply call the following function before doing any lock operations. If you're using pthreads, remember to define _REENTRANT at the top of the program or using -D_REENTRANT on the compile line.
+.br
+pthreads is the normal way of using the DLM. This way you simply initialize the DLM's thread and all the AST routines will be delivered in that thread. You just call the dlm_lock() etc routines in the main line of your program.
+.br
+If you don't want to use pthreads or you want to handle the dlm callback ASTs yourself then you can get an FD handle to the DLM device and call 
+.B dlm_dispatch()
+on it whenever it becomes active. That was ASTs will be delivered in the context of the thread/process that called 
+.B dlm_dispatch().
+
+
+.SS int dlm_pthread_init()
+.br
+Creates a thread to receive all lock ASTs. The AST callback function for lock operations will be called in the context of this thread. If there is a potential for local resource access conflicts you must provide your own pthread-based locking in the AST routine.
+.PP
+.SS int dlm_ls_pthread_init(dlm_lshandle_t lockspace)
+.br
+As dlm_pthread_init but initializes a thread for the specified lockspace.
+.PP
+.SS int dlm_pthread_cleanup()
+.br
+Cleans up the default lockspace threads after use. Normally you don't need to call this, but if the locking code is in a dynamically loadable shared library this will probably be necessary.
+.br
+For non-pthread based applications the DLM provides a file descriptor that the program can feed into poll/select. If activity is detected on that FD then a dispatch function should be called:
+.PP
+.SS int dlm_get_fd()
+Returns a file-descriptor for the DLM suitable for passing in to poll() or select().
+.PP
+.SS int dlm_dispatch(int fd)
+.br
+Reads from the DLM and calls any AST routines that may be needed. This routine runs in the context of the caller so no extra locking is needed to protect local resources.
+.PP
+
+
+.SH libdlm_lt
+There also exists a "light" version of the libdlm library called libdlm_lt. This is provided for those applications that do not want to use pthread functions. If you use this library it is important that your application is NOT compiled with -D_REENTRANT or linked with libpthread.
+
+.SH EXAMPLES
+
+Create a lockspace and start a thread to deliver its callbacks:
+.nf
+dlm_lshandle_t ls;
+
+ls = dlm_create_lockspace("myLS", 0660);
+dlm_ls_pthread_init(ls);
+
+ ...
+
+status = dlm_ls_lock(ls,
+                     ... );
+
+
+.fi
+.PP
+ Using poll(2) to wait for and dispatch ASTs
+.nf
+
+
+static int poll_for_ast(dlm_lshandle_t ls)
+{
+    struct pollfd pfd;
+
+    pfd.fd = dlm_ls_get_fd(ls);
+    pfd.events = POLLIN;
+    while (!ast_called)
+    {
+        if (poll(&pfd, 1, 0) < 0)
+        {
+            perror("poll");
+            return -1;
+        }
+        dlm_dispatch(dlm_ls_get_fd(ls));
+    }
+    ast_called = 0;
+    return 0;
+}
+.fi
+
+
+.SH SEE ALSO
+
+.BR libdlm (3),
+.BR dlm_lock (3),
+.BR dlm_unlock (3),
+.BR dlm_open_lockspace (3),
+.BR dlm_create_lockspace (3),
+.BR dlm_close_lockspace (3),
+.BR dlm_release_lockspace (3)


More information about the cluster-commits mailing list