-lnet_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;
+LNetCtl(unsigned int cmd, void *arg)
+{
+ struct libcfs_ioctl_data *data = arg;
+ struct lnet_ioctl_config_data *config;
+ lnet_process_id_t id = {0};
+ lnet_ni_t *ni;
+ int rc;
+
+ BUILD_BUG_ON(sizeof(struct lnet_ioctl_net_config) +
+ sizeof(struct lnet_ioctl_config_data) > LIBCFS_IOC_DATA_MAX);
+
+ switch (cmd) {
+ case IOC_LIBCFS_GET_NI:
+ rc = LNetGetId(data->ioc_count, &id);
+ data->ioc_nid = id.nid;
+ return rc;
+
+ case IOC_LIBCFS_FAIL_NID:
+ return lnet_fail_nid(data->ioc_nid, data->ioc_count);
+
+ case IOC_LIBCFS_ADD_ROUTE:
+ config = arg;
+
+ if (config->cfg_hdr.ioc_len < sizeof(*config))
+ return -EINVAL;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ rc = lnet_add_route(config->cfg_net,
+ config->cfg_config_u.cfg_route.rtr_hop,
+ config->cfg_nid,
+ config->cfg_config_u.cfg_route.
+ rtr_priority);
+ if (rc == 0) {
+ rc = lnet_check_routes();
+ if (rc != 0)
+ lnet_del_route(config->cfg_net,
+ config->cfg_nid);
+ }
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return rc;
+
+ case IOC_LIBCFS_DEL_ROUTE:
+ config = arg;
+
+ if (config->cfg_hdr.ioc_len < sizeof(*config))
+ return -EINVAL;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ rc = lnet_del_route(config->cfg_net, config->cfg_nid);
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return rc;
+
+ case IOC_LIBCFS_GET_ROUTE:
+ config = arg;
+
+ if (config->cfg_hdr.ioc_len < sizeof(*config))
+ return -EINVAL;
+
+ return lnet_get_route(config->cfg_count,
+ &config->cfg_net,
+ &config->cfg_config_u.cfg_route.rtr_hop,
+ &config->cfg_nid,
+ &config->cfg_config_u.cfg_route.rtr_flags,
+ &config->cfg_config_u.cfg_route.
+ rtr_priority);
+
+ case IOC_LIBCFS_GET_NET: {
+ size_t total = sizeof(*config) +
+ sizeof(struct lnet_ioctl_net_config);
+ config = arg;
+
+ if (config->cfg_hdr.ioc_len < total)
+ return -EINVAL;
+
+ return lnet_get_net_config(config);
+ }
+
+ case IOC_LIBCFS_GET_LNET_STATS:
+ {
+ struct lnet_ioctl_lnet_stats *lnet_stats = arg;
+
+ if (lnet_stats->st_hdr.ioc_len < sizeof(*lnet_stats))
+ return -EINVAL;
+
+ lnet_counters_get(&lnet_stats->st_cntrs);
+ return 0;
+ }
+
+ case IOC_LIBCFS_CONFIG_RTR:
+ config = arg;
+
+ if (config->cfg_hdr.ioc_len < sizeof(*config))
+ return -EINVAL;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ if (config->cfg_config_u.cfg_buffers.buf_enable) {
+ rc = lnet_rtrpools_enable();
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return rc;
+ }
+ lnet_rtrpools_disable();
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return 0;
+
+ case IOC_LIBCFS_ADD_BUF:
+ config = arg;
+
+ if (config->cfg_hdr.ioc_len < sizeof(*config))
+ return -EINVAL;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ rc = lnet_rtrpools_adjust(config->cfg_config_u.cfg_buffers.
+ buf_tiny,
+ config->cfg_config_u.cfg_buffers.
+ buf_small,
+ config->cfg_config_u.cfg_buffers.
+ buf_large);
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return rc;
+
+ case IOC_LIBCFS_GET_BUF: {
+ struct lnet_ioctl_pool_cfg *pool_cfg;
+ size_t total = sizeof(*config) + sizeof(*pool_cfg);
+
+ config = arg;
+
+ if (config->cfg_hdr.ioc_len < total)
+ return -EINVAL;
+
+ pool_cfg = (struct lnet_ioctl_pool_cfg *)config->cfg_bulk;
+ return lnet_get_rtr_pool_cfg(config->cfg_count, pool_cfg);
+ }
+
+ case IOC_LIBCFS_GET_PEER_INFO: {
+ struct lnet_ioctl_peer *peer_info = arg;
+
+ if (peer_info->pr_hdr.ioc_len < sizeof(*peer_info))
+ return -EINVAL;
+
+ return lnet_get_peer_info(
+ peer_info->pr_count,
+ &peer_info->pr_nid,
+ peer_info->pr_lnd_u.pr_peer_credits.cr_aliveness,
+ &peer_info->pr_lnd_u.pr_peer_credits.cr_ncpt,
+ &peer_info->pr_lnd_u.pr_peer_credits.cr_refcount,
+ &peer_info->pr_lnd_u.pr_peer_credits.cr_ni_peer_tx_credits,
+ &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_tx_credits,
+ &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_rtr_credits,
+ &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_min_rtr_credits,
+ &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_tx_qnob);
+ }
+
+ case IOC_LIBCFS_NOTIFY_ROUTER: {
+ unsigned long jiffies_passed;
+
+ jiffies_passed = ktime_get_real_seconds() - data->ioc_u64[0];
+ jiffies_passed = cfs_time_seconds(jiffies_passed);
+
+ return lnet_notify(NULL, data->ioc_nid, data->ioc_flags,
+ jiffies - jiffies_passed);
+ }
+
+ 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_net_lock(LNET_LOCK_EX);
+ the_lnet.ln_testprotocompat = data->ioc_flags;
+ lnet_net_unlock(LNET_LOCK_EX);
+ return 0;
+
+ case IOC_LIBCFS_LNET_FAULT:
+ return lnet_fault_ctl(data->ioc_flags, data);
+
+ case IOC_LIBCFS_PING: {
+ signed long timeout;
+
+ id.nid = data->ioc_nid;
+ id.pid = data->ioc_u32[0];
+
+ /* Don't block longer than 2 minutes */
+ if (data->ioc_u32[1] > 120 * MSEC_PER_SEC)
+ return -EINVAL;
+
+ /* If timestamp is negative then disable timeout */
+ if ((s32)data->ioc_u32[1] < 0)
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ else
+ timeout = msecs_to_jiffies(data->ioc_u32[1]);
+
+ rc = lnet_ping(id, timeout, data->ioc_pbuf1,
+ data->ioc_plen1 / sizeof(lnet_process_id_t));
+ if (rc < 0)
+ return rc;
+ data->ioc_count = rc;
+ return 0;
+ }
+ default:
+ ni = lnet_net2ni(data->ioc_net);
+ if (ni == NULL)
+ return -EINVAL;
+
+ if (ni->ni_net->net_lnd->lnd_ctl == NULL)
+ rc = -EINVAL;
+ else
+ rc = ni->ni_net->net_lnd->lnd_ctl(ni, cmd, arg);
+
+ return rc;
+ }
+ /* not reached */