@@ -534,6 +534,8 @@ int lnet_get_peer_list(u32 *countp, u32 *sizep,
int lnet_rtrpools_enable(void);
void lnet_rtrpools_disable(void);
void lnet_rtrpools_free(int keep_pools);
+void lnet_rtr_transfer_to_peer(struct lnet_peer *src,
+ struct lnet_peer *target);
struct lnet_remotenet *lnet_find_rnet_locked(u32 net);
int lnet_dyn_add_net(struct lnet_ioctl_config_data *conf);
int lnet_dyn_del_net(u32 net);
@@ -1355,6 +1355,18 @@ struct lnet_peer_net *
}
/* If this is the primary NID, destroy the peer. */
if (lnet_peer_ni_is_primary(lpni)) {
+ struct lnet_peer *rtr_lp =
+ lpni->lpni_peer_net->lpn_peer;
+ int rtr_refcount = rtr_lp->lp_rtr_refcount;
+
+ /* if we're trying to delete a router it means
+ * we're moving this peer NI to a new peer so must
+ * transfer router properties to the new peer
+ */
+ if (rtr_refcount > 0) {
+ flags |= LNET_PEER_RTR_NI_FORCE_DEL;
+ lnet_rtr_transfer_to_peer(rtr_lp, lp);
+ }
lnet_peer_del(lpni->lpni_peer_net->lpn_peer);
lpni = lnet_peer_ni_alloc(nid);
if (!lpni) {
@@ -136,6 +136,35 @@ static int rtr_sensitivity_set(const char *val,
return 0;
}
+void
+lnet_rtr_transfer_to_peer(struct lnet_peer *src, struct lnet_peer *target)
+{
+ struct lnet_route *route;
+
+ lnet_net_lock(LNET_LOCK_EX);
+ target->lp_rtr_refcount += src->lp_rtr_refcount;
+ /* move the list of queued messages to the new peer */
+ list_splice_init(&src->lp_rtrq, &target->lp_rtrq);
+ /* move all the routes that reference the peer */
+ list_splice_init(&src->lp_routes, &target->lp_routes);
+ /* update all the routes to point to the new peer */
+ list_for_each_entry(route, &target->lp_routes, lr_gwlist)
+ route->lr_gateway = target;
+ /* remove the old peer from the ln_routers list */
+ list_del_init(&src->lp_rtr_list);
+ /* add the new peer to the ln_routers list */
+ if (list_empty(&target->lp_rtr_list)) {
+ lnet_peer_addref_locked(target);
+ list_add_tail(&target->lp_rtr_list, &the_lnet.ln_routers);
+ }
+ /* reset the ref count on the old peer and decrement its ref count */
+ src->lp_rtr_refcount = 0;
+ lnet_peer_decref_locked(src);
+ /* update the router version */
+ the_lnet.ln_routers_version++;
+ lnet_net_unlock(LNET_LOCK_EX);
+}
+
int
lnet_peers_start_down(void)
{