dlm: recover nodes that are removed and re-added
If a node is removed from a lockspace, and then added back before the dlm is notified of the removal, the dlm will not detect the removal and won't clear the old state from the node. This is fixed by using a list of added nodes so the membership recovery can detect when a newly added node is already in the member list. Signed-off-by: David Teigland <teigland@redhat.com>
This commit is contained in:
Родитель
761b9d3ffc
Коммит
d44e0fc704
|
@ -284,6 +284,7 @@ struct node {
|
||||||
struct list_head list; /* space->members */
|
struct list_head list; /* space->members */
|
||||||
int nodeid;
|
int nodeid;
|
||||||
int weight;
|
int weight;
|
||||||
|
int new;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct configfs_group_operations clusters_ops = {
|
static struct configfs_group_operations clusters_ops = {
|
||||||
|
@ -565,6 +566,7 @@ static struct config_item *make_node(struct config_group *g, const char *name)
|
||||||
config_item_init_type_name(&nd->item, name, &node_type);
|
config_item_init_type_name(&nd->item, name, &node_type);
|
||||||
nd->nodeid = -1;
|
nd->nodeid = -1;
|
||||||
nd->weight = 1; /* default weight of 1 if none is set */
|
nd->weight = 1; /* default weight of 1 if none is set */
|
||||||
|
nd->new = 1; /* set to 0 once it's been read by dlm_nodeid_list() */
|
||||||
|
|
||||||
mutex_lock(&sp->members_lock);
|
mutex_lock(&sp->members_lock);
|
||||||
list_add(&nd->list, &sp->members);
|
list_add(&nd->list, &sp->members);
|
||||||
|
@ -805,12 +807,13 @@ static void put_comm(struct comm *cm)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* caller must free mem */
|
/* caller must free mem */
|
||||||
int dlm_nodeid_list(char *lsname, int **ids_out)
|
int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
|
||||||
|
int **new_out, int *new_count_out)
|
||||||
{
|
{
|
||||||
struct space *sp;
|
struct space *sp;
|
||||||
struct node *nd;
|
struct node *nd;
|
||||||
int i = 0, rv = 0;
|
int i = 0, rv = 0, ids_count = 0, new_count = 0;
|
||||||
int *ids;
|
int *ids, *new;
|
||||||
|
|
||||||
sp = get_space(lsname);
|
sp = get_space(lsname);
|
||||||
if (!sp)
|
if (!sp)
|
||||||
|
@ -818,23 +821,50 @@ int dlm_nodeid_list(char *lsname, int **ids_out)
|
||||||
|
|
||||||
mutex_lock(&sp->members_lock);
|
mutex_lock(&sp->members_lock);
|
||||||
if (!sp->members_count) {
|
if (!sp->members_count) {
|
||||||
rv = 0;
|
rv = -EINVAL;
|
||||||
|
printk(KERN_ERR "dlm: zero members_count\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ids = kcalloc(sp->members_count, sizeof(int), GFP_KERNEL);
|
ids_count = sp->members_count;
|
||||||
|
|
||||||
|
ids = kcalloc(ids_count, sizeof(int), GFP_KERNEL);
|
||||||
if (!ids) {
|
if (!ids) {
|
||||||
rv = -ENOMEM;
|
rv = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = sp->members_count;
|
list_for_each_entry(nd, &sp->members, list) {
|
||||||
list_for_each_entry(nd, &sp->members, list)
|
|
||||||
ids[i++] = nd->nodeid;
|
ids[i++] = nd->nodeid;
|
||||||
|
if (nd->new)
|
||||||
|
new_count++;
|
||||||
|
}
|
||||||
|
|
||||||
if (rv != i)
|
if (ids_count != i)
|
||||||
printk("bad nodeid count %d %d\n", rv, i);
|
printk(KERN_ERR "dlm: bad nodeid count %d %d\n", ids_count, i);
|
||||||
|
|
||||||
|
if (!new_count)
|
||||||
|
goto out_ids;
|
||||||
|
|
||||||
|
new = kcalloc(new_count, sizeof(int), GFP_KERNEL);
|
||||||
|
if (!new) {
|
||||||
|
kfree(ids);
|
||||||
|
rv = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
list_for_each_entry(nd, &sp->members, list) {
|
||||||
|
if (nd->new) {
|
||||||
|
new[i++] = nd->nodeid;
|
||||||
|
nd->new = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*new_count_out = new_count;
|
||||||
|
*new_out = new;
|
||||||
|
|
||||||
|
out_ids:
|
||||||
|
*ids_count_out = ids_count;
|
||||||
*ids_out = ids;
|
*ids_out = ids;
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&sp->members_lock);
|
mutex_unlock(&sp->members_lock);
|
||||||
|
|
|
@ -35,7 +35,8 @@ extern struct dlm_config_info dlm_config;
|
||||||
int dlm_config_init(void);
|
int dlm_config_init(void);
|
||||||
void dlm_config_exit(void);
|
void dlm_config_exit(void);
|
||||||
int dlm_node_weight(char *lsname, int nodeid);
|
int dlm_node_weight(char *lsname, int nodeid);
|
||||||
int dlm_nodeid_list(char *lsname, int **ids_out);
|
int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
|
||||||
|
int **new_out, int *new_count_out);
|
||||||
int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
|
int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
|
||||||
int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
|
int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
|
||||||
int dlm_our_nodeid(void);
|
int dlm_our_nodeid(void);
|
||||||
|
|
|
@ -133,8 +133,10 @@ struct dlm_member {
|
||||||
|
|
||||||
struct dlm_recover {
|
struct dlm_recover {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
int *nodeids;
|
int *nodeids; /* nodeids of all members */
|
||||||
int node_count;
|
int node_count;
|
||||||
|
int *new; /* nodeids of new members */
|
||||||
|
int new_count;
|
||||||
uint64_t seq;
|
uint64_t seq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,23 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add an entry to ls_nodes_gone for members that were removed and
|
||||||
|
then added again, so that previous state for these nodes will be
|
||||||
|
cleared during recovery. */
|
||||||
|
|
||||||
|
for (i = 0; i < rv->new_count; i++) {
|
||||||
|
if (!dlm_is_member(ls, rv->new[i]))
|
||||||
|
continue;
|
||||||
|
log_debug(ls, "new nodeid %d is a re-added member", rv->new[i]);
|
||||||
|
|
||||||
|
memb = kzalloc(sizeof(struct dlm_member), GFP_KERNEL);
|
||||||
|
if (!memb)
|
||||||
|
return -ENOMEM;
|
||||||
|
memb->nodeid = rv->new[i];
|
||||||
|
list_add_tail(&memb->list, &ls->ls_nodes_gone);
|
||||||
|
neg++;
|
||||||
|
}
|
||||||
|
|
||||||
/* add new members to ls_nodes */
|
/* add new members to ls_nodes */
|
||||||
|
|
||||||
for (i = 0; i < rv->node_count; i++) {
|
for (i = 0; i < rv->node_count; i++) {
|
||||||
|
@ -314,15 +331,16 @@ int dlm_ls_stop(struct dlm_ls *ls)
|
||||||
int dlm_ls_start(struct dlm_ls *ls)
|
int dlm_ls_start(struct dlm_ls *ls)
|
||||||
{
|
{
|
||||||
struct dlm_recover *rv = NULL, *rv_old;
|
struct dlm_recover *rv = NULL, *rv_old;
|
||||||
int *ids = NULL;
|
int *ids = NULL, *new = NULL;
|
||||||
int error, count;
|
int error, ids_count = 0, new_count = 0;
|
||||||
|
|
||||||
rv = kzalloc(sizeof(struct dlm_recover), GFP_KERNEL);
|
rv = kzalloc(sizeof(struct dlm_recover), GFP_KERNEL);
|
||||||
if (!rv)
|
if (!rv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
error = count = dlm_nodeid_list(ls->ls_name, &ids);
|
error = dlm_nodeid_list(ls->ls_name, &ids, &ids_count,
|
||||||
if (error <= 0)
|
&new, &new_count);
|
||||||
|
if (error < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
spin_lock(&ls->ls_recover_lock);
|
spin_lock(&ls->ls_recover_lock);
|
||||||
|
@ -337,14 +355,19 @@ int dlm_ls_start(struct dlm_ls *ls)
|
||||||
}
|
}
|
||||||
|
|
||||||
rv->nodeids = ids;
|
rv->nodeids = ids;
|
||||||
rv->node_count = count;
|
rv->node_count = ids_count;
|
||||||
|
rv->new = new;
|
||||||
|
rv->new_count = new_count;
|
||||||
rv->seq = ++ls->ls_recover_seq;
|
rv->seq = ++ls->ls_recover_seq;
|
||||||
rv_old = ls->ls_recover_args;
|
rv_old = ls->ls_recover_args;
|
||||||
ls->ls_recover_args = rv;
|
ls->ls_recover_args = rv;
|
||||||
spin_unlock(&ls->ls_recover_lock);
|
spin_unlock(&ls->ls_recover_lock);
|
||||||
|
|
||||||
if (rv_old) {
|
if (rv_old) {
|
||||||
|
log_error(ls, "unused recovery %llx %d",
|
||||||
|
(unsigned long long)rv_old->seq, rv_old->node_count);
|
||||||
kfree(rv_old->nodeids);
|
kfree(rv_old->nodeids);
|
||||||
|
kfree(rv_old->new);
|
||||||
kfree(rv_old);
|
kfree(rv_old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,6 +377,7 @@ int dlm_ls_start(struct dlm_ls *ls)
|
||||||
fail:
|
fail:
|
||||||
kfree(rv);
|
kfree(rv);
|
||||||
kfree(ids);
|
kfree(ids);
|
||||||
|
kfree(new);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -257,6 +257,7 @@ static void do_ls_recovery(struct dlm_ls *ls)
|
||||||
if (rv) {
|
if (rv) {
|
||||||
ls_recover(ls, rv);
|
ls_recover(ls, rv);
|
||||||
kfree(rv->nodeids);
|
kfree(rv->nodeids);
|
||||||
|
kfree(rv->new);
|
||||||
kfree(rv);
|
kfree(rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче