@@ -134,4 +134,11 @@ int lnet_udsp_marshal(struct lnet_udsp *udsp,
*/
int lnet_udsp_demarshal_add(void *bulk, u32 bulk_size);
+/**
+ * lnet_udsp_get_construct_info
+ * get information of how the UDSP policies impacted the given
+ * construct.
+ */
+void lnet_udsp_get_construct_info(struct lnet_ioctl_construct_udsp_info *info);
+
#endif /* UDSP_H */
@@ -152,6 +152,9 @@ struct libcfs_ioctl_data {
#define IOC_LIBCFS_GET_RECOVERY_QUEUE _IOWR(IOC_LIBCFS_TYPE, 104, IOCTL_CONFIG_SIZE)
#define IOC_LIBCFS_ADD_UDSP _IOWR(IOC_LIBCFS_TYPE, 105, IOCTL_CONFIG_SIZE)
#define IOC_LIBCFS_DEL_UDSP _IOWR(IOC_LIBCFS_TYPE, 106, IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_MAX_NR 106
+#define IOC_LIBCFS_GET_UDSP_SIZE _IOWR(IOC_LIBCFS_TYPE, 107, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_GET_UDSP _IOWR(IOC_LIBCFS_TYPE, 108, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_GET_CONST_UDSP_INFO _IOWR(IOC_LIBCFS_TYPE, 109, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_MAX_NR 109
#endif /* __LIBCFS_IOCTL_H__ */
@@ -4162,6 +4162,70 @@ u32 lnet_get_dlc_seq_locked(void)
return rc;
}
+ case IOC_LIBCFS_GET_UDSP_SIZE: {
+ struct lnet_ioctl_udsp *ioc_udsp = arg;
+ struct lnet_udsp *udsp;
+
+ if (ioc_udsp->iou_hdr.ioc_len < sizeof(*ioc_udsp))
+ return -EINVAL;
+
+ rc = 0;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ udsp = lnet_udsp_get_policy(ioc_udsp->iou_idx);
+ if (!udsp) {
+ rc = -ENOENT;
+ } else {
+ /* coming in iou_idx will hold the idx of the udsp
+ * to get the size of. going out the iou_idx will
+ * hold the size of the UDSP found at the passed
+ * in index.
+ */
+ ioc_udsp->iou_idx = lnet_get_udsp_size(udsp);
+ if (ioc_udsp->iou_idx < 0)
+ rc = -EINVAL;
+ }
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return rc;
+ }
+
+ case IOC_LIBCFS_GET_UDSP: {
+ struct lnet_ioctl_udsp *ioc_udsp = arg;
+ struct lnet_udsp *udsp;
+
+ if (ioc_udsp->iou_hdr.ioc_len < sizeof(*ioc_udsp))
+ return -EINVAL;
+
+ rc = 0;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ udsp = lnet_udsp_get_policy(ioc_udsp->iou_idx);
+ if (!udsp)
+ rc = -ENOENT;
+ else
+ rc = lnet_udsp_marshal(udsp, ioc_udsp);
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return rc;
+ }
+
+ case IOC_LIBCFS_GET_CONST_UDSP_INFO: {
+ struct lnet_ioctl_construct_udsp_info *info = arg;
+
+ if (info->cud_hdr.ioc_len < sizeof(*info))
+ return -EINVAL;
+
+ CDEBUG(D_NET, "GET_UDSP_INFO for %s\n",
+ libcfs_nid2str(info->cud_nid));
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ lnet_udsp_get_construct_info(info);
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return 0;
+ }
+
default:
ni = lnet_net2ni_addref(data->ioc_net);
if (!ni)
@@ -980,6 +980,94 @@ struct lnet_udsp *
return 0;
}
+static void
+lnet_udsp_get_ni_info(struct lnet_ioctl_construct_udsp_info *info,
+ struct lnet_ni *ni)
+{
+ struct lnet_nid_list *ne;
+ struct lnet_net *net = ni->ni_net;
+ int i = 0;
+
+ LASSERT(ni);
+
+ info->cud_nid_priority = ni->ni_sel_priority;
+ if (net) {
+ info->cud_net_priority = ni->ni_net->net_sel_priority;
+ list_for_each_entry(ne, &net->net_rtr_pref_nids, nl_list) {
+ if (i < LNET_MAX_SHOW_NUM_NID)
+ info->cud_pref_rtr_nid[i] = ne->nl_nid;
+ else
+ break;
+ i++;
+ }
+ }
+}
+
+static void
+lnet_udsp_get_peer_info(struct lnet_ioctl_construct_udsp_info *info,
+ struct lnet_peer_ni *lpni)
+{
+ struct lnet_nid_list *ne;
+ int i = 0;
+
+ /* peer tree structure needs to be in existence */
+ LASSERT(lpni && lpni->lpni_peer_net &&
+ lpni->lpni_peer_net->lpn_peer);
+
+ info->cud_nid_priority = lpni->lpni_sel_priority;
+ CDEBUG(D_NET, "lpni %s has %d pref nids\n",
+ libcfs_nid2str(lpni->lpni_nid),
+ lpni->lpni_pref_nnids);
+ if (lpni->lpni_pref_nnids == 1) {
+ info->cud_pref_nid[0] = lpni->lpni_pref.nid;
+ } else if (lpni->lpni_pref_nnids > 1) {
+ struct list_head *list = &lpni->lpni_pref.nids;
+
+ list_for_each_entry(ne, list, nl_list) {
+ if (i < LNET_MAX_SHOW_NUM_NID)
+ info->cud_pref_nid[i] = ne->nl_nid;
+ else
+ break;
+ i++;
+ }
+ }
+
+ i = 0;
+ list_for_each_entry(ne, &lpni->lpni_rtr_pref_nids, nl_list) {
+ if (i < LNET_MAX_SHOW_NUM_NID)
+ info->cud_pref_rtr_nid[i] = ne->nl_nid;
+ else
+ break;
+ i++;
+ }
+
+ info->cud_net_priority = lpni->lpni_peer_net->lpn_sel_priority;
+}
+
+void
+lnet_udsp_get_construct_info(struct lnet_ioctl_construct_udsp_info *info)
+{
+ struct lnet_ni *ni;
+ struct lnet_peer_ni *lpni;
+
+ lnet_net_lock(0);
+ if (!info->cud_peer) {
+ ni = lnet_nid2ni_locked(info->cud_nid, 0);
+ if (ni)
+ lnet_udsp_get_ni_info(info, ni);
+ } else {
+ lpni = lnet_find_peer_ni_locked(info->cud_nid);
+ if (!lpni) {
+ CDEBUG(D_NET, "nid %s is not found\n",
+ libcfs_nid2str(info->cud_nid));
+ } else {
+ lnet_udsp_get_peer_info(info, lpni);
+ lnet_peer_ni_decref_locked(lpni);
+ }
+ }
+ lnet_net_unlock(0);
+}
+
struct lnet_udsp *
lnet_udsp_alloc(void)
{