Hi all, The attached patch provides SAF AIS lock APIs support based on current GDLM. It's just simplest wrap of GDLM's user mode api and didn't touch GDLM's codes. I think it can be a good complementarity to GDLM. The patch is against lastest CVS codes. Any interests or comments? Best Regards, Stan -- Opinions expressed are those of the author and do not represent Intel Corporation "gpg --recv-keys --keyserver wwwkeys.pgp.net E1390A7F" {E1390A7F:3AD1 1B0C 2019 E183 0CFF 55E8 369A 8B75 E139 0A7F}
diff -Nur -X /usr/src/dontdiff old/cluster/dlm/lib/libaislock.c cluster/dlm/lib/libaislock.c --- old/cluster/dlm/lib/libaislock.c 1970-01-01 08:00:00.000000000 +0800 +++ cluster/dlm/lib/libaislock.c 2004-12-09 21:22:03.224061752 +0800 @@ -0,0 +1,463 @@ +# ifdef _REENTRANT +# include <pthread.h> +# endif +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> + +#include "dlm.h" +#define BUILDING_LIBDLM +#include "libdlm.h" +#include "libaislock.h" +#include "dlm_device.h" + +enum { + SA_LCK_GRANT_CB = 1, + SA_LCK_WAITER_CB = 2, +}; + +static struct dlm_ls_info *sa_default_ls = NULL; + +inline int lkmode_ais2dlm(SaLckLockModeT mode) +{ + switch(mode) + { + case SA_LCK_PR_LOCK_MODE: + return DLM_LOCK_PR; + case SA_LCK_EX_LOCK_MODE: + return DLM_LOCK_EX; + default: + return -1; + } +} + +inline SaLckLockModeT lkmode_dlm2ais(int mode) +{ + switch(mode) + { + case DLM_LOCK_PR: + return SA_LCK_PR_LOCK_MODE; + case DLM_LOCK_EX: + return SA_LCK_EX_LOCK_MODE; + default: + return -1; + } +} + +inline unsigned long lkflag_ais2dlm(SaLckLockFlagsT flag) +{ + unsigned long dlm_flag = 0; + + if(flag & SA_LCK_LOCK_NO_QUEUE) + dlm_flag |= DLM_LKF_NOQUEUE; + if(flag & SA_LCK_LOCK_ORPHAN) + dlm_flag |= DLM_LKF_ORPHAN; + + return dlm_flag; +} + +inline SaLckLockStatusT lkstatus_dlm2ais(int status) +{ + switch(status) + { + case -ENOMEM: + return SA_LCK_LOCK_NO_MORE; + case 0: + return SA_LCK_LOCK_GRANTED; + case -EAGAIN: + return SA_LCK_LOCK_NOT_QUEUED; + default: + return -1; + } +} + +inline SaErrorT lkerr_dlm2ais(int status) +{ + switch(status) + { + case -EINVAL: + return SA_ERR_INVALID_PARAM; + case 0: + return SA_OK; + default: + return -1; + } +} + + +SaErrorT +saLckInitialize(SaLckHandleT *lckHandle, const SaLckCallbacksT *lckCallbacks, + const SaVersionT *version) +{ + dlm_lshandle_t ls = NULL; + + if (NULL == lckHandle) + return SA_ERR_INVALID_PARAM; + + if (lckCallbacks) { + lckHandle->callback.saLckLockGrantCallback = + lckCallbacks->saLckLockGrantCallback; + lckHandle->callback.saLckLockWaiterCallback = + lckCallbacks->saLckLockWaiterCallback; + lckHandle->callback.saLckResourceUnlockCallback = + lckCallbacks->saLckResourceUnlockCallback; + } else { + lckHandle->callback.saLckLockGrantCallback = NULL; + lckHandle->callback.saLckLockWaiterCallback = NULL; + lckHandle->callback.saLckResourceUnlockCallback = NULL; + } + lckHandle->version.releaseCode = version->releaseCode; + lckHandle->version.major = version->major; + lckHandle->version.minor = version->minor; + + ls = dlm_create_lockspace("sa_default", 0600); + if (!ls) + return SA_ERR_LIBRARY; + + sa_default_ls = (struct dlm_ls_info *)ls; + return SA_OK; +} + + +SaErrorT +saLckFinalize(SaLckHandleT *lckHandle) +{ + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + if(!dlm_release_lockspace("sa_default", sa_default_ls, 1)) { + return SA_OK; + } else { + return SA_ERR_LIBRARY; + } +} + +SaErrorT +saLckResourceOpen(const SaLckHandleT *lckHandle, const SaNameT *lockName, + SaLckResourceIdT *resourceId) +{ + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + if (lockName->length <= 31 ) /* OpenDLM only support namelen <= 31*/ + { + resourceId->name.length = lockName->length; + strncpy(resourceId->name.value, lockName->value, lockName->length); + } else { + return SA_ERR_NO_MEMORY; + } + + return SA_OK; +} + + +SaErrorT +saLckResourceClose(SaLckHandleT *lckHandle, SaLckResourceIdT *resourceId) +{ + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + return SA_OK; +} + + +SaErrorT +saLckSelectionObjectGet(const SaLckHandleT *lckHandle, + SaSelectionObjectT *selectionObject) +{ + int fd = -1; + + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + fd = dlm_ls_get_fd(sa_default_ls); + + if(!fd) + return SA_ERR_LIBRARY; + + *selectionObject = fd; + + return SA_OK; +} + + +SaErrorT +saLckDispatch(const SaLckHandleT *lckHandle, + const SaDispatchFlagsT dispatchFlags) +{ + int status; + int fdflags; + char resultbuf[sizeof(struct dlm_lock_result)]; + struct dlm_lock_result *result = (struct dlm_lock_result *)resultbuf; + char *fullresult=NULL; + SaLckLockIdT *lkid; + SaLckLockModeT lock_mode; + int fd = -1; + + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + fd = dlm_ls_get_fd(sa_default_ls); + + if(!fd) + return SA_ERR_LIBRARY; + + fdflags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, fdflags | O_NONBLOCK); + + do + { + + /* Just read the header first */ + status = read(fd, result, sizeof(struct dlm_lock_result)); + if (status <= 0) + break; + + if (result->length != status) + { + int newstat; + + fullresult = malloc(result->length); + if (!fullresult) + break; + + newstat = read(fd, 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 *)fullresult; + } + + /* 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; + + /* Need not to care LVB*/ + + /* Copy optional items */ + 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; + } + + 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); + + /* Call AST */ + lkid = (SaLckLockIdT *)result->user_astparam; + if (lkid->unlock) { + /* dispatch unlock ast */ + lkid->unlock = 0; + lkid->held_mode = 0; + if(lckHandle->callback.saLckResourceUnlockCallback) + lckHandle->callback. + saLckResourceUnlockCallback( + lkid->args, lkid->resource, lkid, + SA_LCK_LOCK_RELEASED, SA_OK); + + } else if (SA_LCK_GRANT_CB == (int)result->user_astaddr) { + /* dispatch lock ast */ + if (0 == lkid->lksb.sb_status) { + lkid->held_mode = lkid->requested_mode; + lock_mode = lkid->requested_mode; + } else { + lock_mode = lkid->held_mode; + } + + if(lckHandle->callback.saLckLockGrantCallback) + lckHandle->callback. + saLckLockGrantCallback( + lkid->args, lkid->resource, + lkid, lock_mode, + lkstatus_dlm2ais( + lkid->lksb.sb_status), + SA_OK); + } else if (SA_LCK_WAITER_CB == (int)result->user_astaddr) { + /* dispatch waiter ast */ + if(lckHandle->callback.saLckLockWaiterCallback) + lckHandle->callback. + saLckLockWaiterCallback( + lkid->args, lkid->resource, + lkid, lkid->held_mode, result->bast_mode); + } else { + return SA_ERR_LIBRARY; + } + } while (0 !=status && SA_DISPATCH_ONE != dispatchFlags); + + /* EAGAIN is not an error */ + if (status < 0 && errno == EAGAIN) + status = 0; + + fcntl(fd, F_SETFL, fdflags); + return SA_OK; + } + +SaErrorT +SaLckResourceLockAsync(const SaLckHandleT *lckHandle, SaInvocationT invocation, + const SaLckResourceIdT *resourceId, SaLckLockIdT *lockId, + SaLckLockModeT lockMode, SaLckLockFlagsT lockFlags, + SaTimeT timeout) +{ + int ret_val; /* value to be returned from function */ + + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + /*FIXME deal with timeout in lock/lockasync/unlock. + */ + lockId->resource = (SaLckResourceIdT *)resourceId; + lockId->requested_mode = lockMode; + lockId->args = invocation; + + ret_val = dlm_ls_lock(sa_default_ls, lkmode_ais2dlm(lockMode), + &(lockId->lksb), lkflag_ais2dlm(lockFlags), + (void *)(resourceId->name.value), + resourceId->name.length, 0, (void *)SA_LCK_GRANT_CB, + lockId, (void *)SA_LCK_WAITER_CB, NULL); + + return lkerr_dlm2ais(ret_val); +} + +SaErrorT +saLckResourceLock(const SaLckHandleT *lckHandle, SaInvocationT invocation, + const SaLckResourceIdT *resourceId, SaLckLockIdT *lockId, + SaLckLockModeT lockMode, SaLckLockFlagsT lockFlags, + SaTimeT timeout, SaLckLockStatusT *lockStatus) + +{ + int ret_val; /* value to be returned from function */ + + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + lockId->resource = (SaLckResourceIdT *)resourceId; + lockId->requested_mode = lockMode; + lockId->args = invocation; + + ret_val = dlm_ls_lock_wait(sa_default_ls, lkmode_ais2dlm(lockMode), + &(lockId->lksb), lkflag_ais2dlm(lockFlags), + (void *)(resourceId->name.value), + resourceId->name.length, 0, lockId, + (void *)SA_LCK_WAITER_CB, NULL); + + *lockStatus = lkstatus_dlm2ais(lockId->lksb.sb_status); + lockId->held_mode = lockId->requested_mode; + + return lkerr_dlm2ais(ret_val); +} + +SaErrorT +saLckResourceUnlock(const SaLckHandleT *lckHandle, SaLckLockIdT *lockId, + SaTimeT timeout) +{ + int ret_val; /* value to be returned from function */ + + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + ret_val = dlm_ls_unlock_wait(sa_default_ls, lockId->lksb.sb_lkid, 0, + &(lockId->lksb)); + lockId->held_mode = 0; + + return lkerr_dlm2ais(ret_val); +} + +SaErrorT +saLckResourceUnlockAsync(const SaLckHandleT *lckHandle, + SaInvocationT invocation, SaLckLockIdT *lockId) +{ + int ret_val; /* value to be returned from function */ + + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + lockId->unlock = 1; + lockId->args = invocation; + + + ret_val = dlm_ls_unlock(sa_default_ls, lockId->lksb.sb_lkid, 0, &(lockId->lksb), + lockId); + + return lkerr_dlm2ais(ret_val); +} + + +SaErrorT +saLckLockPurge(const SaLckHandleT *lckHandle, + const SaLckResourceIdT *resourceId) +{ + int ret_val; /* value to be returned from function */ + SaLckLockIdT lockId; + struct dlm_lksb lksb; + struct dlm_resinfo resinfo; + static struct dlm_queryinfo qinfo; + struct dlm_lockinfo *p; + + qinfo.gqi_resinfo = &resinfo; + qinfo.gqi_lockinfo = malloc(sizeof(struct dlm_lockinfo) * 10); + qinfo.gqi_locksize = 10; + + + if ( NULL == sa_default_ls ) { + return SA_ERR_LIBRARY; + } + + lockId.resource = (SaLckResourceIdT *)resourceId; + lockId.requested_mode = DLM_LOCK_NL; + + ret_val = dlm_ls_lock_wait(sa_default_ls, DLM_LOCK_NL, + &(lockId.lksb), DLM_LKF_EXPEDITE, + (void *)(resourceId->name.value), + resourceId->name.length, 0, &lockId, + (void *)SA_LCK_WAITER_CB, NULL); + + dlm_ls_query_wait(sa_default_ls, &(lockId.lksb), + DLM_QUERY_QUEUE_ALL|DLM_QUERY_LOCKS_ORPHAN, &qinfo); + + for ( p = qinfo.gqi_lockinfo; 0 != p->lki_lkid; p++ ) { + lksb.sb_lkid = p->lki_lkid; + ret_val = dlm_ls_unlock_wait(sa_default_ls, p->lki_lkid, 0, + &lksb); + } + + ret_val = dlm_ls_unlock_wait(sa_default_ls, lockId.lksb.sb_lkid, 0, + &(lockId.lksb)); + + return lkerr_dlm2ais(ret_val); +} + diff -Nur -X /usr/src/dontdiff old/cluster/dlm/lib/libaislock.h cluster/dlm/lib/libaislock.h --- old/cluster/dlm/lib/libaislock.h 1970-01-01 08:00:00.000000000 +0800 +++ cluster/dlm/lib/libaislock.h 2004-12-08 21:47:34.000000000 +0800 @@ -0,0 +1,190 @@ +typedef char SaInt8T; +typedef short SaInt16T; +typedef long SaInt32T; +typedef long long SaInt64T; +typedef unsigned char SaUint8T; +typedef unsigned short SaUint16T; +typedef unsigned long SaUint32T; +typedef unsigned long long SaUint64T; +typedef SaInt64T SaTimeT; + +#define SA_MAX_NAME_LENGTH 256 + +typedef struct { + SaUint16T length; + unsigned char value[SA_MAX_NAME_LENGTH]; +} SaNameT; + +typedef struct { + char releaseCode; + unsigned char major; + unsigned char minor; +} SaVersionT; + +typedef int SaSelectionObjectT; + +typedef void *SaInvocationT; + +typedef enum { + SA_DISPATCH_ONE = 1, + SA_DISPATCH_ALL = 2, + SA_DISPATCH_BLOCKING = 3 +} SaDispatchFlagsT; + +typedef enum { + SA_OK = 1, + SA_ERR_LIBRARY = 2, + SA_ERR_VERSION = 3, + SA_ERR_INIT = 4, + SA_ERR_TIMEOUT = 5, + SA_ERR_TRY_AGAIN = 6, + SA_ERR_INVALID_PARAM = 7, + SA_ERR_NO_MEMORY = 8, + SA_ERR_BAD_HANDLE = 9, + SA_ERR_BUSY = 10, + SA_ERR_ACCESS = 11, + SA_ERR_NOT_EXIST = 12, + SA_ERR_NAME_TOO_LONG = 13, + SA_ERR_EXIST = 14, + SA_ERR_NO_SPACE = 15, + SA_ERR_INTERRUPT =16, + SA_ERR_SYSTEM = 17, + SA_ERR_NAME_NOT_FOUND = 18, + SA_ERR_NO_RESOURCES = 19, + SA_ERR_NOT_SUPPORTED = 20, + SA_ERR_BAD_OPERATION = 21, + SA_ERR_FAILED_OPERATION = 22, + SA_ERR_MESSAGE_ERROR = 23, + SA_ERR_NO_MESSAGE = 24, + SA_ERR_QUEUE_FULL = 25, + SA_ERR_QUEUE_NOT_AVAILABLE = 26, + SA_ERR_BAD_CHECKPOINT = 27, + SA_ERR_BAD_FLAGS = 28 +} SaErrorT; + +/* Chapter 10 */ +typedef enum { + SA_LCK_PR_LOCK_MODE = 1, + SA_LCK_EX_LOCK_MODE = 2 +} SaLckLockModeT; + +typedef struct{ + int site; + int pid; +} SaLckLockHolderT; + +typedef struct { + SaLckLockHolderT orphan_holder; + SaNameT name; +} SaLckResourceIdT; + +typedef struct { + struct dlm_lksb lksb; + SaLckResourceIdT *resource; + SaLckLockModeT held_mode; + SaLckLockModeT requested_mode; + int unlock; + SaInvocationT args; +} SaLckLockIdT; + +#define SA_LCK_LOCK_NO_QUEUE 0x1 +#define SA_LCK_LOCK_ORPHAN 0x2 +#define SA_LCK_LOCK_TIMEOUT 0X4 +typedef SaUint32T SaLckLockFlagsT; + +typedef enum { + SA_LCK_LOCK_GRANTED = 1, + SA_LCK_LOCK_RELEASED = 2, + SA_LCK_LOCK_DEADLOCK = 3, + SA_LCK_LOCK_NOT_QUEUED = 4, + SA_LCK_LOCK_TIMED_OUT = 5, + SA_LCK_LOCK_ORPHANED = 6, + SA_LCK_LOCK_NO_MORE = 7 +} SaLckLockStatusT; + +typedef void +(*SaLckLockGrantCallbackT)(SaInvocationT invocation, + const SaLckResourceIdT *resourceId, + const SaLckLockIdT *lockId, + SaLckLockModeT lockMode, + SaLckLockStatusT lockStatus, + SaErrorT error); + +typedef void +(*SaLckLockWaiterCallbackT)(SaInvocationT invocation, + const SaLckResourceIdT *resourceId, + const SaLckLockIdT *lockId, + SaLckLockModeT modeHeld, + SaLckLockModeT modeRequested); + +typedef void +(*SaLckResourceUnlockCallbackT)(SaInvocationT invocation, + const SaLckResourceIdT *resourceId, + const SaLckLockIdT *lockId, + SaLckLockStatusT lockStatus, + SaErrorT error); +typedef struct SaLckCallbacks { + SaLckLockGrantCallbackT saLckLockGrantCallback; + SaLckLockWaiterCallbackT saLckLockWaiterCallback; + SaLckResourceUnlockCallbackT saLckResourceUnlockCallback; +}SaLckCallbacksT; + +typedef struct { + SaLckCallbacksT callback; + SaVersionT version; +} SaLckHandleT; + + SaErrorT +saLckInitialize(SaLckHandleT *lckHandle, const SaLckCallbacksT *lckCallbacks, + const SaVersionT *version); + + SaErrorT +saLckSelectionObjectGet(const SaLckHandleT *lckHandle, + SaSelectionObjectT *selectionObject); + + SaErrorT +saLckDispatch(const SaLckHandleT *lckHandle, + const SaDispatchFlagsT dispatchFlags); + + SaErrorT +saLckFinalize(SaLckHandleT *lckHandle); + + SaErrorT +saLckResourceOpen(const SaLckHandleT *lckHandle, + const SaNameT *lockName, + SaLckResourceIdT *resourceId); + + SaErrorT +saLckResourceClose(SaLckHandleT *lckHandle, SaLckResourceIdT *resourceId); + + SaErrorT +saLckResourceLock(const SaLckHandleT *lckHandle, SaInvocationT invocation, + const SaLckResourceIdT *resourceId, + SaLckLockIdT *lockId, + SaLckLockModeT lockMode, + SaLckLockFlagsT lockFlags, + SaTimeT timeout, + SaLckLockStatusT *lockStatus); + + SaErrorT +SaLckResourceLockAsync(const SaLckHandleT *lckHandle, + SaInvocationT invocation, + const SaLckResourceIdT *resourceId, + SaLckLockIdT *lockId, + SaLckLockModeT lockMode, + SaLckLockFlagsT lockFlags, + SaTimeT timeout); + + SaErrorT +saLckResourceUnlock(const SaLckHandleT *lckHandle, + SaLckLockIdT *lockId, + SaTimeT timeout); + + SaErrorT +saLckResourceUnlockAsync(const SaLckHandleT *lckHandle, + SaInvocationT invocation, + SaLckLockIdT *lockId); + + SaErrorT +saLckLockPurge(const SaLckHandleT *lckHandle, + const SaLckResourceIdT *resourceId); diff -Nur -X /usr/src/dontdiff old/cluster/dlm/lib/Makefile cluster/dlm/lib/Makefile --- old/cluster/dlm/lib/Makefile 2004-10-26 01:52:29.000000000 +0800 +++ cluster/dlm/lib/Makefile 2004-12-08 21:47:20.000000000 +0800 @@ -11,7 +11,7 @@ ############################################################################### ############################################################################### -SOURCE=libdlm.c +SOURCE=libdlm.c libaislock.c LIBNAME=libdlm SHAREDLIB=$(LIBNAME).so.${RELEASE_MAJOR}.${RELEASE_MINOR} $(LIBNAME)_lt.so.${RELEASE_MAJOR}.${RELEASE_MINOR} @@ -37,16 +37,16 @@ all: $(STATICLIB) $(SHAREDLIB) -$(LIBNAME).a: libdlm.o - ${AR} r libdlm.a libdlm.o +$(LIBNAME).a: libdlm.o libaislock.o + ${AR} cr libdlm.a libdlm.o libaislock.o ${RANLIB} libdlm.a -$(LIBNAME)_lt.a: libdlm_lt.o - ${AR} r libdlm_lt.a libdlm_lt.o +$(LIBNAME)_lt.a: libdlm_lt.o + ${AR} r libdlm_lt.a libdlm_lt.o ${RANLIB} libdlm_lt.a -$(LIBNAME).so.${RELEASE_MAJOR}.${RELEASE_MINOR}: libdlm.po - $(CC) -shared -o $@ -Wl,-soname=$(LIBNAME).so.$(RELEASE_MAJOR) $^ +$(LIBNAME).so.${RELEASE_MAJOR}.${RELEASE_MINOR}: libdlm.po libaislock.po + $(LD) -shared -o $@ -soname=$(LIBNAME).so.$(RELEASE_MAJOR) $^ $(LIBNAME)_lt.so.${RELEASE_MAJOR}.${RELEASE_MINOR}: libdlm_lt.po $(CC) -shared -o $@ -Wl,-soname=$(LIBNAME)_lt.so.$(RELEASE_MAJOR) $^ @@ -57,6 +57,12 @@ libdlm.o: libdlm.c $(CC) $(CFLAGS) -D_REENTRANT -c -o $@ $< +libaislock.po: libaislock.c + $(CC) $(CFLAGS) -D_REENTRANT -c -o $@ $< + +libaislock.o: libaislock.c + $(CC) $(CFLAGS) -D_REENTRANT -c -o $@ $< + libdlm_lt.po: libdlm.c $(CC) $(CFLAGS) -c -o $@ $<