]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/ocfs2/dlm/dlmrecovery.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[karo-tx-linux.git] / fs / ocfs2 / dlm / dlmrecovery.c
index 0b5adca1b1787bbc09284255417979c0c13f3f32..fe29f7978f81a515519fde46b2c14aacb862b399 100644 (file)
@@ -537,7 +537,10 @@ master_here:
                /* success!  see if any other nodes need recovery */
                mlog(0, "DONE mastering recovery of %s:%u here(this=%u)!\n",
                     dlm->name, dlm->reco.dead_node, dlm->node_num);
-               dlm_reset_recovery(dlm);
+               spin_lock(&dlm->spinlock);
+               __dlm_reset_recovery(dlm);
+               dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE;
+               spin_unlock(&dlm->spinlock);
        }
        dlm_end_recovery(dlm);
 
@@ -695,6 +698,14 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
                if (all_nodes_done) {
                        int ret;
 
+                       /* Set this flag on recovery master to avoid
+                        * a new recovery for another dead node start
+                        * before the recovery is not done. That may
+                        * cause recovery hung.*/
+                       spin_lock(&dlm->spinlock);
+                       dlm->reco.state |= DLM_RECO_STATE_FINALIZE;
+                       spin_unlock(&dlm->spinlock);
+
                        /* all nodes are now in DLM_RECO_NODE_DATA_DONE state
                         * just send a finalize message to everyone and
                         * clean up */
@@ -1750,13 +1761,13 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
                                     struct dlm_migratable_lockres *mres)
 {
        struct dlm_migratable_lock *ml;
-       struct list_head *queue;
+       struct list_head *queue, *iter;
        struct list_head *tmpq = NULL;
        struct dlm_lock *newlock = NULL;
        struct dlm_lockstatus *lksb = NULL;
        int ret = 0;
        int i, j, bad;
-       struct dlm_lock *lock = NULL;
+       struct dlm_lock *lock;
        u8 from = O2NM_MAX_NODES;
        unsigned int added = 0;
        __be64 c;
@@ -1791,14 +1802,16 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
                        /* MIGRATION ONLY! */
                        BUG_ON(!(mres->flags & DLM_MRES_MIGRATION));
 
+                       lock = NULL;
                        spin_lock(&res->spinlock);
                        for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) {
                                tmpq = dlm_list_idx_to_ptr(res, j);
-                               list_for_each_entry(lock, tmpq, list) {
-                                       if (lock->ml.cookie != ml->cookie)
-                                               lock = NULL;
-                                       else
+                               list_for_each(iter, tmpq) {
+                                       lock = list_entry(iter,
+                                                 struct dlm_lock, list);
+                                       if (lock->ml.cookie == ml->cookie)
                                                break;
+                                       lock = NULL;
                                }
                                if (lock)
                                        break;
@@ -1886,6 +1899,13 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
                if (ml->type == LKM_NLMODE)
                        goto skip_lvb;
 
+               /*
+                * If the lock is in the blocked list it can't have a valid lvb,
+                * so skip it
+                */
+               if (ml->list == DLM_BLOCKED_LIST)
+                       goto skip_lvb;
+
                if (!dlm_lvb_is_empty(mres->lvb)) {
                        if (lksb->flags & DLM_LKSB_PUT_LVB) {
                                /* other node was trying to update
@@ -2875,8 +2895,8 @@ int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data,
                                BUG();
                        }
                        dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE;
+                       __dlm_reset_recovery(dlm);
                        spin_unlock(&dlm->spinlock);
-                       dlm_reset_recovery(dlm);
                        dlm_kick_recovery_thread(dlm);
                        break;
                default: