dlm: dlm_device interface changes
David Teigland
maintainerPATCH 3/6 dlm: dlm_device interface changes
Change the user/kernel device interface used by libdlm:
- Add ability for userspace to check the version of the interface. libdlm can now adapt to different versions of the kernel interface.
- Increase the size of the flags passed in a lock request so all possible flags can be used from userspace.
- Add an opaque "xid" value for each lock. This "transaction id" will be used later to associate locks with each other during deadlock detection.
- Add a "timeout" value for each lock. This is used along with the DLM_LKF_TIMEOUT flag.
Also, remove a fragment of unused code in device_read().
This patch requires updating libdlm which is backward compatible with older kernels.
Signed-off-by David Teigland <[email protected]>
fs/dlm/user.c +43 -10
@@ -33,16 +33,17 @@struct dlm_lock_params32 {__u8 mode;__u8 namelen; -__u16 flags; +__u16 unused; +__u32 flags;__u32 lkid;__u32 parent; - +__u64 xid; +__u64 timeout;__u32 castparam;__u32 castaddr;__u32 bastparam;__u32 bastaddr;__u32 lksb; -char lvb[DLM_USER_LVB_LEN ];char name[0 ]; };
@@ -68,6 +69,7 @@ };struct dlm_lock_result32 { +__u32 version[3 ];__u32 length;__u32 user_astaddr;__u32 user_astparam;
@@ -102,6 +104,8 @@ kb->i.lock.flags = kb32->i.lock.flags; kb->i.lock.lkid = kb32->i.lock.lkid; kb->i.lock.parent = kb32->i.lock.parent; + kb->i.lock.xid = kb32->i.lock.xid; + kb->i.lock.timeout = kb32->i.lock.timeout; kb->i.lock.castparam = (void *)(long )kb32->i.lock.castparam; kb->i.lock.castaddr = (void *)(long )kb32->i.lock.castaddr; kb->i.lock.bastparam = (void *)(long )kb32->i.lock.bastparam;
@@ -115,6 +119,10 @@static void compat_output (struct dlm_lock_result *res,struct dlm_lock_result32 *res32) { + res32->version[0 ] = res->version[0 ]; + res32->version[1 ] = res->version[1 ]; + res32->version[2 ] = res->version[2 ]; + res32->user_astaddr = (__u32 )(long )res->user_astaddr; res32->user_astparam = (__u32 )(long )res->user_astparam; res32->user_lksb = (__u32 )(long )res->user_lksb;
@@ -252,16 +260,18 @@ ua->castaddr = params->castaddr; ua->bastparam = params->bastparam; ua->bastaddr = params->bastaddr; + ua->xid = params->xid;if (params->flags &DLM_LKF_CONVERT ) error =dlm_user_convert (ls, ua, params->mode, params->flags, - params->lkid, params->lvb); + params->lkid, params->lvb, + (unsigned long ) params->timeout);else { error =dlm_user_request (ls, ua, params->mode, params->flags, params->name, params->namelen, - params->parent); + (unsigned long ) params->timeout);if (!error) error = ua->lksb.sb_lkid; }
@@ -641,6 +651,9 @@int struct_len;memset (&result,0 ,sizeof (struct dlm_lock_result )); + result.version[0 ] =DLM_DEVICE_VERSION_MAJOR ; + result.version[1 ] =DLM_DEVICE_VERSION_MINOR ; + result.version[2 ] =DLM_DEVICE_VERSION_PATCH ;memcpy (&result.lksb, &ua->lksb,sizeof (struct dlm_lksb )); result.user_lksb = ua->user_lksb;
@@ -699,6 +712,20 @@return error; } +static int copy_version_to_user (char __user *buf,size_t count) +{ +struct dlm_device_version ver; + +memset (&ver,0 ,sizeof (struct dlm_device_version )); + ver.version[0 ] =DLM_DEVICE_VERSION_MAJOR ; + ver.version[1 ] =DLM_DEVICE_VERSION_MINOR ; + ver.version[2 ] =DLM_DEVICE_VERSION_PATCH ; + +if (copy_to_user (buf, &ver,sizeof (struct dlm_device_version ))) +return -EFAULT ; +return sizeof (struct dlm_device_version ); +} +/* a read returns a single ast described in a struct dlm_lock_result */ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
@@ -710,6 +737,16 @@DECLARE_WAITQUEUE (wait, current);int error, type=0 , bmode=0 , removed =0 ; +if (count ==sizeof (struct dlm_device_version )) { + error =copy_version_to_user (buf, count); +return error; + } + +if (!proc) { +log_print ("non-version read from control device %zu" , count); +return -EINVAL ; + } +#ifdef CONFIG_COMPAT if (count <sizeof (struct dlm_lock_result32 )) #else
@@ -747,11 +784,6 @@ } } -if (list_empty (&proc->asts)) { -spin_unlock (&proc->asts_spin); -return -EAGAIN ; - } -/* there may be both completion and blocking asts to return for the lkb, don't remove lkb from asts list unless no asts remain */
@@ -823,6 +855,7 @@static const struct file_operations ctl_device_fops = { .open = ctl_device_open, .release = ctl_device_close, + .read = device_read, .write = device_write, .owner =THIS_MODULE , };
include/linux/dlm_device.h +15 -6
@@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions
@@ -18,21 +18,24 @@#define DLM_USER_LVB_LEN 32/* Version of the device interface */ -#define DLM_DEVICE_VERSION_MAJOR 5 -#define DLM_DEVICE_VERSION_MINOR 1 +#define DLM_DEVICE_VERSION_MAJOR 6 +#define DLM_DEVICE_VERSION_MINOR 0#define DLM_DEVICE_VERSION_PATCH 0/* struct passed to the lock write */ struct dlm_lock_params {__u8 mode;__u8 namelen; -__u16 flags; +__u16 unused; +__u32 flags;__u32 lkid;__u32 parent; -void __user *castparam; +__u64 xid; +__u64 timeout; +void __user *castparam;void __user *castaddr;void __user *bastparam; -void __user *bastaddr; +void __user *bastaddr;struct dlm_lksb __user *lksb;char lvb[DLM_USER_LVB_LEN ];char name[0 ];
@@ -62,9 +65,15 @@ } i; }; +struct dlm_device_version { +__u32 version[3 ]; +}; +/* struct read from the "device" fd, consists mainly of userspace pointers for the library to use */ +struct dlm_lock_result { +__u32 version[3 ];__u32 length;void __user * user_astaddr;void __user * user_astparam;
fs/dlm/dlm_internal.h +2 -0
@@ -151,6 +151,7 @@void *bastaddr;int mode;struct dlm_lksb *lksb; +unsigned long timeout; };
@@ -528,6 +529,7 @@void __user *castaddr;void __user *bastparam;void __user *bastaddr; +uint64_t xid; };#define DLM_PROC_FLAGS_CLOSING 1
fs/dlm/lock.c +13 -11
@@ -1098,6 +1098,8 @@ }if (do_cancel) { +log_debug ("timeout cancel %x node %d %s" , lkb->lkb_id, + lkb->lkb_nodeid, r->res_name); lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN ; lkb->lkb_flags |=DLM_IFL_TIMEOUT_CANCEL ;del_timeout (lkb);
@@ -1864,7 +1866,7 @@ }static int set_lock_args (int mode,struct dlm_lksb *lksb,uint32_t flags, -int namelen,uint32_t parent_lkid,void *ast, +int namelen,unsigned long timeout_cs,void *ast,void *astarg,void *bast,struct dlm_args *args) {int rv = -EINVAL ;
@@ -1907,10 +1909,6 @@if (flags &DLM_LKF_VALBLK && !lksb->sb_lvbptr) goto out; -/* parent/child locks not yet supported */ -if (parent_lkid) - goto out; -if (flags &DLM_LKF_CONVERT && !lksb->sb_lkid) goto out;
@@ -1922,6 +1920,7 @@ args->astaddr = ast; args->astparam = (long ) astarg; args->bastaddr = bast; + args->timeout = timeout_cs; args->mode = mode; args->lksb = lksb; rv =0 ;
@@ -1976,6 +1975,7 @@ lkb->lkb_lksb = args->lksb; lkb->lkb_lvbptr = args->lksb->sb_lvbptr; lkb->lkb_ownpid = (int ) current->pid; + lkb->lkb_timeout_cs = args->timeout; rv =0 ; out:return rv;
@@ -2423,7 +2423,7 @@if (error) goto out; - error =set_lock_args (mode, lksb, flags, namelen, parent_lkid, ast, + error =set_lock_args (mode, lksb, flags, namelen,0 , ast, astarg, bast, &args);if (error) goto out_put;
@@ -4175,7 +4175,7 @@int dlm_user_request (struct dlm_ls *ls,struct dlm_user_args *ua,int mode,uint32_t flags,void *name,unsigned int namelen, -uint32_t parent_lkid) +unsigned long timeout_cs) {struct dlm_lkb *lkb;struct dlm_args args;
@@ -4203,7 +4203,7 @@When DLM_IFL_USER is set, the dlm knows that this is a userspace lock and that lkb_astparam is the dlm_user_args structure. */ - error =set_lock_args (mode, &ua->lksb, flags, namelen, parent_lkid, + error =set_lock_args (mode, &ua->lksb, flags, namelen, timeout_cs,DLM_FAKE_USER_AST , ua,DLM_FAKE_USER_AST , &args); lkb->lkb_flags |=DLM_IFL_USER ; ua->old_mode =DLM_LOCK_IV ;
@@ -4240,7 +4240,8 @@ }int dlm_user_convert (struct dlm_ls *ls,struct dlm_user_args *ua_tmp, -int mode,uint32_t flags,uint32_t lkid,char *lvb_in) +int mode,uint32_t flags,uint32_t lkid,char *lvb_in, +unsigned long timeout_cs) {struct dlm_lkb *lkb;struct dlm_args args;
@@ -4268,6 +4269,7 @@if (lvb_in && ua->lksb.sb_lvbptr)memcpy (ua->lksb.sb_lvbptr, lvb_in,DLM_USER_LVB_LEN ); + ua->xid = ua_tmp->xid; ua->castparam = ua_tmp->castparam; ua->castaddr = ua_tmp->castaddr; ua->bastparam = ua_tmp->bastparam;
@@ -4275,8 +4277,8 @@ ua->user_lksb = ua_tmp->user_lksb; ua->old_mode = lkb->lkb_grmode; - error =set_lock_args (mode, &ua->lksb, flags,0 ,0 ,DLM_FAKE_USER_AST , - ua,DLM_FAKE_USER_AST , &args); + error =set_lock_args (mode, &ua->lksb, flags,0 , timeout_cs, +DLM_FAKE_USER_AST , ua,DLM_FAKE_USER_AST , &args);if (error) goto out_put;
fs/dlm/lock.h +4 -2
@@ -38,9 +38,11 @@int dlm_recover_process_copy (struct dlm_ls *ls,struct dlm_rcom *rc);int dlm_user_request (struct dlm_ls *ls,struct dlm_user_args *ua,int mode, -uint32_t flags,void *name,unsigned int namelen,uint32_t parent_lkid); +uint32_t flags,void *name,unsigned int namelen, +unsigned long timeout_cs);int dlm_user_convert (struct dlm_ls *ls,struct dlm_user_args *ua_tmp, -int mode,uint32_t flags,uint32_t lkid,char *lvb_in); +int mode,uint32_t flags,uint32_t lkid,char *lvb_in, +unsigned long timeout_cs);int dlm_user_unlock (struct dlm_ls *ls,struct dlm_user_args *ua_tmp,uint32_t flags,uint32_t lkid,char *lvb_in); int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,