Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[cascardo/linux.git] / fs / dlm / member.c
index cd0c51e..d099775 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -56,8 +56,10 @@ static int dlm_add_member(struct dlm_ls *ls, int nodeid)
                return -ENOMEM;
 
        w = dlm_node_weight(ls->ls_name, nodeid);
-       if (w < 0)
+       if (w < 0) {
+               kfree(memb);
                return w;
+       }
 
        memb->nodeid = nodeid;
        memb->weight = w;
@@ -162,11 +164,23 @@ static void make_member_array(struct dlm_ls *ls)
 
 /* send a status request to all members just to establish comms connections */
 
-static void ping_members(struct dlm_ls *ls)
+static int ping_members(struct dlm_ls *ls)
 {
        struct dlm_member *memb;
-       list_for_each_entry(memb, &ls->ls_nodes, list)
-               dlm_rcom_status(ls, memb->nodeid);
+       int error = 0;
+
+       list_for_each_entry(memb, &ls->ls_nodes, list) {
+               error = dlm_recovery_stopped(ls);
+               if (error)
+                       break;
+               error = dlm_rcom_status(ls, memb->nodeid);
+               if (error)
+                       break;
+       }
+       if (error)
+               log_debug(ls, "ping_members aborted %d last nodeid %d",
+                         error, ls->ls_recover_nodeid);
+       return error;
 }
 
 int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
@@ -174,6 +188,14 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
        struct dlm_member *memb, *safe;
        int i, error, found, pos = 0, neg = 0, low = -1;
 
+       /* previously removed members that we've not finished removing need to
+          count as a negative change so the "neg" recovery steps will happen */
+
+       list_for_each_entry(memb, &ls->ls_nodes_gone, list) {
+               log_debug(ls, "prev removed member %d", memb->nodeid);
+               neg++;
+       }
+
        /* move departed members from ls_nodes to ls_nodes_gone */
 
        list_for_each_entry_safe(memb, safe, &ls->ls_nodes, list) {
@@ -212,10 +234,19 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
        dlm_set_recover_status(ls, DLM_RS_NODES);
        *neg_out = neg;
 
-       ping_members(ls);
+       error = ping_members(ls);
+       if (!error || error == -EPROTO) {
+               /* new_lockspace() may be waiting to know if the config
+                  is good or bad */
+               ls->ls_members_result = error;
+               complete(&ls->ls_members_done);
+       }
+       if (error)
+               goto out;
 
        error = dlm_recover_members_wait(ls);
-       log_debug(ls, "total members %d", ls->ls_num_nodes);
+ out:
+       log_debug(ls, "total members %d error %d", ls->ls_num_nodes, error);
        return error;
 }
 
@@ -261,6 +292,9 @@ int dlm_ls_stop(struct dlm_ls *ls)
        dlm_recoverd_suspend(ls);
        ls->ls_recover_status = 0;
        dlm_recoverd_resume(ls);
+
+       if (!ls->ls_recover_begin)
+               ls->ls_recover_begin = jiffies;
        return 0;
 }