Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7db923e authored by David Teigland's avatar David Teigland Committed by Steven Whitehouse
Browse files

[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: default avatarDavid Teigland <teigland@redhat.com>
Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent 3ae1acf9
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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
+13 −11
Original line number Original line Diff line number Diff line
@@ -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;


+4 −2
Original line number Original line Diff line number Diff line
@@ -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,
+43 −10
Original line number Original line Diff line number Diff line
@@ -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,
};
};
+15 −6
Original line number Original line Diff line number Diff line
@@ -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,17 +18,20 @@
#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;
	__u64 xid;
	__u64 timeout;
	void __user *castparam;
	void __user *castparam;
	void __user *castaddr;
	void __user *castaddr;
	void __user *bastparam;
	void __user *bastparam;
@@ -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;