router.c

来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,077 行 · 第 1/3 页

C
1,077
字号
                        }                        /* our loopups must be true */                        LASSERT (route2->lr_gateway->lp_nid != gateway);                }        }                if (add_route) {                ni = route->lr_gateway->lp_ni;                lnet_ni_addref_locked(ni);                                LASSERT (rc == 0);                list_add_tail(&route->lr_list, &rnet2->lrn_routes);                the_lnet.ln_remote_nets_version++;                lnet_rtr_addref_locked(route->lr_gateway);                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));        while (!list_empty(&zombies)) {                route = list_entry(zombies.next, lnet_route_t, lr_list);                list_del(&route->lr_list);                                LNET_LOCK();                lnet_rtr_decref_locked(route->lr_gateway);                lnet_peer_decref_locked(route->lr_gateway);                LNET_UNLOCK();                LIBCFS_FREE(route, sizeof(*route));        }        return rc;}intlnet_check_routes (void){        lnet_remotenet_t    *rnet;        lnet_route_t        *route;        lnet_route_t        *route2;        struct list_head    *e1;        struct list_head    *e2;        LNET_LOCK();        list_for_each (e1, &the_lnet.ln_remote_nets) {                rnet = list_entry(e1, lnet_remotenet_t, lrn_list);                route2 = NULL;                list_for_each (e2, &rnet->lrn_routes) {                        route = list_entry(e2, lnet_route_t, lr_list);                        if (route2 == NULL)                                route2 = route;                        else if (route->lr_gateway->lp_ni !=                                 route2->lr_gateway->lp_ni) {                                LNET_UNLOCK();                                                                CERROR("Routes to %s via %s and %s not supported\n",                                       libcfs_net2str(rnet->lrn_net),                                       libcfs_nid2str(route->lr_gateway->lp_nid),                                       libcfs_nid2str(route2->lr_gateway->lp_nid));                                return -EINVAL;                        }                }        }                LNET_UNLOCK();        return 0;}intlnet_del_route (__u32 net, lnet_nid_t gw_nid){        lnet_remotenet_t    *rnet;        lnet_route_t        *route;        struct list_head    *e1;        struct list_head    *e2;        int                  rc = -ENOENT;        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) */ again:        LNET_LOCK();        list_for_each (e1, &the_lnet.ln_remote_nets) {                rnet = list_entry(e1, lnet_remotenet_t, lrn_list);                if (!(net == LNET_NIDNET(LNET_NID_ANY) ||                      net == rnet->lrn_net))                        continue;                list_for_each (e2, &rnet->lrn_routes) {                        route = list_entry(e2, lnet_route_t, lr_list);                        if (!(gw_nid == LNET_NID_ANY ||                              gw_nid == route->lr_gateway->lp_nid))                                continue;                        list_del(&route->lr_list);                        the_lnet.ln_remote_nets_version++;                        if (list_empty(&rnet->lrn_routes))                                list_del(&rnet->lrn_list);                        else                                rnet = NULL;                        lnet_rtr_decref_locked(route->lr_gateway);                        lnet_peer_decref_locked(route->lr_gateway);                        LNET_UNLOCK();                        LIBCFS_FREE(route, sizeof (*route));                        if (rnet != NULL)                                LIBCFS_FREE(rnet, sizeof(*rnet));                        rc = 0;                        goto again;                }        }        LNET_UNLOCK();        return rc;}voidlnet_destroy_routes (void){        lnet_del_route(LNET_NIDNET(LNET_NID_ANY), LNET_NID_ANY);}intlnet_get_route (int idx, __u32 *net, __u32 *hops,               lnet_nid_t *gateway, __u32 *alive){	struct list_head    *e1;	struct list_head    *e2;        lnet_remotenet_t    *rnet;        lnet_route_t        *route;        LNET_LOCK();        list_for_each (e1, &the_lnet.ln_remote_nets) {                rnet = list_entry(e1, lnet_remotenet_t, lrn_list);                list_for_each (e2, &rnet->lrn_routes) {                        route = list_entry(e2, lnet_route_t, lr_list);                        if (idx-- == 0) {                                *net     = rnet->lrn_net;                                *hops    = rnet->lrn_hops;                                *gateway = route->lr_gateway->lp_nid;                                *alive   = route->lr_gateway->lp_alive;                                LNET_UNLOCK();                                return 0;                        }                }        }        LNET_UNLOCK();        return -ENOENT;}#if defined(__KERNEL__) && defined(LNET_ROUTER)static voidlnet_router_checker_event (lnet_event_t *event){        /* CAVEAT EMPTOR: I'm called with LNET_LOCKed and I'm not allowed to         * drop it (that's how come I see _every_ event, even ones that would         * overflow my EQ) */        lnet_peer_t   *lp;        lnet_nid_t     nid;        if (event->unlinked) {                /* The router checker thread has unlinked the rc_md                 * and exited. */                LASSERT (the_lnet.ln_rc_state == LNET_RC_STATE_UNLINKING);                the_lnet.ln_rc_state = LNET_RC_STATE_UNLINKED;                 mutex_up(&the_lnet.ln_rc_signal);                 return;        }        LASSERT (event->type == LNET_EVENT_SEND ||                  event->type == LNET_EVENT_REPLY);                nid = (event->type == LNET_EVENT_SEND) ?              event->target.nid : event->initiator.nid;        lp = lnet_find_peer_locked(nid);        if (lp == NULL) {                /* router may have been removed */                CDEBUG(D_NET, "Router %s not found\n", libcfs_nid2str(nid));                return;        }        if (event->type == LNET_EVENT_SEND)     /* re-enable another ping */                lp->lp_ping_notsent = 0;        if (lnet_isrouter(lp) &&                /* ignore if no longer a router */            (event->status != 0 ||             event->type == LNET_EVENT_REPLY)) {                                /* A successful REPLY means the router is up.  If _any_ comms                 * to the router fail I assume it's down (this will happen if                 * we ping alive routers to try to detect router death before                 * apps get burned). */                lnet_notify_locked(lp, 1, (event->status == 0),                                   cfs_time_current_sec());                /* The router checker will wake up very shortly and do the                 * actual notification.                   * XXX If 'lp' stops being a router before then, it will still                 * have the notification pending!!! */        }        /* This decref will NOT drop LNET_LOCK (it had to have 1 ref when it         * was in the peer table and I've not dropped the lock, so no-one else         * can have reduced the refcount) */        LASSERT(lp->lp_refcount > 1);        lnet_peer_decref_locked(lp);}static intlnet_router_checker(void *arg){        static lnet_ping_info_t   pinginfo;        int                  rc;        lnet_handle_md_t     mdh;        lnet_peer_t         *rtr;        struct list_head    *entry;        time_t               now;        lnet_process_id_t    rtr_id;        int                  secs;	cfs_daemonize("router_checker");	cfs_block_allsigs();        rtr_id.pid = LUSTRE_SRV_LNET_PID;        LASSERT (the_lnet.ln_rc_state == LNET_RC_STATE_SHUTDOWN);        rc = LNetMDBind((lnet_md_t){.start     = &pinginfo,                                    .length    = sizeof(pinginfo),                                    .threshold = LNET_MD_THRESH_INF,                                    .options   = LNET_MD_TRUNCATE,                                    .eq_handle = the_lnet.ln_rc_eqh},                        LNET_UNLINK,                        &mdh);        if (rc < 0) {                CERROR("Can't bind MD: %d\n", rc);                the_lnet.ln_rc_state = rc;                mutex_up(&the_lnet.ln_rc_signal);                return rc;        }        LASSERT (rc == 0);        the_lnet.ln_rc_state = LNET_RC_STATE_RUNNING;        mutex_up(&the_lnet.ln_rc_signal);       /* let my parent go */	while (the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING) {                __u64 version;                LNET_LOCK();rescan:                version = the_lnet.ln_routers_version;                list_for_each (entry, &the_lnet.ln_routers) {                        rtr = list_entry(entry, lnet_peer_t, lp_rtr_list);                        lnet_peer_addref_locked(rtr);                        now = cfs_time_current_sec();                        if (rtr->lp_ping_deadline != 0 && /* ping timed out? */                            now > rtr->lp_ping_deadline)                                lnet_notify_locked(rtr, 1, 0, now);                        LNET_UNLOCK();                        /* Run any outstanding notificiations */                        lnet_do_notify(rtr);                        if (rtr->lp_alive) {                                secs = live_router_check_interval;                        } else {                                secs = dead_router_check_interval;                        }                        if (secs <= 0)                                secs = 0;                                                if (secs != 0 &&                            !rtr->lp_ping_notsent &&                            now > rtr->lp_ping_timestamp + secs) {                                CDEBUG(D_NET, "Check: %s\n",                                       libcfs_nid2str(rtr->lp_nid));                                LNET_LOCK();                                rtr_id.nid = rtr->lp_nid;                                rtr->lp_ping_notsent = 1;                                rtr->lp_ping_timestamp = now;                                if (rtr->lp_ping_deadline == 0)                                        rtr->lp_ping_deadline =                                                 now + router_ping_timeout;                                LNET_UNLOCK();                                LNetGet(LNET_NID_ANY, mdh, rtr_id,                                        LNET_RESERVED_PORTAL,                                        LNET_PROTO_PING_MATCHBITS, 0);                        }                                                LNET_LOCK();                        lnet_peer_decref_locked(rtr);                        if (version != the_lnet.ln_routers_version) {                                /* the routers list has changed */                                goto rescan;                        }                }                LNET_UNLOCK();                /* Call cfs_pause() here always adds 1 to load average                  * because kernel counts # active tasks as nr_running                  * + nr_uninterruptible. */                set_current_state(CFS_TASK_INTERRUPTIBLE);                cfs_schedule_timeout(CFS_TASK_INTERRUPTIBLE,                                     cfs_time_seconds(1));	}        LASSERT (the_lnet.ln_rc_state == LNET_RC_STATE_STOPTHREAD);        the_lnet.ln_rc_state = LNET_RC_STATE_UNLINKING;                rc = LNetMDUnlink(mdh);        LASSERT (rc == 0);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?