* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, 2016, Intel Corporation.
+ * Copyright (c) 2011, 2017, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
*/
#define DEBUG_SUBSYSTEM S_LNET
+
+#include <linux/ctype.h>
#include <linux/log2.h>
#include <linux/ktime.h>
#include <linux/moduleparam.h>
+#include <linux/uaccess.h>
#include <lnet/lib-lnet.h>
MODULE_PARM_DESC(lnet_numa_range,
"NUMA range to consider during Multi-Rail selection");
+/*
+ * lnet_health_sensitivity determines by how much we decrement the health
+ * value on sending error. The value defaults to 100, which means health
+ * interface health is decremented by 100 points every failure.
+ */
+unsigned int lnet_health_sensitivity = 100;
+static int sensitivity_set(const char *val, cfs_kernel_param_arg_t *kp);
+#ifdef HAVE_KERNEL_PARAM_OPS
+static struct kernel_param_ops param_ops_health_sensitivity = {
+ .set = sensitivity_set,
+ .get = param_get_int,
+};
+#define param_check_health_sensitivity(name, p) \
+ __param_check(name, p, int)
+module_param(lnet_health_sensitivity, health_sensitivity, S_IRUGO|S_IWUSR);
+#else
+module_param_call(lnet_health_sensitivity, sensitivity_set, param_get_int,
+ &lnet_health_sensitivity, S_IRUGO|S_IWUSR);
+#endif
+MODULE_PARM_DESC(lnet_health_sensitivity,
+ "Value to decrement the health value by on error");
+
+/*
+ * lnet_recovery_interval determines how often we should perform recovery
+ * on unhealthy interfaces.
+ */
+unsigned int lnet_recovery_interval = 1;
+static int recovery_interval_set(const char *val, cfs_kernel_param_arg_t *kp);
+#ifdef HAVE_KERNEL_PARAM_OPS
+static struct kernel_param_ops param_ops_recovery_interval = {
+ .set = recovery_interval_set,
+ .get = param_get_int,
+};
+#define param_check_recovery_interval(name, p) \
+ __param_check(name, p, int)
+module_param(lnet_recovery_interval, recovery_interval, S_IRUGO|S_IWUSR);
+#else
+module_param_call(lnet_recovery_interval, recovery_interval_set, param_get_int,
+ &lnet_recovery_interval, S_IRUGO|S_IWUSR);
+#endif
+MODULE_PARM_DESC(lnet_recovery_interval,
+ "Interval to recover unhealthy interfaces in seconds");
+
static int lnet_interfaces_max = LNET_INTERFACES_MAX_DEFAULT;
-static int intf_max_set(const char *val, struct kernel_param *kp);
+static int intf_max_set(const char *val, cfs_kernel_param_arg_t *kp);
+
+static struct kernel_param_ops param_ops_interfaces_max = {
+ .set = intf_max_set,
+ .get = param_get_int,
+};
+
+#define param_check_interfaces_max(name, p) \
+ __param_check(name, p, int)
+
+#ifdef HAVE_KERNEL_PARAM_OPS
+module_param(lnet_interfaces_max, interfaces_max, 0644);
+#else
module_param_call(lnet_interfaces_max, intf_max_set, param_get_int,
- &lnet_interfaces_max, S_IRUGO|S_IWUSR);
+ ¶m_ops_interfaces_max, 0644);
+#endif
MODULE_PARM_DESC(lnet_interfaces_max,
"Maximum number of interfaces in a node.");
unsigned lnet_peer_discovery_disabled = 0;
-static int discovery_set(const char *val, struct kernel_param *kp);
+static int discovery_set(const char *val, cfs_kernel_param_arg_t *kp);
+
+static struct kernel_param_ops param_ops_discovery_disabled = {
+ .set = discovery_set,
+ .get = param_get_int,
+};
+
+#define param_check_discovery_disabled(name, p) \
+ __param_check(name, p, int)
+#ifdef HAVE_KERNEL_PARAM_OPS
+module_param(lnet_peer_discovery_disabled, discovery_disabled, 0644);
+#else
module_param_call(lnet_peer_discovery_disabled, discovery_set, param_get_int,
- &lnet_peer_discovery_disabled, S_IRUGO|S_IWUSR);
+ ¶m_ops_discovery_disabled, 0644);
+#endif
MODULE_PARM_DESC(lnet_peer_discovery_disabled,
"Set to 1 to disable peer discovery on this node.");
+unsigned int lnet_drop_asym_route;
+static int drop_asym_route_set(const char *val, cfs_kernel_param_arg_t *kp);
+
+static struct kernel_param_ops param_ops_drop_asym_route = {
+ .set = drop_asym_route_set,
+ .get = param_get_int,
+};
+
+#define param_check_drop_asym_route(name, p) \
+ __param_check(name, p, int)
+#ifdef HAVE_KERNEL_PARAM_OPS
+module_param(lnet_drop_asym_route, drop_asym_route, 0644);
+#else
+module_param_call(lnet_drop_asym_route, drop_asym_route_set, param_get_int,
+ ¶m_ops_drop_asym_route, 0644);
+#endif
+MODULE_PARM_DESC(lnet_drop_asym_route,
+ "Set to 1 to drop asymmetrical route messages.");
+
+#define LNET_TRANSACTION_TIMEOUT_NO_HEALTH_DEFAULT 50
+#define LNET_TRANSACTION_TIMEOUT_HEALTH_DEFAULT 10
+
+unsigned lnet_transaction_timeout = LNET_TRANSACTION_TIMEOUT_HEALTH_DEFAULT;
+static int transaction_to_set(const char *val, cfs_kernel_param_arg_t *kp);
+#ifdef HAVE_KERNEL_PARAM_OPS
+static struct kernel_param_ops param_ops_transaction_timeout = {
+ .set = transaction_to_set,
+ .get = param_get_int,
+};
+
+#define param_check_transaction_timeout(name, p) \
+ __param_check(name, p, int)
+module_param(lnet_transaction_timeout, transaction_timeout, S_IRUGO|S_IWUSR);
+#else
+module_param_call(lnet_transaction_timeout, transaction_to_set, param_get_int,
+ &lnet_transaction_timeout, S_IRUGO|S_IWUSR);
+#endif
+MODULE_PARM_DESC(lnet_transaction_timeout,
+ "Maximum number of seconds to wait for a peer response.");
+
+#define LNET_RETRY_COUNT_HEALTH_DEFAULT 3
+unsigned lnet_retry_count = LNET_RETRY_COUNT_HEALTH_DEFAULT;
+static int retry_count_set(const char *val, cfs_kernel_param_arg_t *kp);
+#ifdef HAVE_KERNEL_PARAM_OPS
+static struct kernel_param_ops param_ops_retry_count = {
+ .set = retry_count_set,
+ .get = param_get_int,
+};
+
+#define param_check_retry_count(name, p) \
+ __param_check(name, p, int)
+module_param(lnet_retry_count, retry_count, S_IRUGO|S_IWUSR);
+#else
+module_param_call(lnet_retry_count, retry_count_set, param_get_int,
+ &lnet_retry_count, S_IRUGO|S_IWUSR);
+#endif
+MODULE_PARM_DESC(lnet_retry_count,
+ "Maximum number of times to retry transmitting a message");
+
+
+unsigned lnet_lnd_timeout = LNET_LND_DEFAULT_TIMEOUT;
+unsigned int lnet_current_net_count;
+
/*
* This sequence number keeps track of how many times DLC was used to
* update the local NIs. It is incremented when a NI is added or
static int lnet_ping(struct lnet_process_id id, signed long timeout,
struct lnet_process_id __user *ids, int n_ids);
-static int lnet_discover(lnet_process_id_t id, __u32 force,
- lnet_process_id_t __user *ids, int n_ids);
+static int lnet_discover(struct lnet_process_id id, __u32 force,
+ struct lnet_process_id __user *ids, int n_ids);
+
+static int
+sensitivity_set(const char *val, cfs_kernel_param_arg_t *kp)
+{
+ int rc;
+ unsigned *sensitivity = (unsigned *)kp->arg;
+ unsigned long value;
+
+ rc = kstrtoul(val, 0, &value);
+ if (rc) {
+ CERROR("Invalid module parameter value for 'lnet_health_sensitivity'\n");
+ return rc;
+ }
+
+ /*
+ * The purpose of locking the api_mutex here is to ensure that
+ * the correct value ends up stored properly.
+ */
+ mutex_lock(&the_lnet.ln_api_mutex);
+
+ if (value > LNET_MAX_HEALTH_VALUE) {
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ CERROR("Invalid health value. Maximum: %d value = %lu\n",
+ LNET_MAX_HEALTH_VALUE, value);
+ return -EINVAL;
+ }
+
+ /*
+ * if we're turning on health then use the health timeout
+ * defaults.
+ */
+ if (*sensitivity == 0 && value != 0) {
+ lnet_transaction_timeout = LNET_TRANSACTION_TIMEOUT_HEALTH_DEFAULT;
+ lnet_retry_count = LNET_RETRY_COUNT_HEALTH_DEFAULT;
+ /*
+ * if we're turning off health then use the no health timeout
+ * default.
+ */
+ } else if (*sensitivity != 0 && value == 0) {
+ lnet_transaction_timeout =
+ LNET_TRANSACTION_TIMEOUT_NO_HEALTH_DEFAULT;
+ lnet_retry_count = 0;
+ }
+
+ *sensitivity = value;
+
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return 0;
+}
+
+static int
+recovery_interval_set(const char *val, cfs_kernel_param_arg_t *kp)
+{
+ int rc;
+ unsigned *interval = (unsigned *)kp->arg;
+ unsigned long value;
+
+ rc = kstrtoul(val, 0, &value);
+ if (rc) {
+ CERROR("Invalid module parameter value for 'lnet_recovery_interval'\n");
+ return rc;
+ }
+
+ if (value < 1) {
+ CERROR("lnet_recovery_interval must be at least 1 second\n");
+ return -EINVAL;
+ }
+
+ /*
+ * The purpose of locking the api_mutex here is to ensure that
+ * the correct value ends up stored properly.
+ */
+ mutex_lock(&the_lnet.ln_api_mutex);
+
+ *interval = value;
+
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return 0;
+}
static int
-discovery_set(const char *val, struct kernel_param *kp)
+discovery_set(const char *val, cfs_kernel_param_arg_t *kp)
{
int rc;
unsigned *discovery = (unsigned *)kp->arg;
}
static int
-intf_max_set(const char *val, struct kernel_param *kp)
+drop_asym_route_set(const char *val, cfs_kernel_param_arg_t *kp)
+{
+ int rc;
+ unsigned int *drop_asym_route = (unsigned int *)kp->arg;
+ unsigned long value;
+
+ rc = kstrtoul(val, 0, &value);
+ if (rc) {
+ CERROR("Invalid module parameter value for "
+ "'lnet_drop_asym_route'\n");
+ return rc;
+ }
+
+ /*
+ * The purpose of locking the api_mutex here is to ensure that
+ * the correct value ends up stored properly.
+ */
+ mutex_lock(&the_lnet.ln_api_mutex);
+
+ if (value == *drop_asym_route) {
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return 0;
+ }
+
+ *drop_asym_route = value;
+
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return 0;
+}
+
+static int
+transaction_to_set(const char *val, cfs_kernel_param_arg_t *kp)
+{
+ int rc;
+ unsigned *transaction_to = (unsigned *)kp->arg;
+ unsigned long value;
+
+ rc = kstrtoul(val, 0, &value);
+ if (rc) {
+ CERROR("Invalid module parameter value for 'lnet_transaction_timeout'\n");
+ return rc;
+ }
+
+ /*
+ * The purpose of locking the api_mutex here is to ensure that
+ * the correct value ends up stored properly.
+ */
+ mutex_lock(&the_lnet.ln_api_mutex);
+
+ if (value < lnet_retry_count || value == 0) {
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ CERROR("Invalid value for lnet_transaction_timeout (%lu). "
+ "Has to be greater than lnet_retry_count (%u)\n",
+ value, lnet_retry_count);
+ return -EINVAL;
+ }
+
+ if (value == *transaction_to) {
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return 0;
+ }
+
+ *transaction_to = value;
+ if (lnet_retry_count == 0)
+ lnet_lnd_timeout = value;
+ else
+ lnet_lnd_timeout = value / lnet_retry_count;
+
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return 0;
+}
+
+static int
+retry_count_set(const char *val, cfs_kernel_param_arg_t *kp)
+{
+ int rc;
+ unsigned *retry_count = (unsigned *)kp->arg;
+ unsigned long value;
+
+ rc = kstrtoul(val, 0, &value);
+ if (rc) {
+ CERROR("Invalid module parameter value for 'lnet_retry_count'\n");
+ return rc;
+ }
+
+ /*
+ * The purpose of locking the api_mutex here is to ensure that
+ * the correct value ends up stored properly.
+ */
+ mutex_lock(&the_lnet.ln_api_mutex);
+
+ if (lnet_health_sensitivity == 0) {
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ CERROR("Can not set retry_count when health feature is turned off\n");
+ return -EINVAL;
+ }
+
+ if (value > lnet_transaction_timeout) {
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ CERROR("Invalid value for lnet_retry_count (%lu). "
+ "Has to be smaller than lnet_transaction_timeout (%u)\n",
+ value, lnet_transaction_timeout);
+ return -EINVAL;
+ }
+
+ *retry_count = value;
+
+ if (value == 0)
+ lnet_lnd_timeout = lnet_transaction_timeout;
+ else
+ lnet_lnd_timeout = lnet_transaction_timeout / value;
+
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return 0;
+}
+
+static int
+intf_max_set(const char *val, cfs_kernel_param_arg_t *kp)
{
int value, rc;
lnet_init_locks(void)
{
spin_lock_init(&the_lnet.ln_eq_wait_lock);
+ spin_lock_init(&the_lnet.ln_msg_resend_lock);
init_waitqueue_head(&the_lnet.ln_eq_waitq);
- init_waitqueue_head(&the_lnet.ln_rc_waitq);
+ init_completion(&the_lnet.ln_mt_wait_complete);
mutex_init(&the_lnet.ln_lnd_mutex);
}
* with gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) */
/* Constants... */
- CLASSERT(LNET_PROTO_TCP_MAGIC == 0xeebc0ded);
- CLASSERT(LNET_PROTO_TCP_VERSION_MAJOR == 1);
- CLASSERT(LNET_PROTO_TCP_VERSION_MINOR == 0);
- CLASSERT(LNET_MSG_ACK == 0);
- CLASSERT(LNET_MSG_PUT == 1);
- CLASSERT(LNET_MSG_GET == 2);
- CLASSERT(LNET_MSG_REPLY == 3);
- CLASSERT(LNET_MSG_HELLO == 4);
+ BUILD_BUG_ON(LNET_PROTO_TCP_MAGIC != 0xeebc0ded);
+ BUILD_BUG_ON(LNET_PROTO_TCP_VERSION_MAJOR != 1);
+ BUILD_BUG_ON(LNET_PROTO_TCP_VERSION_MINOR != 0);
+ BUILD_BUG_ON(LNET_MSG_ACK != 0);
+ BUILD_BUG_ON(LNET_MSG_PUT != 1);
+ BUILD_BUG_ON(LNET_MSG_GET != 2);
+ BUILD_BUG_ON(LNET_MSG_REPLY != 3);
+ BUILD_BUG_ON(LNET_MSG_HELLO != 4);
/* Checks for struct lnet_handle_wire */
- CLASSERT((int)sizeof(struct lnet_handle_wire) == 16);
- CLASSERT((int)offsetof(struct lnet_handle_wire, wh_interface_cookie) == 0);
- CLASSERT((int)sizeof(((struct lnet_handle_wire *)0)->wh_interface_cookie) == 8);
- CLASSERT((int)offsetof(struct lnet_handle_wire, wh_object_cookie) == 8);
- CLASSERT((int)sizeof(((struct lnet_handle_wire *)0)->wh_object_cookie) == 8);
+ BUILD_BUG_ON((int)sizeof(struct lnet_handle_wire) != 16);
+ BUILD_BUG_ON((int)offsetof(struct lnet_handle_wire,
+ wh_interface_cookie) != 0);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_handle_wire *)0)->wh_interface_cookie) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_handle_wire,
+ wh_object_cookie) != 8);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_handle_wire *)0)->wh_object_cookie) != 8);
/* Checks for struct struct lnet_magicversion */
- CLASSERT((int)sizeof(struct lnet_magicversion) == 8);
- CLASSERT((int)offsetof(struct lnet_magicversion, magic) == 0);
- CLASSERT((int)sizeof(((struct lnet_magicversion *)0)->magic) == 4);
- CLASSERT((int)offsetof(struct lnet_magicversion, version_major) == 4);
- CLASSERT((int)sizeof(((struct lnet_magicversion *)0)->version_major) == 2);
- CLASSERT((int)offsetof(struct lnet_magicversion, version_minor) == 6);
- CLASSERT((int)sizeof(((struct lnet_magicversion *)0)->version_minor) == 2);
+ BUILD_BUG_ON((int)sizeof(struct lnet_magicversion) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_magicversion, magic) != 0);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_magicversion *)0)->magic) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_magicversion, version_major) != 4);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_magicversion *)0)->version_major) != 2);
+ BUILD_BUG_ON((int)offsetof(struct lnet_magicversion,
+ version_minor) != 6);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_magicversion *)0)->version_minor) != 2);
/* Checks for struct struct lnet_hdr */
- CLASSERT((int)sizeof(struct lnet_hdr) == 72);
- CLASSERT((int)offsetof(struct lnet_hdr, dest_nid) == 0);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->dest_nid) == 8);
- CLASSERT((int)offsetof(struct lnet_hdr, src_nid) == 8);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->src_nid) == 8);
- CLASSERT((int)offsetof(struct lnet_hdr, dest_pid) == 16);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->dest_pid) == 4);
- CLASSERT((int)offsetof(struct lnet_hdr, src_pid) == 20);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->src_pid) == 4);
- CLASSERT((int)offsetof(struct lnet_hdr, type) == 24);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->type) == 4);
- CLASSERT((int)offsetof(struct lnet_hdr, payload_length) == 28);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->payload_length) == 4);
- CLASSERT((int)offsetof(struct lnet_hdr, msg) == 32);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg) == 40);
+ BUILD_BUG_ON((int)sizeof(struct lnet_hdr) != 72);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, dest_nid) != 0);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->dest_nid) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, src_nid) != 8);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->src_nid) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, dest_pid) != 16);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->dest_pid) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, src_pid) != 20);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->src_pid) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, type) != 24);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->type) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, payload_length) != 28);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->payload_length) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg) != 32);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg) != 40);
/* Ack */
- CLASSERT((int)offsetof(struct lnet_hdr, msg.ack.dst_wmd) == 32);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.ack.dst_wmd) == 16);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.ack.match_bits) == 48);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.ack.match_bits) == 8);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.ack.mlength) == 56);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.ack.mlength) == 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.ack.dst_wmd) != 32);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.ack.dst_wmd) != 16);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.ack.match_bits) != 48);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.ack.match_bits) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.ack.mlength) != 56);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.ack.mlength) != 4);
/* Put */
- CLASSERT((int)offsetof(struct lnet_hdr, msg.put.ack_wmd) == 32);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.ack_wmd) == 16);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.put.match_bits) == 48);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.match_bits) == 8);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.put.hdr_data) == 56);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.hdr_data) == 8);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.put.ptl_index) == 64);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.ptl_index) == 4);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.put.offset) == 68);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.offset) == 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.ack_wmd) != 32);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.ack_wmd) != 16);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.match_bits) != 48);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.match_bits) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.hdr_data) != 56);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.hdr_data) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.ptl_index) != 64);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.ptl_index) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.offset) != 68);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.offset) != 4);
/* Get */
- CLASSERT((int)offsetof(struct lnet_hdr, msg.get.return_wmd) == 32);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.return_wmd) == 16);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.get.match_bits) == 48);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.match_bits) == 8);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.get.ptl_index) == 56);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.ptl_index) == 4);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.get.src_offset) == 60);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.src_offset) == 4);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.get.sink_length) == 64);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.sink_length) == 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.return_wmd) != 32);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.return_wmd) != 16);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.match_bits) != 48);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.match_bits) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.ptl_index) != 56);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.ptl_index) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.src_offset) != 60);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.src_offset) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.sink_length) != 64);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.sink_length) != 4);
/* Reply */
- CLASSERT((int)offsetof(struct lnet_hdr, msg.reply.dst_wmd) == 32);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.reply.dst_wmd) == 16);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.reply.dst_wmd) != 32);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.reply.dst_wmd) != 16);
/* Hello */
- CLASSERT((int)offsetof(struct lnet_hdr, msg.hello.incarnation) == 32);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.hello.incarnation) == 8);
- CLASSERT((int)offsetof(struct lnet_hdr, msg.hello.type) == 40);
- CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.hello.type) == 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.hello.incarnation) != 32);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.hello.incarnation) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.hello.type) != 40);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.hello.type) != 4);
/* Checks for struct lnet_ni_status and related constants */
- CLASSERT(LNET_NI_STATUS_INVALID == 0x00000000);
- CLASSERT(LNET_NI_STATUS_UP == 0x15aac0de);
- CLASSERT(LNET_NI_STATUS_DOWN == 0xdeadface);
+ BUILD_BUG_ON(LNET_NI_STATUS_INVALID != 0x00000000);
+ BUILD_BUG_ON(LNET_NI_STATUS_UP != 0x15aac0de);
+ BUILD_BUG_ON(LNET_NI_STATUS_DOWN != 0xdeadface);
/* Checks for struct lnet_ni_status */
- CLASSERT((int)sizeof(struct lnet_ni_status) == 16);
- CLASSERT((int)offsetof(struct lnet_ni_status, ns_nid) == 0);
- CLASSERT((int)sizeof(((struct lnet_ni_status *)0)->ns_nid) == 8);
- CLASSERT((int)offsetof(struct lnet_ni_status, ns_status) == 8);
- CLASSERT((int)sizeof(((struct lnet_ni_status *)0)->ns_status) == 4);
- CLASSERT((int)offsetof(struct lnet_ni_status, ns_unused) == 12);
- CLASSERT((int)sizeof(((struct lnet_ni_status *)0)->ns_unused) == 4);
+ BUILD_BUG_ON((int)sizeof(struct lnet_ni_status) != 16);
+ BUILD_BUG_ON((int)offsetof(struct lnet_ni_status, ns_nid) != 0);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_ni_status *)0)->ns_nid) != 8);
+ BUILD_BUG_ON((int)offsetof(struct lnet_ni_status, ns_status) != 8);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_ni_status *)0)->ns_status) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_ni_status, ns_unused) != 12);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_ni_status *)0)->ns_unused) != 4);
/* Checks for struct lnet_ping_info and related constants */
- CLASSERT(LNET_PROTO_PING_MAGIC == 0x70696E67);
- CLASSERT(LNET_PING_FEAT_INVAL == 0);
- CLASSERT(LNET_PING_FEAT_BASE == 1);
- CLASSERT(LNET_PING_FEAT_NI_STATUS == 2);
- CLASSERT(LNET_PING_FEAT_RTE_DISABLED == 4);
- CLASSERT(LNET_PING_FEAT_MULTI_RAIL == 8);
- CLASSERT(LNET_PING_FEAT_DISCOVERY == 16);
- CLASSERT(LNET_PING_FEAT_BITS == 31);
+ BUILD_BUG_ON(LNET_PROTO_PING_MAGIC != 0x70696E67);
+ BUILD_BUG_ON(LNET_PING_FEAT_INVAL != 0);
+ BUILD_BUG_ON(LNET_PING_FEAT_BASE != 1);
+ BUILD_BUG_ON(LNET_PING_FEAT_NI_STATUS != 2);
+ BUILD_BUG_ON(LNET_PING_FEAT_RTE_DISABLED != 4);
+ BUILD_BUG_ON(LNET_PING_FEAT_MULTI_RAIL != 8);
+ BUILD_BUG_ON(LNET_PING_FEAT_DISCOVERY != 16);
+ BUILD_BUG_ON(LNET_PING_FEAT_BITS != 31);
/* Checks for struct lnet_ping_info */
- CLASSERT((int)sizeof(struct lnet_ping_info) == 16);
- CLASSERT((int)offsetof(struct lnet_ping_info, pi_magic) == 0);
- CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_magic) == 4);
- CLASSERT((int)offsetof(struct lnet_ping_info, pi_features) == 4);
- CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_features) == 4);
- CLASSERT((int)offsetof(struct lnet_ping_info, pi_pid) == 8);
- CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_pid) == 4);
- CLASSERT((int)offsetof(struct lnet_ping_info, pi_nnis) == 12);
- CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_nnis) == 4);
- CLASSERT((int)offsetof(struct lnet_ping_info, pi_ni) == 16);
- CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_ni) == 0);
+ BUILD_BUG_ON((int)sizeof(struct lnet_ping_info) != 16);
+ BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_magic) != 0);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_magic) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_features) != 4);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_features) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_pid) != 8);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_pid) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_nnis) != 12);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_nnis) != 4);
+ BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_ni) != 16);
+ BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_ni) != 0);
}
static struct lnet_lnd *lnet_find_lnd_by_type(__u32 type)
{
struct lnet_lnd *lnd;
- struct list_head *tmp;
/* holding lnd mutex */
- list_for_each(tmp, &the_lnet.ln_lnds) {
- lnd = list_entry(tmp, struct lnet_lnd, lnd_list);
+ if (type >= NUM_LNDS)
+ return NULL;
+ lnd = the_lnet.ln_lnds[type];
+ LASSERT(!lnd || lnd->lnd_type == type);
- if (lnd->lnd_type == type)
- return lnd;
- }
- return NULL;
+ return lnd;
}
+unsigned int
+lnet_get_lnd_timeout(void)
+{
+ return lnet_lnd_timeout;
+}
+EXPORT_SYMBOL(lnet_get_lnd_timeout);
+
void
lnet_register_lnd(struct lnet_lnd *lnd)
{
LASSERT(libcfs_isknown_lnd(lnd->lnd_type));
LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == NULL);
- list_add_tail(&lnd->lnd_list, &the_lnet.ln_lnds);
- lnd->lnd_refcount = 0;
+ the_lnet.ln_lnds[lnd->lnd_type] = lnd;
CDEBUG(D_NET, "%s LND registered\n", libcfs_lnd2str(lnd->lnd_type));
mutex_lock(&the_lnet.ln_lnd_mutex);
LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == lnd);
- LASSERT(lnd->lnd_refcount == 0);
- list_del(&lnd->lnd_list);
+ the_lnet.ln_lnds[lnd->lnd_type] = NULL;
CDEBUG(D_NET, "%s LND unregistered\n", libcfs_lnd2str(lnd->lnd_type));
mutex_unlock(&the_lnet.ln_lnd_mutex);
EXPORT_SYMBOL(lnet_unregister_lnd);
void
+lnet_counters_get_common(struct lnet_counters_common *common)
+{
+ struct lnet_counters *ctr;
+ int i;
+
+ memset(common, 0, sizeof(*common));
+
+ lnet_net_lock(LNET_LOCK_EX);
+
+ cfs_percpt_for_each(ctr, i, the_lnet.ln_counters) {
+ common->lcc_msgs_max += ctr->lct_common.lcc_msgs_max;
+ common->lcc_msgs_alloc += ctr->lct_common.lcc_msgs_alloc;
+ common->lcc_errors += ctr->lct_common.lcc_errors;
+ common->lcc_send_count += ctr->lct_common.lcc_send_count;
+ common->lcc_recv_count += ctr->lct_common.lcc_recv_count;
+ common->lcc_route_count += ctr->lct_common.lcc_route_count;
+ common->lcc_drop_count += ctr->lct_common.lcc_drop_count;
+ common->lcc_send_length += ctr->lct_common.lcc_send_length;
+ common->lcc_recv_length += ctr->lct_common.lcc_recv_length;
+ common->lcc_route_length += ctr->lct_common.lcc_route_length;
+ common->lcc_drop_length += ctr->lct_common.lcc_drop_length;
+ }
+ lnet_net_unlock(LNET_LOCK_EX);
+}
+EXPORT_SYMBOL(lnet_counters_get_common);
+
+void
lnet_counters_get(struct lnet_counters *counters)
{
struct lnet_counters *ctr;
+ struct lnet_counters_health *health = &counters->lct_health;
int i;
memset(counters, 0, sizeof(*counters));
+ lnet_counters_get_common(&counters->lct_common);
+
lnet_net_lock(LNET_LOCK_EX);
cfs_percpt_for_each(ctr, i, the_lnet.ln_counters) {
- counters->msgs_max += ctr->msgs_max;
- counters->msgs_alloc += ctr->msgs_alloc;
- counters->errors += ctr->errors;
- counters->send_count += ctr->send_count;
- counters->recv_count += ctr->recv_count;
- counters->route_count += ctr->route_count;
- counters->drop_count += ctr->drop_count;
- counters->send_length += ctr->send_length;
- counters->recv_length += ctr->recv_length;
- counters->route_length += ctr->route_length;
- counters->drop_length += ctr->drop_length;
-
+ health->lch_rst_alloc += ctr->lct_health.lch_rst_alloc;
+ health->lch_resend_count += ctr->lct_health.lch_resend_count;
+ health->lch_response_timeout_count +=
+ ctr->lct_health.lch_response_timeout_count;
+ health->lch_local_interrupt_count +=
+ ctr->lct_health.lch_local_interrupt_count;
+ health->lch_local_dropped_count +=
+ ctr->lct_health.lch_local_dropped_count;
+ health->lch_local_aborted_count +=
+ ctr->lct_health.lch_local_aborted_count;
+ health->lch_local_no_route_count +=
+ ctr->lct_health.lch_local_no_route_count;
+ health->lch_local_timeout_count +=
+ ctr->lct_health.lch_local_timeout_count;
+ health->lch_local_error_count +=
+ ctr->lct_health.lch_local_error_count;
+ health->lch_remote_dropped_count +=
+ ctr->lct_health.lch_remote_dropped_count;
+ health->lch_remote_error_count +=
+ ctr->lct_health.lch_remote_error_count;
+ health->lch_remote_timeout_count +=
+ ctr->lct_health.lch_remote_timeout_count;
+ health->lch_network_timeout_count +=
+ ctr->lct_health.lch_network_timeout_count;
}
lnet_net_unlock(LNET_LOCK_EX);
}
list_add(&lh->lh_hash_chain, &rec->rec_lh_hash[hash]);
}
+struct list_head **
+lnet_create_array_of_queues(void)
+{
+ struct list_head **qs;
+ struct list_head *q;
+ int i;
+
+ qs = cfs_percpt_alloc(lnet_cpt_table(),
+ sizeof(struct list_head));
+ if (!qs) {
+ CERROR("Failed to allocate queues\n");
+ return NULL;
+ }
+
+ cfs_percpt_for_each(q, i, qs)
+ INIT_LIST_HEAD(q);
+
+ return qs;
+}
+
static int lnet_unprepare(void);
static int
INIT_LIST_HEAD(&the_lnet.ln_dc_request);
INIT_LIST_HEAD(&the_lnet.ln_dc_working);
INIT_LIST_HEAD(&the_lnet.ln_dc_expired);
+ INIT_LIST_HEAD(&the_lnet.ln_mt_localNIRecovq);
+ INIT_LIST_HEAD(&the_lnet.ln_mt_peerNIRecovq);
init_waitqueue_head(&the_lnet.ln_dc_waitq);
+ LNetInvalidateEQHandle(&the_lnet.ln_mt_eqh);
+ init_completion(&the_lnet.ln_started);
rc = lnet_descriptor_setup();
if (rc != 0)
goto failed;
}
+ the_lnet.ln_mt_zombie_rstqs = lnet_create_array_of_queues();
+ if (!the_lnet.ln_mt_zombie_rstqs) {
+ rc = -ENOMEM;
+ goto failed;
+ }
+
return 0;
failed:
static int
lnet_unprepare (void)
{
+ int rc;
+
/* NB no LNET_LOCK since this is the last reference. All LND instances
* have shut down already, so it is safe to unlink and free all
* descriptors, even those that appear committed to a network op (eg MD
LASSERT(list_empty(&the_lnet.ln_test_peers));
LASSERT(list_empty(&the_lnet.ln_nets));
+ if (the_lnet.ln_mt_zombie_rstqs) {
+ lnet_clean_zombie_rstqs();
+ the_lnet.ln_mt_zombie_rstqs = NULL;
+ }
+
+ if (!LNetEQHandleIsInvalid(the_lnet.ln_mt_eqh)) {
+ rc = LNetEQFree(the_lnet.ln_mt_eqh);
+ LNetInvalidateEQHandle(&the_lnet.ln_mt_eqh);
+ LASSERT(rc == 0);
+ }
+
lnet_portals_destroy();
if (the_lnet.ln_md_containers != NULL) {
EXPORT_SYMBOL(lnet_cpt_of_nid);
int
-lnet_islocalnet(__u32 net_id)
+lnet_islocalnet_locked(__u32 net_id)
{
struct lnet_net *net;
- int cpt;
- bool local;
-
- cpt = lnet_net_lock_current();
+ bool local;
net = lnet_get_net_locked(net_id);
local = net != NULL;
- lnet_net_unlock(cpt);
-
return local;
}
-bool
-lnet_is_ni_healthy_locked(struct lnet_ni *ni)
+int
+lnet_islocalnet(__u32 net_id)
{
- if (ni->ni_state == LNET_NI_STATE_ACTIVE ||
- ni->ni_state == LNET_NI_STATE_DEGRADED)
- return true;
+ int cpt;
+ bool local;
- return false;
+ cpt = lnet_net_lock_current();
+
+ local = lnet_islocalnet_locked(net_id);
+
+ lnet_net_unlock(cpt);
+
+ return local;
}
struct lnet_ni *
}
int
+lnet_get_net_count(void)
+{
+ struct lnet_net *net;
+ int count = 0;
+
+ lnet_net_lock(0);
+
+ list_for_each_entry(net, &the_lnet.ln_nets, net_list) {
+ count++;
+ }
+
+ lnet_net_unlock(0);
+
+ return count;
+}
+
+void
+lnet_swap_pinginfo(struct lnet_ping_buffer *pbuf)
+{
+ struct lnet_ni_status *stat;
+ int nnis;
+ int i;
+
+ __swab32s(&pbuf->pb_info.pi_magic);
+ __swab32s(&pbuf->pb_info.pi_features);
+ __swab32s(&pbuf->pb_info.pi_pid);
+ __swab32s(&pbuf->pb_info.pi_nnis);
+ nnis = pbuf->pb_info.pi_nnis;
+ if (nnis > pbuf->pb_nnis)
+ nnis = pbuf->pb_nnis;
+ for (i = 0; i < nnis; i++) {
+ stat = &pbuf->pb_info.pi_ni[i];
+ __swab64s(&stat->ns_nid);
+ __swab32s(&stat->ns_status);
+ }
+}
+
+int
lnet_ping_info_validate(struct lnet_ping_info *pinfo)
{
if (!pinfo)
/* Resize the push target. */
int lnet_push_target_resize(void)
{
- lnet_process_id_t id = { LNET_NID_ANY, LNET_PID_ANY };
- lnet_md_t md = { NULL };
- lnet_handle_me_t meh;
- lnet_handle_md_t mdh;
- lnet_handle_md_t old_mdh;
+ struct lnet_process_id id = { LNET_NID_ANY, LNET_PID_ANY };
+ struct lnet_md md = { NULL };
+ struct lnet_handle_me meh;
+ struct lnet_handle_md mdh;
+ struct lnet_handle_md old_mdh;
struct lnet_ping_buffer *pbuf;
struct lnet_ping_buffer *old_pbuf;
int nnis = the_lnet.ln_push_target_nnis;
static void
lnet_ni_unlink_locked(struct lnet_ni *ni)
{
- if (!list_empty(&ni->ni_cptlist)) {
- list_del_init(&ni->ni_cptlist);
- lnet_ni_decref_locked(ni, 0);
- }
-
/* move it to zombie list and nobody can find it anymore */
LASSERT(!list_empty(&ni->ni_netlist));
list_move(&ni->ni_netlist, &ni->ni_net->net_ni_zombie);
struct lnet_net *net = ni->ni_net;
lnet_net_lock(LNET_LOCK_EX);
+ lnet_ni_lock(ni);
ni->ni_state = LNET_NI_STATE_DELETING;
+ lnet_ni_unlock(ni);
lnet_ni_unlink_locked(ni);
lnet_incr_dlc_seq();
lnet_net_unlock(LNET_LOCK_EX);
lnet_net_lock(LNET_LOCK_EX);
- net->net_state = LNET_NET_STATE_DELETING;
-
list_del_init(&net->net_list);
while (!list_empty(&net->net_ni_list)) {
/* Do peer table cleanup for this net */
lnet_peer_tables_cleanup(net);
- lnet_net_lock(LNET_LOCK_EX);
- /*
- * decrement ref count on lnd only when the entire network goes
- * away
- */
- net->net_lnd->lnd_refcount--;
-
- lnet_net_unlock(LNET_LOCK_EX);
-
lnet_net_free(net);
}
lnet_shutdown_lndnets(void)
{
struct lnet_net *net;
+ struct list_head resend;
+ struct lnet_msg *msg, *tmp;
+
+ INIT_LIST_HEAD(&resend);
/* NB called holding the global mutex */
lnet_shutdown_lndnet(net);
}
+ spin_lock(&the_lnet.ln_msg_resend_lock);
+ list_splice(&the_lnet.ln_msg_resend, &resend);
+ spin_unlock(&the_lnet.ln_msg_resend_lock);
+
+ list_for_each_entry_safe(msg, tmp, &resend, msg_list) {
+ list_del_init(&msg->msg_list);
+ msg->msg_no_resend = true;
+ lnet_finalize(msg, -ECANCELED);
+ }
+
lnet_net_lock(LNET_LOCK_EX);
the_lnet.ln_state = LNET_STATE_SHUTDOWN;
lnet_net_unlock(LNET_LOCK_EX);
if (rc != 0) {
LCONSOLE_ERROR_MSG(0x105, "Error %d starting up LNI %s\n",
rc, libcfs_lnd2str(net->net_lnd->lnd_type));
- lnet_net_lock(LNET_LOCK_EX);
- net->net_lnd->lnd_refcount--;
- lnet_net_unlock(LNET_LOCK_EX);
goto failed0;
}
+ lnet_ni_lock(ni);
ni->ni_state = LNET_NI_STATE_ACTIVE;
+ lnet_ni_unlock(ni);
/* We keep a reference on the loopback net through the loopback NI */
if (net->net_lnd->lnd_type == LOLND) {
atomic_set(&ni->ni_tx_credits,
lnet_ni_tq_credits(ni) * ni->ni_ncpts);
+ atomic_set(&ni->ni_healthv, LNET_MAX_HEALTH_VALUE);
CDEBUG(D_LNI, "Added LNI %s [%d/%d/%d/%d]\n",
libcfs_nid2str(ni->ni_nid),
if (lnet_net_unique(net->net_id, &the_lnet.ln_nets, &net_l)) {
lnd_type = LNET_NETTYP(net->net_id);
- LASSERT(libcfs_isknown_lnd(lnd_type));
-
mutex_lock(&the_lnet.ln_lnd_mutex);
lnd = lnet_find_lnd_by_type(lnd_type);
}
}
- lnet_net_lock(LNET_LOCK_EX);
- lnd->lnd_refcount++;
- lnet_net_unlock(LNET_LOCK_EX);
-
net->net_lnd = lnd;
mutex_unlock(&the_lnet.ln_lnd_mutex);
* up is actually unique. if it's not fail. */
if (!lnet_ni_unique_net(&net_l->net_ni_list,
ni->ni_interfaces[0])) {
- rc = -EINVAL;
+ rc = -EEXIST;
goto failed1;
}
rc = lnet_startup_lndni(ni, tun);
- LASSERT(ni->ni_net->net_tunables.lct_peer_timeout <= 0 ||
- ni->ni_net->net_lnd->lnd_query != NULL);
-
if (rc < 0)
goto failed1;
+ LASSERT(ni->ni_net->net_tunables.lct_peer_timeout <= 0 ||
+ ni->ni_net->net_lnd->lnd_query != NULL);
+
lnet_ni_addref(ni);
list_add_tail(&ni->ni_netlist, &local_ni_list);
*/
lnet_net_free(net);
} else {
- net->net_state = LNET_NET_STATE_ACTIVE;
/*
* restore tunables after it has been overwitten by the
* lnd
lnet_net_unlock(LNET_LOCK_EX);
}
+ /* update net count */
+ lnet_current_net_count = lnet_get_net_count();
+
return ni_count;
failed1:
}
the_lnet.ln_refcount = 0;
- LNetInvalidateEQHandle(&the_lnet.ln_rc_eqh);
- INIT_LIST_HEAD(&the_lnet.ln_lnds);
INIT_LIST_HEAD(&the_lnet.ln_net_zombie);
- INIT_LIST_HEAD(&the_lnet.ln_rcd_zombie);
- INIT_LIST_HEAD(&the_lnet.ln_rcd_deathrow);
+ INIT_LIST_HEAD(&the_lnet.ln_msg_resend);
/* The hash table size is the number of bits it takes to express the set
* ln_num_routes, minus 1 (better to under estimate than over so we
*
* \pre lnet_lib_init() called with success.
* \pre All LNet users called LNetNIFini() for matching LNetNIInit() calls.
+ *
+ * As this happens at module-unload, all lnds must already be unloaded,
+ * so they must already be unregistered.
*/
void lnet_lib_exit(void)
{
- LASSERT(the_lnet.ln_refcount == 0);
+ int i;
- while (!list_empty(&the_lnet.ln_lnds))
- lnet_unregister_lnd(list_entry(the_lnet.ln_lnds.next,
- struct lnet_lnd, lnd_list));
+ LASSERT(the_lnet.ln_refcount == 0);
+ lnet_unregister_lnd(&the_lolnd);
+ for (i = 0; i < NUM_LNDS; i++)
+ LASSERT(!the_lnet.ln_lnds[i]);
lnet_destroy_locks();
}
if (rc != 0)
goto err_shutdown_lndnis;
- rc = lnet_check_routes();
- if (rc != 0)
- goto err_destroy_routes;
-
rc = lnet_rtrpools_alloc(im_a_router);
if (rc != 0)
goto err_destroy_routes;
lnet_ping_target_update(pbuf, ping_mdh);
- rc = lnet_router_checker_start();
- if (rc != 0)
+ rc = LNetEQAlloc(0, lnet_mt_event_handler, &the_lnet.ln_mt_eqh);
+ if (rc != 0) {
+ CERROR("Can't allocate monitor thread EQ: %d\n", rc);
goto err_stop_ping;
+ }
rc = lnet_push_target_init();
if (rc != 0)
- goto err_stop_router_checker;
+ goto err_stop_ping;
rc = lnet_peer_discovery_start();
if (rc != 0)
goto err_destroy_push_target;
+ rc = lnet_monitor_thr_start();
+ if (rc != 0)
+ goto err_stop_discovery_thr;
+
lnet_fault_init();
- lnet_proc_init();
+ lnet_router_debugfs_init();
mutex_unlock(&the_lnet.ln_api_mutex);
+ complete_all(&the_lnet.ln_started);
+
+ /* wait for all routers to start */
+ lnet_wait_router_start();
+
return 0;
+err_stop_discovery_thr:
+ lnet_peer_discovery_stop();
err_destroy_push_target:
lnet_push_target_fini();
-err_stop_router_checker:
- lnet_router_checker_stop();
err_stop_ping:
lnet_ping_target_fini();
err_acceptor_stop:
* \return always 0 for current implementation.
*/
int
-LNetNIFini()
+LNetNIFini(void)
{
mutex_lock(&the_lnet.ln_api_mutex);
lnet_fault_fini();
- lnet_proc_fini();
+ lnet_router_debugfs_fini();
+ lnet_monitor_thr_stop();
lnet_peer_discovery_stop();
lnet_push_target_fini();
- lnet_router_checker_stop();
lnet_ping_target_fini();
/* Teardown fns that use my own API functions BEFORE here */
struct lnet_ni *ni;
struct lnet_net *net = mynet;
+ /*
+ * It is possible that the net has been cleaned out while there is
+ * a message being sent. This function accessed the net without
+ * checking if the list is empty
+ */
if (prev == NULL) {
if (net == NULL)
net = list_entry(the_lnet.ln_nets.next, struct lnet_net,
net_list);
+ if (list_empty(&net->net_ni_list))
+ return NULL;
ni = list_entry(net->net_ni_list.next, struct lnet_ni,
ni_netlist);
/* get the next net */
net = list_entry(prev->ni_net->net_list.next, struct lnet_net,
net_list);
+ if (list_empty(&net->net_ni_list))
+ return NULL;
/* get the ni on it */
ni = list_entry(net->net_ni_list.next, struct lnet_ni,
ni_netlist);
return ni;
}
+ if (list_empty(&prev->ni_netlist))
+ return NULL;
+
/* there are more nis left */
ni = list_entry(prev->ni_netlist.next, struct lnet_ni, ni_netlist);
struct lnet_ni *ni;
struct lnet_ioctl_config_lnd_tunables *tun = NULL;
int rc, i;
- __u32 net_id;
+ __u32 net_id, lnd_type;
/* get the tunables if they are available */
if (conf->lic_cfg_hdr.ioc_len >=
tun);
net_id = LNET_NIDNET(conf->lic_nid);
+ lnd_type = LNET_NETTYP(net_id);
+
+ if (!libcfs_isknown_lnd(lnd_type)) {
+ CERROR("No valid net and lnd information provided\n");
+ return -EINVAL;
+ }
net = lnet_net_alloc(net_id, NULL);
if (!net)
return atomic_read(&lnet_dlc_seq_no);
}
+static void
+lnet_ni_set_healthv(lnet_nid_t nid, int value, bool all)
+{
+ struct lnet_net *net;
+ struct lnet_ni *ni;
+
+ lnet_net_lock(LNET_LOCK_EX);
+ list_for_each_entry(net, &the_lnet.ln_nets, net_list) {
+ list_for_each_entry(ni, &net->net_ni_list, ni_netlist) {
+ if (ni->ni_nid == nid || all) {
+ atomic_set(&ni->ni_healthv, value);
+ if (list_empty(&ni->ni_recovery) &&
+ value < LNET_MAX_HEALTH_VALUE) {
+ CERROR("manually adding local NI %s to recovery\n",
+ libcfs_nid2str(ni->ni_nid));
+ list_add_tail(&ni->ni_recovery,
+ &the_lnet.ln_mt_localNIRecovq);
+ lnet_ni_addref_locked(ni, 0);
+ }
+ if (!all) {
+ lnet_net_unlock(LNET_LOCK_EX);
+ return;
+ }
+ }
+ }
+ }
+ lnet_net_unlock(LNET_LOCK_EX);
+}
+
+static int
+lnet_get_local_ni_hstats(struct lnet_ioctl_local_ni_hstats *stats)
+{
+ int cpt, rc = 0;
+ struct lnet_ni *ni;
+ lnet_nid_t nid = stats->hlni_nid;
+
+ cpt = lnet_net_lock_current();
+ ni = lnet_nid2ni_locked(nid, cpt);
+
+ if (!ni) {
+ rc = -ENOENT;
+ goto unlock;
+ }
+
+ stats->hlni_local_interrupt = atomic_read(&ni->ni_hstats.hlt_local_interrupt);
+ stats->hlni_local_dropped = atomic_read(&ni->ni_hstats.hlt_local_dropped);
+ stats->hlni_local_aborted = atomic_read(&ni->ni_hstats.hlt_local_aborted);
+ stats->hlni_local_no_route = atomic_read(&ni->ni_hstats.hlt_local_no_route);
+ stats->hlni_local_timeout = atomic_read(&ni->ni_hstats.hlt_local_timeout);
+ stats->hlni_local_error = atomic_read(&ni->ni_hstats.hlt_local_error);
+ stats->hlni_health_value = atomic_read(&ni->ni_healthv);
+
+unlock:
+ lnet_net_unlock(cpt);
+
+ return rc;
+}
+
+static int
+lnet_get_local_ni_recovery_list(struct lnet_ioctl_recovery_list *list)
+{
+ struct lnet_ni *ni;
+ int i = 0;
+
+ lnet_net_lock(LNET_LOCK_EX);
+ list_for_each_entry(ni, &the_lnet.ln_mt_localNIRecovq, ni_recovery) {
+ list->rlst_nid_array[i] = ni->ni_nid;
+ i++;
+ if (i >= LNET_MAX_SHOW_NUM_NID)
+ break;
+ }
+ lnet_net_unlock(LNET_LOCK_EX);
+ list->rlst_num_nids = i;
+
+ return 0;
+}
+
+static int
+lnet_get_peer_ni_recovery_list(struct lnet_ioctl_recovery_list *list)
+{
+ struct lnet_peer_ni *lpni;
+ int i = 0;
+
+ lnet_net_lock(LNET_LOCK_EX);
+ list_for_each_entry(lpni, &the_lnet.ln_mt_peerNIRecovq, lpni_recovery) {
+ list->rlst_nid_array[i] = lpni->lpni_nid;
+ i++;
+ if (i >= LNET_MAX_SHOW_NUM_NID)
+ break;
+ }
+ lnet_net_unlock(LNET_LOCK_EX);
+ list->rlst_num_nids = i;
+
+ return 0;
+}
+
/**
* LNet ioctl handler.
*
case IOC_LIBCFS_FAIL_NID:
return lnet_fail_nid(data->ioc_nid, data->ioc_count);
- case IOC_LIBCFS_ADD_ROUTE:
+ case IOC_LIBCFS_ADD_ROUTE: {
+ /* default router sensitivity to 1 */
+ unsigned int sensitivity = 1;
config = arg;
if (config->cfg_hdr.ioc_len < sizeof(*config))
return -EINVAL;
+ if (config->cfg_config_u.cfg_route.rtr_sensitivity) {
+ sensitivity =
+ config->cfg_config_u.cfg_route.rtr_sensitivity;
+ }
+
mutex_lock(&the_lnet.ln_api_mutex);
rc = lnet_add_route(config->cfg_net,
config->cfg_config_u.cfg_route.rtr_hop,
config->cfg_nid,
config->cfg_config_u.cfg_route.
- rtr_priority);
- if (rc == 0) {
- rc = lnet_check_routes();
- if (rc != 0)
- lnet_del_route(config->cfg_net,
- config->cfg_nid);
- }
+ rtr_priority, sensitivity);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
+ }
case IOC_LIBCFS_DEL_ROUTE:
config = arg;
&config->cfg_nid,
&config->cfg_config_u.cfg_route.rtr_flags,
&config->cfg_config_u.cfg_route.
- rtr_priority);
+ rtr_priority,
+ &config->cfg_config_u.cfg_route.
+ rtr_sensitivity);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
return rc;
}
+ case IOC_LIBCFS_GET_LOCAL_HSTATS: {
+ struct lnet_ioctl_local_ni_hstats *stats = arg;
+
+ if (stats->hlni_hdr.ioc_len < sizeof(*stats))
+ return -EINVAL;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ rc = lnet_get_local_ni_hstats(stats);
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return rc;
+ }
+
+ case IOC_LIBCFS_GET_RECOVERY_QUEUE: {
+ struct lnet_ioctl_recovery_list *list = arg;
+ if (list->rlst_hdr.ioc_len < sizeof(*list))
+ return -EINVAL;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ if (list->rlst_type == LNET_HEALTH_TYPE_LOCAL_NI)
+ rc = lnet_get_local_ni_recovery_list(list);
+ else
+ rc = lnet_get_peer_ni_recovery_list(list);
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return rc;
+ }
+
case IOC_LIBCFS_ADD_PEER_NI: {
struct lnet_ioctl_peer_cfg *cfg = arg;
mutex_lock(&the_lnet.ln_api_mutex);
rc = lnet_get_peer_list(&cfg->prcfg_count, &cfg->prcfg_size,
- (lnet_process_id_t __user *)cfg->prcfg_bulk);
+ (struct lnet_process_id __user *)cfg->prcfg_bulk);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
}
- case IOC_LIBCFS_NOTIFY_ROUTER: {
- unsigned long jiffies_passed;
+ case IOC_LIBCFS_SET_HEALHV: {
+ struct lnet_ioctl_reset_health_cfg *cfg = arg;
+ int value;
+ if (cfg->rh_hdr.ioc_len < sizeof(*cfg))
+ return -EINVAL;
+ if (cfg->rh_value < 0 ||
+ cfg->rh_value > LNET_MAX_HEALTH_VALUE)
+ value = LNET_MAX_HEALTH_VALUE;
+ else
+ value = cfg->rh_value;
+ CDEBUG(D_NET, "Manually setting healthv to %d for %s:%s. all = %d\n",
+ value, (cfg->rh_type == LNET_HEALTH_TYPE_LOCAL_NI) ?
+ "local" : "peer", libcfs_nid2str(cfg->rh_nid), cfg->rh_all);
+ mutex_lock(&the_lnet.ln_api_mutex);
+ if (cfg->rh_type == LNET_HEALTH_TYPE_LOCAL_NI)
+ lnet_ni_set_healthv(cfg->rh_nid, value,
+ cfg->rh_all);
+ else
+ lnet_peer_ni_set_healthv(cfg->rh_nid, value,
+ cfg->rh_all);
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return 0;
+ }
- jiffies_passed = ktime_get_real_seconds() - data->ioc_u64[0];
- jiffies_passed = cfs_time_seconds(jiffies_passed);
+ case IOC_LIBCFS_NOTIFY_ROUTER: {
+ time64_t deadline = ktime_get_real_seconds() - data->ioc_u64[0];
- return lnet_notify(NULL, data->ioc_nid, data->ioc_flags,
- jiffies - jiffies_passed);
+ /* The deadline passed in by the user should be some time in
+ * seconds in the future since the UNIX epoch. We have to map
+ * that deadline to the wall clock.
+ */
+ deadline += ktime_get_seconds();
+ return lnet_notify(NULL, data->ioc_nid, data->ioc_flags, false,
+ deadline);
}
case IOC_LIBCFS_LNET_DIST:
/* If timeout is negative then set default of 3 minutes */
if (((s32)data->ioc_u32[1] <= 0) ||
data->ioc_u32[1] > (DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC))
- timeout = msecs_to_jiffies(DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC);
+ timeout = cfs_time_seconds(DEFAULT_PEER_TIMEOUT);
else
- timeout = msecs_to_jiffies(data->ioc_u32[1]);
+ timeout = nsecs_to_jiffies(data->ioc_u32[1] * NSEC_PER_MSEC);
rc = lnet_ping(id, timeout, data->ioc_pbuf1,
data->ioc_plen1 / sizeof(struct lnet_process_id));
/* If timeout is negative then set default of 3 minutes */
if (((s32)ping->op_param) <= 0 ||
ping->op_param > (DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC))
- timeout = msecs_to_jiffies(DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC);
+ timeout = cfs_time_seconds(DEFAULT_PEER_TIMEOUT);
else
- timeout = msecs_to_jiffies(ping->op_param);
+ timeout = nsecs_to_jiffies(ping->op_param * NSEC_PER_MSEC);
rc = lnet_ping(ping->ping_id, timeout,
ping->ping_buf,
if (rc < 0)
return rc;
+ mutex_lock(&the_lnet.ln_api_mutex);
lp = lnet_find_peer(ping->ping_id.nid);
if (lp) {
ping->ping_id.nid = lp->lp_primary_nid;
ping->mr_info = lnet_peer_is_multi_rail(lp);
+ lnet_peer_decref_locked(lp);
}
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
ping->ping_count = rc;
return 0;
}
discover->ping_count);
if (rc < 0)
return rc;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
lp = lnet_find_peer(discover->ping_id.nid);
if (lp) {
discover->ping_id.nid = lp->lp_primary_nid;
discover->mr_info = lnet_peer_is_multi_rail(lp);
+ lnet_peer_decref_locked(lp);
}
+ mutex_unlock(&the_lnet.ln_api_mutex);
discover->ping_count = rc;
return 0;
int which;
int unlinked = 0;
int replied = 0;
- const signed long a_long_time = msecs_to_jiffies(60 * MSEC_PER_SEC);
+ const signed long a_long_time = cfs_time_seconds(60);
struct lnet_ping_buffer *pbuf;
struct lnet_process_id tmpid;
int i;
rc = LNetGet(LNET_NID_ANY, mdh, id,
LNET_RESERVED_PORTAL,
- LNET_PROTO_PING_MATCHBITS, 0);
+ LNET_PROTO_PING_MATCHBITS, 0, false);
if (rc != 0) {
/* Don't CERROR; this could be deliberate! */
}
static int
-lnet_discover(lnet_process_id_t id, __u32 force, lnet_process_id_t __user *ids,
- int n_ids)
+lnet_discover(struct lnet_process_id id, __u32 force,
+ struct lnet_process_id __user *ids, int n_ids)
{
struct lnet_peer_ni *lpni;
struct lnet_peer_ni *p;
struct lnet_peer *lp;
- lnet_process_id_t *buf;
+ struct lnet_process_id *buf;
int cpt;
int i;
int rc;
return rc;
}
+
+/**
+ * Retrieve peer discovery status.
+ *
+ * \retval 1 if lnet_peer_discovery_disabled is 0
+ * \retval 0 if lnet_peer_discovery_disabled is 1
+ */
+int
+LNetGetPeerDiscoveryStatus(void)
+{
+ return !lnet_peer_discovery_disabled;
+}
+EXPORT_SYMBOL(LNetGetPeerDiscoveryStatus);