Whamcloud - gitweb
LU-1201 checksum: add libcfs crypto hash
[fs/lustre-release.git] / lustre / ptlrpc / import.c
index 1a461f1..4ef4afe 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
  * GPL HEADER START
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -28,6 +26,8 @@
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2011, Whamcloud, Inc.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -118,8 +118,7 @@ int ptlrpc_init_import(struct obd_import *imp)
 EXPORT_SYMBOL(ptlrpc_init_import);
 
 #define UUID_STR "_UUID"
-static void deuuidify(char *uuid, const char *prefix, char **uuid_start,
-                      int *uuid_len)
+void deuuidify(char *uuid, const char *prefix, char **uuid_start, int *uuid_len)
 {
         *uuid_start = !prefix || strncmp(uuid, prefix, strlen(prefix))
                 ? uuid : uuid + strlen(prefix);
@@ -133,6 +132,7 @@ static void deuuidify(char *uuid, const char *prefix, char **uuid_start,
                     UUID_STR, strlen(UUID_STR)))
                 *uuid_len -= strlen(UUID_STR);
 }
+EXPORT_SYMBOL(deuuidify);
 
 /**
  * Returns true if import was FULL, false if import was already not
@@ -160,15 +160,15 @@ int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt)
                           &target_start, &target_len);
 
                 if (imp->imp_replayable) {
-                        LCONSOLE_WARN("%s: Connection to service %.*s via nid "
-                               "%s was lost; in progress operations using this "
-                               "service will wait for recovery to complete.\n",
+                        LCONSOLE_WARN("%s: Connection to %.*s (at %s) was "
+                               "lost; in progress operations using this "
+                               "service will wait for recovery to complete\n",
                                imp->imp_obd->obd_name, target_len, target_start,
                                libcfs_nid2str(imp->imp_connection->c_peer.nid));
                 } else {
-                        LCONSOLE_ERROR_MSG(0x166, "%s: Connection to service "
-                               "%.*s via nid %s was lost; in progress "
-                               "operations using this service will fail.\n",
+                        LCONSOLE_ERROR_MSG(0x166, "%s: Connection to "
+                               "%.*s (at %s) was lost; in progress "
+                               "operations using this service will fail\n",
                                imp->imp_obd->obd_name,
                                target_len, target_start,
                                libcfs_nid2str(imp->imp_connection->c_peer.nid));
@@ -444,10 +444,9 @@ int ptlrpc_reconnect_import(struct obd_import *imp)
         /* Remove 'invalid' flag */
         ptlrpc_activate_import(imp);
         /* Attempt a new connect */
-        ptlrpc_recover_import(imp, NULL);
+        ptlrpc_recover_import(imp, NULL, 0);
         return 0;
 }
-
 EXPORT_SYMBOL(ptlrpc_reconnect_import);
 
 /**
@@ -459,7 +458,8 @@ static int import_select_connection(struct obd_import *imp)
 {
         struct obd_import_conn *imp_conn = NULL, *conn;
         struct obd_export *dlmexp;
-        int tried_all = 1;
+        char *target_start;
+        int target_len, tried_all = 1;
         ENTRY;
 
         cfs_spin_lock(&imp->imp_lock);
@@ -476,12 +476,6 @@ static int import_select_connection(struct obd_import *imp)
                        imp->imp_obd->obd_name,
                        libcfs_nid2str(conn->oic_conn->c_peer.nid),
                        conn->oic_last_attempt);
-                /* Don't thrash connections */
-                if (cfs_time_before_64(cfs_time_current_64(),
-                                     conn->oic_last_attempt +
-                                     cfs_time_seconds(CONNECTION_SWITCH_MIN))) {
-                        continue;
-                }
 
                 /* If we have not tried this connection since
                    the last successful attempt, go with this one */
@@ -517,17 +511,16 @@ static int import_select_connection(struct obd_import *imp)
            state associated with the last connection attempt to drain before
            trying to reconnect on it.) */
         if (tried_all && (imp->imp_conn_list.next == &imp_conn->oic_item)) {
-                if (at_get(&imp->imp_at.iat_net_latency) <
-                    CONNECTION_SWITCH_MAX) {
-                        at_measured(&imp->imp_at.iat_net_latency,
-                                    at_get(&imp->imp_at.iat_net_latency) +
-                                    CONNECTION_SWITCH_INC);
-                }
-                LASSERT(imp_conn->oic_last_attempt);
-                CWARN("%s: tried all connections, increasing latency to %ds\n",
-                      imp->imp_obd->obd_name,
-                      at_get(&imp->imp_at.iat_net_latency));
-        }
+               struct adaptive_timeout *at = &imp->imp_at.iat_net_latency;
+               if (at_get(at) < CONNECTION_SWITCH_MAX) {
+                       at_measured(at, at_get(at) + CONNECTION_SWITCH_INC);
+                       if (at_get(at) > CONNECTION_SWITCH_MAX)
+                               at_reset(at, CONNECTION_SWITCH_MAX);
+               }
+               LASSERT(imp_conn->oic_last_attempt);
+               CDEBUG(D_HA, "%s: tried all connections, increasing latency "
+                       "to %ds\n", imp->imp_obd->obd_name, at_get(at));
+       }
 
         imp_conn->oic_last_attempt = cfs_time_current_64();
 
@@ -544,10 +537,17 @@ static int import_select_connection(struct obd_import *imp)
         class_export_put(dlmexp);
 
         if (imp->imp_conn_current != imp_conn) {
-                if (imp->imp_conn_current)
-                        CDEBUG(D_HA, "Changing connection for %s to %s/%s\n",
-                               imp->imp_obd->obd_name, imp_conn->oic_uuid.uuid,
+                if (imp->imp_conn_current) {
+                        deuuidify(obd2cli_tgt(imp->imp_obd), NULL,
+                                  &target_start, &target_len);
+
+                        CDEBUG(D_HA, "%s: Connection changing to"
+                               " %.*s (at %s)\n",
+                               imp->imp_obd->obd_name,
+                               target_len, target_start,
                                libcfs_nid2str(imp_conn->oic_conn->c_peer.nid));
+                }
+
                 imp->imp_conn_current = imp_conn;
         }
 
@@ -587,7 +587,7 @@ static int ptlrpc_first_transno(struct obd_import *imp, __u64 *transno)
  * actual sending.
  * Returns 0 on success or error code.
  */
-int ptlrpc_connect_import(struct obd_import *imp, char *new_uuid)
+int ptlrpc_connect_import(struct obd_import *imp)
 {
         struct obd_device *obd = imp->imp_obd;
         int initial_connect = 0;
@@ -632,15 +632,6 @@ int ptlrpc_connect_import(struct obd_import *imp, char *new_uuid)
                                            &imp->imp_connect_data.ocd_transno);
         cfs_spin_unlock(&imp->imp_lock);
 
-        if (new_uuid) {
-                struct obd_uuid uuid;
-
-                obd_str2uuid(&uuid, new_uuid);
-                rc = import_set_conn_priority(imp, &uuid);
-                if (rc)
-                        GOTO(out, rc);
-        }
-
         rc = import_select_connection(imp);
         if (rc)
                 GOTO(out, rc);
@@ -718,7 +709,7 @@ int ptlrpc_connect_import(struct obd_import *imp, char *new_uuid)
 
         DEBUG_REQ(D_RPCTRACE, request, "(re)connect request (timeout %d)",
                   request->rq_timeout);
-        ptlrpcd_add_req(request, PSCOPE_OTHER);
+        ptlrpcd_add_req(request, PDL_POLICY_ROUND, -1);
         rc = 0;
 out:
         if (rc != 0) {
@@ -732,42 +723,18 @@ EXPORT_SYMBOL(ptlrpc_connect_import);
 static void ptlrpc_maybe_ping_import_soon(struct obd_import *imp)
 {
 #ifdef __KERNEL__
-        struct obd_import_conn *imp_conn;
-#endif
-        int wake_pinger = 0;
-
-        ENTRY;
+        int force_verify;
 
         cfs_spin_lock(&imp->imp_lock);
-        if (cfs_list_empty(&imp->imp_conn_list))
-                GOTO(unlock, 0);
+        force_verify = imp->imp_force_verify != 0;
+        cfs_spin_unlock(&imp->imp_lock);
 
-#ifdef __KERNEL__
-        imp_conn = cfs_list_entry(imp->imp_conn_list.prev,
-                                  struct obd_import_conn,
-                                  oic_item);
-
-        /* XXX: When the failover node is the primary node, it is possible
-         * to have two identical connections in imp_conn_list. We must
-         * compare not conn's pointers but NIDs, otherwise we can defeat
-         * connection throttling. (See bug 14774.) */
-        if (imp->imp_conn_current->oic_conn->c_peer.nid !=
-                                imp_conn->oic_conn->c_peer.nid) {
-                ptlrpc_ping_import_soon(imp);
-                wake_pinger = 1;
-        }
+        if (force_verify)
+                ptlrpc_pinger_wake_up();
 #else
         /* liblustre has no pinger thread, so we wakeup pinger anyway */
-        wake_pinger = 1;
+        ptlrpc_pinger_wake_up();
 #endif
-
- unlock:
-        cfs_spin_unlock(&imp->imp_lock);
-
-        if (wake_pinger)
-                ptlrpc_pinger_wake_up();
-
-        EXIT;
 }
 
 static int ptlrpc_busy_reconnect(int rc)
@@ -804,6 +771,7 @@ static int ptlrpc_connect_interpret(const struct lu_env *env,
                  * for connecting*/
                 imp->imp_force_reconnect = ptlrpc_busy_reconnect(rc);
                 cfs_spin_unlock(&imp->imp_lock);
+                ptlrpc_maybe_ping_import_soon(imp);
                 GOTO(out, rc);
         }
 
@@ -814,6 +782,7 @@ static int ptlrpc_connect_interpret(const struct lu_env *env,
         /* All imports are pingable */
         imp->imp_pingable = 1;
         imp->imp_force_reconnect = 0;
+        imp->imp_force_verify = 0;
 
         if (aa->pcaa_initial_connect) {
                 if (msg_flags & MSG_CONNECT_REPLAYABLE) {
@@ -854,10 +823,11 @@ static int ptlrpc_connect_interpret(const struct lu_env *env,
                 memset(&old_hdl, 0, sizeof(old_hdl));
                 if (!memcmp(&old_hdl, lustre_msg_get_handle(request->rq_repmsg),
                             sizeof (old_hdl))) {
-                        CERROR("%s@%s didn't like our handle "LPX64
-                               ", failed\n", obd2cli_tgt(imp->imp_obd),
-                               imp->imp_connection->c_remote_uuid.uuid,
-                               imp->imp_dlm_handle.cookie);
+                        LCONSOLE_WARN("Reconnect to %s (at @%s) failed due "
+                                      "bad handle "LPX64"\n",
+                                      obd2cli_tgt(imp->imp_obd),
+                                      imp->imp_connection->c_remote_uuid.uuid,
+                                      imp->imp_dlm_handle.cookie);
                         GOTO(out, rc = -ENOTCONN);
                 }
 
@@ -874,15 +844,27 @@ static int ptlrpc_connect_interpret(const struct lu_env *env,
                          * eviction. If it is in recovery - we are safe to
                          * participate since we can reestablish all of our state
                          * with server again */
-                        CDEBUG(level,"%s@%s changed server handle from "
-                                     LPX64" to "LPX64"%s\n",
-                                     obd2cli_tgt(imp->imp_obd),
-                                     imp->imp_connection->c_remote_uuid.uuid,
-                                     imp->imp_remote_handle.cookie,
-                                     lustre_msg_get_handle(request->rq_repmsg)->
-                                                                        cookie,
-                                     (MSG_CONNECT_RECOVERING & msg_flags) ?
-                                         " but is still in recovery" : "");
+                        if ((MSG_CONNECT_RECOVERING & msg_flags)) {
+                                CDEBUG(level,"%s@%s changed server handle from "
+                                       LPX64" to "LPX64
+                                       " but is still in recovery\n",
+                                       obd2cli_tgt(imp->imp_obd),
+                                       imp->imp_connection->c_remote_uuid.uuid,
+                                       imp->imp_remote_handle.cookie,
+                                       lustre_msg_get_handle(
+                                       request->rq_repmsg)->cookie);
+                        } else {
+                                LCONSOLE_WARN("Evicted from %s (at %s) "
+                                              "after server handle changed from "
+                                              LPX64" to "LPX64"\n",
+                                              obd2cli_tgt(imp->imp_obd),
+                                              imp->imp_connection-> \
+                                              c_remote_uuid.uuid,
+                                              imp->imp_remote_handle.cookie,
+                                              lustre_msg_get_handle(
+                                              request->rq_repmsg)->cookie);
+                        }
+
 
                         imp->imp_remote_handle =
                                      *lustre_msg_get_handle(request->rq_repmsg);
@@ -954,7 +936,7 @@ finish:
                                "invalidating and reconnecting\n",
                                obd2cli_tgt(imp->imp_obd),
                                imp->imp_connection->c_remote_uuid.uuid);
-                        ptlrpc_connect_import(imp, NULL);
+                        ptlrpc_connect_import(imp);
                         RETURN(0);
                 }
         } else {
@@ -982,6 +964,8 @@ finish:
                 }
 
                 imp->imp_connect_data = *ocd;
+                CDEBUG(D_HA, "obd %s to target with inst %u\n",
+                       imp->imp_obd->obd_name, ocd->ocd_instance);
 
                 exp = class_conn2export(&imp->imp_dlm_handle);
                 cfs_spin_unlock(&imp->imp_lock);
@@ -1020,13 +1004,14 @@ finish:
                         /* Sigh, some compilers do not like #ifdef in the middle
                            of macro arguments */
 #ifdef __KERNEL__
-                        const char *older =
-                                "older. Consider upgrading this client";
+                        const char *older = "older. Consider upgrading server "
+                                            "or downgrading client";
 #else
-                        const char *older =
-                                "older. Consider recompiling this application";
+                        const char *older = "older. Consider recompiling this "
+                                            "application";
 #endif
-                        const char *newer = "newer than client version";
+                        const char *newer = "newer than client version. "
+                                            "Consider upgrading client";
 
                         LCONSOLE_WARN("Server %s version (%d.%d.%d.%d) "
                                       "is much %s (%s)\n",
@@ -1039,42 +1024,37 @@ finish:
                                       newer : older, LUSTRE_VERSION_STRING);
                 }
 
-                if (ocd->ocd_connect_flags & OBD_CONNECT_CKSUM) {
-                        /* We sent to the server ocd_cksum_types with bits set
-                         * for algorithms we understand. The server masked off
-                         * the checksum types it doesn't support */
-                        if ((ocd->ocd_cksum_types & OBD_CKSUM_ALL) == 0) {
-                                LCONSOLE_WARN("The negotiation of the checksum "
-                                              "alogrithm to use with server %s "
-                                              "failed (%x/%x), disabling "
-                                              "checksums\n",
-                                              obd2cli_tgt(imp->imp_obd),
-                                              ocd->ocd_cksum_types,
-                                              OBD_CKSUM_ALL);
-                                cli->cl_checksum = 0;
-                                cli->cl_supp_cksum_types = OBD_CKSUM_CRC32;
-                                cli->cl_cksum_type = OBD_CKSUM_CRC32;
-                        } else {
-                                cli->cl_supp_cksum_types = ocd->ocd_cksum_types;
-
-                                if (ocd->ocd_cksum_types & OSC_DEFAULT_CKSUM)
-                                        cli->cl_cksum_type = OSC_DEFAULT_CKSUM;
-                                else if (ocd->ocd_cksum_types & OBD_CKSUM_ADLER)
-                                        cli->cl_cksum_type = OBD_CKSUM_ADLER;
-                                else
-                                        cli->cl_cksum_type = OBD_CKSUM_CRC32;
-                        }
-                } else {
-                        /* The server does not support OBD_CONNECT_CKSUM.
-                         * Enforce CRC32 for backward compatibility*/
-                        cli->cl_supp_cksum_types = OBD_CKSUM_CRC32;
-                        cli->cl_cksum_type = OBD_CKSUM_CRC32;
-                }
-
-                if (ocd->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) {
+               if (ocd->ocd_connect_flags & OBD_CONNECT_CKSUM) {
+                       /* We sent to the server ocd_cksum_types with bits set
+                        * for algorithms we understand. The server masked off
+                        * the checksum types it doesn't support */
+                       if ((ocd->ocd_cksum_types &
+                            cksum_types_supported_client()) == 0) {
+                               LCONSOLE_WARN("The negotiation of the checksum "
+                                             "alogrithm to use with server %s "
+                                             "failed (%x/%x), disabling "
+                                             "checksums\n",
+                                             obd2cli_tgt(imp->imp_obd),
+                                             ocd->ocd_cksum_types,
+                                             cksum_types_supported_client());
+                               cli->cl_checksum = 0;
+                               cli->cl_supp_cksum_types = OBD_CKSUM_ADLER;
+                       } else {
+                               cli->cl_supp_cksum_types = ocd->ocd_cksum_types;
+                       }
+               } else {
+                       /* The server does not support OBD_CONNECT_CKSUM.
+                        * Enforce ADLER for backward compatibility*/
+                       cli->cl_supp_cksum_types = OBD_CKSUM_ADLER;
+               }
+                cli->cl_cksum_type =cksum_type_select(cli->cl_supp_cksum_types);
+
+                if (ocd->ocd_connect_flags & OBD_CONNECT_BRW_SIZE)
                         cli->cl_max_pages_per_rpc =
                                 ocd->ocd_brw_size >> CFS_PAGE_SHIFT;
-                }
+                else if (imp->imp_connect_op == MDS_CONNECT ||
+                         imp->imp_connect_op == MGS_CONNECT)
+                        cli->cl_max_pages_per_rpc = 1;
 
                 /* Reset ns_connect_flags only for initial connect. It might be
                  * changed in while using FS and if we reset it in reconnect
@@ -1194,7 +1174,7 @@ static int completed_replay_interpret(const struct lu_env *env,
                                req->rq_import->imp_obd->obd_name,
                                req->rq_status);
                 }
-                ptlrpc_connect_import(req->rq_import, NULL);
+                ptlrpc_connect_import(req->rq_import);
         }
 
         RETURN(0);
@@ -1209,6 +1189,9 @@ static int signal_completed_replay(struct obd_import *imp)
         struct ptlrpc_request *req;
         ENTRY;
 
+        if (unlikely(OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_FINISH_REPLAY)))
+                RETURN(0);
+
         LASSERT(cfs_atomic_read(&imp->imp_replay_inflight) == 0);
         cfs_atomic_inc(&imp->imp_replay_inflight);
 
@@ -1227,7 +1210,7 @@ static int signal_completed_replay(struct obd_import *imp)
                 req->rq_timeout *= 3;
         req->rq_interpret_reply = completed_replay_interpret;
 
-        ptlrpcd_add_req(req, PSCOPE_OTHER);
+        ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
         RETURN(0);
 }
 
@@ -1273,7 +1256,7 @@ static int ptlrpc_invalidate_import_thread(void *data)
  * If we came to server that is in recovery, we enter IMP_REPLAY import state.
  * We go through our list of requests to replay and send them to server one by
  * one.
- * After sending all request from the list we change import state to 
+ * After sending all request from the list we change import state to
  * IMP_REPLAY_LOCKS and re-request all the locks we believe we have from server
  * and also all the locks we don't yet have and wait for server to grant us.
  * After that we send a special "replay completed" request and change import
@@ -1317,8 +1300,8 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp)
                  * invalidate thread without reference to import and import can
                  * be freed at same time. */
                 class_import_get(imp);
-                rc = cfs_kernel_thread(ptlrpc_invalidate_import_thread, imp,
-                                       CLONE_VM | CLONE_FILES);
+                rc = cfs_create_thread(ptlrpc_invalidate_import_thread, imp,
+                                       CFS_DAEMON_FLAGS);
                 if (rc < 0) {
                         class_import_put(imp);
                         CERROR("error starting invalidate thread: %d\n", rc);
@@ -1376,8 +1359,8 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp)
 
                 deuuidify(obd2cli_tgt(imp->imp_obd), NULL,
                           &target_start, &target_len);
-                LCONSOLE_INFO("%s: Connection restored to service %.*s "
-                              "using nid %s.\n", imp->imp_obd->obd_name,
+                LCONSOLE_INFO("%s: Connection restored to %.*s (at %s)\n",
+                              imp->imp_obd->obd_name,
                               target_len, target_start,
                               libcfs_nid2str(imp->imp_connection->c_peer.nid));
         }