if (err == -EINVAL)
continue;
- if (err == 0) {
- if (copy_to_user(uparam, hdr, hdr->ioc_len))
- err = -EFAULT;
- }
+ if (copy_to_user(uparam, hdr, hdr->ioc_len))
+ err = -EFAULT;
break;
}
up_read(&ioctl_list_sem);
extern int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand);
extern int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp,
struct libcfs_ioctl_hdr __user *uparam);
+extern int lnet_get_peer_list(__u32 *countp, __u32 *sizep,
+ lnet_process_id_t __user *ids);
void lnet_proc_init(void);
void lnet_proc_fini(void);
int lnet_peer_ni_set_non_mr_pref_nid(struct lnet_peer_ni *lpni, lnet_nid_t nid);
int lnet_add_peer_ni(lnet_nid_t key_nid, lnet_nid_t nid, bool mr);
int lnet_del_peer_ni(lnet_nid_t key_nid, lnet_nid_t nid);
-int lnet_get_peer_info(__u32 idx, lnet_nid_t *primary_nid, lnet_nid_t *nid,
- bool *mr,
- struct lnet_peer_ni_credit_info __user *peer_ni_info,
- struct lnet_ioctl_element_stats __user *peer_ni_stats);
+int lnet_get_peer_info(lnet_nid_t *primary_nid, lnet_nid_t *nid,
+ __u32 *nnis, bool *mr, __u32 *sizep,
+ void __user *bulk);
int lnet_get_peer_ni_info(__u32 peer_index, __u64 *nid,
char alivness[LNET_MAX_STR_LEN],
__u32 *cpt_iter, __u32 *refcount,
* pt_hash[...]
* pt_peer_list
* pt_peers
- * pt_peer_nnids
* protected by pt_zombie_lock:
* pt_zombie_list
* pt_zombies
struct list_head *pt_hash; /* NID->peer hash */
struct list_head pt_peer_list; /* peers */
int pt_peers; /* # peers */
- int pt_peer_nnids; /* # NIDS on listed peers */
struct list_head pt_zombie_list; /* zombie peer_ni */
int pt_zombies; /* # zombie peers_ni */
spinlock_t pt_zombie_lock; /* protect list and count */
#define IOC_LIBCFS_GET_LOCAL_NI _IOWR(IOC_LIBCFS_TYPE, 97, IOCTL_CONFIG_SIZE)
#define IOC_LIBCFS_SET_NUMA_RANGE _IOWR(IOC_LIBCFS_TYPE, 98, IOCTL_CONFIG_SIZE)
#define IOC_LIBCFS_GET_NUMA_RANGE _IOWR(IOC_LIBCFS_TYPE, 99, IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_MAX_NR 99
+#define IOC_LIBCFS_GET_PEER_LIST _IOWR(IOC_LIBCFS_TYPE, 100, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_MAX_NR 100
extern int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data);
case IOC_LIBCFS_GET_PEER_NI: {
struct lnet_ioctl_peer_cfg *cfg = arg;
- struct lnet_peer_ni_credit_info __user *lpni_cri;
- struct lnet_ioctl_element_stats __user *lpni_stats;
- size_t usr_size = sizeof(*lpni_cri) + sizeof(*lpni_stats);
- if ((cfg->prcfg_hdr.ioc_len != sizeof(*cfg)) ||
- (cfg->prcfg_size != usr_size))
+ if (cfg->prcfg_hdr.ioc_len < sizeof(*cfg))
return -EINVAL;
- lpni_cri = cfg->prcfg_bulk;
- lpni_stats = cfg->prcfg_bulk + sizeof(*lpni_cri);
+ mutex_lock(&the_lnet.ln_api_mutex);
+ rc = lnet_get_peer_info(&cfg->prcfg_prim_nid,
+ &cfg->prcfg_cfg_nid,
+ &cfg->prcfg_count,
+ &cfg->prcfg_mr,
+ &cfg->prcfg_size,
+ (void __user *)cfg->prcfg_bulk);
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return rc;
+ }
+
+ case IOC_LIBCFS_GET_PEER_LIST: {
+ struct lnet_ioctl_peer_cfg *cfg = arg;
+
+ if (cfg->prcfg_hdr.ioc_len < sizeof(*cfg))
+ return -EINVAL;
mutex_lock(&the_lnet.ln_api_mutex);
- rc = lnet_get_peer_info(cfg->prcfg_count, &cfg->prcfg_prim_nid,
- &cfg->prcfg_cfg_nid, &cfg->prcfg_mr,
- lpni_cri, lpni_stats);
+ rc = lnet_get_peer_list(&cfg->prcfg_count, &cfg->prcfg_size,
+ (lnet_process_id_t __user *)cfg->prcfg_bulk);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
}
/* Update peer NID count. */
lp = lpn->lpn_peer;
- ptable = the_lnet.ln_peer_tables[lp->lp_cpt];
lp->lp_nnis--;
- ptable->pt_peer_nnids--;
/*
* If there are no more peer nets, make the peer unfindable
*/
if (list_empty(&lp->lp_peer_nets)) {
list_del_init(&lp->lp_peer_list);
+ ptable = the_lnet.ln_peer_tables[lp->lp_cpt];
ptable->pt_peers--;
} else if (the_lnet.ln_dc_state != LNET_DC_STATE_RUNNING) {
/* Discovery isn't running, nothing to do here. */
}
struct lnet_peer_ni *
-lnet_get_peer_ni_idx_locked(int idx, struct lnet_peer_net **lpn,
- struct lnet_peer **lp)
-{
- struct lnet_peer_table *ptable;
- struct lnet_peer_ni *lpni;
- int lncpt;
- int cpt;
-
- lncpt = cfs_percpt_number(the_lnet.ln_peer_tables);
-
- for (cpt = 0; cpt < lncpt; cpt++) {
- ptable = the_lnet.ln_peer_tables[cpt];
- if (ptable->pt_peer_nnids > idx)
- break;
- idx -= ptable->pt_peer_nnids;
- }
- if (cpt >= lncpt)
- return NULL;
-
- list_for_each_entry((*lp), &ptable->pt_peer_list, lp_peer_list) {
- if ((*lp)->lp_nnis <= idx) {
- idx -= (*lp)->lp_nnis;
- continue;
- }
- list_for_each_entry((*lpn), &((*lp)->lp_peer_nets),
- lpn_peer_nets) {
- list_for_each_entry(lpni, &((*lpn)->lpn_peer_nis),
- lpni_peer_nis) {
- if (idx-- == 0)
- return lpni;
- }
- }
- }
-
- return NULL;
-}
-
-struct lnet_peer_ni *
lnet_get_next_peer_ni_locked(struct lnet_peer *peer,
struct lnet_peer_net *peer_net,
struct lnet_peer_ni *prev)
return lpni;
}
+/* Call with the ln_api_mutex held */
+int
+lnet_get_peer_list(__u32 *countp, __u32 *sizep, lnet_process_id_t __user *ids)
+{
+ lnet_process_id_t id;
+ struct lnet_peer_table *ptable;
+ struct lnet_peer *lp;
+ __u32 count = 0;
+ __u32 size = 0;
+ int lncpt;
+ int cpt;
+ __u32 i;
+ int rc;
+
+ rc = -ESHUTDOWN;
+ if (the_lnet.ln_state != LNET_STATE_RUNNING)
+ goto done;
+
+ lncpt = cfs_percpt_number(the_lnet.ln_peer_tables);
+
+ /*
+ * Count the number of peers, and return E2BIG if the buffer
+ * is too small. We'll also return the desired size.
+ */
+ rc = -E2BIG;
+ for (cpt = 0; cpt < lncpt; cpt++) {
+ ptable = the_lnet.ln_peer_tables[cpt];
+ count += ptable->pt_peers;
+ }
+ size = count * sizeof(*ids);
+ if (size > *sizep)
+ goto done;
+
+ /*
+ * Walk the peer lists and copy out the primary nids.
+ * This is safe because the peer lists are only modified
+ * while the ln_api_mutex is held. So we don't need to
+ * hold the lnet_net_lock as well, and can therefore
+ * directly call copy_to_user().
+ */
+ rc = -EFAULT;
+ memset(&id, 0, sizeof(id));
+ id.pid = LNET_PID_LUSTRE;
+ i = 0;
+ for (cpt = 0; cpt < lncpt; cpt++) {
+ ptable = the_lnet.ln_peer_tables[cpt];
+ list_for_each_entry(lp, &ptable->pt_peer_list, lp_peer_list) {
+ if (i >= count)
+ goto done;
+ id.nid = lp->lp_primary_nid;
+ if (copy_to_user(&ids[i], &id, sizeof(id)))
+ goto done;
+ i++;
+ }
+ }
+ rc = 0;
+done:
+ *countp = count;
+ *sizep = size;
+ return rc;
+}
+
/*
* Start pushes to peers that need to be updated for a configuration
* change on this node.
spin_unlock(&lp->lp_lock);
lp->lp_nnis++;
- the_lnet.ln_peer_tables[lp->lp_cpt]->pt_peer_nnids++;
lnet_net_unlock(LNET_LOCK_EX);
CDEBUG(D_NET, "peer %s NID %s flags %#x\n",
}
/* ln_api_mutex is held, which keeps the peer list stable */
-int lnet_get_peer_info(__u32 idx, lnet_nid_t *primary_nid, lnet_nid_t *nid,
- bool *mr,
- struct lnet_peer_ni_credit_info __user *peer_ni_info,
- struct lnet_ioctl_element_stats __user *peer_ni_stats)
+int lnet_get_peer_info(lnet_nid_t *primary_nid, lnet_nid_t *nidp,
+ __u32 *nnis, bool *mr, __u32 *sizep,
+ void __user *bulk)
{
- struct lnet_peer_ni *lpni = NULL;
- struct lnet_peer_net *lpn = NULL;
- struct lnet_peer *lp = NULL;
- struct lnet_peer_ni_credit_info ni_info;
- struct lnet_ioctl_element_stats ni_stats;
+ struct lnet_ioctl_element_stats *lpni_stats;
+ struct lnet_peer_ni_credit_info *lpni_info;
+ struct lnet_peer_ni *lpni;
+ struct lnet_peer *lp;
+ lnet_nid_t nid;
+ __u32 size;
int rc;
- lpni = lnet_get_peer_ni_idx_locked(idx, &lpn, &lp);
+ lp = lnet_find_peer(*primary_nid);
- if (!lpni)
- return -ENOENT;
+ if (!lp) {
+ rc = -ENOENT;
+ goto out;
+ }
+
+ size = sizeof(nid) + sizeof(*lpni_info) + sizeof(*lpni_stats);
+ size *= lp->lp_nnis;
+ if (size > *sizep) {
+ *sizep = size;
+ rc = -E2BIG;
+ goto out_lp_decref;
+ }
*primary_nid = lp->lp_primary_nid;
*mr = lnet_peer_is_multi_rail(lp);
- *nid = lpni->lpni_nid;
- snprintf(ni_info.cr_aliveness, LNET_MAX_STR_LEN, "NA");
- if (lnet_isrouter(lpni) ||
- lnet_peer_aliveness_enabled(lpni))
- snprintf(ni_info.cr_aliveness, LNET_MAX_STR_LEN,
- lpni->lpni_alive ? "up" : "down");
-
- ni_info.cr_refcount = atomic_read(&lpni->lpni_refcount);
- ni_info.cr_ni_peer_tx_credits = (lpni->lpni_net != NULL) ?
- lpni->lpni_net->net_tunables.lct_peer_tx_credits : 0;
- ni_info.cr_peer_tx_credits = lpni->lpni_txcredits;
- ni_info.cr_peer_rtr_credits = lpni->lpni_rtrcredits;
- ni_info.cr_peer_min_rtr_credits = lpni->lpni_minrtrcredits;
- ni_info.cr_peer_min_tx_credits = lpni->lpni_mintxcredits;
- ni_info.cr_peer_tx_qnob = lpni->lpni_txqnob;
- ni_info.cr_ncpt = lpni->lpni_cpt;
-
- ni_stats.iel_send_count = atomic_read(&lpni->lpni_stats.send_count);
- ni_stats.iel_recv_count = atomic_read(&lpni->lpni_stats.recv_count);
- ni_stats.iel_drop_count = atomic_read(&lpni->lpni_stats.drop_count);
-
- /* If copy_to_user fails */
- rc = -EFAULT;
- if (copy_to_user(peer_ni_info, &ni_info, sizeof(ni_info)))
- goto copy_failed;
+ *nidp = lp->lp_primary_nid;
+ *nnis = lp->lp_nnis;
+ *sizep = size;
- if (copy_to_user(peer_ni_stats, &ni_stats, sizeof(ni_stats)))
- goto copy_failed;
+ /* Allocate helper buffers. */
+ rc = -ENOMEM;
+ LIBCFS_ALLOC(lpni_info, sizeof(*lpni_info));
+ if (!lpni_info)
+ goto out_lp_decref;
+ LIBCFS_ALLOC(lpni_stats, sizeof(*lpni_stats));
+ if (!lpni_stats)
+ goto out_free_info;
+ lpni = NULL;
+ rc = -EFAULT;
+ while ((lpni = lnet_get_next_peer_ni_locked(lp, NULL, lpni)) != NULL) {
+ nid = lpni->lpni_nid;
+ if (copy_to_user(bulk, &nid, sizeof(nid)))
+ goto out_free_stats;
+ bulk += sizeof(nid);
+
+ memset(lpni_info, 0, sizeof(*lpni_info));
+ snprintf(lpni_info->cr_aliveness, LNET_MAX_STR_LEN, "NA");
+ if (lnet_isrouter(lpni) ||
+ lnet_peer_aliveness_enabled(lpni))
+ snprintf(lpni_info->cr_aliveness, LNET_MAX_STR_LEN,
+ lpni->lpni_alive ? "up" : "down");
+
+ lpni_info->cr_refcount = atomic_read(&lpni->lpni_refcount);
+ lpni_info->cr_ni_peer_tx_credits = (lpni->lpni_net != NULL) ?
+ lpni->lpni_net->net_tunables.lct_peer_tx_credits : 0;
+ lpni_info->cr_peer_tx_credits = lpni->lpni_txcredits;
+ lpni_info->cr_peer_rtr_credits = lpni->lpni_rtrcredits;
+ lpni_info->cr_peer_min_rtr_credits = lpni->lpni_minrtrcredits;
+ lpni_info->cr_peer_min_tx_credits = lpni->lpni_mintxcredits;
+ lpni_info->cr_peer_tx_qnob = lpni->lpni_txqnob;
+ if (copy_to_user(bulk, lpni_info, sizeof(*lpni_info)))
+ goto out_free_stats;
+ bulk += sizeof(*lpni_info);
+
+ memset(lpni_stats, 0, sizeof(*lpni_stats));
+ lpni_stats->iel_send_count =
+ atomic_read(&lpni->lpni_stats.send_count);
+ lpni_stats->iel_recv_count =
+ atomic_read(&lpni->lpni_stats.recv_count);
+ lpni_stats->iel_drop_count =
+ atomic_read(&lpni->lpni_stats.drop_count);
+ if (copy_to_user(bulk, lpni_stats, sizeof(*lpni_stats)))
+ goto out_free_stats;
+ bulk += sizeof(*lpni_stats);
+ }
rc = 0;
-copy_failed:
+out_free_stats:
+ LIBCFS_FREE(lpni_stats, sizeof(*lpni_stats));
+out_free_info:
+ LIBCFS_FREE(lpni_info, sizeof(*lpni_info));
+out_lp_decref:
+ lnet_peer_decref_locked(lp);
+out:
return rc;
}
struct lnet_ioctl_peer_cfg peer_info;
struct lnet_peer_ni_credit_info *lpni_cri;
struct lnet_ioctl_element_stats *lpni_stats;
- int rc = LUSTRE_CFG_RC_OUT_OF_MEM, ncpt = 0, i = 0, j = 0;
+ lnet_nid_t *nidp;
+ int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
+ int i;
+ int j;
int l_errno = 0;
+ __u32 count;
+ __u32 size;
struct cYAML *root = NULL, *peer = NULL, *peer_ni = NULL,
*first_seq = NULL, *peer_root = NULL, *tmp = NULL;
char err_str[LNET_MAX_STR_LEN];
- lnet_nid_t prev_primary_nid = LNET_NID_ANY, primary_nid = LNET_NID_ANY;
- int data_size = sizeof(*lpni_cri) + sizeof(*lpni_stats);
- char *data = malloc(data_size);
- bool new_peer = true;
+ lnet_process_id_t *list = NULL;
+ void *data = NULL;
+ void *lpni_data;
snprintf(err_str, sizeof(err_str),
"\"out of memory\"");
- if (data == NULL)
- goto out;
-
/* create struct cYAML root object */
root = cYAML_create_object(NULL, NULL);
if (root == NULL)
if (peer_root == NULL)
goto out;
- if (knid != NULL)
- primary_nid = libcfs_str2nid(knid);
-
- do {
- for (i = 0;; i++) {
- memset(data, 0, data_size);
+ count = 1000;
+ size = count * sizeof(lnet_process_id_t);
+ list = malloc(size);
+ if (list == NULL) {
+ l_errno = ENOMEM;
+ goto out;
+ }
+ if (knid != NULL) {
+ list[0].nid = libcfs_str2nid(knid);
+ count = 1;
+ } else {
+ for (;;) {
memset(&peer_info, 0, sizeof(peer_info));
LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
- peer_info.prcfg_count = i;
- peer_info.prcfg_bulk = (void *)data;
- peer_info.prcfg_size = data_size;
-
- rc = l_ioctl(LNET_DEV_ID,
- IOC_LIBCFS_GET_PEER_NI, &peer_info);
- if (rc != 0) {
- l_errno = errno;
+ peer_info.prcfg_size = size;
+ peer_info.prcfg_bulk = list;
+
+ l_errno = 0;
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER_LIST,
+ &peer_info);
+ count = peer_info.prcfg_count;
+ if (rc == 0)
break;
+ l_errno = errno;
+ if (l_errno != E2BIG) {
+ snprintf(err_str,
+ sizeof(err_str),
+ "\"cannot get peer list: %s\"",
+ strerror(l_errno));
+ rc = -l_errno;
+ goto out;
}
+ free(list);
+ size = peer_info.prcfg_size;
+ list = malloc(size);
+ if (list == NULL) {
+ l_errno = ENOMEM;
+ goto out;
+ }
+ }
+ }
- if (primary_nid != LNET_NID_ANY &&
- primary_nid != peer_info.prcfg_prim_nid)
- continue;
+ size = 4096;
+ data = malloc(size);
+ if (data == NULL) {
+ l_errno = ENOMEM;
+ goto out;
+ }
+ for (i = 0; i < count; i++) {
+ for (;;) {
+ memset(&peer_info, 0, sizeof(peer_info));
+ LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
+ peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
+ peer_info.prcfg_prim_nid = list[i].nid;
+ peer_info.prcfg_size = size;
+ peer_info.prcfg_bulk = data;
+
+ l_errno = 0;
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER_NI,
+ &peer_info);
+ if (rc == 0)
+ break;
+ l_errno = errno;
+ if (l_errno != E2BIG) {
+ snprintf(err_str,
+ sizeof(err_str),
+ "\"cannot get peer information: %s\"",
+ strerror(l_errno));
+ rc = -l_errno;
+ goto out;
+ }
+ free(data);
+ size = peer_info.prcfg_size;
+ data = malloc(size);
+ if (data == NULL) {
+ l_errno = ENOMEM;
+ goto out;
+ }
+ }
- lpni_cri = peer_info.prcfg_bulk;
- lpni_stats = peer_info.prcfg_bulk + sizeof(*lpni_cri);
+ peer = cYAML_create_seq_item(peer_root);
+ if (peer == NULL)
+ goto out;
- peer = cYAML_create_seq_item(peer_root);
- if (peer == NULL)
- goto out;
+ if (first_seq == NULL)
+ first_seq = peer;
- if (peer_info.prcfg_prim_nid != prev_primary_nid) {
- prev_primary_nid = peer_info.prcfg_prim_nid;
- new_peer = true;
- }
+ lnet_nid_t pnid = peer_info.prcfg_prim_nid;
+ if (cYAML_create_string(peer, "primary nid",
+ libcfs_nid2str(pnid))
+ == NULL)
+ goto out;
+ if (cYAML_create_string(peer, "Multi-Rail",
+ peer_info.prcfg_mr ? "True" : "False")
+ == NULL)
+ goto out;
- if (new_peer) {
- lnet_nid_t pnid = peer_info.prcfg_prim_nid;
- if (cYAML_create_string(peer, "primary nid",
- libcfs_nid2str(pnid))
- == NULL)
- goto out;
- if (cYAML_create_string(peer, "Multi-Rail",
- peer_info.prcfg_mr ?
- "True" : "False")
- == NULL)
- goto out;
- tmp = cYAML_create_seq(peer, "peer ni");
- if (tmp == NULL)
- goto out;
- new_peer = false;
- }
+ tmp = cYAML_create_seq(peer, "peer ni");
+ if (tmp == NULL)
+ goto out;
- if (first_seq == NULL)
- first_seq = peer;
+ lpni_data = data;
+ for (j = 0; j < peer_info.prcfg_count; j++) {
+ nidp = lpni_data;
+ lpni_cri = (void*)nidp + sizeof(nidp);
+ lpni_stats = (void *)lpni_cri + sizeof(*lpni_cri);
+ lpni_data = (void *)lpni_stats + sizeof(*lpni_stats);
peer_ni = cYAML_create_seq_item(tmp);
if (peer_ni == NULL)
goto out;
if (cYAML_create_string(peer_ni, "nid",
- libcfs_nid2str
- (peer_info.prcfg_cfg_nid))
+ libcfs_nid2str(*nidp))
== NULL)
goto out;
lpni_cri->cr_refcount) == NULL)
goto out;
}
+ }
+
+ /* print output iff show_rc is not provided */
+ if (show_rc == NULL)
+ cYAML_print_tree(root);
+
+ snprintf(err_str, sizeof(err_str), "\"success\"");
+ rc = LUSTRE_CFG_RC_NO_ERR;
+
+out:
+ free(list);
+ free(data);
+ if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_free_tree(root);
+ } else if (show_rc != NULL && *show_rc != NULL) {
+ struct cYAML *show_node;
+ /* find the peer node, if one doesn't exist then
+ * insert one. Otherwise add to the one there
+ */
+ show_node = cYAML_get_object_item(*show_rc,
+ "peer");
+ if (show_node != NULL && cYAML_is_sequence(show_node)) {
+ cYAML_insert_child(show_node, first_seq);
+ free(peer_root);
+ free(root);
+ } else if (show_node == NULL) {
+ cYAML_insert_sibling((*show_rc)->cy_child,
+ peer_root);
+ free(root);
+ } else {
+ cYAML_free_tree(root);
+ }
+ } else {
+ *show_rc = root;
+ }
+
+ cYAML_build_error(rc, seq_no, SHOW_CMD, "peer", err_str,
+ err_rc);
+
+ return rc;
+}
+
+int lustre_lnet_list_peer(int seq_no,
+ struct cYAML **show_rc, struct cYAML **err_rc)
+{
+ struct lnet_ioctl_peer_cfg peer_info;
+ int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
+ __u32 count;
+ __u32 size;
+ int i = 0;
+ int l_errno = 0;
+ struct cYAML *root = NULL, *list_root = NULL, *first_seq = NULL;
+ char err_str[LNET_MAX_STR_LEN];
+ lnet_process_id_t *list = NULL;
+
+ snprintf(err_str, sizeof(err_str),
+ "\"out of memory\"");
+
+ memset(&peer_info, 0, sizeof(peer_info));
+
+ /* create struct cYAML root object */
+ root = cYAML_create_object(NULL, NULL);
+ if (root == NULL)
+ goto out;
+
+ list_root = cYAML_create_seq(root, "peer list");
+ if (list_root == NULL)
+ goto out;
+
+ count = 1000;
+ size = count * sizeof(lnet_process_id_t);
+ list = malloc(size);
+ if (list == NULL) {
+ l_errno = ENOMEM;
+ goto out;
+ }
+ for (;;) {
+ LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
+ peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
+ peer_info.prcfg_size = size;
+ peer_info.prcfg_bulk = list;
- if (l_errno != ENOENT) {
+ l_errno = 0;
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER_LIST, &peer_info);
+ count = peer_info.prcfg_count;
+ if (rc == 0)
+ break;
+ l_errno = errno;
+ if (l_errno != E2BIG) {
snprintf(err_str,
sizeof(err_str),
- "\"cannot get peer information: %s\"",
+ "\"cannot get peer list: %s\"",
strerror(l_errno));
rc = -l_errno;
goto out;
}
+ free(list);
+ size = peer_info.prcfg_size;
+ list = malloc(size);
+ if (list == NULL) {
+ l_errno = ENOMEM;
+ goto out;
+ }
+ }
- j++;
- } while (j < ncpt);
+ /* count is now the actual number of ids in the list. */
+ for (i = 0; i < count; i++) {
+ if (cYAML_create_string(list_root, "nid",
+ libcfs_nid2str(list[i].nid))
+ == NULL)
+ goto out;
+ }
/* print output iff show_rc is not provided */
if (show_rc == NULL)
rc = LUSTRE_CFG_RC_NO_ERR;
out:
+ if (list != NULL)
+ free(list);
if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
cYAML_free_tree(root);
} else if (show_rc != NULL && *show_rc != NULL) {
"peer");
if (show_node != NULL && cYAML_is_sequence(show_node)) {
cYAML_insert_child(show_node, first_seq);
- free(peer_root);
+ free(list_root);
free(root);
} else if (show_node == NULL) {
cYAML_insert_sibling((*show_rc)->cy_child,
- peer_root);
+ list_root);
free(root);
} else {
cYAML_free_tree(root);
struct cYAML **show_rc, struct cYAML **err_rc);
/*
+ * lustre_lnet_list_peer
+ * List the known peers.
+ *
+ * seq_no - sequence number of the command
+ * show_rc - YAML structure of the resultant show
+ * err_rc - YAML strucutre of the resultant return code.
+ *
+ */
+int lustre_lnet_list_peer(int seq_no,
+ struct cYAML **show_rc, struct cYAML **err_rc);
+
+/*
* lustre_yaml_config
* Parses the provided YAML file and then calls the specific APIs
* to configure the entities identified in the file
static int jt_del_peer_nid(int argc, char **argv);
static int jt_set_max_intf(int argc, char **argv);
static int jt_set_discovery(int argc, char **argv);
+static int jt_list_peer(int argc, char **argv);
/*static int jt_show_peer(int argc, char **argv);*/
static int lnetctl_list_commands(int argc, char **argv);
{"show", jt_show_peer, 0, "show peer information\n"
"\t--nid: NID of peer to filter on.\n"
"\t--verbose: Include extended statistics\n"},
+ {"list", jt_list_peer, 0, "list all peers\n"},
{ 0, 0, 0, NULL }
};
rc = LUSTRE_CFG_RC_OUT_OF_MEM;
break;
case 'h':
- print_help(peer_cmds, "peer", "del");
+ print_help(peer_cmds, "peer", "show");
return 0;
default:
return 0;
return rc;
}
+static int jt_list_peer(int argc, char **argv)
+{
+ int rc, opt;
+ struct cYAML *err_rc = NULL, *list_rc = NULL;
+
+ const char *const short_options = "h";
+ const struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { NULL, 0, NULL, 0 },
+ };
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'h':
+ print_help(peer_cmds, "peer", "list");
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ rc = lustre_lnet_list_peer(-1, &list_rc, &err_rc);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+ else if (list_rc)
+ cYAML_print_tree(list_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(list_rc);
+
+ return rc;
+}
+
command_t list[] = {
{"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"},
{"route", jt_route, 0, "route {add | del | show | help}"},