
There are five ways to request a dlm lock (and five corresponding ways to
unlock).

- lock_resource
- dlm_lock
- dlm_ls_lock
- dlm_lock_wait
- dlm_ls_lock_wait

- unlock_resource
- dlm_unlock
- dlm_ls_unlock
- dlm_unlock_wait
- dlm_ls_unlock_wait

There is also a set of "administrative" functions that are used along with
some of the lock/unlock requests.  Which are used depends on which locking
method is used or whether the application is threaded.

- dlm_pthread_init
- dlm_ls_pthread_init
- dlm_pthread_cleanup
- dlm_get_fd
- dlm_ls_get_fd
- dlm_dispatch
- dlm_create_lockspace
- dlm_open_lockspace
- dlm_release_lockspace
- dlm_close_lockspace


Overview of lock request methods
--------------------------------

- synchronous, default lockspace
  use dlm_pthread_init/dlm_pthread_cleanup if app is threaded
  use dlm_get_fd/dlm_dispatch if app is not threaded
  use unlock_resource to unlock

int lock_resource(
        const char *resource,
        uint32_t mode,
        uint32_t flags,
        uint32_t *lkid);


- asynchronous, default lockspace
  use dlm_pthread_init/dlm_pthread_cleanup if app is threaded
  use dlm_get_fd/dlm_dispatch if app is not threaded
  use dlm_unlock/dlm_unlock_wait to unlock

int dlm_lock(
        uint32_t mode,
        struct dlm_lksb *lksb,
        uint32_t flags,
        void *name,
        unsigned int namelen,
        uint32_t parent,
        void (*ast) (void *astarg),
        void *astarg,
        void (*bast) (void *astarg),
        struct dlm_range *range);


- synchronous, default lockspace
  use dlm_pthread_init/dlm_pthread_cleanup if app is threaded
  use dlm_get_fd/dlm_dispatch if app is not threaded
  use dlm_unlock/dlm_unlock_wait to unlock

int dlm_lock_wait(
        uint32_t mode,
        struct dlm_lksb *lksb,
        uint32_t flags,
        void *name,
        unsigned int namelen,
        uint32_t parent,
        void *bastarg,
        void (*bast) (void *bastarg),
        struct dlm_range *range);


- asynchronous, any lockspace
  use dlm_ls_pthread_init/dlm_pthread_cleanup if app is threaded
  use dlm_ls_get_fd/dlm_dispatch if app is not threaded
  use dlm_create_lockspace/dlm_open_lockspace to start
  use dlm_release_lockspace/dlm_close_lockspace to finish
  use dlm_ls_unlock/dlm_ls_unlock_wait to unlock

int dlm_ls_lock(
        dlm_lshandle_t lockspace,
        uint32_t mode,
        struct dlm_lksb *lksb,
        uint32_t flags,
        void *name,
        unsigned int namelen,
        uint32_t parent,
        void (*ast) (void *astarg),
        void *astarg,
        void (*bast) (void *astarg),
        struct dlm_range *range);


- synchronous, any lockspace
  use dlm_ls_pthread_init/dlm_pthread_cleanup if app is threaded
  use dlm_ls_get_fd/dlm_dispatch if app is not threaded
  use dlm_create_lockspace/dlm_open_lockspace to start
  use dlm_release_lockspace/dlm_close_lockspace to finish
  use dlm_ls_unlock/dlm_ls_unlock_wait to unlock

int dlm_ls_lock_wait(
        dlm_lshandle_t lockspace,
        uint32_t mode,
        struct dlm_lksb *lksb,
        uint32_t flags,
        void *name,
        unsigned int namelen,
        uint32_t parent,
        void *bastarg,
        void (*bast) (void *bastarg),
        struct dlm_range *range);



Corresponding unlock requests 
-----------------------------

int unlock_resource(
	uint32_t lkid);

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);

int dlm_ls_unlock(
	dlm_lshandle_t lockspace,
	uint32_t lkid,
	uint32_t flags,
	struct dlm_lksb *lksb,
	void *astarg);

int dlm_ls_unlock_wait(
	dlm_lshandle_t lockspace,
	uint32_t lkid,
	uint32_t flags,
	struct dlm_lksb *lksb);



Common to all of the above
--------------------------

#define DLM_RESNAME_MAXLEN (64)
#define DLM_LVB_LEN        (32)

#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 */

#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 ECANCEL            (0x10001)
#define EUNLOCK            (0x10002)
#define EINPROG            (0x10003)

struct dlm_lksb {
	int sb_status;
	uint32_t sb_lkid;
	char sb_flags;
	char *sb_lvbptr;
};

struct dlm_range {
	uint64_t ra_start;
	uint64_t ra_end;
};




Overview of administrative functions
------------------------------------

- dlm_pthread_init
- dlm_ls_pthread_init
- dlm_pthread_cleanup
- dlm_get_fd
- dlm_ls_get_fd
- dlm_dispatch
- dlm_create_lockspace
- dlm_open_lockspace
- dlm_release_lockspace
- dlm_close_lockspace


typedef void * dlm_lshandle_t;

dlm_lshandle_t dlm_create_lockspace(const char *name, mode_t mode);

int dlm_release_lockspace(const char *name, dlm_lshandle_t ls, int force);

dlm_lshandle_t dlm_open_lockspace(const char *name);

int dlm_close_lockspace(dlm_lshandle_t ls);

int dlm_pthread_init();

int dlm_ls_pthread_init(dlm_lshandle_t lockspace);

int dlm_pthread_cleanup();

int dlm_get_fd();

int dlm_ls_get_fd(dlm_lshandle_t ls);

int dlm_dispatch(int fd);



Query functions
---------------

Query functions follow the same pattern as the lock and unlock functions.

int dlm_query(
	struct dlm_lksb *lksb,
	int query,
	struct dlm_queryinfo *qinfo,
	void (*astaddr) (void *astarg),
	void *astarg);

int dlm_query_wait(
	struct dlm_lksb *lksb,
	int query,
	struct dlm_queryinfo *qinfo);

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_query_wait(
	dlm_lshandle_t lockspace,
	struct dlm_lksb *lksb,
	int query,
	struct dlm_queryinfo *qinfo);

#define DLM_LOCK_THIS            0x0007
#define DLM_QUERY_MODE_MASK      0x0007

#define DLM_QUERY_QUEUE_WAIT     0x0008
#define DLM_QUERY_QUEUE_CONVERT  0x0010
#define DLM_QUERY_QUEUE_GRANT    0x0020
#define DLM_QUERY_QUEUE_GRANTED  0x0030
#define DLM_QUERY_QUEUE_ALL      0x0038

#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_MASK           0x0F00

#define DLM_QUERY_GRMODE         0x0000
#define DLM_QUERY_RQMODE         0x1000

struct dlm_lockinfo {
        int lki_lkid;
        int lki_mstlkid;
        int lki_parent;
        int lki_node;
        int lki_ownpid;
        uint8_t lki_state;
        uint8_t lki_grmode;
        uint8_t lki_rqmode;
        struct dlm_range lki_grrange;
        struct dlm_range lki_rqrange;
};

struct dlm_resinfo {
        int rsi_length;
        int rsi_grantcount;
        int rsi_convcount;
        int rsi_waitcount;
        int rsi_masternode;
        char rsi_name[DLM_RESNAME_MAXLEN];
        char rsi_valblk[DLM_LVB_LEN];
};

struct dlm_queryinfo {
        struct dlm_resinfo *gqi_resinfo;
        struct dlm_lockinfo *gqi_lockinfo;
        int gqi_locksize;
        int gqi_lockcount;
};



