📄 api-ni.c
字号:
return rc; case IOC_LIBCFS_FAIL_NID: return lnet_fail_nid(data->ioc_nid, data->ioc_count); case IOC_LIBCFS_ADD_ROUTE: rc = lnet_add_route(data->ioc_net, data->ioc_count, data->ioc_nid); return (rc != 0) ? rc : lnet_check_routes(); case IOC_LIBCFS_DEL_ROUTE: return lnet_del_route(data->ioc_net, data->ioc_nid); case IOC_LIBCFS_GET_ROUTE: return lnet_get_route(data->ioc_count, &data->ioc_net, &data->ioc_count, &data->ioc_nid, &data->ioc_flags); case IOC_LIBCFS_NOTIFY_ROUTER: return lnet_notify(NULL, data->ioc_nid, data->ioc_flags, (time_t)data->ioc_u64[0]); case IOC_LIBCFS_PORTALS_COMPATIBILITY: return the_lnet.ln_ptlcompat; case IOC_LIBCFS_LNET_DIST: rc = LNetDist(data->ioc_nid, &data->ioc_nid, &data->ioc_u32[1]); if (rc < 0 && rc != -EHOSTUNREACH) return rc; data->ioc_u32[0] = rc; return 0; case IOC_LIBCFS_TESTPROTOCOMPAT: LNET_LOCK(); the_lnet.ln_testprotocompat = data->ioc_flags; LNET_UNLOCK(); return 0; case IOC_LIBCFS_PING: rc = lnet_ping((lnet_process_id_t) {.nid = data->ioc_nid, .pid = data->ioc_u32[0]}, data->ioc_u32[1], /* timeout */ (lnet_process_id_t *)data->ioc_pbuf1, data->ioc_plen1/sizeof(lnet_process_id_t)); if (rc < 0) return rc; data->ioc_count = rc; return 0; case IOC_LIBCFS_DEBUG_PEER: { /* CAVEAT EMPTOR: this one designed for calling directly; not * via an ioctl */ lnet_process_id_t *id = arg; lnet_debug_peer(id->nid); ni = lnet_net2ni(LNET_NIDNET(id->nid)); if (ni == NULL) { CDEBUG(D_WARNING, "No NI for %s\n", libcfs_id2str(*id)); } else { if (ni->ni_lnd->lnd_ctl == NULL) { CDEBUG(D_WARNING, "No ctl for %s\n", libcfs_id2str(*id)); } else { (void)ni->ni_lnd->lnd_ctl(ni, cmd, arg); } lnet_ni_decref(ni); } return 0; } default: ni = lnet_net2ni(data->ioc_net); if (ni == NULL) return -EINVAL; if (ni->ni_lnd->lnd_ctl == NULL) rc = -EINVAL; else rc = ni->ni_lnd->lnd_ctl(ni, cmd, arg); lnet_ni_decref(ni); return rc; } /* not reached */}intLNetGetId(unsigned int index, lnet_process_id_t *id){ lnet_ni_t *ni; struct list_head *tmp; int rc = -ENOENT; LASSERT (the_lnet.ln_init); LASSERT (the_lnet.ln_refcount > 0); LNET_LOCK(); list_for_each(tmp, &the_lnet.ln_nis) { if (index-- != 0) continue; ni = list_entry(tmp, lnet_ni_t, ni_list); id->nid = ni->ni_nid; id->pid = the_lnet.ln_pid; rc = 0; break; } LNET_UNLOCK(); return rc;}voidLNetSnprintHandle(char *str, int len, lnet_handle_any_t h){ snprintf(str, len, LPX64, h.cookie);}intlnet_ping_target_init(void){ lnet_handle_me_t meh; lnet_process_id_t id; int rc; int rc2; int n; int infosz; int i; for (n = 0; ; n++) { rc = LNetGetId(n, &id); if (rc == -ENOENT) break; LASSERT (rc == 0); } infosz = offsetof(lnet_ping_info_t, pi_nid[n]); LIBCFS_ALLOC(the_lnet.ln_ping_info, infosz); if (the_lnet.ln_ping_info == NULL) { CERROR("Can't allocate ping info[%d]\n", n); return -ENOMEM; } the_lnet.ln_ping_info->pi_magic = LNET_PROTO_PING_MAGIC; the_lnet.ln_ping_info->pi_version = LNET_PROTO_PING_VERSION; the_lnet.ln_ping_info->pi_pid = the_lnet.ln_pid; the_lnet.ln_ping_info->pi_nnids = n; for (i = 0; i < n; i++) { rc = LNetGetId(i, &id); LASSERT (rc == 0); the_lnet.ln_ping_info->pi_nid[i] = id.nid; } /* We can have a tiny EQ since we only need to see the unlink event on * teardown, which by definition is the last one! */ rc = LNetEQAlloc(2, LNET_EQ_HANDLER_NONE, &the_lnet.ln_ping_target_eq); if (rc != 0) { CERROR("Can't allocate ping EQ: %d\n", rc); goto failed_0; } rc = LNetMEAttach(LNET_RESERVED_PORTAL, (lnet_process_id_t){.nid = LNET_NID_ANY, .pid = LNET_PID_ANY}, LNET_PROTO_PING_MATCHBITS, 0LL, LNET_UNLINK, LNET_INS_AFTER, &meh); if (rc != 0) { CERROR("Can't create ping ME: %d\n", rc); goto failed_1; } rc = LNetMDAttach(meh, (lnet_md_t){.start = the_lnet.ln_ping_info, .length = infosz, .threshold = LNET_MD_THRESH_INF, .options = (LNET_MD_OP_GET | LNET_MD_TRUNCATE | LNET_MD_MANAGE_REMOTE), .eq_handle = the_lnet.ln_ping_target_eq}, LNET_RETAIN, &the_lnet.ln_ping_target_md); if (rc != 0) { CERROR("Can't attach ping MD: %d\n", rc); goto failed_2; } return 0; failed_2: rc2 = LNetMEUnlink(meh); LASSERT (rc2 == 0); failed_1: rc2 = LNetEQFree(the_lnet.ln_ping_target_eq); LASSERT (rc2 == 0); failed_0: LIBCFS_FREE(the_lnet.ln_ping_info, infosz); return rc;}voidlnet_ping_target_fini(void){ lnet_event_t event; int rc; int which; int timeout_ms = 1000; cfs_sigset_t blocked = cfs_block_allsigs(); LNetMDUnlink(the_lnet.ln_ping_target_md); /* NB md could be busy; this just starts the unlink */ for (;;) { rc = LNetEQPoll(&the_lnet.ln_ping_target_eq, 1, timeout_ms, &event, &which); /* I expect overflow... */ LASSERT (rc >= 0 || rc == -EOVERFLOW); if (rc == 0) { /* timed out: provide a diagnostic */ CWARN("Still waiting for ping MD to unlink\n"); timeout_ms *= 2; continue; } /* Got a valid event */ if (event.unlinked) break; } rc = LNetEQFree(the_lnet.ln_ping_target_eq); LASSERT (rc == 0); LIBCFS_FREE(the_lnet.ln_ping_info, offsetof(lnet_ping_info_t, pi_nid[the_lnet.ln_ping_info->pi_nnids])); cfs_restore_sigs(blocked);}intlnet_ping (lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_ids){ lnet_handle_eq_t eqh; lnet_handle_md_t mdh; lnet_event_t event; int which; int unlinked = 0; int replied = 0; const int a_long_time = 60000; /* mS */ int infosz = offsetof(lnet_ping_info_t, pi_nid[n_ids]); lnet_ping_info_t *info; lnet_process_id_t tmpid; int i; int nob; int rc; int rc2; cfs_sigset_t blocked; if (n_ids <= 0 || id.nid == LNET_NID_ANY || timeout_ms > 500000 || /* arbitrary limit! */ n_ids > 20) /* arbitrary limit! */ return -EINVAL; if (id.pid == LNET_PID_ANY) id.pid = LUSTRE_SRV_LNET_PID; LIBCFS_ALLOC(info, infosz); if (info == NULL) return -ENOMEM; /* NB 2 events max (including any unlink event) */ rc = LNetEQAlloc(2, LNET_EQ_HANDLER_NONE, &eqh); if (rc != 0) { CERROR("Can't allocate EQ: %d\n", rc); goto out_0; } rc = LNetMDBind((lnet_md_t){.start = info, .length = infosz, .threshold = 2, /* GET/REPLY */ .options = LNET_MD_TRUNCATE, .eq_handle = eqh}, LNET_UNLINK, &mdh); if (rc != 0) { CERROR("Can't bind MD: %d\n", rc); goto out_1; } rc = LNetGet(LNET_NID_ANY, mdh, id, LNET_RESERVED_PORTAL, LNET_PROTO_PING_MATCHBITS, 0); if (rc != 0) { /* Don't CERROR; this could be deliberate! */ rc2 = LNetMDUnlink(mdh); LASSERT (rc2 == 0); /* NB must wait for the UNLINK event below... */ unlinked = 1; timeout_ms = a_long_time; } do { /* MUST block for unlink to complete */ if (unlinked) blocked = cfs_block_allsigs(); rc2 = LNetEQPoll(&eqh, 1, timeout_ms, &event, &which); if (unlinked) cfs_restore_sigs(blocked); CDEBUG(D_NET, "poll %d(%d %d)%s\n", rc2, (rc2 <= 0) ? -1 : event.type, (rc2 <= 0) ? -1 : event.status, (rc2 > 0 && event.unlinked) ? " unlinked" : ""); LASSERT (rc2 != -EOVERFLOW); /* can't miss anything */ if (rc2 <= 0 || event.status != 0) { /* timeout or error */ if (!replied && rc == 0) rc = (rc2 < 0) ? rc2 : (rc2 == 0) ? -ETIMEDOUT : event.status; if (!unlinked) { /* Ensure completion in finite time... */ LNetMDUnlink(mdh); /* No assertion (racing with network) */ unlinked = 1; timeout_ms = a_long_time; } else if (rc2 == 0) { /* timed out waiting for unlink */ CWARN("ping %s: late network completion\n", libcfs_id2str(id)); } } else if (event.type == LNET_EVENT_REPLY) { replied = 1; rc = event.mlength; } } while (rc2 <= 0 || !event.unlinked); if (!replied) { if (rc >= 0) CWARN("%s: Unexpected rc >= 0 but no reply!\n", libcfs_id2str(id)); rc = -EIO; goto out_1; } nob = rc; LASSERT (nob >= 0 && nob <= infosz); rc = -EPROTO; /* if I can't parse... */ if (nob < 8) { /* can't check magic/version */ CERROR("%s: ping info too short %d\n", libcfs_id2str(id), nob); goto out_1; } if (info->pi_magic == __swab32(LNET_PROTO_PING_MAGIC)) { /* NB I might be swabbing garbage until I check below, but it * doesn't matter */ __swab32s(&info->pi_version); __swab32s(&info->pi_pid); __swab32s(&info->pi_nnids); for (i = 0; i < info->pi_nnids && i < n_ids; i++) __swab64s(&info->pi_nid[i]); } else if (info->pi_magic != LNET_PROTO_PING_MAGIC) { CERROR("%s: Unexpected magic %08x\n", libcfs_id2str(id), info->pi_magic); goto out_1; } if (info->pi_version != LNET_PROTO_PING_VERSION) { CERROR("%s: Unexpected version 0x%x\n", libcfs_id2str(id), info->pi_version); goto out_1; } if (nob < offsetof(lnet_ping_info_t, pi_nid[0])) { CERROR("%s: Short reply %d(%d min)\n", libcfs_id2str(id), nob, (int)offsetof(lnet_ping_info_t, pi_nid[0])); goto out_1; } if (info->pi_nnids < n_ids) n_ids = info->pi_nnids; if (nob < offsetof(lnet_ping_info_t, pi_nid[n_ids])) { CERROR("%s: Short reply %d(%d expected)\n", libcfs_id2str(id), nob, (int)offsetof(lnet_ping_info_t, pi_nid[n_ids])); goto out_1; } rc = -EFAULT; /* If I SEGV... */ for (i = 0; i < n_ids; i++) { tmpid.pid = info->pi_pid; tmpid.nid = info->pi_nid[i];#ifdef __KERNEL__ if (copy_to_user(&ids[i], &tmpid, sizeof(tmpid))) goto out_1;#else ids[i] = tmpid;#endif } rc = info->pi_nnids; out_1: rc2 = LNetEQFree(eqh); if (rc2 != 0) CERROR("rc2 %d\n", rc2); LASSERT (rc2 == 0); out_0: LIBCFS_FREE(info, infosz); return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -