Whamcloud - gitweb
- many gcc4 compilation fixes (warnings)
[fs/lustre-release.git] / lustre / ptlrpc / recover.c
index 76469cb..6bf1d35 100644 (file)
@@ -54,7 +54,7 @@ void ptlrpc_run_recovery_over_upcall(struct obd_device *obd)
 
         argv[0] = obd_lustre_upcall;
         argv[1] = "RECOVERY_OVER";
-        argv[2] = obd->obd_uuid.uuid;
+        argv[2] = (char *)obd->obd_uuid.uuid;
         argv[3] = NULL;
         
         envp[0] = "HOME=/";
@@ -68,8 +68,8 @@ void ptlrpc_run_recovery_over_upcall(struct obd_device *obd)
                        argv[0], argv[1], argv[2], rc);
 
         } else {
-                CERROR("Invoked upcall %s %s %s\n",
-                       argv[0], argv[1], argv[2]);
+                CWARN("Invoked upcall %s %s %s\n",
+                      argv[0], argv[1], argv[2]);
         }
 }
 
@@ -92,10 +92,10 @@ void ptlrpc_run_failed_import_upcall(struct obd_import* imp)
         
         argv[0] = obd_lustre_upcall;
         argv[1] = "FAILED_IMPORT";
-        argv[2] = imp->imp_target_uuid.uuid;
+        argv[2] = (char *)imp->imp_target_uuid.uuid;
         argv[3] = imp->imp_obd->obd_name;
-        argv[4] = imp->imp_connection->c_remote_uuid.uuid;
-        argv[5] = imp->imp_obd->obd_uuid.uuid;
+        argv[4] = (char *)imp->imp_connection->c_remote_uuid.uuid;
+        argv[5] = (char *)imp->imp_obd->obd_uuid.uuid;
         argv[6] = NULL;
 
         envp[0] = "HOME=/";
@@ -105,12 +105,12 @@ void ptlrpc_run_failed_import_upcall(struct obd_import* imp)
         rc = USERMODEHELPER(argv[0], argv, envp);
         if (rc < 0) {
                 CERROR("Error invoking recovery upcall %s %s %s %s %s: %d; "
-                       "check /proc/sys/lustre/lustre_upcall\n",
+                       "check /proc/sys/lustre/upcall\n",
                        argv[0], argv[1], argv[2], argv[3], argv[4],rc);
 
         } else {
-                CERROR("Invoked upcall %s %s %s %s %s\n",
-                       argv[0], argv[1], argv[2], argv[3], argv[4]);
+                CWARN("Invoked upcall %s %s %s %s %s\n",
+                      argv[0], argv[1], argv[2], argv[3], argv[4]);
         }
 #else
         if (imp->imp_state == LUSTRE_IMP_CLOSED) {
@@ -121,16 +121,43 @@ void ptlrpc_run_failed_import_upcall(struct obd_import* imp)
 #endif
 }
 
-int ptlrpc_replay_next(struct obd_import *imp)
+/* This might block waiting for the upcall to start, so it should
+ * not be called from a thread that shouldn't block. (Like ptlrpcd) */
+void ptlrpc_initiate_recovery(struct obd_import *imp)
+{
+        ENTRY;
+
+        LASSERT (obd_lustre_upcall != NULL);
+        
+        if (strcmp(obd_lustre_upcall, "DEFAULT") == 0) {
+                CDEBUG(D_HA, "%s: starting recovery without upcall\n",
+                        imp->imp_target_uuid.uuid);
+                ptlrpc_connect_import(imp, NULL);
+        } 
+        else if (strcmp(obd_lustre_upcall, "NONE") == 0) {
+                CDEBUG(D_HA, "%s: recovery disabled\n",
+                        imp->imp_target_uuid.uuid);
+        } 
+        else {
+                CDEBUG(D_HA, "%s: calling upcall to start recovery\n",
+                        imp->imp_target_uuid.uuid);
+                ptlrpc_run_failed_import_upcall(imp);
+        }
+
+        EXIT;
+}
+
+int ptlrpc_replay_next(struct obd_import *imp, int *inflight)
 {
         int rc = 0;
         struct list_head *tmp, *pos;
-        struct ptlrpc_request *req;
+        struct ptlrpc_request *req = NULL;
         unsigned long flags;
         __u64 last_transno;
-        int sent_req = 0;
         ENTRY;
 
+        *inflight = 0;
+
         /* It might have committed some after we last spoke, so make sure we
          * get rid of them now.
          */
@@ -139,8 +166,10 @@ int ptlrpc_replay_next(struct obd_import *imp)
         last_transno = imp->imp_last_replay_transno;
         spin_unlock_irqrestore(&imp->imp_lock, flags);
 
-        CDEBUG(D_HA, "import %p from %s has committed "LPD64"\n",
-               imp, imp->imp_target_uuid.uuid, imp->imp_peer_committed_transno);
+        CDEBUG(D_HA, "import %p from %s committed "LPU64" last "LPU64"\n",
+               imp, imp->imp_target_uuid.uuid, imp->imp_peer_committed_transno,
+               last_transno);
+
         /* Do I need to hold a lock across this iteration?  We shouldn't be
          * racing with any additions to the list, because we're in recovery
          * and are therefore not processing additional requests to add.  Calls
@@ -158,26 +187,37 @@ int ptlrpc_replay_next(struct obd_import *imp)
          */
         list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
                 req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
+
+                /* If need to resend, stop on the matching one first. It's 
+                   possible though it's already been committed, so in that case 
+                   we'll just continue with replay */
+                if (imp->imp_resend_replay && 
+                    req->rq_transno == last_transno) {
+                        lustre_msg_add_flags(req->rq_reqmsg, MSG_RESENT);
+                        break;
+                }
+
                 if (req->rq_transno > last_transno) {
-                        /* remove from list so ptlrpcd can send the
-                           req, it should be reinserted after it is
-                           sent and replied.  Perhaps better solution
-                           would be to add req->rq_replay_list so the
-                           req can be saved for replay and still go
-                           through the normal send thread. */
-                        rc = ptlrpc_replay_req(req);
-                        if (rc) {
-                                CERROR("recovery replay error %d for req "LPD64"\n",
-                                       rc, req->rq_xid);
-                                RETURN(rc);
-                        }
-                        sent_req = 1;
+                        imp->imp_last_replay_transno = req->rq_transno;
                         break;
                 }
 
+                req = NULL;
         }
 
-        RETURN(sent_req);
+        imp->imp_resend_replay = 0;
+
+        if (req != NULL) {
+                rc = ptlrpc_replay_req(req);
+                if (rc) {
+                        CERROR("recovery replay error %d for req "
+                               LPD64"\n", rc, req->rq_xid);
+                        RETURN(rc);
+                }
+                imp->imp_reqs_replayed++;
+                *inflight = 1;
+        }
+        RETURN(rc);
 }
 
 int ptlrpc_resend(struct obd_import *imp)
@@ -225,35 +265,6 @@ void ptlrpc_wake_delayed(struct obd_import *imp)
         spin_unlock_irqrestore(&imp->imp_lock, flags);
 }
 
-inline void ptlrpc_invalidate_import_state(struct obd_import *imp)
-{
-        struct obd_device *obd = imp->imp_obd;
-        struct ldlm_namespace *ns = obd->obd_namespace;
-
-        ptlrpc_abort_inflight(imp);
-
-        obd_invalidate_import(obd, imp);
-
-        ldlm_namespace_cleanup(ns, LDLM_FL_LOCAL_ONLY);
-}
-
-void ptlrpc_handle_failed_import(struct obd_import *imp)
-{
-        ENTRY;
-
-        if (!imp->imp_replayable) {
-                CDEBUG(D_HA,
-                       "import %s@%s for %s not replayable, deactivating\n",
-                       imp->imp_target_uuid.uuid,
-                       imp->imp_connection->c_remote_uuid.uuid,
-                       imp->imp_obd->obd_name);
-                ptlrpc_set_import_active(imp, 0);
-        }
-
-        ptlrpc_run_failed_import_upcall(imp);
-        EXIT;
-}
-
 void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req)
 {
         int rc;
@@ -266,67 +277,67 @@ void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req)
                imp->imp_target_uuid.uuid,
                imp->imp_connection->c_remote_uuid.uuid);
         
-        ptlrpc_set_import_discon(imp);
+        if (ptlrpc_set_import_discon(imp)) {
+                if (!imp->imp_replayable) {
+                        CDEBUG(D_HA, "import %s@%s for %s not replayable, "
+                               "auto-deactivating\n",
+                               imp->imp_target_uuid.uuid,
+                               imp->imp_connection->c_remote_uuid.uuid,
+                               imp->imp_obd->obd_name);
+                        ptlrpc_deactivate_import(imp);
+                }
+
+                /* to control recovery via lctl {disable|enable}_recovery */
+                if (imp->imp_deactive == 0)
+                        rc = ptlrpc_connect_import(imp, NULL);
+        }
 
-        rc = ptlrpc_connect_import(imp, NULL);
-        
         /* Wait for recovery to complete and resend. If evicted, then
            this request will be errored out later.*/
         spin_lock_irqsave(&failed_req->rq_lock, flags);
-        if (!failed_req->rq_no_resend)
-                failed_req->rq_resend = 1;
+        failed_req->rq_resend = 1;
         spin_unlock_irqrestore(&failed_req->rq_lock, flags);
-        
+
         EXIT;
 }
 
+/*
+ * This should only be called by the ioctl interface, currently
+ * with the lctl deactivate and activate commands.
+ */
 int ptlrpc_set_import_active(struct obd_import *imp, int active)
 {
         struct obd_device *obd = imp->imp_obd;
-        unsigned long flags;
+        int rc = 0;
 
         LASSERT(obd);
 
         /* When deactivating, mark import invalid, and abort in-flight
          * requests. */
         if (!active) {
-                spin_lock_irqsave(&imp->imp_lock, flags);
-                /* This is a bit of a hack, but invalidating replayable
-                 * imports makes a temporary reconnect failure into a much more
-                 * ugly -- and hard to remedy -- situation. */
-                if (!imp->imp_replayable) {
-                        CDEBUG(D_HA, "setting import %s INVALID\n",
-                               imp->imp_target_uuid.uuid);
-                        imp->imp_invalid = 1;
-                }
-                imp->imp_generation++;
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
-                ptlrpc_invalidate_import_state(imp);
+                ptlrpc_invalidate_import(imp, 0);
+                imp->imp_deactive = 1;
         }
 
-        /* When activating, mark import valid */
+        /* When activating, mark import valid, and attempt recovery */
         if (active) {
+                imp->imp_deactive = 0;
                 CDEBUG(D_HA, "setting import %s VALID\n",
                        imp->imp_target_uuid.uuid);
-                spin_lock_irqsave(&imp->imp_lock, flags);
-                imp->imp_invalid = 0;
-                spin_unlock_irqrestore(&imp->imp_lock, flags);
+                rc = ptlrpc_recover_import(imp, NULL);
         }
 
-        if (obd->obd_observer)
-                RETURN(obd_notify(obd->obd_observer, obd, active));
-
-        RETURN(0);
+        RETURN(rc);
 }
 
 int ptlrpc_recover_import(struct obd_import *imp, char *new_uuid)
 {
         int rc;
         ENTRY;
-        
+
         /* force import to be disconnected. */
         ptlrpc_set_import_discon(imp);
-        
+
         rc = ptlrpc_recover_import_no_retry(imp, new_uuid);
 
         RETURN(rc);
@@ -345,6 +356,24 @@ int ptlrpc_import_in_recovery(struct obd_import *imp)
         return in_recovery;
 }
 
+int ptlrpc_import_control_recovery(struct obd_import *imp, int disable)
+{
+        unsigned long flags;
+
+        /* with imp_deactivate == 1 pinger won't initiate re-connect */
+        spin_lock_irqsave(&imp->imp_lock, flags);
+        if (disable)
+                imp->imp_deactive = 1;
+        else
+                imp->imp_deactive = 0;
+        if (imp->imp_state == LUSTRE_IMP_DISCON) {
+                imp->imp_force_verify = 1;
+                ptlrpc_pinger_wake_up();
+        }
+        spin_unlock_irqrestore(&imp->imp_lock, flags);
+        RETURN(0);
+}
+
 static int ptlrpc_recover_import_no_retry(struct obd_import *imp,
                                           char *new_uuid)
 {
@@ -357,28 +386,26 @@ static int ptlrpc_recover_import_no_retry(struct obd_import *imp,
         spin_lock_irqsave(&imp->imp_lock, flags);
         if (imp->imp_state != LUSTRE_IMP_DISCON) {
                 in_recovery = 1;
-        } 
+        }
         spin_unlock_irqrestore(&imp->imp_lock, flags);
 
         if (in_recovery == 1)
                 RETURN(-EALREADY);
 
-        
         rc = ptlrpc_connect_import(imp, new_uuid);
         if (rc)
                 RETURN(rc);
 
-        CDEBUG(D_ERROR, "%s: recovery started, waiting\n", 
-               imp->imp_client->cli_name);
+        CDEBUG(D_HA, "%s: recovery started, waiting\n",
+               imp->imp_target_uuid.uuid);
 
         lwi = LWI_TIMEOUT(MAX(obd_timeout * HZ, 1), NULL, NULL);
-        rc = l_wait_event(imp->imp_recovery_waitq, 
+        rc = l_wait_event(imp->imp_recovery_waitq,
                           !ptlrpc_import_in_recovery(imp), &lwi);
-        CDEBUG(D_ERROR, "%s: recovery finished\n", 
-               imp->imp_client->cli_name);
+        CDEBUG(D_HA, "%s: recovery finished\n",
+               imp->imp_target_uuid.uuid);
 
         RETURN(rc);
-        
 }
 
 void ptlrpc_fail_export(struct obd_export *exp)
@@ -400,6 +427,9 @@ void ptlrpc_fail_export(struct obd_export *exp)
         CDEBUG(D_HA, "disconnecting export %p/%s\n",
                exp, exp->exp_client_uuid.uuid);
 
+        if (obd_dump_on_timeout)
+                portals_debug_dumplog();
+
         /* Most callers into obd_disconnect are removing their own reference
          * (request, for example) in addition to the one from the hash table.
          * We don't have such a reference here, so make one. */