Skip to content

Commit

Permalink
Merge tag 'dlm-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/…
Browse files Browse the repository at this point in the history
…teigland/linux-dlm

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
  • Loading branch information
Linus Torvalds committed Oct 1, 2012
2 parents cc150a2 + 2b75bc9 commit 40689ac
Show file tree
Hide file tree
Showing 13 changed files with 289 additions and 130 deletions.
4 changes: 2 additions & 2 deletions fs/dlm/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
#include "lock.h"
#include "user.h"

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

static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb)
{
Expand Down
79 changes: 15 additions & 64 deletions fs/dlm/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
if (cm->nodeid != nodeid)
continue;
found = 1;
config_item_get(i);
break;
}
mutex_unlock(&clusters_root.subsys.su_mutex);

Expand Down Expand Up @@ -995,36 +968,14 @@ 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;
put_comm(cm);
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;
Expand Down
2 changes: 0 additions & 2 deletions fs/dlm/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
46 changes: 36 additions & 10 deletions fs/dlm/dlm_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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 */
Expand Down Expand Up @@ -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)
Expand Down
15 changes: 12 additions & 3 deletions fs/dlm/lockspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
Loading

0 comments on commit 40689ac

Please sign in to comment.