[DLM] dlm_device interface changes [3/6]

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 <teigland@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
David Teigland 2007-05-18 09:00:32 -05:00 committed by Steven Whitehouse
parent 3ae1acf93a
commit d7db923ea4
5 changed files with 77 additions and 29 deletions

View File

@ -151,6 +151,7 @@ struct dlm_args {
void *bastaddr; void *bastaddr;
int mode; int mode;
struct dlm_lksb *lksb; struct dlm_lksb *lksb;
unsigned long timeout;
}; };
@ -528,6 +529,7 @@ struct dlm_user_args {
void __user *castaddr; void __user *castaddr;
void __user *bastparam; void __user *bastparam;
void __user *bastaddr; void __user *bastaddr;
uint64_t xid;
}; };
#define DLM_PROC_FLAGS_CLOSING 1 #define DLM_PROC_FLAGS_CLOSING 1

View File

@ -1098,6 +1098,8 @@ void dlm_scan_timeout(struct dlm_ls *ls)
} }
if (do_cancel) { 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_WATCH_TIMEWARN;
lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL; lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL;
del_timeout(lkb); del_timeout(lkb);
@ -1864,7 +1866,7 @@ static void confirm_master(struct dlm_rsb *r, int error)
} }
static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, 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) void *astarg, void *bast, struct dlm_args *args)
{ {
int rv = -EINVAL; int rv = -EINVAL;
@ -1907,10 +1909,6 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr) if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr)
goto out; goto out;
/* parent/child locks not yet supported */
if (parent_lkid)
goto out;
if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid) if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid)
goto out; goto out;
@ -1922,6 +1920,7 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
args->astaddr = ast; args->astaddr = ast;
args->astparam = (long) astarg; args->astparam = (long) astarg;
args->bastaddr = bast; args->bastaddr = bast;
args->timeout = timeout_cs;
args->mode = mode; args->mode = mode;
args->lksb = lksb; args->lksb = lksb;
rv = 0; rv = 0;
@ -1976,6 +1975,7 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
lkb->lkb_lksb = args->lksb; lkb->lkb_lksb = args->lksb;
lkb->lkb_lvbptr = args->lksb->sb_lvbptr; lkb->lkb_lvbptr = args->lksb->sb_lvbptr;
lkb->lkb_ownpid = (int) current->pid; lkb->lkb_ownpid = (int) current->pid;
lkb->lkb_timeout_cs = args->timeout;
rv = 0; rv = 0;
out: out:
return rv; return rv;
@ -2423,7 +2423,7 @@ int dlm_lock(dlm_lockspace_t *lockspace,
if (error) if (error)
goto out; 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); astarg, bast, &args);
if (error) if (error)
goto out_put; goto out_put;
@ -4175,7 +4175,7 @@ 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 dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
int mode, uint32_t flags, void *name, unsigned int namelen, int mode, uint32_t flags, void *name, unsigned int namelen,
uint32_t parent_lkid) unsigned long timeout_cs)
{ {
struct dlm_lkb *lkb; struct dlm_lkb *lkb;
struct dlm_args args; struct dlm_args args;
@ -4203,7 +4203,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
When DLM_IFL_USER is set, the dlm knows that this is a userspace 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. */ 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); DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
lkb->lkb_flags |= DLM_IFL_USER; lkb->lkb_flags |= DLM_IFL_USER;
ua->old_mode = DLM_LOCK_IV; ua->old_mode = DLM_LOCK_IV;
@ -4240,7 +4240,8 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
} }
int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 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_lkb *lkb;
struct dlm_args args; struct dlm_args args;
@ -4268,6 +4269,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
if (lvb_in && ua->lksb.sb_lvbptr) if (lvb_in && ua->lksb.sb_lvbptr)
memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN);
ua->xid = ua_tmp->xid;
ua->castparam = ua_tmp->castparam; ua->castparam = ua_tmp->castparam;
ua->castaddr = ua_tmp->castaddr; ua->castaddr = ua_tmp->castaddr;
ua->bastparam = ua_tmp->bastparam; ua->bastparam = ua_tmp->bastparam;
@ -4275,8 +4277,8 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
ua->user_lksb = ua_tmp->user_lksb; ua->user_lksb = ua_tmp->user_lksb;
ua->old_mode = lkb->lkb_grmode; ua->old_mode = lkb->lkb_grmode;
error = set_lock_args(mode, &ua->lksb, flags, 0, 0, DLM_FAKE_USER_AST, error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs,
ua, DLM_FAKE_USER_AST, &args); DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
if (error) if (error)
goto out_put; goto out_put;

View File

@ -38,9 +38,11 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc); 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, 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 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, int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
uint32_t flags, uint32_t lkid, char *lvb_in); uint32_t flags, uint32_t lkid, char *lvb_in);
int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,

View File

@ -33,16 +33,17 @@ static const struct file_operations device_fops;
struct dlm_lock_params32 { struct dlm_lock_params32 {
__u8 mode; __u8 mode;
__u8 namelen; __u8 namelen;
__u16 flags; __u16 unused;
__u32 flags;
__u32 lkid; __u32 lkid;
__u32 parent; __u32 parent;
__u64 xid;
__u64 timeout;
__u32 castparam; __u32 castparam;
__u32 castaddr; __u32 castaddr;
__u32 bastparam; __u32 bastparam;
__u32 bastaddr; __u32 bastaddr;
__u32 lksb; __u32 lksb;
char lvb[DLM_USER_LVB_LEN]; char lvb[DLM_USER_LVB_LEN];
char name[0]; char name[0];
}; };
@ -68,6 +69,7 @@ struct dlm_lksb32 {
}; };
struct dlm_lock_result32 { struct dlm_lock_result32 {
__u32 version[3];
__u32 length; __u32 length;
__u32 user_astaddr; __u32 user_astaddr;
__u32 user_astparam; __u32 user_astparam;
@ -102,6 +104,8 @@ static void compat_input(struct dlm_write_request *kb,
kb->i.lock.flags = kb32->i.lock.flags; kb->i.lock.flags = kb32->i.lock.flags;
kb->i.lock.lkid = kb32->i.lock.lkid; kb->i.lock.lkid = kb32->i.lock.lkid;
kb->i.lock.parent = kb32->i.lock.parent; 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.castparam = (void *)(long)kb32->i.lock.castparam;
kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr; kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam; kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
@ -115,6 +119,10 @@ static void compat_input(struct dlm_write_request *kb,
static void compat_output(struct dlm_lock_result *res, static void compat_output(struct dlm_lock_result *res,
struct dlm_lock_result32 *res32) 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_astaddr = (__u32)(long)res->user_astaddr;
res32->user_astparam = (__u32)(long)res->user_astparam; res32->user_astparam = (__u32)(long)res->user_astparam;
res32->user_lksb = (__u32)(long)res->user_lksb; res32->user_lksb = (__u32)(long)res->user_lksb;
@ -252,16 +260,18 @@ static int device_user_lock(struct dlm_user_proc *proc,
ua->castaddr = params->castaddr; ua->castaddr = params->castaddr;
ua->bastparam = params->bastparam; ua->bastparam = params->bastparam;
ua->bastaddr = params->bastaddr; ua->bastaddr = params->bastaddr;
ua->xid = params->xid;
if (params->flags & DLM_LKF_CONVERT) if (params->flags & DLM_LKF_CONVERT)
error = dlm_user_convert(ls, ua, error = dlm_user_convert(ls, ua,
params->mode, params->flags, params->mode, params->flags,
params->lkid, params->lvb); params->lkid, params->lvb,
(unsigned long) params->timeout);
else { else {
error = dlm_user_request(ls, ua, error = dlm_user_request(ls, ua,
params->mode, params->flags, params->mode, params->flags,
params->name, params->namelen, params->name, params->namelen,
params->parent); (unsigned long) params->timeout);
if (!error) if (!error)
error = ua->lksb.sb_lkid; error = ua->lksb.sb_lkid;
} }
@ -641,6 +651,9 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
int struct_len; int struct_len;
memset(&result, 0, sizeof(struct dlm_lock_result)); 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)); memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
result.user_lksb = ua->user_lksb; result.user_lksb = ua->user_lksb;
@ -699,6 +712,20 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
return error; 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 */ /* 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, static ssize_t device_read(struct file *file, char __user *buf, size_t count,
@ -710,6 +737,16 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int error, type=0, bmode=0, removed = 0; 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 #ifdef CONFIG_COMPAT
if (count < sizeof(struct dlm_lock_result32)) if (count < sizeof(struct dlm_lock_result32))
#else #else
@ -747,11 +784,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
} }
} }
if (list_empty(&proc->asts)) {
spin_unlock(&proc->asts_spin);
return -EAGAIN;
}
/* there may be both completion and blocking asts to return for /* there may be both completion and blocking asts to return for
the lkb, don't remove lkb from asts list unless no asts remain */ the lkb, don't remove lkb from asts list unless no asts remain */
@ -823,6 +855,7 @@ static const struct file_operations device_fops = {
static const struct file_operations ctl_device_fops = { static const struct file_operations ctl_device_fops = {
.open = ctl_device_open, .open = ctl_device_open,
.release = ctl_device_close, .release = ctl_device_close,
.read = device_read,
.write = device_write, .write = device_write,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };

View File

@ -2,7 +2,7 @@
******************************************************************************* *******************************************************************************
** **
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. ** 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, ** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions ** modify, copy, or redistribute it subject to the terms and conditions
@ -18,21 +18,24 @@
#define DLM_USER_LVB_LEN 32 #define DLM_USER_LVB_LEN 32
/* Version of the device interface */ /* Version of the device interface */
#define DLM_DEVICE_VERSION_MAJOR 5 #define DLM_DEVICE_VERSION_MAJOR 6
#define DLM_DEVICE_VERSION_MINOR 1 #define DLM_DEVICE_VERSION_MINOR 0
#define DLM_DEVICE_VERSION_PATCH 0 #define DLM_DEVICE_VERSION_PATCH 0
/* struct passed to the lock write */ /* struct passed to the lock write */
struct dlm_lock_params { struct dlm_lock_params {
__u8 mode; __u8 mode;
__u8 namelen; __u8 namelen;
__u16 flags; __u16 unused;
__u32 flags;
__u32 lkid; __u32 lkid;
__u32 parent; __u32 parent;
void __user *castparam; __u64 xid;
__u64 timeout;
void __user *castparam;
void __user *castaddr; void __user *castaddr;
void __user *bastparam; void __user *bastparam;
void __user *bastaddr; void __user *bastaddr;
struct dlm_lksb __user *lksb; struct dlm_lksb __user *lksb;
char lvb[DLM_USER_LVB_LEN]; char lvb[DLM_USER_LVB_LEN];
char name[0]; char name[0];
@ -62,9 +65,15 @@ struct dlm_write_request {
} i; } i;
}; };
struct dlm_device_version {
__u32 version[3];
};
/* struct read from the "device" fd, /* struct read from the "device" fd,
consists mainly of userspace pointers for the library to use */ consists mainly of userspace pointers for the library to use */
struct dlm_lock_result { struct dlm_lock_result {
__u32 version[3];
__u32 length; __u32 length;
void __user * user_astaddr; void __user * user_astaddr;
void __user * user_astparam; void __user * user_astparam;