1    	/*
2    	 * Copyright 2004-2011 Red Hat, Inc.
3    	 *
4    	 * This library is free software; you can redistribute it and/or
5    	 * modify it under the terms of the GNU Lesser General Public
6    	 * License as published by the Free Software Foundation; either
7    	 * version 2.1 of the License, or (at your option) any later version.
8    	 */
9    	
10   	#ifdef _REENTRANT
11   	#include <pthread.h>
12   	#endif
13   	#include <sys/types.h>
14   	#include <sys/ioctl.h>
15   	#include <sys/param.h>
16   	#include <sys/stat.h>
17   	#include <stdint.h>
18   	#include <stdlib.h>
19   	#include <inttypes.h>
20   	#include <unistd.h>
21   	#include <fcntl.h>
22   	#include <errno.h>
23   	#include <string.h>
24   	#include <stdio.h>
25   	#include <dirent.h>
26   	#include <linux/major.h>
27   	#include <sys/sysmacros.h>
28   	#ifdef HAVE_SELINUX
29   	#include <selinux/selinux.h>
30   	#endif
31   	#include <linux/types.h>
32   	#include <linux/dlm.h>
33   	#define BUILDING_LIBDLM
34   	#include "libdlm.h"
35   	#include <linux/dlm_device.h>
36   	
37   	#define MISC_PREFIX		"/dev/misc/"
38   	#define DLM_PREFIX		"dlm_"
39   	#define DLM_MISC_PREFIX		MISC_PREFIX DLM_PREFIX
40   	#define DLM_CONTROL_NAME	"dlm-control"
41   	#define DLM_CONTROL_PATH	MISC_PREFIX DLM_CONTROL_NAME
42   	#define DEFAULT_LOCKSPACE	"default"
43   	
44   	/*
45   	 * V5 of the dlm_device.h kernel/user interface structs
46   	 */
47   	
48   	struct dlm_lock_params_v5 {
49   		__u8 mode;
50   		__u8 namelen;
51   		__u16 flags;
52   		__u32 lkid;
53   		__u32 parent;
54   		void *castparam;
55   		void *castaddr;
56   		void *bastparam;
57   		void *bastaddr;
58   		struct dlm_lksb *lksb;
59   		char lvb[DLM_USER_LVB_LEN];
60   		char name[0];
61   	};
62   	
63   	struct dlm_write_request_v5 {
64   		__u32 version[3];
65   		__u8 cmd;
66   		__u8 is64bit;
67   		__u8 unused[2];
68   	
69   		union  {
70   			struct dlm_lock_params_v5 lock;
71   			struct dlm_lspace_params lspace;
72   		} i;
73   	};
74   	
75   	struct dlm_lock_result_v5 {
76   		__u32 length;
77   		void *user_astaddr;
78   		void *user_astparam;
79   		struct dlm_lksb *user_lksb;
80   		struct dlm_lksb lksb;
81   		__u8 bast_mode;
82   		__u8 unused[3];
83   		/* Offsets may be zero if no data is present */
84   		__u32 lvb_offset;
85   	};
86   	
87   	
88   	/*
89   	 * One of these per lockspace in use by the application
90   	 */
91   	
92   	struct dlm_ls_info {
93   	    int fd;
94   	#ifdef _REENTRANT
95   	    pthread_t tid;
96   	#else
97   	    int tid;
98   	#endif
99   	};
100  	
101  	/*
102  	 * The default lockspace.
103  	 * I've resisted putting locking around this as the user should be
104  	 * "sensible" and only do lockspace operations either in the
105  	 * main thread or ... carefully...
106  	 */
107  	
108  	static struct dlm_ls_info *default_ls = NULL;
109  	static int control_fd = -1;
110  	static struct dlm_device_version kernel_version;
111  	static int kernel_version_detected = 0;
112  	
113  	
114  	static int release_lockspace(uint32_t minor, uint32_t flags);
115  	
116  	
117  	static void ls_dev_name(const char *lsname, char *devname, int devlen)
118  	{
119  		snprintf(devname, devlen, DLM_MISC_PREFIX "%s", lsname);
120  	}
121  	
122  	static void dummy_ast_routine(void *arg)
123  	{
124  	}
125  	
126  	#ifdef _REENTRANT
127  	/* Used for the synchronous and "simplified, synchronous" API routines */
128  	struct lock_wait
129  	{
130  	    pthread_cond_t  cond;
131  	    pthread_mutex_t mutex;
132  	    struct dlm_lksb lksb;
133  	};
134  	
135  	static void sync_ast_routine(void *arg)
136  	{
137  	    struct lock_wait *lwait = arg;
138  	
139  	    pthread_mutex_lock(&lwait->mutex);
140  	    pthread_cond_signal(&lwait->cond);
141  	    pthread_mutex_unlock(&lwait->mutex);
142  	}
143  	
144  	/* lock_resource & unlock_resource
145  	 * are the simplified, synchronous API.
146  	 * Aways uses the default lockspace.
147  	 */
148  	int lock_resource(const char *resource, int mode, int flags, int *lockid)
149  	{
150  	    int status;
151  	    struct lock_wait lwait;
152  	
153  	    if (default_ls == NULL)
154  	    {
155  		if (dlm_pthread_init())
156  		{
157  		    return -1;
158  		}
159  	    }
160  	
161  	    if (!lockid)
162  	    {
163  		errno = EINVAL;
164  		return -1;
165  	    }
166  	
167  	    /* Conversions need the lockid in the LKSB */
168  	    if (flags & LKF_CONVERT)
169  		lwait.lksb.sb_lkid = *lockid;
170  	
171  	    pthread_cond_init(&lwait.cond, NULL);
172  	    pthread_mutex_init(&lwait.mutex, NULL);
173  	    pthread_mutex_lock(&lwait.mutex);
174  	
175  	    status = dlm_lock(mode,
176  			      &lwait.lksb,
177  			      flags,
178  			      resource,
179  			      strlen(resource),
180  			      0,
181  			      sync_ast_routine,
182  			      &lwait,
183  			      NULL,
184  			      NULL);
185  	    if (status)
186  		return status;
187  	
188  	    /* Wait for it to complete */
189  	    pthread_cond_wait(&lwait.cond, &lwait.mutex);
190  	    pthread_mutex_unlock(&lwait.mutex);
191  	
192  	    *lockid = lwait.lksb.sb_lkid;
193  	
194  	    errno = lwait.lksb.sb_status;
195  	    if (lwait.lksb.sb_status)
196  		return -1;
197  	    else
198  		return 0;
199  	}
200  	
201  	
202  	int unlock_resource(int lockid)
203  	{
204  	    int status;
205  	    struct lock_wait lwait;
206  	
207  	    if (default_ls == NULL)
208  	    {
209  		errno = -ENOTCONN;
210  		return -1;
211  	    }
212  	
213  	    pthread_cond_init(&lwait.cond, NULL);
214  	    pthread_mutex_init(&lwait.mutex, NULL);
215  	    pthread_mutex_lock(&lwait.mutex);
216  	
217  	    status = dlm_unlock(lockid, 0, &lwait.lksb, &lwait);
218  	
219  	    if (status)
220  		return status;
221  	
222  	    /* Wait for it to complete */
223  	    pthread_cond_wait(&lwait.cond, &lwait.mutex);
224  	    pthread_mutex_unlock(&lwait.mutex);
225  	
226  	    errno = lwait.lksb.sb_status;
227  	    if (lwait.lksb.sb_status != DLM_EUNLOCK)
228  		return -1;
229  	    else
230  		return 0;
231  	}
232  	
233  	/* Tidy up threads after a lockspace is closed */
234  	static int ls_pthread_cleanup(struct dlm_ls_info *lsinfo)
235  	{
236  	    int status = 0;
237  	    int fd;
238  	
239  	    /* Must close the fd after the thread has finished */
240  	    fd = lsinfo->fd;
241  	    if (lsinfo->tid)
242  	    {
243  		status = pthread_cancel(lsinfo->tid);
244  		if (!status)
245  		    pthread_join(lsinfo->tid, NULL);
246  	    }
247  	    if (!status)
248  	    {
249  		free(lsinfo);
250  		close(fd);
251  	    }
252  	
253  	    return status;
254  	}
255  	
256  	/* Cleanup default lockspace */
257  	int dlm_pthread_cleanup(void)
258  	{
259  	    struct dlm_ls_info *lsinfo = default_ls;
260  	
261  	    /* Protect users from their own stupidity */
262  	    if (!lsinfo)
263  		return 0;
264  	
265  	    default_ls = NULL;
266  	
267  	    return ls_pthread_cleanup(lsinfo);
268  	}
269  	#else
270  	
271  	/* Non-pthread version of cleanup */
272  	static int ls_pthread_cleanup(struct dlm_ls_info *lsinfo)
273  	{
274  	    close(lsinfo->fd);
275  	    free(lsinfo);
276  	    return 0;
277  	}
278  	#endif
279  	
280  	
281  	static void set_version_v5(struct dlm_write_request_v5 *req)
282  	{
283  		req->version[0] = kernel_version.version[0];
284  		req->version[1] = kernel_version.version[1];
285  		req->version[2] = kernel_version.version[2];
286  		if (sizeof(long) == sizeof(long long))
287  			req->is64bit = 1;
288  		else
289  			req->is64bit = 0;
290  	}
291  	
292  	static void set_version_v6(struct dlm_write_request *req)
293  	{
294  		req->version[0] = kernel_version.version[0];
295  		req->version[1] = kernel_version.version[1];
296  		req->version[2] = kernel_version.version[2];
297  		if (sizeof(long) == sizeof(long long))
298  			req->is64bit = 1;
299  		else
300  			req->is64bit = 0;
301  	}
302  	
303  	static int open_default_lockspace(void)
304  	{
305  		if (!default_ls) {
306  			dlm_lshandle_t ls;
307  	
308  			/* This isn't the race it looks, create_lockspace will
309  			 * do the right thing if the lockspace has already been
310  			 * created.
311  			 */
312  	
313  			ls = dlm_open_lockspace(DEFAULT_LOCKSPACE);
314  			if (!ls)
315  				ls = dlm_create_lockspace(DEFAULT_LOCKSPACE, 0600);
316  			if (!ls)
317  				return -1;
318  	
319  			default_ls = (struct dlm_ls_info *)ls;
320  		}
321  		return 0;
322  	}
323  	
324  	static void detect_kernel_version(void)
325  	{
326  		struct dlm_device_version v;
327  		int rv;
328  	
329  		rv = read(control_fd, &v, sizeof(struct dlm_device_version));
330  		if (rv < 0) {
331  			kernel_version.version[0] = 5;
332  			kernel_version.version[1] = 0;
333  			kernel_version.version[2] = 0;
334  		} else {
335  			kernel_version.version[0] = v.version[0];
336  			kernel_version.version[1] = v.version[1];
337  			kernel_version.version[2] = v.version[2];
338  		}
339  	
340  		kernel_version_detected = 1;
341  	}
342  	
343  	static int find_control_minor(int *minor)
344  	{
345  		FILE *f;
346  		char name[256];
347  		int found = 0, m = 0;
348  	
349  		f = fopen("/proc/misc", "r");
350  		if (!f)
351  			return -1;
352  	
353  		while (!feof(f)) {
354  			if (fscanf(f, "%d %s", &m, name) != 2)
355  				continue;
356  			if (strcmp(name, DLM_CONTROL_NAME))
357  				continue;
358  			found = 1;
359  			break;
360  		}
361  		fclose(f);
362  	
363  		if (found) {
364  			*minor = m;
365  			return 0;
366  		}
367  		return -1;
368  	}
369  	
370  	static int open_control_device(void)
371  	{
372  		struct stat st;
373  		int i, rv, minor, found = 0;
374  	
(1) Event cond_false: Condition "control_fd > -1", taking false branch.
375  		if (control_fd > -1)
(2) Event if_end: End of if statement.
376  			goto out;
377  	
378  		rv = find_control_minor(&minor);
(3) Event cond_false: Condition "rv < 0", taking false branch.
379  		if (rv < 0)
(4) Event if_end: End of if statement.
380  			return -1;
381  	
382  		/* wait for udev to create the device */
383  	
(5) Event cond_true: Condition "i < 10", taking true branch.
384  		for (i = 0; i < 10; i++) {
(6) Event fs_check_call: Calling function "stat" to perform check on ""/dev/misc/dlm-control"".
(7) Event cond_true: Condition "stat("/dev/misc/dlm-control", &st) == 0", taking true branch.
(8) Event cond_true: Condition "gnu_dev_minor(st.st_rdev) == minor", taking true branch.
Also see events: [toctou]
385  			if (stat(DLM_CONTROL_PATH, &st) == 0 &&
386  			    minor(st.st_rdev) == minor) {
387  				found = 1;
(9) Event break: Breaking from loop.
388  				break;
389  			}
390  			sleep(1);
391  			continue;
(10) Event loop_end: Reached end of loop.
392  		}
393  	
(11) Event cond_false: Condition "!found", taking false branch.
394  		if (!found)
(12) Event if_end: End of if statement.
395  			return -1;
396  	
(13) Event toctou: Calling function "open" that uses ""/dev/misc/dlm-control"" after a check function. This can cause a time-of-check, time-of-use race condition.
Also see events: [fs_check_call]
397  		control_fd = open(DLM_CONTROL_PATH, O_RDWR);
398  		if (control_fd == -1)
399  			return -1;
400  	
401  	 out:
402  		fcntl(control_fd, F_SETFD, 1);
403  	
404  		if (!kernel_version_detected)
405  			detect_kernel_version();
406  		return 0;
407  	}
408  	
409  	/* the max number of characters in a sysfs device name, not including \0 */
410  	#define MAX_SYSFS_NAME 19
411  	
412  	static int find_udev_device(const char *lockspace, int minor, char *udev_path)
413  	{
414  		char bname[PATH_MAX];
415  		char tmp_path[PATH_MAX];
416  		DIR *d;
417  		struct dirent *de;
418  		struct stat st;
419  		size_t basename_len;
420  		int i;
421  	
422  		ls_dev_name(lockspace, udev_path, PATH_MAX);
423  		snprintf(bname, PATH_MAX, DLM_PREFIX "%s", lockspace);
424  		basename_len = strlen(bname);
425  	
426  		for (i = 0; i < 10; i++) {
427  	
428  			/* look for a device with the full name */
429  	
430  			if (stat(udev_path, &st) == 0 && minor(st.st_rdev) == minor)
431  				return 0;
432  	
433  			if (basename_len < MAX_SYSFS_NAME) {
434  				sleep(1);
435  				continue;
436  			}
437  	
438  			/* look for a device with a truncated name */
439  	
440  			d = opendir(MISC_PREFIX);
441  			while ((de = readdir(d))) {
442  				if (de->d_name[0] == '.')
443  					continue;
444  				if (strlen(de->d_name) < MAX_SYSFS_NAME)
445  					continue;
446  				if (strncmp(de->d_name, bname, MAX_SYSFS_NAME))
447  					continue;
448  				snprintf(tmp_path, PATH_MAX, MISC_PREFIX "%s",
449  					 de->d_name);
450  				if (stat(tmp_path, &st))
451  					continue;
452  				if (minor(st.st_rdev) != minor)
453  					continue;
454  	
455  				/* truncated name */
456  				strncpy(udev_path, tmp_path, PATH_MAX);
457  				closedir(d);
458  				return 0;
459  			}
460  			closedir(d);
461  			sleep(1);
462  		}
463  	
464  		return -1;
465  	}
466  	
467  	/*
468  	 * do_dlm_dispatch()
469  	 * Read an ast from the kernel.
470  	 */
471  	
472  	static int do_dlm_dispatch_v5(int fd)
473  	{
474  		char resultbuf[sizeof(struct dlm_lock_result_v5) + DLM_USER_LVB_LEN];
475  		struct dlm_lock_result_v5 *result = (struct dlm_lock_result_v5 *)resultbuf;
476  		char *fullresult = NULL;
477  		int status;
478  		void (*astaddr)(void *astarg);
479  	
480  		status = read(fd, result, sizeof(resultbuf));
481  		if (status <= 0)
482  			return -1;
483  	
484  		/* This shouldn't happen any more, can probably be removed */
485  	
486  		if (result->length != status) {
487  			int newstat;
488  	
489  			fullresult = malloc(result->length);
490  			if (!fullresult)
491  				return -1;
492  	
493  			newstat = read(fd, (struct dlm_lock_result_v5 *)fullresult,
494  				       result->length);
495  	
496  			/* If it read OK then use the new data. otherwise we can
497  			   still deliver the AST, it just might not have all the
498  			   info in it...hmmm */
499  	
500  			if (newstat == result->length)
501  				result = (struct dlm_lock_result_v5 *)fullresult;
502  		} else {
503  			fullresult = resultbuf;
504  		}
505  	
506  	
507  		/* Copy lksb to user's buffer - except the LVB ptr */
508  		memcpy(result->user_lksb, &result->lksb,
509  		       sizeof(struct dlm_lksb) - sizeof(char*));
510  	
511  		/* Flip the status. Kernel space likes negative return codes,
512  		   userspace positive ones */
513  		result->user_lksb->sb_status = -result->user_lksb->sb_status;
514  	
515  		/* Copy optional items */
516  		if (result->lvb_offset)
517  			memcpy(result->user_lksb->sb_lvbptr,
518  			       fullresult + result->lvb_offset, DLM_LVB_LEN);
519  	
520  		/* Call AST */
521  		if (result->user_astaddr) {
522  			astaddr = result->user_astaddr;
523  			astaddr(result->user_astparam);
524  		}
525  	
526  		if (fullresult != resultbuf)
527  			free(fullresult);
528  	
529  		return 0;
530  	}
531  	
532  	static int do_dlm_dispatch_v6(int fd)
533  	{
534  		char resultbuf[sizeof(struct dlm_lock_result) + DLM_USER_LVB_LEN];
535  		struct dlm_lock_result *result = (struct dlm_lock_result *)resultbuf;
536  		int status;
537  		void (*astaddr)(void *astarg);
538  	
539  		status = read(fd, result, sizeof(resultbuf));
540  		if (status <= 0)
541  			return -1;
542  	
543  		/* Copy lksb to user's buffer - except the LVB ptr */
544  		memcpy(result->user_lksb, &result->lksb,
545  		       sizeof(struct dlm_lksb) - sizeof(char*));
546  	
547  		/* Copy lvb to user's buffer */
548  		if (result->lvb_offset)
549  			memcpy(result->user_lksb->sb_lvbptr,
550  			       (char *)result + result->lvb_offset, DLM_LVB_LEN);
551  	
552  		result->user_lksb->sb_status = -result->user_lksb->sb_status;
553  	
554  		if (result->user_astaddr) {
555  			astaddr = result->user_astaddr;
556  			astaddr(result->user_astparam);
557  		}
558  	
559  		return 0;
560  	}
561  	
562  	static int do_dlm_dispatch(int fd)
563  	{
564  		if (kernel_version.version[0] == 5)
565  			return do_dlm_dispatch_v5(fd);
566  		else
567  			return do_dlm_dispatch_v6(fd);
568  	}
569  	
570  	
571  	/*
572  	 * sync_write()
573  	 * Helper routine which supports the synchronous DLM calls. This
574  	 * writes a parameter block down to the DLM and waits for the
575  	 * operation to complete. This hides the different completion mechanism
576  	 * used when called from the main thread or the DLM 'AST' thread.
577  	 */
578  	
579  	#ifdef _REENTRANT
580  	
581  	static int sync_write_v5(struct dlm_ls_info *lsinfo,
582  				 struct dlm_write_request_v5 *req, int len)
583  	{
584  		struct lock_wait lwait;
585  		int status;
586  	
587  		if (pthread_self() == lsinfo->tid) {
588  			/* This is the DLM worker thread, don't use lwait to sync */
589  			req->i.lock.castaddr  = dummy_ast_routine;
590  			req->i.lock.castparam = NULL;
591  	
592  			status = write(lsinfo->fd, req, len);
593  			if (status < 0)
594  				return -1;
595  	
596  			while (req->i.lock.lksb->sb_status == EINPROG) {
597  				do_dlm_dispatch_v5(lsinfo->fd);
598  			}
599  		} else {
600  			pthread_cond_init(&lwait.cond, NULL);
601  			pthread_mutex_init(&lwait.mutex, NULL);
602  			pthread_mutex_lock(&lwait.mutex);
603  	
604  			req->i.lock.castaddr  = sync_ast_routine;
605  			req->i.lock.castparam = &lwait;
606  	
607  			status = write(lsinfo->fd, req, len);
608  			if (status < 0)
609  				return -1;
610  	
611  			pthread_cond_wait(&lwait.cond, &lwait.mutex);
612  			pthread_mutex_unlock(&lwait.mutex);
613  		}
614  	
615  		return status; /* lock status is in the lksb */
616  	}
617  	
618  	static int sync_write_v6(struct dlm_ls_info *lsinfo,
619  				 struct dlm_write_request *req, int len)
620  	{
621  		struct lock_wait lwait;
622  		int status;
623  	
624  		if (pthread_self() == lsinfo->tid) {
625  			/* This is the DLM worker thread, don't use lwait to sync */
626  			req->i.lock.castaddr  = dummy_ast_routine;
627  			req->i.lock.castparam = NULL;
628  	
629  			status = write(lsinfo->fd, req, len);
630  			if (status < 0)
631  				return -1;
632  	
633  			while (req->i.lock.lksb->sb_status == EINPROG) {
634  				do_dlm_dispatch_v6(lsinfo->fd);
635  			}
636  		} else {
637  			pthread_cond_init(&lwait.cond, NULL);
638  			pthread_mutex_init(&lwait.mutex, NULL);
639  			pthread_mutex_lock(&lwait.mutex);
640  	
641  			req->i.lock.castaddr  = sync_ast_routine;
642  			req->i.lock.castparam = &lwait;
643  	
644  			status = write(lsinfo->fd, req, len);
645  			if (status < 0)
646  				return -1;
647  	
648  			pthread_cond_wait(&lwait.cond, &lwait.mutex);
649  			pthread_mutex_unlock(&lwait.mutex);
650  		}
651  	
652  		return status; /* lock status is in the lksb */
653  	}
654  	
655  	#else /* _REENTRANT */
656  	
657  	static int sync_write_v5(struct dlm_ls_info *lsinfo,
658  				 struct dlm_write_request_v5 *req, int len)
659  	{
660  		int status;
661  	
662  		req->i.lock.castaddr  = dummy_ast_routine;
663  		req->i.lock.castparam = NULL;
664  	
665  		status = write(lsinfo->fd, req, len);
666  		if (status < 0)
667  			return -1;
668  	
669  		while (req->i.lock.lksb->sb_status == EINPROG) {
670  			do_dlm_dispatch_v5(lsinfo->fd);
671  		}
672  	
673  		errno = req->i.lock.lksb->sb_status;
674  		if (errno && errno != EUNLOCK)
675  			return -1;
676  		return 0;
677  	}
678  	
679  	static int sync_write_v6(struct dlm_ls_info *lsinfo,
680  				 struct dlm_write_request *req, int len)
681  	{
682  		int status;
683  	
684  		req->i.lock.castaddr  = dummy_ast_routine;
685  		req->i.lock.castparam = NULL;
686  	
687  		status = write(lsinfo->fd, req, len);
688  		if (status < 0)
689  			return -1;
690  	
691  		while (req->i.lock.lksb->sb_status == EINPROG) {
692  			do_dlm_dispatch_v6(lsinfo->fd);
693  		}
694  	
695  		errno = req->i.lock.lksb->sb_status;
696  		if (errno && errno != EUNLOCK)
697  			return -1;
698  		return 0;
699  	}
700  	
701  	#endif /* _REENTRANT */
702  	
703  	
704  	/*
705  	 * Lock
706  	 * All the ways to request/convert a lock
707  	 */
708  	
709  	static int ls_lock_v5(dlm_lshandle_t ls,
710  			uint32_t mode,
711  			struct dlm_lksb *lksb,
712  			uint32_t flags,
713  			const void *name,
714  			unsigned int namelen,
715  			uint32_t parent,
716  			void (*astaddr) (void *astarg),
717  			void *astarg,
718  			void (*bastaddr) (void *astarg))
719  	{
720  		char parambuf[sizeof(struct dlm_write_request_v5) + DLM_RESNAME_MAXLEN];
721  		struct dlm_write_request_v5 *req = (struct dlm_write_request_v5 *)parambuf;
722  		struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
723  		int status;
724  		int len;
725  	
726  		memset(req, 0, sizeof(*req));
727  		set_version_v5(req);
728  	
729  		req->cmd = DLM_USER_LOCK;
730  		req->i.lock.mode = mode;
731  		req->i.lock.flags = (flags & ~LKF_WAIT);
732  		req->i.lock.lkid = lksb->sb_lkid;
733  		req->i.lock.parent = parent;
734  		req->i.lock.lksb = lksb;
735  		req->i.lock.castaddr = astaddr;
736  		req->i.lock.bastaddr = bastaddr;
737  		req->i.lock.castparam = astarg;	/* same comp and blocking ast arg */
738  		req->i.lock.bastparam = astarg;
739  	
740  		if (flags & LKF_CONVERT) {
741  			req->i.lock.namelen = 0;
742  		} else {
743  			if (namelen > DLM_RESNAME_MAXLEN) {
744  				errno = EINVAL;
745  				return -1;
746  			}
747  			req->i.lock.namelen = namelen;
748  			memcpy(req->i.lock.name, name, namelen);
749  		}
750  	
751  		if (flags & LKF_VALBLK) {
752  			memcpy(req->i.lock.lvb, lksb->sb_lvbptr, DLM_LVB_LEN);
753  		}
754  	
755  		len = sizeof(struct dlm_write_request_v5) + namelen;
756  		lksb->sb_status = EINPROG;
757  	
758  		if (flags & LKF_WAIT)
759  			status = sync_write_v5(lsinfo, req, len);
760  		else
761  			status = write(lsinfo->fd, req, len);
762  	
763  		if (status < 0)
764  			return -1;
765  	
766  		/*
767  		 * the lock id is the return value from the write on the device
768  		 */
769  	
770  		if (status > 0)
771  			lksb->sb_lkid = status;
772  		return 0;
773  	}
774  	
775  	static int ls_lock_v6(dlm_lshandle_t ls,
776  			uint32_t mode,
777  			struct dlm_lksb *lksb,
778  			uint32_t flags,
779  			const void *name,
780  			unsigned int namelen,
781  			uint32_t parent,
782  			void (*astaddr) (void *astarg),
783  			void *astarg,
784  			void (*bastaddr) (void *astarg),
785  			uint64_t *xid,
786  			uint64_t *timeout)
787  	{
788  		char parambuf[sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN];
789  		struct dlm_write_request *req = (struct dlm_write_request *)parambuf;
790  		struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
791  		int status;
792  		int len;
793  	
794  		memset(req, 0, sizeof(*req));
795  		set_version_v6(req);
796  	
797  		req->cmd = DLM_USER_LOCK;
798  		req->i.lock.mode = mode;
799  		req->i.lock.flags = (flags & ~LKF_WAIT);
800  		req->i.lock.lkid = lksb->sb_lkid;
801  		req->i.lock.parent = parent;
802  		req->i.lock.lksb = lksb;
803  		req->i.lock.castaddr = astaddr;
804  		req->i.lock.bastaddr = bastaddr;
805  		req->i.lock.castparam = astarg;	/* same comp and blocking ast arg */
806  		req->i.lock.bastparam = astarg;
807  	
808  		if (xid)
809  			req->i.lock.xid = *xid;
810  	
811  		if (flags & LKF_CONVERT) {
812  			req->i.lock.namelen = 0;
813  		} else {
814  			if (namelen > DLM_RESNAME_MAXLEN) {
815  				errno = EINVAL;
816  				return -1;
817  			}
818  			req->i.lock.namelen = namelen;
819  			memcpy(req->i.lock.name, name, namelen);
820  		}
821  	
822  		if (flags & LKF_VALBLK) {
823  			memcpy(req->i.lock.lvb, lksb->sb_lvbptr, DLM_LVB_LEN);
824  		}
825  	
826  		len = sizeof(struct dlm_write_request) + namelen;
827  		lksb->sb_status = EINPROG;
828  	
829  		if (flags & LKF_WAIT)
830  			status = sync_write_v6(lsinfo, req, len);
831  		else
832  			status = write(lsinfo->fd, req, len);
833  	
834  		if (status < 0)
835  			return -1;
836  	
837  		/*
838  		 * the lock id is the return value from the write on the device
839  		 */
840  	
841  		if (status > 0)
842  			lksb->sb_lkid = status;
843  		return 0;
844  	}
845  	
846  	static int ls_lock(dlm_lshandle_t ls,
847  			uint32_t mode,
848  			struct dlm_lksb *lksb,
849  			uint32_t flags,
850  			const void *name,
851  			unsigned int namelen,
852  			uint32_t parent,
853  			void (*astaddr) (void *astarg),
854  			void *astarg,
855  			void (*bastaddr) (void *astarg),
856  			void *range)
857  	{
858  		/* no support for range locks */
859  		if (range) {
860  			errno = ENOSYS;
861  			return -1;
862  		}
863  	
864  		if (flags & LKF_VALBLK && !lksb->sb_lvbptr) {
865  			errno = EINVAL;
866  			return -1;
867  		}
868  	
869  		if (kernel_version.version[0] == 5)
870  			return ls_lock_v5(ls, mode, lksb, flags, name, namelen, parent,
871  					  astaddr, astarg, bastaddr);
872  		else
873  			return ls_lock_v6(ls, mode, lksb, flags, name, namelen, parent,
874  					  astaddr, astarg, bastaddr, NULL, NULL);
875  	}
876  	
877  	/*
878  	 * Extended async locking in own lockspace
879  	 */
880  	int dlm_ls_lockx(dlm_lshandle_t ls,
881  			 uint32_t mode,
882  			 struct dlm_lksb *lksb,
883  			 uint32_t flags,
884  			 const void *name,
885  			 unsigned int namelen,
886  			 uint32_t parent,
887  			 void (*astaddr) (void *astarg),
888  			 void *astarg,
889  			 void (*bastaddr) (void *astarg),
890  			 uint64_t *xid,
891  			 uint64_t *timeout)
892  	{
893  		if (kernel_version.version[0] < 6) {
894  			errno = ENOSYS;
895  			return -1;
896  		}
897  	
898  		return ls_lock_v6(ls, mode, lksb, flags, name, namelen, parent,
899  				  astaddr, astarg, bastaddr, xid, timeout);
900  	}
901  	
902  	/*
903  	 * Async locking in own lockspace
904  	 */
905  	int dlm_ls_lock(dlm_lshandle_t ls,
906  			uint32_t mode,
907  			struct dlm_lksb *lksb,
908  			uint32_t flags,
909  			const void *name,
910  			unsigned int namelen,
911  			uint32_t parent,
912  			void (*astaddr) (void *astarg),
913  			void *astarg,
914  			void (*bastaddr) (void *astarg),
915  			void *range)
916  	{
917  		return ls_lock(ls, mode, lksb, flags, name, namelen, parent,
918  			       astaddr, astarg, bastaddr, range);
919  	}
920  	
921  	/*
922  	 * Sync locking in own lockspace
923  	 */
924  	int dlm_ls_lock_wait(dlm_lshandle_t ls,
925  			     uint32_t mode,
926  			     struct dlm_lksb *lksb,
927  			     uint32_t flags,
928  			     const void *name,
929  			     unsigned int namelen,
930  			     uint32_t parent,
931  			     void *bastarg,
932  			     void (*bastaddr) (void *bastarg),
933  			     void *range)
934  	{
935  		return ls_lock(ls, mode, lksb, flags | LKF_WAIT, name, namelen, parent,
936  			       NULL, bastarg, bastaddr, range);
937  	}
938  	
939  	/*
940  	 * Async locking in the default lockspace
941  	 */
942  	int dlm_lock(uint32_t mode,
943  		     struct dlm_lksb *lksb,
944  		     uint32_t flags,
945  		     const void *name,
946  		     unsigned int namelen,
947  		     uint32_t parent,
948  		     void (*astaddr) (void *astarg),
949  		     void *astarg,
950  		     void (*bastaddr) (void *astarg),
951  		     void *range)
952  	{
953  		if (open_default_lockspace())
954  			return -1;
955  	
956  		return ls_lock(default_ls, mode, lksb, flags, name, namelen, parent,
957  			       astaddr, astarg, bastaddr, range);
958  	}
959  	
960  	/*
961  	 * Sync locking in the default lockspace
962  	 */
963  	int dlm_lock_wait(uint32_t mode,
964  			     struct dlm_lksb *lksb,
965  			     uint32_t flags,
966  			     const void *name,
967  			     unsigned int namelen,
968  			     uint32_t parent,
969  			     void *bastarg,
970  			     void (*bastaddr) (void *bastarg),
971  			     void *range)
972  	{
973  		if (open_default_lockspace())
974  			return -1;
975  	
976  		return ls_lock(default_ls, mode, lksb, flags | LKF_WAIT, name, namelen,
977  			       parent, NULL, bastarg, bastaddr, range);
978  	}
979  	
980  	
981  	/*
982  	 * Unlock
983  	 * All the ways to unlock/cancel a lock
984  	 */
985  	
986  	static int ls_unlock_v5(struct dlm_ls_info *lsinfo, uint32_t lkid,
987  				uint32_t flags, struct dlm_lksb *lksb, void *astarg)
988  	{
989  		struct dlm_write_request_v5 req;
990  	
991  		set_version_v5(&req);
992  		req.cmd = DLM_USER_UNLOCK;
993  		req.i.lock.lkid = lkid;
994  		req.i.lock.flags = (flags & ~LKF_WAIT);
995  		req.i.lock.lksb  = lksb;
996  		req.i.lock.castparam = astarg;
997  		/* DLM_USER_UNLOCK will default to existing completion AST */
998  		req.i.lock.castaddr = 0;
999  		lksb->sb_status = EINPROG;
1000 	
1001 		if (flags & LKF_WAIT)
1002 			return sync_write_v5(lsinfo, &req, sizeof(req));
1003 		else
1004 			return write(lsinfo->fd, &req, sizeof(req));
1005 	}
1006 	
1007 	static int ls_unlock_v6(struct dlm_ls_info *lsinfo, uint32_t lkid,
1008 				uint32_t flags, struct dlm_lksb *lksb, void *astarg)
1009 	{
1010 		struct dlm_write_request req;
1011 	
1012 		set_version_v6(&req);
1013 		req.cmd = DLM_USER_UNLOCK;
1014 		req.i.lock.lkid = lkid;
1015 		req.i.lock.flags = (flags & ~LKF_WAIT);
1016 		req.i.lock.lksb  = lksb;
1017 		req.i.lock.namelen = 0;
1018 		req.i.lock.castparam = astarg;
1019 		/* DLM_USER_UNLOCK will default to existing completion AST */
1020 		req.i.lock.castaddr = 0;
1021 		lksb->sb_status = EINPROG;
1022 	
1023 		if (flags & LKF_WAIT)
1024 			return sync_write_v6(lsinfo, &req, sizeof(req));
1025 		else
1026 			return write(lsinfo->fd, &req, sizeof(req));
1027 	}
1028 	
1029 	int dlm_ls_unlock(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags,
1030 			  struct dlm_lksb *lksb, void *astarg)
1031 	{
1032 		struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
1033 		int status;
1034 	
1035 		if (ls == NULL) {
1036 			errno = ENOTCONN;
1037 			return -1;
1038 		}
1039 	
1040 		if (!lkid) {
1041 			errno = EINVAL;
1042 			return -1;
1043 		}
1044 	
1045 		if (kernel_version.version[0] == 5)
1046 			status = ls_unlock_v5(lsinfo, lkid, flags, lksb, astarg);
1047 		else
1048 			status = ls_unlock_v6(lsinfo, lkid, flags, lksb, astarg);
1049 	
1050 		if (status < 0)
1051 			return -1;
1052 		return 0;
1053 	}
1054 	
1055 	int dlm_ls_unlock_wait(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags,
1056 			       struct dlm_lksb *lksb)
1057 	{
1058 		return dlm_ls_unlock(ls, lkid, flags | LKF_WAIT, lksb, NULL);
1059 	}
1060 	
1061 	int dlm_unlock_wait(uint32_t lkid, uint32_t flags, struct dlm_lksb *lksb)
1062 	{
1063 		return dlm_ls_unlock_wait(default_ls, lkid, flags | LKF_WAIT, lksb);
1064 	}
1065 	
1066 	int dlm_unlock(uint32_t lkid, uint32_t flags, struct dlm_lksb *lksb,
1067 		       void *astarg)
1068 	{
1069 		return dlm_ls_unlock(default_ls, lkid, flags, lksb, astarg);
1070 	}
1071 	
1072 	int dlm_ls_deadlock_cancel(dlm_lshandle_t ls, uint32_t lkid, uint32_t flags)
1073 	{
1074 		struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
1075 		struct dlm_write_request req;
1076 	
1077 		if (kernel_version.version[0] < 6) {
1078 			errno = ENOSYS;
1079 			return -1;
1080 		}
1081 	
1082 		if (ls == NULL) {
1083 			errno = ENOTCONN;
1084 			return -1;
1085 		}
1086 	
1087 		if (!lkid) {
1088 			errno = EINVAL;
1089 			return -1;
1090 		}
1091 	
1092 		set_version_v6(&req);
1093 		req.cmd = DLM_USER_DEADLOCK;
1094 		req.i.lock.lkid = lkid;
1095 		req.i.lock.flags = flags;
1096 	
1097 		return write(lsinfo->fd, &req, sizeof(req));
1098 	}
1099 	
1100 	
1101 	/*
1102 	 * Purge
1103 	 * Clear away orphan locks
1104 	 */
1105 	
1106 	int dlm_ls_purge(dlm_lshandle_t ls, int nodeid, int pid)
1107 	{
1108 		struct dlm_write_request req;
1109 		struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
1110 		int status;
1111 	
1112 		if (kernel_version.version[0] < 6) {
1113 			errno = ENOSYS;
1114 			return -1;
1115 		}
1116 	
1117 		if (ls == NULL) {
1118 			errno = ENOTCONN;
1119 			return -1;
1120 		}
1121 	
1122 		set_version_v6(&req);
1123 		req.cmd = DLM_USER_PURGE;
1124 		req.i.purge.nodeid = nodeid;
1125 		req.i.purge.pid = pid;
1126 	
1127 		status = write(lsinfo->fd, &req, sizeof(req));
1128 	
1129 		if (status < 0)
1130 			return -1;
1131 		return 0;
1132 	}
1133 	
1134 	
1135 	/* These two routines for for users that want to
1136 	 * do their own fd handling.
1137 	 * This allows a non-threaded app to use the DLM.
1138 	 */
1139 	int dlm_get_fd(void)
1140 	{
1141 	    if (default_ls)
1142 	    {
1143 		return default_ls->fd;
1144 	    }
1145 	    else
1146 	    {
1147 		if (open_default_lockspace())
1148 		    return -1;
1149 		else
1150 		    return default_ls->fd;
1151 	    }
1152 	}
1153 	
1154 	int dlm_dispatch(int fd)
1155 	{
1156 	    int status;
1157 	    int fdflags;
1158 	
1159 	    fdflags = fcntl(fd, F_GETFL, 0);
1160 	    fcntl(fd, F_SETFL,  fdflags | O_NONBLOCK);
1161 	    do
1162 	    {
1163 		status = do_dlm_dispatch(fd);
1164 	    } while (status == 0);
1165 	
1166 	    /* EAGAIN is not an error */
1167 	    if (status < 0 && errno == EAGAIN)
1168 		status = 0;
1169 	
1170 	    fcntl(fd, F_SETFL, fdflags);
1171 	    return status;
1172 	}
1173 	
1174 	/* Converts a lockspace handle into a file descriptor */
1175 	int dlm_ls_get_fd(dlm_lshandle_t lockspace)
1176 	{
1177 	    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)lockspace;
1178 	
1179 	    return lsinfo->fd;
1180 	}
1181 	
1182 	#ifdef _REENTRANT
1183 	static void *dlm_recv_thread(void *lsinfo)
1184 	{
1185 		struct dlm_ls_info *lsi = lsinfo;
1186 	
1187 		for (;;)
1188 			do_dlm_dispatch(lsi->fd);
1189 	
1190 		return NULL;
1191 	}
1192 	
1193 	/* Multi-threaded callers normally use this */
1194 	int dlm_pthread_init(void)
1195 	{
1196 	    if (open_default_lockspace())
1197 		return -1;
1198 	
1199 	    if (default_ls->tid)
1200 	    {
1201 		errno = EEXIST;
1202 		return -1;
1203 	    }
1204 	
1205 	    if (pthread_create(&default_ls->tid, NULL, dlm_recv_thread, default_ls))
1206 	    {
1207 		int saved_errno = errno;
1208 		close(default_ls->fd);
1209 		free(default_ls);
1210 		default_ls = NULL;
1211 		errno = saved_errno;
1212 		return -1;
1213 	    }
1214 	    return 0;
1215 	}
1216 	
1217 	/* And same, for those with their own lockspace */
1218 	int dlm_ls_pthread_init(dlm_lshandle_t ls)
1219 	{
1220 	    struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
1221 	
1222 	    if (lsinfo->tid)
1223 	    {
1224 		errno = EEXIST;
1225 		return -1;
1226 	    }
1227 	
1228 	    return pthread_create(&lsinfo->tid, NULL, dlm_recv_thread, (void *)ls);
1229 	}
1230 	#endif
1231 	
1232 	/*
1233 	 * Lockspace manipulation functions
1234 	 * Privileged users (checked by the kernel) can create/release lockspaces
1235 	 */
1236 	
1237 	static int create_lockspace_v5(const char *name, uint32_t flags)
1238 	{
1239 		char reqbuf[sizeof(struct dlm_write_request_v5) + DLM_LOCKSPACE_LEN];
1240 		struct dlm_write_request_v5 *req = (struct dlm_write_request_v5 *)reqbuf;
1241 		int namelen = strlen(name);
1242 		int minor;
1243 	
1244 		memset(reqbuf, 0, sizeof(reqbuf));
1245 		set_version_v5(req);
1246 	
1247 		req->cmd = DLM_USER_CREATE_LOCKSPACE;
1248 		req->i.lspace.flags = flags;
1249 	
1250 		if (namelen > DLM_LOCKSPACE_LEN) {
1251 			errno = EINVAL;
1252 			return -1;
1253 		}
1254 		memcpy(req->i.lspace.name, name, namelen);
1255 	
1256 		minor = write(control_fd, req, sizeof(*req) + namelen);
1257 	
1258 		return minor;
1259 	}
1260 	
1261 	static int create_lockspace_v6(const char *name, uint32_t flags)
1262 	{
1263 		char reqbuf[sizeof(struct dlm_write_request) + DLM_LOCKSPACE_LEN];
1264 		struct dlm_write_request *req = (struct dlm_write_request *)reqbuf;
1265 		int namelen = strlen(name);
1266 		int minor;
1267 	
1268 		memset(reqbuf, 0, sizeof(reqbuf));
1269 		set_version_v6(req);
1270 	
1271 		req->cmd = DLM_USER_CREATE_LOCKSPACE;
1272 		req->i.lspace.flags = flags;
1273 	
1274 		if (namelen > DLM_LOCKSPACE_LEN) {
1275 			errno = EINVAL;
1276 			return -1;
1277 		}
1278 		memcpy(req->i.lspace.name, name, namelen);
1279 	
1280 		minor = write(control_fd, req, sizeof(*req) + namelen);
1281 	
1282 		return minor;
1283 	}
1284 	
1285 	static dlm_lshandle_t create_lockspace(const char *name, mode_t mode,
1286 					       uint32_t flags)
1287 	{
1288 		char dev_path[PATH_MAX];
1289 		char udev_path[PATH_MAX];
1290 		struct dlm_ls_info *newls;
1291 		int error, saved_errno, minor;
1292 	
1293 		/* We use the control device for creating lockspaces. */
1294 		if (open_control_device())
1295 			return NULL;
1296 	
1297 		newls = malloc(sizeof(struct dlm_ls_info));
1298 		if (!newls)
1299 			return NULL;
1300 	
1301 		ls_dev_name(name, dev_path, sizeof(dev_path));
1302 	
1303 		if (kernel_version.version[0] == 5)
1304 			minor = create_lockspace_v5(name, flags);
1305 		else
1306 			minor = create_lockspace_v6(name, flags);
1307 	
1308 		if (minor < 0)
1309 			goto fail;
1310 	
1311 		/* Wait for udev to create the device; the device it creates may
1312 		   have a truncated name due to the sysfs device name limit. */
1313 		   
1314 		error = find_udev_device(name, minor, udev_path);
1315 		if (error)
1316 			goto fail;
1317 	
1318 		/* If the symlink already exists, find_udev_device() will return
1319 		   it and we'll skip this. */
1320 	
1321 		if (strcmp(dev_path, udev_path)) {
1322 			error = symlink(udev_path, dev_path);
1323 			if (error)
1324 				goto fail;
1325 		}
1326 	
1327 		/* Open it and return the struct as a handle */
1328 	
1329 		newls->fd = open(dev_path, O_RDWR);
1330 		if (newls->fd == -1)
1331 			goto fail;
1332 		if (mode)
1333 			fchmod(newls->fd, mode);
1334 		newls->tid = 0;
1335 		fcntl(newls->fd, F_SETFD, 1);
1336 		return (dlm_lshandle_t)newls;
1337 	
1338 	 fail:
1339 		saved_errno = errno;
1340 		free(newls);
1341 		errno = saved_errno;
1342 		return NULL;
1343 	}
1344 	
1345 	dlm_lshandle_t dlm_new_lockspace(const char *name, mode_t mode, uint32_t flags)
1346 	{
1347 		flags &= ~DLM_LSFL_TIMEWARN;
1348 		return create_lockspace(name, mode, flags);
1349 	}
1350 	
1351 	dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode)
1352 	{
1353 		return create_lockspace(name, mode, 0);
1354 	}
1355 	
1356 	static int release_lockspace_v5(uint32_t minor, uint32_t flags)
1357 	{
1358 		struct dlm_write_request_v5 req;
1359 	
1360 		set_version_v5(&req);
1361 		req.cmd = DLM_USER_REMOVE_LOCKSPACE;
1362 		req.i.lspace.minor = minor;
1363 		req.i.lspace.flags = flags;
1364 	
1365 		return write(control_fd, &req, sizeof(req));
1366 	}
1367 	
1368 	static int release_lockspace_v6(uint32_t minor, uint32_t flags)
1369 	{
1370 		struct dlm_write_request req;
1371 	
1372 		set_version_v6(&req);
1373 		req.cmd = DLM_USER_REMOVE_LOCKSPACE;
1374 		req.i.lspace.minor = minor;
1375 		req.i.lspace.flags = flags;
1376 	
1377 		return write(control_fd, &req, sizeof(req));
1378 	}
1379 	
1380 	static int release_lockspace(uint32_t minor, uint32_t flags)
1381 	{
1382 		if (kernel_version.version[0] == 5)
1383 			return release_lockspace_v5(minor, flags);
1384 		else
1385 			return release_lockspace_v6(minor, flags);
1386 	}
1387 	
1388 	int dlm_release_lockspace(const char *name, dlm_lshandle_t ls, int force)
1389 	{
1390 		char dev_path[PATH_MAX];
1391 		struct stat st;
1392 		struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
1393 		uint32_t flags = 0;
1394 		int fd, is_symlink = 0;
1395 	
1396 		ls_dev_name(name, dev_path, sizeof(dev_path));
1397 		if (!lstat(dev_path, &st) && S_ISLNK(st.st_mode))
1398 			is_symlink = 1;
1399 	
1400 		/* We need the minor number */
1401 		if (fstat(lsinfo->fd, &st))
1402 			return -1;
1403 	
1404 		/* Close the lockspace first if it's in use */
1405 		ls_pthread_cleanup(lsinfo);
1406 	
1407 		if (open_control_device())
1408 			return -1;
1409 	
1410 		if (force)
1411 			flags = DLM_USER_LSFLG_FORCEFREE;
1412 	
1413 		release_lockspace(minor(st.st_rdev), flags);
1414 	
1415 		if (!is_symlink)
1416 			return 0;
1417 	
1418 		/* The following open is used to detect if our release was the last.
1419 		   It will fail if our release was the last, because either:
1420 		   . udev has already removed the truncated sysfs device name (ENOENT)
1421 		   . the misc device has been deregistered in the kernel (ENODEV)
1422 		     (the deregister completes before release returns)
1423 	
1424 		   So, if the open fails, we know that our release was the last,
1425 		   udev will be removing the device with the truncated name (if it
1426 		   hasn't already), and we should remove the symlink. */
1427 	
1428 		fd = open(dev_path, O_RDWR);
1429 		if (fd < 0)
1430 			unlink(dev_path);
1431 		else
1432 			close(fd); /* our release was not the last */
1433 	
1434 		return 0;
1435 	}
1436 	
1437 	/*
1438 	 * Normal users just open/close lockspaces
1439 	 */
1440 	
1441 	dlm_lshandle_t dlm_open_lockspace(const char *name)
1442 	{
1443 		char dev_name[PATH_MAX];
1444 		struct dlm_ls_info *newls;
1445 		int saved_errno;
1446 	
1447 		/* Need to detect kernel version */
1448 		if (open_control_device())
1449 			return NULL;
1450 	
1451 		newls = malloc(sizeof(struct dlm_ls_info));
1452 		if (!newls)
1453 			return NULL;
1454 	
1455 		newls->tid = 0;
1456 		ls_dev_name(name, dev_name, sizeof(dev_name));
1457 	
1458 		newls->fd = open(dev_name, O_RDWR);
1459 		saved_errno = errno;
1460 	
1461 		if (newls->fd == -1) {
1462 			free(newls);
1463 			errno = saved_errno;
1464 			return NULL;
1465 		}
1466 		fcntl(newls->fd, F_SETFD, 1);
1467 		return (dlm_lshandle_t)newls;
1468 	}
1469 	
1470 	int dlm_close_lockspace(dlm_lshandle_t ls)
1471 	{
1472 		struct dlm_ls_info *lsinfo = (struct dlm_ls_info *)ls;
1473 	
1474 		ls_pthread_cleanup(lsinfo);
1475 		return 0;
1476 	}
1477 	
1478 	int dlm_kernel_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
1479 	{
1480 		if (open_control_device())
1481 			return -1;
1482 		*major = kernel_version.version[0];
1483 		*minor = kernel_version.version[1];
1484 		*patch = kernel_version.version[2];
1485 		return 0;
1486 	}
1487 	
1488 	void dlm_library_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
1489 	{
1490 		*major = DLM_DEVICE_VERSION_MAJOR;
1491 		*minor = DLM_DEVICE_VERSION_MINOR;
1492 		*patch = DLM_DEVICE_VERSION_PATCH;
1493 	}
1494 	
1495