[Cluster-devel] cluster/dlm/lib libdlm.c libdlm.h

teigland at sourceware.org teigland at sourceware.org
Fri May 18 16:35:17 UTC 2007


CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	teigland at sourceware.org	2007-05-18 16:35:16

Modified files:
	dlm/lib        : libdlm.c libdlm.h 

Log message:
	Make new features available based on recent dlm kernel patches.
	
	The kernel patches change the user/kernel device interface used by libdlm.
	(You'll need the new dlm_device.h kernel header installed on your system
	to build the lib.) libdlm is backward compatible with the old kernel
	interface, but some of the new features will return errors on old kernels.
	
	New API's provided by libdlm:
	- dlm_new_lockspace() is just like dlm_create_lockspace() but has a flags
	arg so flags can be passed when creating/joining a lockspace.
	- DLM_LSFL_NODIR and DLM_LSFL_TIMEWARN are new flags that can be used with
	dlm_new_lockspace().
	- dlm_ls_purge() is new and can be used to purge orphan locks.
	- all DLM_LKF flags can now be used with dlm_lock* routines (flags above
	16 bits couldn't be used before)
	- new DLM_LKF_TIMEOUT flag to enable lock timeouts
	- dlm_ls_lockx() is new and adds "xid" and "timeout" args
	
	All previous API's are still available, and programs compiled against
	previous versions of libdlm should still work.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/dlm/lib/libdlm.c.diff?cvsroot=cluster&r1=1.33&r2=1.34
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/dlm/lib/libdlm.h.diff?cvsroot=cluster&r1=1.13&r2=1.14

--- cluster/dlm/lib/libdlm.c	2007/01/31 10:53:47	1.33
+++ cluster/dlm/lib/libdlm.c	2007/05/18 16:35:15	1.34
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This library is free software; you can redistribute it and/or
 **  modify it under the terms of the GNU Lesser General Public
@@ -47,19 +47,68 @@
 #include "libdlm.h"
 #include <linux/dlm_device.h>
 
-#define MISC_PREFIX "/dev/misc/"
-#define PROC_MISC "/proc/misc"
-#define DLM_PREFIX "dlm_"
-#define DLM_MISC_PREFIX MISC_PREFIX DLM_PREFIX
-#define DLM_CONTROL_DEV "dlm-control"
-#define DEFAULT_LOCKSPACE "default"
 
-/* This is the name of the control device */
+#define PROC_MISC		"/proc/misc"
+#define MISC_PREFIX		"/dev/misc/"
+#define DLM_PREFIX		"dlm_"
+#define DLM_MISC_PREFIX		MISC_PREFIX DLM_PREFIX
+#define DLM_CONTROL_DEV		"dlm-control"
+#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;
+};
+
+/*
+ * This is the name of the control device
+ */
+
 #define DLM_CTL_DEVICE_NAME MISC_PREFIX DLM_CONTROL_DEV
 
-/* One of these per lockspace in use by the application */
-struct dlm_ls_info
-{
+/*
+ * One of these per lockspace in use by the application
+ */
+
+struct dlm_ls_info {
     int fd;
 #ifdef _REENTRANT
     pthread_t tid;
@@ -68,17 +117,25 @@
 #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...
-*/
+/*
+ * 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);
+	snprintf(devname, devlen, DLM_MISC_PREFIX "%s", lsname);
 }
 
 #ifdef HAVE_SELINUX
@@ -103,7 +160,6 @@
 }
 #endif
 
-
 static void dummy_ast_routine(void *arg)
 {
 }
@@ -262,40 +318,51 @@
 }
 #endif
 
-static void set_version(struct dlm_write_request *req)
+
+static void set_version_v5(struct dlm_write_request_v5 *req)
 {
-    req->version[0] = DLM_DEVICE_VERSION_MAJOR;
-    req->version[1] = DLM_DEVICE_VERSION_MINOR;
-    req->version[2] = DLM_DEVICE_VERSION_PATCH;
-    if (sizeof(long) == sizeof(long long))
-	req->is64bit = 1;
-    else
-	req->is64bit = 0;
+	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;
 }
 
-/* Open the default lockspace */
-static int open_default_lockspace()
+static void set_version_v6(struct dlm_write_request *req)
 {
-    if (!default_ls)
-    {
-	dlm_lshandle_t ls;
+	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;
+}
 
-	/* 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;
+static int open_default_lockspace(void)
+{
+	if (!default_ls) {
+		dlm_lshandle_t ls;
 
-	default_ls = (struct dlm_ls_info *)ls;
-    }
-    return 0;
+		/* 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 int create_control_device()
+static int create_control_device(void)
 {
     FILE *pmisc;
     int minor;
@@ -371,203 +438,367 @@
     return 0;
 }
 
-static int open_control_device()
+static void detect_kernel_version(void)
 {
-    int minor;
-    struct stat st;
-    int stat_ret;
+	struct dlm_device_version v;
+	int rv;
 
-    if (control_fd == -1)
-    {
-	stat_ret = stat(DLM_CTL_DEVICE_NAME, &st);
-
-	if (!stat_ret)
-	{
-	    minor = find_minor_from_proc("",DLM_CONTROL_DEV);
-	    if (S_ISCHR(st.st_mode) && st.st_rdev != makedev(MISC_MAJOR, minor))
-		unlink(DLM_CTL_DEVICE_NAME);
+	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];
 	}
 
-	control_fd = open(DLM_CTL_DEVICE_NAME, O_RDWR);
+	kernel_version_detected = 1;
+}
 
-	if (control_fd == -1)
-	{
-		if (create_control_device())
-			return -1;
+static int open_control_device(void)
+{
+	int minor;
+	struct stat st;
+	int stat_ret;
+
+	if (control_fd == -1) {
+		stat_ret = stat(DLM_CTL_DEVICE_NAME, &st);
+		if (!stat_ret) {
+			minor = find_minor_from_proc("", DLM_CONTROL_DEV);
+			if (S_ISCHR(st.st_mode) &&
+			    st.st_rdev != makedev(MISC_MAJOR, minor))
+				unlink(DLM_CTL_DEVICE_NAME);
+		}
 
 		control_fd = open(DLM_CTL_DEVICE_NAME, O_RDWR);
-		if (control_fd == -1)
+
+		if (control_fd == -1) {
+			if (create_control_device())
+				return -1;
+
+			control_fd = open(DLM_CTL_DEVICE_NAME, O_RDWR);
+			if (control_fd == -1)
+				return -1;
+		}
+	}
+	fcntl(control_fd, F_SETFD, 1);
+
+	if (!kernel_version_detected)
+		detect_kernel_version();
+	return 0;
+}
+
+/*
+ * 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;
 	}
-    }
-    fcntl(control_fd, F_SETFD, 1);
-    return 0;
+
+
+	/* 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,
+		       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)
 {
-    char resultbuf[sizeof(struct dlm_lock_result) + DLM_USER_LVB_LEN];
-    struct dlm_lock_result *result = (struct dlm_lock_result *)resultbuf;
-    char *fullresult = NULL;
-    int status;
-    void (*astaddr)(void *astarg);
+	if (kernel_version.version[0] == 5)
+		return do_dlm_dispatch_v5(fd);
+	else
+		return do_dlm_dispatch_v6(fd);
+}
 
-    /* Just read the header & LVB first */
-    status = read(fd, result, sizeof(resultbuf));
-    if (status <= 0)
-	return -1;
 
-    if (result->length != status)
-    {
-        int newstat;
+/*
+ * 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.
+ */
 
-	fullresult = malloc(result->length);
-	if (!fullresult)
-	    return -1;
+#ifdef _REENTRANT
 
-	newstat = read(fd, (struct dlm_lock_result *)fullresult, result->length);
+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 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 *)fullresult;
-    }
-    else
-    {
-	fullresult = resultbuf;
-    }
+	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;
 
-    /* Copy lksb to user's buffer - except the LVB ptr */
-    memcpy(result->user_lksb, &result->lksb, sizeof(struct dlm_lksb) - sizeof(char*));
+		status = write(lsinfo->fd, req, len);
+		if (status < 0)
+			return -1;
 
-    /* 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);
-#ifdef QUERY
-    if (result->qinfo_offset)
-    {
-	/* Just need the lockcount written out here */
-	struct dlm_queryinfo *qi = (struct dlm_queryinfo *)(fullresult+result->qinfo_offset);
-	result->user_qinfo->gqi_lockcount = qi->gqi_lockcount;
-    }
+		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);
 
-    if (result->qresinfo_offset)
-	memcpy(result->user_qinfo->gqi_resinfo, fullresult+result->qresinfo_offset,
-	       sizeof(struct dlm_resinfo));
-
-    if (result->qlockinfo_offset)
-	memcpy(result->user_qinfo->gqi_lockinfo, fullresult+result->qlockinfo_offset,
-	       sizeof(struct dlm_lockinfo) * result->user_qinfo->gqi_lockcount);
-#endif
+		req->i.lock.castaddr  = sync_ast_routine;
+		req->i.lock.castparam = &lwait;
 
-    /* Call AST */
-    if (result->user_astaddr)
-    {
-	astaddr = result->user_astaddr;
-	astaddr(result->user_astparam);
-    }
+		status = write(lsinfo->fd, req, len);
+		if (status < 0)
+			return -1;
 
-    if (fullresult != resultbuf)
-	free(fullresult);
-    return 0;
+		pthread_cond_wait(&lwait.cond, &lwait.mutex);
+		pthread_mutex_unlock(&lwait.mutex);
+	}
+
+	return status; /* lock status is in the lksb */
 }
 
-#ifdef _REENTRANT
-/* 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.
-*/
-static int sync_write(struct dlm_ls_info *lsinfo, struct dlm_write_request *req, int len)
+static int sync_write_v6(struct dlm_ls_info *lsinfo,
+			 struct dlm_write_request *req, int len)
 {
-    int	status;
-    struct lock_wait lwait;
+	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;
 
-    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;
+		return -1;
 
 	while (req->i.lock.lksb->sb_status == EINPROG) {
-	    do_dlm_dispatch(lsinfo->fd);
+		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;
+	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;
+		return -1;
 
-	pthread_cond_wait(&lwait.cond, &lwait.mutex);
-	pthread_mutex_unlock(&lwait.mutex);
-    }
-    return status;	/* lock status is in the lksb */
+	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;
 }
-#else
-static int sync_write(struct dlm_ls_info *lsinfo, struct dlm_write_request *req, int len)
+
+#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;
 
-        req->i.lock.castaddr  = dummy_ast_routine;
-        req->i.lock.castparam = NULL;
+	memset(req, 0, sizeof(*req));
+	set_version_v5(req);
 
-        status = write(lsinfo->fd, req, len);
-        if (status < 0)
-            return -1;
-
-        while (req->i.lock.lksb->sb_status == EINPROG) {
-            do_dlm_dispatch(lsinfo->fd);
-        }
-
-        errno = req->i.lock.lksb->sb_status;
-        if (errno && errno != EUNLOCK)
- 		return -1;
+	req->cmd = DLM_USER_LOCK;
+	req->i.lock.mode = mode;
+	req->i.lock.flags = flags;
+	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
-		return 0;
-}
-#endif
+		status = write(lsinfo->fd, req, len);
 
-/* Lock on 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;
+	if (status < 0)
+		return -1;
 
-    return dlm_ls_lock(default_ls, mode, lksb, flags, name, namelen, parent,
-		       astaddr, astarg, bastaddr, range);
-}
+	/*
+	 * the lock id is the return value from the write on the device
+	 */
 
+	if (status > 0)
+		lksb->sb_lkid = status;
+	return 0;
+}
 
-/*
- * This is the full-fat, aynchronous DLM call
- */
-int dlm_ls_lock(dlm_lshandle_t ls,
+static int ls_lock_v6(dlm_lshandle_t ls,
 		uint32_t mode,
 		struct dlm_lksb *lksb,
 		uint32_t flags,
@@ -577,73 +808,144 @@
 		void (*astaddr) (void *astarg),
 		void *astarg,
 		void (*bastaddr) (void *astarg),
-		void *range)
+		uint64_t *xid,
+		uint64_t *timeout)
 {
-    int len;
-    char param_buf[sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN];
-    struct dlm_write_request *req =  (struct dlm_write_request *)param_buf;
-    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-    int status;
-
-    set_version(req);
+	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;
 
-    req->cmd = DLM_USER_LOCK;
-    req->i.lock.mode = mode;
-    req->i.lock.flags = flags;
-    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;	/* completion and blocking ast arg are the same */
-    req->i.lock.bastparam = astarg;
+	memset(req, 0, sizeof(*req));
+	set_version_v6(req);
 
-    /* dlm2 does not support range locks */
-    if (range)
-    {
-	    errno = ENOSYS;
-	    return -1;
-    }
+	req->cmd = DLM_USER_LOCK;
+	req->i.lock.mode = mode;
+	req->i.lock.flags = flags;
+	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_CONVERT)
-    {
-	req->i.lock.namelen = 0;
-    }
-    else
-    {
-	if (namelen > DLM_RESNAME_MAXLEN)
-	{
-	    errno = EINVAL;
-	    return -1;
+	if (flags & LKF_VALBLK) {
+		memcpy(req->i.lock.lvb, lksb->sb_lvbptr, DLM_LVB_LEN);
 	}
-	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(lsinfo, req, len);
-    else
-	status = write(lsinfo->fd, req, 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)
-    {
-	return -1;
-    }
-    else
-    {
 	if (status > 0)
-	    lksb->sb_lkid = status;
+		lksb->sb_lkid = status;
 	return 0;
-    }
 }
 
-int dlm_lock_wait(uint32_t mode,
+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 (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,
@@ -653,19 +955,35 @@
 		     void (*bastaddr) (void *bastarg),
 		     void *range)
 {
-    if (open_default_lockspace())
-	    return -1;
+	return ls_lock(ls, mode, lksb, flags | LKF_WAIT, name, namelen, parent,
+		       NULL, bastarg, bastaddr, range);
+}
 
-    return dlm_ls_lock(default_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);
 }
 
 /*
- * This is the full-fat, synchronous DLM call
+ * Sync locking in the default lockspace
  */
-int dlm_ls_lock_wait(dlm_lshandle_t ls,
-		     uint32_t mode,
+int dlm_lock_wait(uint32_t mode,
 		     struct dlm_lksb *lksb,
 		     uint32_t flags,
 		     const void *name,
@@ -675,193 +993,137 @@
 		     void (*bastaddr) (void *bastarg),
 		     void *range)
 {
+	if (open_default_lockspace())
+		return -1;
 
-    return dlm_ls_lock(ls, mode, lksb, flags | LKF_WAIT,
-		       name, namelen, parent, NULL, bastarg,
-		       bastaddr, range);
+	return ls_lock(default_ls, mode, lksb, flags | LKF_WAIT, name, namelen,
+		       parent, NULL, bastarg, bastaddr, range);
 }
 
-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);
-}
-#ifdef QUERY
-int dlm_ls_query_wait(dlm_lshandle_t lockspace,
-		      struct dlm_lksb *lksb,
-		      int query,
-		      struct dlm_queryinfo *qinfo)
+/*
+ * 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 req;
-    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)lockspace;
-    int status;
+	struct dlm_write_request_v5 req;
 
-    if (lockspace == NULL)
-    {
-	errno = ENOTCONN;
-	return -1;
-    }
+	set_version_v5(&req);
+	req.cmd = DLM_USER_UNLOCK;
+	req.i.lock.lkid = lkid;
+	req.i.lock.flags = flags;
+	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 (!lksb)
-    {
-	errno = EINVAL;
-	return -1;
-    }
+	if (flags & LKF_WAIT)
+		return sync_write_v5(lsinfo, &req, sizeof(req));
+	else
+		return write(lsinfo->fd, &req, sizeof(req));
+}
 
-    if (!lksb->sb_lkid)
-    {
-	errno = EINVAL;
-	return -1;
-    }
+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(&req);
-    req.cmd = DLM_USER_QUERY;
-    req.i.query.query = query;
-    req.i.query.lksb  = lksb;
-    req.i.query.lkid  = lksb->sb_lkid;
-    req.i.query.qinfo = qinfo;
-    req.i.query.lockinfo_max = qinfo->gqi_locksize;
-    req.i.query.lockinfo = qinfo->gqi_lockinfo;
-    req.i.query.lockinfo_max = qinfo->gqi_locksize;
-    lksb->sb_status = EINPROG;
+	set_version_v6(&req);
+	req.cmd = DLM_USER_UNLOCK;
+	req.i.lock.lkid = lkid;
+	req.i.lock.flags = flags;
+	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;
 
-    status = sync_write(lsinfo, &req, sizeof(req));
-    return (status >= 0);
+	if (flags & LKF_WAIT)
+		return sync_write_v6(lsinfo, &req, sizeof(req));
+	else
+		return write(lsinfo->fd, &req, sizeof(req));
 }
-#endif
 
-int dlm_unlock_wait(uint32_t lkid,
-		    uint32_t flags, struct dlm_lksb *lksb)
+int dlm_ls_unlock(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags,
+		  struct dlm_lksb *lksb, void *astarg)
 {
-    return dlm_ls_unlock_wait(default_ls, lkid, flags | LKF_WAIT, lksb);
+	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;
 }
-#ifdef QUERY
-int dlm_query_wait(struct dlm_lksb *lksb,
-		   int query,
-		   struct dlm_queryinfo *qinfo)
+
+int dlm_ls_unlock_wait(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags,
+		       struct dlm_lksb *lksb)
 {
-    return dlm_ls_query_wait(default_ls, lksb, query, qinfo);
+	return dlm_ls_unlock(ls, lkid, flags | LKF_WAIT, lksb, NULL);
 }
-#endif
 
-/* Unlock on default lockspace*/
-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)
 {
-    return dlm_ls_unlock(default_ls, lkid, flags, lksb, astarg);
+	return dlm_ls_unlock_wait(default_ls, lkid, flags | LKF_WAIT, lksb);
 }
 
-
-int dlm_ls_unlock(dlm_lshandle_t ls, uint32_t lkid,
-		  uint32_t flags, struct dlm_lksb *lksb, void *astarg)
+int dlm_unlock(uint32_t lkid, uint32_t flags, struct dlm_lksb *lksb,
+	       void *astarg)
 {
-    struct dlm_write_request req;
-    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;
-    }
-
-    set_version(&req);
-    req.cmd = DLM_USER_UNLOCK;
-    req.i.lock.lkid = lkid;
-    req.i.lock.flags = flags;
-    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;
+	return dlm_ls_unlock(default_ls, lkid, flags, lksb, astarg);
+}
 
-    if (flags & LKF_WAIT)
-	    status = sync_write(lsinfo, &req, sizeof(req));
-    else
-	    status = write(lsinfo->fd, &req, sizeof(req));
 
-    if (status < 0)
-	return -1;
-    else
-	return 0;
-}
+/*
+ * Purge
+ * Clear away orphan locks
+ */
 
-#ifdef QUERY
-int dlm_ls_query(dlm_lshandle_t lockspace,
-		 struct dlm_lksb *lksb,
-		 int query,
-		 struct dlm_queryinfo *qinfo,
-		 void (*astaddr) (void *astarg),
-		 void *astarg)
+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 *)lockspace;
-    int status;
+	struct dlm_write_request req;
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+	int status;
 
-    if (lockspace == NULL)
-    {
-	errno = ENOTCONN;
-	return -1;
-    }
+	if (kernel_version.version[0] < 6) {
+		errno = ENOSYS;
+		return -1;
+	}
 
-    if (!lksb)
-    {
-	errno = EINVAL;
-	return -1;
-    }
+	if (ls == NULL) {
+		errno = ENOTCONN;
+		return -1;
+	}
 
-    if (!lksb->sb_lkid)
-    {
-	errno = EINVAL;
-	return -1;
-    }
+	set_version_v6(&req);
+	req.cmd = DLM_USER_PURGE;
+	req.i.purge.nodeid = nodeid;
+	req.i.purge.pid = pid;
 
-    set_version(&req);
-    req.cmd = DLM_USER_QUERY;
-    req.i.query.query = query;
-    req.i.query.lksb  = lksb;
-    req.i.query.lkid  = lksb->sb_lkid;
-    req.i.query.castparam = astarg;
-    req.i.query.castaddr = astaddr;
-    req.i.query.qinfo = qinfo;
-    req.i.query.resinfo = qinfo->gqi_resinfo;
-    req.i.query.lockinfo = qinfo->gqi_lockinfo;
-    req.i.query.lockinfo_max = qinfo->gqi_locksize;
-    lksb->sb_status = EINPROG;
+	status = write(lsinfo->fd, &req, sizeof(req));
 
-    status = write(lsinfo->fd, &req, sizeof(req));
-    if (status != sizeof(req))
-	return -1;
-    else
+	if (status < 0)
+		return -1;
 	return 0;
 }
-int dlm_query(struct dlm_lksb *lksb,
-	      int query,
-	      struct dlm_queryinfo *qinfo,
-	      void (*astaddr) (void *astarg),
-	      void *astarg)
-{
-    return dlm_ls_query(default_ls, lksb, query, qinfo, astaddr, astarg);
-}
-#else
-int dlm_query(struct dlm_lksb *lksb,
-              int query,
-              struct dlm_queryinfo *qinfo,
-              void (*astaddr) (void *astarg),
-              void *astarg)
-{
-    return 0;
-}
-
-#endif
 
 
 /* These two routines for for users that want to
@@ -961,194 +1223,259 @@
 
 /*
  * Lockspace manipulation functions
+ * Privileged users (checked by the kernel) can create/release lockspaces
  */
 
-/*
- * Privileged users (checked by the kernel)
- * can create/release lockspaces
- */
-dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode)
+static int create_lockspace_v5(const char *name, uint32_t flags)
 {
-    int status;
-    int minor;
-    int i;
-    struct stat st;
-    int stat_ret;
-    int create_dev = 1;
-    char dev_name[PATH_MAX];
-    struct dlm_ls_info *newls;
-    char reqbuf[sizeof(struct dlm_write_request) + strlen(name)];
-    struct dlm_write_request *req = (struct dlm_write_request *)reqbuf;
-
-    /* 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_name, sizeof(dev_name));
-
-    req->cmd = DLM_USER_CREATE_LOCKSPACE;
-    set_version(req);
-
-    /* Make the default lockspace free itself when all users have released it */
-    // TODO: DLM_USER_LSFLG_DEFAULTLS is yet to be added to the upstream DLM
-    if (strcmp(name, DEFAULT_LOCKSPACE) == 0)
-	    req->i.lspace.flags = DLM_USER_LSFLG_AUTOFREE /*| DLM_USER_LSFLG_DEFAULTLS*/;
-    else
-	    req->i.lspace.flags = 0;
-    strcpy(req->i.lspace.name, name);
-    minor = write(control_fd, req, sizeof(*req) + strlen(name));
+	char reqbuf[sizeof(struct dlm_write_request_v5) + strlen(name)];
+	struct dlm_write_request_v5 *req = (struct dlm_write_request_v5 *)reqbuf;
+	int minor;
 
-    if (minor < 0 && errno != EEXIST)
-    {
-	free(newls);
-	return NULL;
-    }
+	req->cmd = DLM_USER_CREATE_LOCKSPACE;
+	set_version_v5(req);
+	strcpy(req->i.lspace.name, name);
+	req->i.lspace.flags = flags;
 
-    /*
-     * If the lockspace already exists, we don't get the minor
-     * number returned, so we need to get it the hard way.
-     */
-    if (minor <= 0)
-	    minor = find_minor_from_proc(DLM_PREFIX,name);
-
-    /* Wait for udev to create the device */
-    for (i=1; i<10; i++) {
-	    if (stat(dev_name, &st) == 0)
-		    break;
-	    sleep(1);
-    }
+	minor = write(control_fd, req, sizeof(*req) + strlen(name));
 
-    /*
-     * If the device exists we check the minor number.
-     * If the device doesn't exist then we have to look in /proc/misc
-     * to find the minor number.
-     */
-    stat_ret = stat(dev_name, &st);
-
-    /* Check if the device exists and has the right modes */
-    if (!stat_ret &&
-	S_ISCHR(st.st_mode) && st.st_rdev == makedev(MISC_MAJOR, minor)) {
-	    create_dev = 0;
-    }
+	return minor;
+}
+
+static int create_lockspace_v6(const char *name, uint32_t flags)
+{
+	char reqbuf[sizeof(struct dlm_write_request) + strlen(name)];
+	struct dlm_write_request *req = (struct dlm_write_request *)reqbuf;
+	int minor;
 
-    if (create_dev) {
-	unlink(dev_name);
+	req->cmd = DLM_USER_CREATE_LOCKSPACE;
+	set_version_v6(req);
+	strcpy(req->i.lspace.name, name);
+	req->i.lspace.flags = flags;
 
-	/* Now try to create the device, EEXIST is OK cos it must have
-	   been devfs or udev that created it */
-	status = mknod(dev_name, S_IFCHR | mode, makedev(MISC_MAJOR, minor));
-	if (status == -1 && errno != EEXIST)
-	{
-	    /* Try to remove it */
-	    req->cmd = DLM_USER_REMOVE_LOCKSPACE;
-	    req->i.lspace.minor = minor;
-	    write(control_fd, req, sizeof(*req));
-	    free(newls);
-	    return NULL;
+	minor = write(control_fd, req, sizeof(*req) + strlen(name));
+
+	return minor;
+}
+
+static dlm_lshandle_t create_lockspace(const char *name, mode_t mode,
+				       uint32_t flags)
+{
+	int status;
+	int minor;
+	int i;
+	struct stat st;
+	int stat_ret;
+	int create_dev = 1;
+	char dev_name[PATH_MAX];
+	struct dlm_ls_info *newls;
+
+	/* 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_name, sizeof(dev_name));
+
+	if (kernel_version.version[0] == 5)
+		minor = create_lockspace_v5(name, flags);
+	else
+		minor = create_lockspace_v6(name, flags);
+
+	if (minor < 0 && errno != EEXIST) {
+		free(newls);
+		return NULL;
+	}
+
+	/*
+	 * If the lockspace already exists, we don't get the minor
+	 * number returned, so we need to get it the hard way.
+	 */
+
+	if (minor <= 0)
+		minor = find_minor_from_proc(DLM_PREFIX,name);
+
+	/* Wait for udev to create the device */
+	for (i=1; i<10; i++) {
+		if (stat(dev_name, &st) == 0)
+			break;
+		sleep(1);
+	}
+
+	/*
+	 * If the device exists we check the minor number.
+	 * If the device doesn't exist then we have to look in /proc/misc
+	 * to find the minor number.
+	 */
+	stat_ret = stat(dev_name, &st);
+
+	/* Check if the device exists and has the right modes */
+	if (!stat_ret &&
+	    S_ISCHR(st.st_mode) && st.st_rdev == makedev(MISC_MAJOR, minor)) {
+		create_dev = 0;
 	}
+
+	if (create_dev) {
+		unlink(dev_name);
+
+		/* Now try to create the device, EEXIST is OK cos it must have
+	   	  been devfs or udev that created it */
+		status = mknod(dev_name, S_IFCHR | mode,
+			       makedev(MISC_MAJOR, minor));
+		if (status == -1 && errno != EEXIST) {
+			release_lockspace(minor, 0);
+			free(newls);
+			return NULL;
+		}
 #ifdef HAVE_SELINUX
-	set_selinux_context(dev_name);
+		set_selinux_context(dev_name);
 #endif
-    }
+	}
 
-    /* Open it and return the struct as a handle */
-    newls->fd = open(dev_name, O_RDWR);
-    if (newls->fd == -1)
-    {
-	int saved_errno = errno;
-	free(newls);
-	errno = saved_errno;
-	return NULL;
-    }
-    newls->tid = 0;
-    fcntl(newls->fd, F_SETFD, 1);
+	/* Open it and return the struct as a handle */
+	newls->fd = open(dev_name, O_RDWR);
+	if (newls->fd == -1) {
+		int saved_errno = errno;
+		free(newls);
+		errno = saved_errno;
+		return NULL;
+	}
+	newls->tid = 0;
+	fcntl(newls->fd, F_SETFD, 1);
+	return (dlm_lshandle_t)newls;
+}
 
-    return (dlm_lshandle_t)newls;
+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);
+}
 
-int dlm_release_lockspace(const char *name, dlm_lshandle_t ls, int force)
+static int release_lockspace_v5(uint32_t minor, uint32_t flags)
 {
-    int status;
-    char dev_name[PATH_MAX];
-    struct stat st;
-    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
-    struct dlm_write_request req;
+	struct dlm_write_request_v5 req;
 
-    /* We need the minor number */
-    if (fstat(lsinfo->fd, &st))
-	return -1;
+	set_version_v5(&req);
+	req.cmd = DLM_USER_REMOVE_LOCKSPACE;
+	req.i.lspace.minor = minor;
+	req.i.lspace.flags = flags;
 
-    /* Close the lockspace first if it's in use */
-    ls_pthread_cleanup(lsinfo);
+	return write(control_fd, &req, sizeof(req));
+}
 
-    if (open_control_device())
-	return -1;
+static int release_lockspace_v6(uint32_t minor, uint32_t flags)
+{
+	struct dlm_write_request req;
 
-    if (force)
-        req.i.lspace.flags = DLM_USER_LSFLG_FORCEFREE;
-    else
-	req.i.lspace.flags = 0;
+	set_version_v6(&req);
+	req.cmd = DLM_USER_REMOVE_LOCKSPACE;
+	req.i.lspace.minor = minor;
+	req.i.lspace.flags = flags;
 
-    set_version(&req);
-    req.cmd = DLM_USER_REMOVE_LOCKSPACE;
-    req.i.lspace.minor = minor(st.st_rdev);
+	return write(control_fd, &req, sizeof(req));
+}
 
-    status = write(control_fd, &req, sizeof(req));
-    if (status < 0)
-	return status;
+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)
+{
+	int status;
+	char dev_name[PATH_MAX];
+	struct stat st;
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+	uint32_t flags = 0;
 
-    /* Remove the device */
-    ls_dev_name(name, dev_name, sizeof(dev_name));
+	/* We need the minor number */
+	if (fstat(lsinfo->fd, &st))
+		return -1;
 
-    status = unlink(dev_name);
+	/* Close the lockspace first if it's in use */
+	ls_pthread_cleanup(lsinfo);
 
-    /* ENOENT is OK here if devfs has cleaned up */
-    if (status == 0 ||
-	(status == -1 && errno == ENOENT))
-	return 0;
-    else
+	if (open_control_device())
+		return -1;
+
+	if (force)
+		flags = DLM_USER_LSFLG_FORCEFREE;
+
+	status = release_lockspace(minor(st.st_rdev), flags);
+
+	/* Remove the device */
+	ls_dev_name(name, dev_name, sizeof(dev_name));
+
+	status = unlink(dev_name);
+
+	/* ENOENT is OK here if devfs has cleaned up */
+	if (status == 0 || (status == -1 && errno == ENOENT))
+		return 0;
 	return -1;
 }
 
 /*
  * 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;
-
-    newls = malloc(sizeof(struct dlm_ls_info));
-    if (!newls)
-	return NULL;
-
-    newls->tid = 0;
-    ls_dev_name(name, dev_name, sizeof(dev_name));
+	char dev_name[PATH_MAX];
+	struct dlm_ls_info *newls;
+	int saved_errno;
+
+	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);
 
-    newls->fd = open(dev_name, O_RDWR);
-    saved_errno = errno;
+	return (dlm_lshandle_t)newls;
+}
 
-    if (newls->fd == -1)
-    {
-	free(newls);
-	errno = saved_errno;
-	return NULL;
-    }
-    fcntl(newls->fd, F_SETFD, 1);
+int dlm_close_lockspace(dlm_lshandle_t ls)
+{
+	struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
 
-    return (dlm_lshandle_t)newls;
+	ls_pthread_cleanup(lsinfo);
+	return 0;
 }
 
-int dlm_close_lockspace(dlm_lshandle_t ls)
+int dlm_kernel_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
 {
-    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
+	if (open_control_device())
+		return -1;
+	*major = kernel_version.version[0];
+	*minor = kernel_version.version[1];
+	*patch = kernel_version.version[2];
+	return 0;
+}
 
-    ls_pthread_cleanup(lsinfo);
-    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;
 }
+
--- cluster/dlm/lib/libdlm.h	2006/09/07 19:17:03	1.13
+++ cluster/dlm/lib/libdlm.h	2007/05/18 16:35:16	1.14
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This library is free software; you can redistribute it and/or
 **  modify it under the terms of the GNU Lesser General Public
@@ -24,16 +24,17 @@
 #ifndef __LIBDLM_H
 #define __LIBDLM_H
 
-typedef void * dlm_lshandle_t;
-
-/* 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.
+/*
+ * 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)
+
+#define DLM_LVB_LEN             32
+
 #ifndef BUILDING_LIBDLM
 
-#define DLM_RESNAME_MAXLEN     (64)
+#define DLM_RESNAME_MAXLEN      64
 
 struct dlm_lksb {
 	int sb_status;
@@ -42,258 +43,242 @@
 	char *sb_lvbptr;
 };
 
-
 /* lksb flags */
-#define DLM_SBF_VALNOTVALID    (0x02)
+#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
 
 #endif
-#ifdef QUERY
-
-/*
- * These defines are the bits that make up the
- * query code.
- */
-
-/* Bits 0, 1, 2, the lock mode or DLM_LOCK_THIS, see DLM_LOCK_NL etc in
- * dlm.h Ignored for DLM_QUERY_LOCKS_ALL */
-#define DLM_LOCK_THIS            0x0007
-#define DLM_QUERY_MODE_MASK      0x0007
-
-/* Bits 3, 4, 5  bitmap of queue(s) to query */
-#define DLM_QUERY_QUEUE_WAIT     0x0008
-#define DLM_QUERY_QUEUE_CONVERT  0x0010
-#define DLM_QUERY_QUEUE_GRANT    0x0020
-#define DLM_QUERY_QUEUE_GRANTED  0x0030	/* Shorthand */
-#define DLM_QUERY_QUEUE_ALL      0x0038	/* Shorthand */
-
-/* Bit 6, Return only the information that can be established without a network
- * round-trip. The caller must be aware of the implications of this. Useful for
- * just getting the master node id or resource name. */
-#define DLM_QUERY_LOCAL          0x0040
-
-/* Bits 8 up, query type */
-#define DLM_QUERY_LOCKS_HIGHER   0x0100
-#define DLM_QUERY_LOCKS_LOWER    0x0200
-#define DLM_QUERY_LOCKS_EQUAL    0x0300
-#define DLM_QUERY_LOCKS_BLOCKING 0x0400
-#define DLM_QUERY_LOCKS_NOTBLOCK 0x0500
-#define DLM_QUERY_LOCKS_ALL      0x0600
-#define DLM_QUERY_LOCKS_ORPHAN   0x0700
-#define DLM_QUERY_MASK           0x0F00
-
-/* GRMODE is the default for mode comparisons,
-   RQMODE might also be handy */
-#define DLM_QUERY_GRMODE         0x0000
-#define DLM_QUERY_RQMODE         0x1000
-
-/* Structures passed into and out of the query */
-
-struct dlm_lockinfo {
-	int lki_lkid;		/* Lock ID on originating node */
-        int lki_mstlkid;        /* Lock ID on master node */
-	int lki_parent;
-	int lki_node;		/* Originating node (not master) */
-	int lki_ownpid;		/* Owner pid on originating node */
-	uint8_t lki_state;	/* Queue the lock is on */
-	uint8_t lki_grmode;	/* Granted mode */
-	uint8_t lki_rqmode;	/* Requested mode */
-};
 
-struct dlm_resinfo {
-	int rsi_length;
-	int rsi_grantcount;	/* No. of nodes on grant queue */
-	int rsi_convcount;	/* No. of nodes on convert queue */
-	int rsi_waitcount;	/* No. of nodes on wait queue */
-	int rsi_masternode;	/* Master for this resource */
-	char rsi_name[DLM_RESNAME_MAXLEN];	/* Resource name */
-	char rsi_valblk[DLM_LVB_LEN];	/* Master's LVB contents, if applicable
-					 */
-};
-
-struct dlm_queryinfo {
-	struct dlm_resinfo *gqi_resinfo;
-	struct dlm_lockinfo *gqi_lockinfo;	/* This points to an array
-						 * of structs */
-	int gqi_locksize;	/* input */
-	int gqi_lockcount;	/* output */
-};
-#else
 
+#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
-/* These synchronous functions require pthreads */
 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,
-		    void (*astaddr) (void *astarg),
-		    void *astarg,
-		    void (*bastaddr) (void *astarg),
-		    void *range);
+		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);
-
+		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,
-			 void *bastarg,
-			 void (*bastaddr) (void *bastarg),
-			 void *range);
-
+		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);
+		uint32_t flags,
+		struct dlm_lksb *lksb);
 
-#ifdef QUERY
-extern int dlm_query(struct dlm_lksb *lksb,
-		     int query,
-		     struct dlm_queryinfo *qinfo,
-		     void (*astaddr) (void *astarg),
-		     void *astarg);
 
+/* 
+ * 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_query_wait(struct dlm_lksb *lksb,
-			  int query,
-			  struct dlm_queryinfo *qinfo);
+extern int dlm_get_fd(void);
+extern int dlm_dispatch(int fd);
 
-#endif
 
-/* These two are for users that want to do their
- * own FD handling
+/*
+ * 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.
  */
-extern int dlm_get_fd(void);
-extern int dlm_dispatch(int fd);
 
-/* Lockspace manipulation calls
-   dlm_create_lockspace() also opens the lockspace and returns
-   a handle to it. privileges are required to create/release
-   lockspaces.
-   dlm_open_lockspace() simply returns a handle an already
-   created lockspace and may be called by ordinary users.
-
-   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 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_purge()
+ */
 
-/* Lockspace-specific locking calls */
 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,
-		       void (*astaddr) (void *astarg),
-		       void *astarg,
-		       void (*bastaddr) (void *astarg),
-		       void *range);
+		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,
-			       void *bastarg,
-			       void (*bastaddr) (void *bastarg),
-			       void *range);
+		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);
+		uint32_t lkid,
+		uint32_t flags,
+		struct dlm_lksb *lksb);
+
+extern int dlm_ls_purge(dlm_lshandle_t lockspace,
+		int nodeid,
+		int pid);
 
-extern int dlm_ls_unlock(dlm_lshandle_t lockspace,
-			 uint32_t lkid,
-			 uint32_t flags, struct dlm_lksb *lksb, void *astarg);
-
-#ifdef QUERY
-extern int dlm_ls_query_wait(dlm_lshandle_t lockspace,
-			     struct dlm_lksb *lksb,
-			     int query,
-			     struct dlm_queryinfo *qinfo);
-
-
-extern int dlm_ls_query(dlm_lshandle_t lockspace,
-			struct dlm_lksb *lksb,
-			int query,
-			struct dlm_queryinfo *qinfo,
-			void (*astaddr) (void *astarg),
-			void *astarg);
-#endif
 
-/* This is for threaded applications. call this
- * before any locking operations and the ASTs will
- * be delivered in their own thread.
+/*
+ * For threaded applications
  *
- * Call the cleanup routine at application exit (optional)
- * or, if the locking functions are in a shared library that
- * is to be unloaded.
+ * 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.
+ * dlm_close/release_lockspace() will tidy the threads for a non-default
+ * lockspace
  */
+
 #ifdef _REENTRANT
 extern int dlm_pthread_init();
 extern int dlm_ls_pthread_init(dlm_lshandle_t lockspace);
 extern int dlm_pthread_cleanup();
 #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 */
 
+/*
+ * Lock modes
+ */
 
-/* Locking flags - these match the ones
- * in dlm.h
+#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)
 
-/* Userspace flag only, for synchronous API calls */
-#define LKF_WAIT           (0x80000000)
+#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 */
+
+#define ECANCEL             0x10001
+#define EUNLOCK             0x10002
+#define	EINPROG		    0x10003     /* lock operation is in progress */
 
 #endif
+




More information about the Cluster-devel mailing list