#define DEBUG_SUBSYSTEM S_LNET
#include <lnet/lib-lnet.h>
+#ifdef __KERNEL__
+#include <linux/log2.h>
+#endif
#ifdef __KERNEL__
#define D_LNI D_CONSOLE
CFS_MODULE_PARM(routes, "s", charp, 0444,
"routes to non-local networks");
+static int rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT;
+CFS_MODULE_PARM(rnet_htable_size, "i", int, 0444,
+ "size of remote network hash table");
+
char *
lnet_get_routes(void)
{
#endif
static int
+lnet_create_remote_nets_table(void)
+{
+ int i;
+ cfs_list_t *hash;
+
+ LASSERT(the_lnet.ln_remote_nets_hash == NULL);
+ LASSERT(the_lnet.ln_remote_nets_hbits > 0);
+ LIBCFS_ALLOC(hash, LNET_REMOTE_NETS_HASH_SIZE * sizeof(*hash));
+ if (hash == NULL) {
+ CERROR("Failed to create remote nets hash table\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++)
+ CFS_INIT_LIST_HEAD(&hash[i]);
+ the_lnet.ln_remote_nets_hash = hash;
+ return 0;
+}
+
+static void
+lnet_destroy_remote_nets_table(void)
+{
+ int i;
+ cfs_list_t *hash;
+
+ if (the_lnet.ln_remote_nets_hash == NULL)
+ return;
+
+ for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++)
+ LASSERT(cfs_list_empty(&the_lnet.ln_remote_nets_hash[i]));
+
+ LIBCFS_FREE(the_lnet.ln_remote_nets_hash,
+ LNET_REMOTE_NETS_HASH_SIZE * sizeof(*hash));
+ the_lnet.ln_remote_nets_hash = NULL;
+}
+
+static int
lnet_create_locks(void)
{
lnet_init_locks();
CFS_INIT_LIST_HEAD(&the_lnet.ln_nis);
CFS_INIT_LIST_HEAD(&the_lnet.ln_nis_cpt);
CFS_INIT_LIST_HEAD(&the_lnet.ln_nis_zombie);
- CFS_INIT_LIST_HEAD(&the_lnet.ln_remote_nets);
CFS_INIT_LIST_HEAD(&the_lnet.ln_routers);
+ rc = lnet_create_remote_nets_table();
+ if (rc != 0)
+ goto failed;
+
the_lnet.ln_interface_cookie = lnet_create_interface_cookie();
the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(),
cfs_percpt_free(the_lnet.ln_counters);
the_lnet.ln_counters = NULL;
}
+ lnet_destroy_remote_nets_table();
return 0;
}
LASSERT(!the_lnet.ln_shutdown);
LASSERT(the_lnet.ln_refcount == 0);
LASSERT(cfs_list_empty(&the_lnet.ln_nis_zombie));
- LASSERT(cfs_list_empty(&the_lnet.ln_remote_nets));
lnet_net_lock(LNET_LOCK_EX);
the_lnet.ln_shutdown = 1; /* flag shutdown */
CFS_INIT_LIST_HEAD(&the_lnet.ln_rcd_deathrow);
#ifdef __KERNEL__
+ /* 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
+ * don't waste memory). */
+ if (rnet_htable_size <= 0)
+ rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT;
+ else if (rnet_htable_size > LNET_REMOTE_NETS_HASH_MAX)
+ rnet_htable_size = LNET_REMOTE_NETS_HASH_MAX;
+ the_lnet.ln_remote_nets_hbits = max_t(int, 1,
+ order_base_2(rnet_htable_size) - 1);
+
/* All LNDs apart from the LOLND are in separate modules. They
* register themselves when their module loads, and unregister
* themselves when their module is unloaded. */
#else
+ the_lnet.ln_remote_nets_hbits = 8;
+
/* Register LNDs
* NB the order here determines default 'networks=' order */
# ifdef HAVE_LIBPTHREAD
lnet_remotenet_t *
lnet_find_net_locked (__u32 net)
{
- lnet_remotenet_t *rnet;
- cfs_list_t *tmp;
+ lnet_remotenet_t *rnet;
+ cfs_list_t *tmp;
+ cfs_list_t *rn_list;
- LASSERT (!the_lnet.ln_shutdown);
+ LASSERT(!the_lnet.ln_shutdown);
- cfs_list_for_each (tmp, &the_lnet.ln_remote_nets) {
- rnet = cfs_list_entry(tmp, lnet_remotenet_t, lrn_list);
+ rn_list = lnet_net2rnethash(net);
+ cfs_list_for_each(tmp, rn_list) {
+ rnet = cfs_list_entry(tmp, lnet_remotenet_t, lrn_list);
- if (rnet->lrn_net == net)
- return rnet;
- }
- return NULL;
+ if (rnet->lrn_net == net)
+ return rnet;
+ }
+ return NULL;
}
static void lnet_shuffle_seed(void)
rnet2 = lnet_find_net_locked(net);
if (rnet2 == NULL) {
/* new network */
- cfs_list_add_tail(&rnet->lrn_list, &the_lnet.ln_remote_nets);
+ cfs_list_add_tail(&rnet->lrn_list, lnet_net2rnethash(net));
rnet2 = rnet;
}
cfs_list_t *e1;
cfs_list_t *e2;
int cpt;
+ cfs_list_t *rn_list;
+ int i;
cpt = lnet_net_lock_current();
- cfs_list_for_each(e1, &the_lnet.ln_remote_nets) {
- rnet = cfs_list_entry(e1, lnet_remotenet_t, lrn_list);
+ for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++) {
+ rn_list = &the_lnet.ln_remote_nets_hash[i];
+ cfs_list_for_each(e1, rn_list) {
+ rnet = cfs_list_entry(e1, lnet_remotenet_t, lrn_list);
- route2 = NULL;
- cfs_list_for_each(e2, &rnet->lrn_routes) {
- lnet_nid_t nid1;
- lnet_nid_t nid2;
- int net;
+ route2 = NULL;
+ cfs_list_for_each(e2, &rnet->lrn_routes) {
+ lnet_nid_t nid1;
+ lnet_nid_t nid2;
+ int net;
- route = cfs_list_entry(e2, lnet_route_t, lr_list);
+ route = cfs_list_entry(e2, lnet_route_t,
+ lr_list);
- if (route2 == NULL) {
- route2 = route;
- continue;
- }
+ if (route2 == NULL) {
+ route2 = route;
+ continue;
+ }
- if (route->lr_gateway->lp_ni ==
- route2->lr_gateway->lp_ni)
- continue;
+ if (route->lr_gateway->lp_ni ==
+ route2->lr_gateway->lp_ni)
+ continue;
- nid1 = route->lr_gateway->lp_nid;
- nid2 = route2->lr_gateway->lp_nid;
- net = rnet->lrn_net;
+ nid1 = route->lr_gateway->lp_nid;
+ nid2 = route2->lr_gateway->lp_nid;
+ net = rnet->lrn_net;
- lnet_net_unlock(cpt);
+ lnet_net_unlock(cpt);
- CERROR("Routes to %s via %s and %s not supported\n",
- libcfs_net2str(net), libcfs_nid2str(nid1),
- libcfs_nid2str(nid2));
- return -EINVAL;
+ CERROR("Routes to %s via %s and %s not "
+ "supported\n",
+ libcfs_net2str(net),
+ libcfs_nid2str(nid1),
+ libcfs_nid2str(nid2));
+ return -EINVAL;
+ }
}
}
lnet_del_route(__u32 net, lnet_nid_t gw_nid)
{
struct lnet_peer *gateway;
- lnet_remotenet_t *rnet;
- lnet_route_t *route;
- cfs_list_t *e1;
- cfs_list_t *e2;
- int rc = -ENOENT;
+ lnet_remotenet_t *rnet;
+ lnet_route_t *route;
+ cfs_list_t *e1;
+ cfs_list_t *e2;
+ int rc = -ENOENT;
+ cfs_list_t *rn_list;
+ int idx = 0;
- CDEBUG(D_NET, "Del route: net %s : gw %s\n",
- libcfs_net2str(net), libcfs_nid2str(gw_nid));
+ CDEBUG(D_NET, "Del route: net %s : gw %s\n",
+ libcfs_net2str(net), libcfs_nid2str(gw_nid));
- /* NB Caller may specify either all routes via the given gateway
- * or a specific route entry actual NIDs) */
+ /* NB Caller may specify either all routes via the given gateway
+ * or a specific route entry actual NIDs) */
- again:
lnet_net_lock(LNET_LOCK_EX);
+ if (net == LNET_NIDNET(LNET_NID_ANY))
+ rn_list = &the_lnet.ln_remote_nets_hash[0];
+ else
+ rn_list = lnet_net2rnethash(net);
- cfs_list_for_each (e1, &the_lnet.ln_remote_nets) {
- rnet = cfs_list_entry(e1, lnet_remotenet_t, lrn_list);
+ again:
+ cfs_list_for_each(e1, rn_list) {
+ rnet = cfs_list_entry(e1, lnet_remotenet_t, lrn_list);
- if (!(net == LNET_NIDNET(LNET_NID_ANY) ||
- net == rnet->lrn_net))
- continue;
+ if (!(net == LNET_NIDNET(LNET_NID_ANY) ||
+ net == rnet->lrn_net))
+ continue;
- cfs_list_for_each (e2, &rnet->lrn_routes) {
- route = cfs_list_entry(e2, lnet_route_t, lr_list);
+ cfs_list_for_each(e2, &rnet->lrn_routes) {
+ route = cfs_list_entry(e2, lnet_route_t, lr_list);
gateway = route->lr_gateway;
if (!(gw_nid == LNET_NID_ANY ||
cfs_list_del(&route->lr_list);
cfs_list_del(&route->lr_gwlist);
- the_lnet.ln_remote_nets_version++;
+ the_lnet.ln_remote_nets_version++;
- if (cfs_list_empty(&rnet->lrn_routes))
- cfs_list_del(&rnet->lrn_list);
- else
- rnet = NULL;
+ if (cfs_list_empty(&rnet->lrn_routes))
+ cfs_list_del(&rnet->lrn_list);
+ else
+ rnet = NULL;
lnet_rtr_decref_locked(gateway);
lnet_peer_decref_locked(gateway);
lnet_net_unlock(LNET_LOCK_EX);
- LIBCFS_FREE(route, sizeof (*route));
+ LIBCFS_FREE(route, sizeof(*route));
- if (rnet != NULL)
- LIBCFS_FREE(rnet, sizeof(*rnet));
+ if (rnet != NULL)
+ LIBCFS_FREE(rnet, sizeof(*rnet));
- rc = 0;
- goto again;
- }
- }
+ rc = 0;
+ lnet_net_lock(LNET_LOCK_EX);
+ goto again;
+ }
+ }
+ if (net == LNET_NIDNET(LNET_NID_ANY) &&
+ ++idx < LNET_REMOTE_NETS_HASH_SIZE) {
+ rn_list = &the_lnet.ln_remote_nets_hash[idx];
+ goto again;
+ }
lnet_net_unlock(LNET_LOCK_EX);
+
return rc;
}
lnet_remotenet_t *rnet;
lnet_route_t *route;
int cpt;
+ int i;
+ cfs_list_t *rn_list;
cpt = lnet_net_lock_current();
- cfs_list_for_each (e1, &the_lnet.ln_remote_nets) {
- rnet = cfs_list_entry(e1, lnet_remotenet_t, lrn_list);
-
- cfs_list_for_each (e2, &rnet->lrn_routes) {
- route = cfs_list_entry(e2, lnet_route_t, lr_list);
-
- if (idx-- == 0) {
- *net = rnet->lrn_net;
- *hops = route->lr_hops;
- *gateway = route->lr_gateway->lp_nid;
- *alive = route->lr_gateway->lp_alive;
- lnet_net_unlock(cpt);
- return 0;
+ for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++) {
+ rn_list = &the_lnet.ln_remote_nets_hash[i];
+ cfs_list_for_each(e1, rn_list) {
+ rnet = cfs_list_entry(e1, lnet_remotenet_t, lrn_list);
+
+ cfs_list_for_each(e2, &rnet->lrn_routes) {
+ route = cfs_list_entry(e2, lnet_route_t,
+ lr_list);
+
+ if (idx-- == 0) {
+ *net = rnet->lrn_net;
+ *hops = route->lr_hops;
+ *gateway = route->lr_gateway->lp_nid;
+ *alive = route->lr_gateway->lp_alive;
+ lnet_net_unlock(cpt);
+ return 0;
+ }
}
}
}