diff options
author | David Teigland <teigland@redhat.com> | 2008-03-18 14:22:11 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2008-04-21 11:18:01 -0500 |
commit | d44e0fc704143624b3e88fbf8fbcfda7a83fd299 (patch) | |
tree | af6c5a5c6ae179051caf725e46f11ff8e2f0f7c8 /fs/dlm/config.c | |
parent | 761b9d3ffc953c24ceb55d8e12ff7e02b17e0484 (diff) | |
download | op-kernel-dev-d44e0fc704143624b3e88fbf8fbcfda7a83fd299.zip op-kernel-dev-d44e0fc704143624b3e88fbf8fbcfda7a83fd299.tar.gz |
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>
Diffstat (limited to 'fs/dlm/config.c')
-rw-r--r-- | fs/dlm/config.c | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 7ceaea3..eac23bd 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -284,6 +284,7 @@ struct node { struct list_head list; /* space->members */ int nodeid; int weight; + int new; }; 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); nd->nodeid = -1; 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); list_add(&nd->list, &sp->members); @@ -805,12 +807,13 @@ static void put_comm(struct comm *cm) } /* 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 node *nd; - int i = 0, rv = 0; - int *ids; + int i = 0, rv = 0, ids_count = 0, new_count = 0; + int *ids, *new; sp = get_space(lsname); if (!sp) @@ -818,23 +821,50 @@ int dlm_nodeid_list(char *lsname, int **ids_out) mutex_lock(&sp->members_lock); if (!sp->members_count) { - rv = 0; + rv = -EINVAL; + printk(KERN_ERR "dlm: zero members_count\n"); 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) { rv = -ENOMEM; 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; + if (nd->new) + new_count++; + } + + if (ids_count != 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; + } - if (rv != i) - printk("bad nodeid count %d %d\n", rv, i); + 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; out: mutex_unlock(&sp->members_lock); |