[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;
int mode;
struct dlm_lksb *lksb;
unsigned long timeout;
};
@ -528,6 +529,7 @@ struct dlm_user_args {
void __user *castaddr;
void __user *bastparam;
void __user *bastaddr;
uint64_t xid;
};
#define DLM_PROC_FLAGS_CLOSING 1

View File

@ -1098,6 +1098,8 @@ void dlm_scan_timeout(struct dlm_ls *ls)
}
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 void confirm_master(struct dlm_rsb *r, int error)
}
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 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
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 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
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 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
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 @@ int dlm_lock(dlm_lockspace_t *lockspace,
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_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)
unsigned long timeout_cs)
{
struct dlm_lkb *lkb;
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
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_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 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 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
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 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
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;

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_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,

View File

@ -33,16 +33,17 @@ static const struct file_operations device_fops;
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_lksb32 {
};
struct dlm_lock_result32 {
__u32 version[3];
__u32 length;
__u32 user_astaddr;
__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.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_input(struct dlm_write_request *kb,
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 @@ static int device_user_lock(struct dlm_user_proc *proc,
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 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
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 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
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 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
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 @@ 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
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 = {
.open = ctl_device_open,
.release = ctl_device_close,
.read = device_read,
.write = device_write,
.owner = THIS_MODULE,
};

View File

@ -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 @@ struct dlm_write_request {
} 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;