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

Commit 40689ac4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull dlm updates from David Teigland:
 "There are two main patches in this set, both related to the userland
  dlm_controld daemon.

  The first fixes a deadlock between dlm_controld and the dlm_send
  workqueue when both access configfs data simultaneously.

  The second reworks some code to get around a long standing, but
  intentional, unlock balance warning.  The userland daemon no longer
  takes a lock that is later released from the kernel.

  The other commits are minor fixes and changes."

* tag 'dlm-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm:
  dlm: check the maximum size of a request from user
  dlm: cleanup send_to_sock routine
  dlm: convert add_sock routine return value type to void
  dlm: remove redundant variable assignments
  dlm: fix unlock balance warnings
  dlm: fix uninitialized spinlock
  dlm: fix deadlock between dlm_send and dlm_controld
parents cc150a28 2b75bc91
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
#include "user.h"

static uint64_t dlm_cb_seq;
static spinlock_t		dlm_cb_seq_spin;
static DEFINE_SPINLOCK(dlm_cb_seq_spin);

static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb)
{
+15 −64
Original line number Diff line number Diff line
@@ -750,6 +750,7 @@ static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
{
	struct sockaddr_storage *addr;
	int rv;

	if (len != sizeof(struct sockaddr_storage))
		return -EINVAL;
@@ -762,6 +763,13 @@ static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
		return -ENOMEM;

	memcpy(addr, buf, len);

	rv = dlm_lowcomms_addr(cm->nodeid, addr, len);
	if (rv) {
		kfree(addr);
		return rv;
	}

	cm->addr[cm->addr_count++] = addr;
	return len;
}
@@ -878,34 +886,7 @@ static void put_space(struct dlm_space *sp)
	config_item_put(&sp->group.cg_item);
}

static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y)
{
	switch (x->ss_family) {
	case AF_INET: {
		struct sockaddr_in *sinx = (struct sockaddr_in *)x;
		struct sockaddr_in *siny = (struct sockaddr_in *)y;
		if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr)
			return 0;
		if (sinx->sin_port != siny->sin_port)
			return 0;
		break;
	}
	case AF_INET6: {
		struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x;
		struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y;
		if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr))
			return 0;
		if (sinx->sin6_port != siny->sin6_port)
			return 0;
		break;
	}
	default:
		return 0;
	}
	return 1;
}

static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr)
static struct dlm_comm *get_comm(int nodeid)
{
	struct config_item *i;
	struct dlm_comm *cm = NULL;
@@ -919,19 +900,11 @@ static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr)
	list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
		cm = config_item_to_comm(i);

		if (nodeid) {
		if (cm->nodeid != nodeid)
			continue;
		found = 1;
		config_item_get(i);
		break;
		} else {
			if (!cm->addr_count || !addr_compare(cm->addr[0], addr))
				continue;
			found = 1;
			config_item_get(i);
			break;
		}
	}
	mutex_unlock(&clusters_root.subsys.su_mutex);

@@ -995,7 +968,7 @@ int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,

int dlm_comm_seq(int nodeid, uint32_t *seq)
{
	struct dlm_comm *cm = get_comm(nodeid, NULL);
	struct dlm_comm *cm = get_comm(nodeid);
	if (!cm)
		return -EEXIST;
	*seq = cm->seq;
@@ -1003,28 +976,6 @@ int dlm_comm_seq(int nodeid, uint32_t *seq)
	return 0;
}

int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr)
{
	struct dlm_comm *cm = get_comm(nodeid, NULL);
	if (!cm)
		return -EEXIST;
	if (!cm->addr_count)
		return -ENOENT;
	memcpy(addr, cm->addr[0], sizeof(*addr));
	put_comm(cm);
	return 0;
}

int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid)
{
	struct dlm_comm *cm = get_comm(0, addr);
	if (!cm)
		return -EEXIST;
	*nodeid = cm->nodeid;
	put_comm(cm);
	return 0;
}

int dlm_our_nodeid(void)
{
	return local_comm ? local_comm->nodeid : 0;
+0 −2
Original line number Diff line number Diff line
@@ -46,8 +46,6 @@ void dlm_config_exit(void);
int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
		     int *count_out);
int dlm_comm_seq(int nodeid, uint32_t *seq);
int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
int dlm_our_nodeid(void);
int dlm_our_addr(struct sockaddr_storage *addr, int num);

+36 −10
Original line number Diff line number Diff line
@@ -604,6 +604,7 @@ struct dlm_ls {
	struct idr		ls_recover_idr;
	spinlock_t		ls_recover_idr_lock;
	wait_queue_head_t	ls_wait_general;
	wait_queue_head_t	ls_recover_lock_wait;
	struct mutex		ls_clear_proc_locks;

	struct list_head	ls_root_list;	/* root resources */
@@ -616,15 +617,40 @@ struct dlm_ls {
	char			ls_name[1];
};

#define LSFL_WORK		0
#define LSFL_RUNNING		1
#define LSFL_RECOVERY_STOP	2
#define LSFL_RCOM_READY		3
#define LSFL_RCOM_WAIT		4
#define LSFL_UEVENT_WAIT	5
#define LSFL_TIMEWARN		6
#define LSFL_CB_DELAY		7
#define LSFL_NODIR		8
/*
 * LSFL_RECOVER_STOP - dlm_ls_stop() sets this to tell dlm recovery routines
 * that they should abort what they're doing so new recovery can be started.
 *
 * LSFL_RECOVER_DOWN - dlm_ls_stop() sets this to tell dlm_recoverd that it
 * should do down_write() on the in_recovery rw_semaphore. (doing down_write
 * within dlm_ls_stop causes complaints about the lock acquired/released
 * in different contexts.)
 *
 * LSFL_RECOVER_LOCK - dlm_recoverd holds the in_recovery rw_semaphore.
 * It sets this after it is done with down_write() on the in_recovery
 * rw_semaphore and clears it after it has released the rw_semaphore.
 *
 * LSFL_RECOVER_WORK - dlm_ls_start() sets this to tell dlm_recoverd that it
 * should begin recovery of the lockspace.
 *
 * LSFL_RUNNING - set when normal locking activity is enabled.
 * dlm_ls_stop() clears this to tell dlm locking routines that they should
 * quit what they are doing so recovery can run.  dlm_recoverd sets
 * this after recovery is finished.
 */

#define LSFL_RECOVER_STOP	0
#define LSFL_RECOVER_DOWN	1
#define LSFL_RECOVER_LOCK	2
#define LSFL_RECOVER_WORK	3
#define LSFL_RUNNING		4

#define LSFL_RCOM_READY		5
#define LSFL_RCOM_WAIT		6
#define LSFL_UEVENT_WAIT	7
#define LSFL_TIMEWARN		8
#define LSFL_CB_DELAY		9
#define LSFL_NODIR		10

/* much of this is just saving user space pointers associated with the
   lock that we pass back to the user lib with an ast */
@@ -667,7 +693,7 @@ static inline int dlm_locking_stopped(struct dlm_ls *ls)

static inline int dlm_recovery_stopped(struct dlm_ls *ls)
{
	return test_bit(LSFL_RECOVERY_STOP, &ls->ls_flags);
	return test_bit(LSFL_RECOVER_STOP, &ls->ls_flags);
}

static inline int dlm_no_directory(struct dlm_ls *ls)
+12 −3
Original line number Diff line number Diff line
@@ -582,8 +582,6 @@ static int new_lockspace(const char *name, const char *cluster,
	INIT_LIST_HEAD(&ls->ls_root_list);
	init_rwsem(&ls->ls_root_sem);

	down_write(&ls->ls_in_recovery);

	spin_lock(&lslist_lock);
	ls->ls_create_count = 1;
	list_add(&ls->ls_list, &lslist);
@@ -597,13 +595,24 @@ static int new_lockspace(const char *name, const char *cluster,
		}
	}

	/* needs to find ls in lslist */
	init_waitqueue_head(&ls->ls_recover_lock_wait);

	/*
	 * Once started, dlm_recoverd first looks for ls in lslist, then
	 * initializes ls_in_recovery as locked in "down" mode.  We need
	 * to wait for the wakeup from dlm_recoverd because in_recovery
	 * has to start out in down mode.
	 */

	error = dlm_recoverd_start(ls);
	if (error) {
		log_error(ls, "can't start dlm_recoverd %d", error);
		goto out_callback;
	}

	wait_event(ls->ls_recover_lock_wait,
		   test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags));

	ls->ls_kobj.kset = dlm_kset;
	error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
				     "%s", ls->ls_name);
Loading