- cfs_list_t *e;
- lnet_remotenet_t *rnet;
- lnet_remotenet_t *rnet2;
- lnet_route_t *route;
- lnet_ni_t *ni;
- int add_route;
- int rc;
-
- CDEBUG(D_NET, "Add route: net %s hops %u gw %s\n",
- libcfs_net2str(net), hops, libcfs_nid2str(gateway));
-
- if (gateway == LNET_NID_ANY ||
- LNET_NETTYP(LNET_NIDNET(gateway)) == LOLND ||
- net == LNET_NIDNET(LNET_NID_ANY) ||
- LNET_NETTYP(net) == LOLND ||
- LNET_NIDNET(gateway) == net ||
- hops < 1 || hops > 255)
- return (-EINVAL);
-
- if (lnet_islocalnet(net)) /* it's a local network */
- return 0; /* ignore the route entry */
-
- /* Assume net, route, all new */
- LIBCFS_ALLOC(route, sizeof(*route));
- LIBCFS_ALLOC(rnet, sizeof(*rnet));
- if (route == NULL || rnet == NULL) {
- CERROR("Out of memory creating route %s %d %s\n",
- libcfs_net2str(net), hops, libcfs_nid2str(gateway));
- if (route != NULL)
- LIBCFS_FREE(route, sizeof(*route));
- if (rnet != NULL)
- LIBCFS_FREE(rnet, sizeof(*rnet));
- return -ENOMEM;
- }
-
- CFS_INIT_LIST_HEAD(&rnet->lrn_routes);
- rnet->lrn_net = net;
- route->lr_hops = hops;
-
- LNET_LOCK();
-
- rc = lnet_nid2peer_locked(&route->lr_gateway, gateway);
- if (rc != 0) {
- LNET_UNLOCK();
-
- LIBCFS_FREE(route, sizeof(*route));
- LIBCFS_FREE(rnet, sizeof(*rnet));
-
- if (rc == -EHOSTUNREACH) /* gateway is not on a local net */
- return 0; /* ignore the route entry */
-
- CERROR("Error %d creating route %s %d %s\n", rc,
- libcfs_net2str(net), hops, libcfs_nid2str(gateway));
- return rc;
- }
-
- LASSERT (!the_lnet.ln_shutdown);
-
- rnet2 = lnet_find_net_locked(net);
- if (rnet2 == NULL) {
- /* new network */
- cfs_list_add_tail(&rnet->lrn_list, &the_lnet.ln_remote_nets);
- rnet2 = rnet;
- }
-
- /* Search for a duplicate route (it's a NOOP if it is) */
- add_route = 1;
- cfs_list_for_each (e, &rnet2->lrn_routes) {
- lnet_route_t *route2 = cfs_list_entry(e, lnet_route_t, lr_list);
-
- if (route2->lr_gateway == route->lr_gateway) {
- add_route = 0;
- break;
- }
-
- /* our lookups must be true */
- LASSERT (route2->lr_gateway->lp_nid != gateway);
- }
-
- if (add_route) {
- ni = route->lr_gateway->lp_ni;
- lnet_ni_addref_locked(ni);
-
- lnet_add_route_to_rnet(rnet2, route);
- LNET_UNLOCK();
-
- /* XXX Assume alive */
- if (ni->ni_lnd->lnd_notify != NULL)
- (ni->ni_lnd->lnd_notify)(ni, gateway, 1);
-
- lnet_ni_decref(ni);
- } else {
- lnet_peer_decref_locked(route->lr_gateway);
- LNET_UNLOCK();
- LIBCFS_FREE(route, sizeof(*route));
- }
-
- if (rnet != rnet2)
- LIBCFS_FREE(rnet, sizeof(*rnet));
-
- return 0;
+ struct list_head *e;
+ lnet_remotenet_t *rnet;
+ lnet_remotenet_t *rnet2;
+ lnet_route_t *route;
+ lnet_ni_t *ni;
+ int add_route;
+ int rc;
+
+ CDEBUG(D_NET, "Add route: net %s hops %u priority %u gw %s\n",
+ libcfs_net2str(net), hops, priority, libcfs_nid2str(gateway));
+
+ if (gateway == LNET_NID_ANY ||
+ LNET_NETTYP(LNET_NIDNET(gateway)) == LOLND ||
+ net == LNET_NIDNET(LNET_NID_ANY) ||
+ LNET_NETTYP(net) == LOLND ||
+ LNET_NIDNET(gateway) == net ||
+ hops < 1 || hops > 255)
+ return -EINVAL;
+
+ if (lnet_islocalnet(net)) /* it's a local network */
+ return 0; /* ignore the route entry */
+
+ /* Assume net, route, all new */
+ LIBCFS_ALLOC(route, sizeof(*route));
+ LIBCFS_ALLOC(rnet, sizeof(*rnet));
+ if (route == NULL || rnet == NULL) {
+ CERROR("Out of memory creating route %s %d %s\n",
+ libcfs_net2str(net), hops, libcfs_nid2str(gateway));
+ if (route != NULL)
+ LIBCFS_FREE(route, sizeof(*route));
+ if (rnet != NULL)
+ LIBCFS_FREE(rnet, sizeof(*rnet));
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&rnet->lrn_routes);
+ rnet->lrn_net = net;
+ route->lr_hops = hops;
+ route->lr_net = net;
+ route->lr_priority = priority;
+
+ lnet_net_lock(LNET_LOCK_EX);
+
+ rc = lnet_nid2peer_locked(&route->lr_gateway, gateway, LNET_LOCK_EX);
+ if (rc != 0) {
+ lnet_net_unlock(LNET_LOCK_EX);
+
+ LIBCFS_FREE(route, sizeof(*route));
+ LIBCFS_FREE(rnet, sizeof(*rnet));
+
+ if (rc == -EHOSTUNREACH) /* gateway is not on a local net. */
+ return 0; /* ignore the route entry */
+ CERROR("Error %d creating route %s %d %s\n", rc,
+ libcfs_net2str(net), hops,
+ libcfs_nid2str(gateway));
+ return rc;
+ }
+
+ LASSERT(!the_lnet.ln_shutdown);
+
+ rnet2 = lnet_find_net_locked(net);
+ if (rnet2 == NULL) {
+ /* new network */
+ list_add_tail(&rnet->lrn_list, lnet_net2rnethash(net));
+ rnet2 = rnet;
+ }
+
+ /* Search for a duplicate route (it's a NOOP if it is) */
+ add_route = 1;
+ list_for_each(e, &rnet2->lrn_routes) {
+ lnet_route_t *route2 = list_entry(e, lnet_route_t, lr_list);
+
+ if (route2->lr_gateway == route->lr_gateway) {
+ add_route = 0;
+ break;
+ }
+
+ /* our lookups must be true */
+ LASSERT(route2->lr_gateway->lp_nid != gateway);
+ }
+
+ if (add_route) {
+ lnet_peer_addref_locked(route->lr_gateway); /* +1 for notify */
+ lnet_add_route_to_rnet(rnet2, route);
+
+ ni = route->lr_gateway->lp_ni;
+ lnet_net_unlock(LNET_LOCK_EX);
+
+ /* XXX Assume alive */
+ if (ni->ni_lnd->lnd_notify != NULL)
+ (ni->ni_lnd->lnd_notify)(ni, gateway, 1);
+
+ lnet_net_lock(LNET_LOCK_EX);
+ }
+
+ /* -1 for notify or !add_route */
+ lnet_peer_decref_locked(route->lr_gateway);
+ lnet_net_unlock(LNET_LOCK_EX);
+
+ if (!add_route)
+ LIBCFS_FREE(route, sizeof(*route));
+
+ if (rnet != rnet2)
+ LIBCFS_FREE(rnet, sizeof(*rnet));
+
+ return 0;