X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lnet%2Flnet%2Fconfig.c;h=5e367f00e577d68efd9d888f57c14ff3396730db;hb=df3904c3486c71da586d43fbfca8f126b5764838;hp=34889e606dcc123d4a75a52bf1613fdaa60c9b06;hpb=8cbb8cd3e771e7f7e0f99cafc19fad32770dc015;p=fs%2Flustre-release.git diff --git a/lnet/lnet/config.c b/lnet/lnet/config.c index 34889e6..5e367f0 100644 --- a/lnet/lnet/config.c +++ b/lnet/lnet/config.c @@ -23,7 +23,7 @@ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2012, 2016, Intel Corporation. + * Copyright (c) 2012, 2017, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -31,6 +31,9 @@ */ #define DEBUG_SUBSYSTEM S_LNET + +#include +#include #include #include #include @@ -85,6 +88,9 @@ lnet_net_unique(__u32 net_id, struct list_head *netlist, { struct lnet_net *net_l; + if (!netlist) + return true; + list_for_each_entry(net_l, netlist, net_list) { if (net_l->net_id == net_id) { if (net != NULL) @@ -118,10 +124,10 @@ lnet_ni_unique_net(struct list_head *nilist, char *iface) /* check that the NI is unique to the interfaces with in the same NI. * This is only a consideration if use_tcp_bonding is set */ static bool -lnet_ni_unique_ni(char *iface_list[LNET_MAX_INTERFACES], char *iface) +lnet_ni_unique_ni(char *iface_list[LNET_INTERFACES_NUM], char *iface) { int i; - for (i = 0; i < LNET_MAX_INTERFACES; i++) { + for (i = 0; i < LNET_INTERFACES_NUM; i++) { if (iface_list[i] != NULL && strncmp(iface_list[i], iface, strlen(iface)) == 0) return false; @@ -170,7 +176,8 @@ lnet_net_append_cpts(__u32 *cpts, __u32 ncpts, struct lnet_net *net) LIBCFS_ALLOC(net->net_cpts, sizeof(*net->net_cpts) * ncpts); if (net->net_cpts == NULL) return -ENOMEM; - memcpy(net->net_cpts, cpts, ncpts); + memcpy(net->net_cpts, cpts, ncpts * sizeof(*net->net_cpts)); + net->net_ncpts = ncpts; return 0; } @@ -303,7 +310,7 @@ lnet_ni_free(struct lnet_ni *ni) if (ni->ni_cpts != NULL) cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts); - for (i = 0; i < LNET_MAX_INTERFACES && + for (i = 0; i < LNET_INTERFACES_NUM && ni->ni_interfaces[i] != NULL; i++) { LIBCFS_FREE(ni->ni_interfaces[i], strlen(ni->ni_interfaces[i]) + 1); @@ -370,9 +377,10 @@ lnet_net_alloc(__u32 net_id, struct list_head *net_list) INIT_LIST_HEAD(&net->net_ni_list); INIT_LIST_HEAD(&net->net_ni_added); INIT_LIST_HEAD(&net->net_ni_zombie); + spin_lock_init(&net->net_lock); net->net_id = net_id; - net->net_state = LNET_NET_STATE_INIT; + net->net_last_alive = ktime_get_real_seconds(); /* initialize global paramters to undefiend */ net->net_tunables.lct_peer_timeout = -1; @@ -380,7 +388,8 @@ lnet_net_alloc(__u32 net_id, struct list_head *net_list) net->net_tunables.lct_peer_tx_credits = -1; net->net_tunables.lct_peer_rtr_credits = -1; - list_add_tail(&net->net_list, net_list); + if (net_list) + list_add_tail(&net->net_list, net_list); return net; } @@ -402,11 +411,11 @@ lnet_ni_add_interface(struct lnet_ni *ni, char *iface) * can free the tokens at the end of the function. * The newly allocated ni_interfaces[] can be * freed when freeing the NI */ - while (niface < LNET_MAX_INTERFACES && + while (niface < LNET_INTERFACES_NUM && ni->ni_interfaces[niface] != NULL) niface++; - if (niface >= LNET_MAX_INTERFACES) { + if (niface >= LNET_INTERFACES_NUM) { LCONSOLE_ERROR_MSG(0x115, "Too many interfaces " "for net %s\n", libcfs_net2str(LNET_NIDNET(ni->ni_nid))); @@ -427,13 +436,11 @@ lnet_ni_add_interface(struct lnet_ni *ni, char *iface) return 0; } -/* allocate and add to the provided network */ -lnet_ni_t * -lnet_ni_alloc(struct lnet_net *net, struct cfs_expr_list *el, char *iface) +static struct lnet_ni * +lnet_ni_alloc_common(struct lnet_net *net, char *iface) { struct lnet_tx_queue *tq; struct lnet_ni *ni; - int rc; int i; if (iface != NULL) @@ -451,8 +458,9 @@ lnet_ni_alloc(struct lnet_net *net, struct cfs_expr_list *el, char *iface) } spin_lock_init(&ni->ni_lock); - INIT_LIST_HEAD(&ni->ni_cptlist); INIT_LIST_HEAD(&ni->ni_netlist); + INIT_LIST_HEAD(&ni->ni_recovery); + LNetInvalidateMDHandle(&ni->ni_ping_mdh); ni->ni_refs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*ni->ni_refs[0])); if (ni->ni_refs == NULL) @@ -466,7 +474,45 @@ lnet_ni_alloc(struct lnet_net *net, struct cfs_expr_list *el, char *iface) cfs_percpt_for_each(tq, i, ni->ni_tx_queues) INIT_LIST_HEAD(&tq->tq_delayed); - if (el == NULL) { + ni->ni_net = net; + /* LND will fill in the address part of the NID */ + ni->ni_nid = LNET_MKNID(net->net_id, 0); + + /* Store net namespace in which current ni is being created */ + if (current->nsproxy->net_ns != NULL) + ni->ni_net_ns = get_net(current->nsproxy->net_ns); + else + ni->ni_net_ns = NULL; + + ni->ni_state = LNET_NI_STATE_INIT; + list_add_tail(&ni->ni_netlist, &net->net_ni_added); + + /* + * if an interface name is provided then make sure to add in that + * interface name in NI + */ + if (iface) + if (lnet_ni_add_interface(ni, iface) != 0) + goto failed; + + return ni; +failed: + lnet_ni_free(ni); + return NULL; +} + +/* allocate and add to the provided network */ +struct lnet_ni * +lnet_ni_alloc(struct lnet_net *net, struct cfs_expr_list *el, char *iface) +{ + struct lnet_ni *ni; + int rc; + + ni = lnet_ni_alloc_common(net, iface); + if (!ni) + return NULL; + + if (!el) { ni->ni_cpts = NULL; ni->ni_ncpts = LNET_CPT_NUMBER; } else { @@ -487,28 +533,42 @@ lnet_ni_alloc(struct lnet_net *net, struct cfs_expr_list *el, char *iface) ni->ni_ncpts = rc; } - ni->ni_net = net; - /* LND will fill in the address part of the NID */ - ni->ni_nid = LNET_MKNID(net->net_id, 0); - - /* Store net namespace in which current ni is being created */ - if (current->nsproxy->net_ns != NULL) - ni->ni_net_ns = get_net(current->nsproxy->net_ns); - else - ni->ni_net_ns = NULL; - - ni->ni_last_alive = ktime_get_real_seconds(); - ni->ni_state = LNET_NI_STATE_INIT; rc = lnet_net_append_cpts(ni->ni_cpts, ni->ni_ncpts, net); if (rc != 0) goto failed; - list_add_tail(&ni->ni_netlist, &net->net_ni_added); - /* if an interface name is provided then make sure to add in that - * interface name in NI */ - if (iface != NULL) - if (lnet_ni_add_interface(ni, iface) != 0) + return ni; +failed: + lnet_ni_free(ni); + return NULL; +} + +struct lnet_ni * +lnet_ni_alloc_w_cpt_array(struct lnet_net *net, __u32 *cpts, __u32 ncpts, + char *iface) +{ + struct lnet_ni *ni; + int rc; + + ni = lnet_ni_alloc_common(net, iface); + if (!ni) + return NULL; + + if (ncpts == 0) { + ni->ni_cpts = NULL; + ni->ni_ncpts = LNET_CPT_NUMBER; + } else { + size_t array_size = ncpts * sizeof(ni->ni_cpts[0]); + LIBCFS_ALLOC(ni->ni_cpts, array_size); + if (ni->ni_cpts == NULL) goto failed; + memcpy(ni->ni_cpts, cpts, array_size); + ni->ni_ncpts = ncpts; + } + + rc = lnet_net_append_cpts(ni->ni_cpts, ni->ni_ncpts, net); + if (rc != 0) + goto failed; return ni; failed: @@ -1186,7 +1246,7 @@ lnet_parse_route (char *str, int *im_a_router) continue; } - rc = lnet_add_route(net, hops, nid, priority); + rc = lnet_add_route(net, hops, nid, priority, 1); if (rc != 0 && rc != -EEXIST && rc != -EHOSTUNREACH) { CERROR("Can't create route " "to %s via %s\n", @@ -1252,7 +1312,7 @@ lnet_parse_routes (char *routes, int *im_a_router) static int lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip) { - struct list_head list = LIST_HEAD_INIT(list); + LIST_HEAD(list); int rc; int i; @@ -1543,111 +1603,136 @@ lnet_match_networks (char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) *networksp = networks; return count; } - -static void -lnet_ipaddr_free_enumeration(__u32 *ipaddrs, int nip) -{ - LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); -} - -static int -lnet_ipaddr_enumerate (__u32 **ipaddrsp) +/* + * kernel 5.3: commit ef11db3310e272d3d8dbe8739e0770820dd20e52 + * added in_dev_for_each_ifa_rtnl and in_dev_for_each_ifa_rcu + * and removed for_ifa and endfor_ifa. + * Use the _rntl variant as the current locking is rtnl. + */ +#ifdef in_dev_for_each_ifa_rtnl +#define DECLARE_CONST_IN_IFADDR(ifa) const struct in_ifaddr *ifa +#define endfor_ifa(in_dev) +#else +#define DECLARE_CONST_IN_IFADDR(ifa) +#define in_dev_for_each_ifa_rtnl(ifa, in_dev) for_ifa((in_dev)) +#endif + +int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns) { - int up; - __u32 netmask; - __u32 *ipaddrs; - __u32 *ipaddrs2; - int nip; - char **ifnames; - int nif = lnet_ipif_enumerate(&ifnames); - int i; - int rc; - - if (nif <= 0) - return nif; - - LIBCFS_ALLOC(ipaddrs, nif * sizeof(*ipaddrs)); - if (ipaddrs == NULL) { - CERROR("Can't allocate ipaddrs[%d]\n", nif); - lnet_ipif_free_enumeration(ifnames, nif); - return -ENOMEM; - } - - for (i = nip = 0; i < nif; i++) { - if (!strcmp(ifnames[i], "lo")) + struct lnet_inetdev *ifaces = NULL; + struct net_device *dev; + int nalloc = 0; + int nip = 0; + DECLARE_CONST_IN_IFADDR(ifa); + + rtnl_lock(); + for_each_netdev(ns, dev) { + int flags = dev_get_flags(dev); + struct in_device *in_dev; + int node_id; + int cpt; + + if (flags & IFF_LOOPBACK) /* skip the loopback IF */ continue; - rc = lnet_ipif_query(ifnames[i], &up, - &ipaddrs[nip], &netmask); - if (rc != 0) { - CWARN("Can't query interface %s: %d\n", - ifnames[i], rc); + if (!(flags & IFF_UP)) { + CWARN("lnet: Ignoring interface %s: it's down\n", + dev->name); continue; } - if (!up) { - CWARN("Ignoring interface %s: it's down\n", - ifnames[i]); + in_dev = __in_dev_get_rtnl(dev); + if (!in_dev) { + CWARN("lnet: Interface %s has no IPv4 status.\n", + dev->name); continue; } - nip++; - } - - lnet_ipif_free_enumeration(ifnames, nif); - - if (nip == nif) { - *ipaddrsp = ipaddrs; - } else { - if (nip > 0) { - LIBCFS_ALLOC(ipaddrs2, nip * sizeof(*ipaddrs2)); - if (ipaddrs2 == NULL) { - CERROR("Can't allocate ipaddrs[%d]\n", nip); - nip = -ENOMEM; - } else { - memcpy(ipaddrs2, ipaddrs, - nip * sizeof(*ipaddrs)); - *ipaddrsp = ipaddrs2; - rc = nip; + node_id = dev_to_node(&dev->dev); + cpt = cfs_cpt_of_node(lnet_cpt_table(), node_id); + + in_dev_for_each_ifa_rtnl(ifa, in_dev) { + if (nip >= nalloc) { + struct lnet_inetdev *tmp; + + nalloc += LNET_INTERFACES_NUM; + tmp = krealloc(ifaces, nalloc * sizeof(*tmp), + GFP_KERNEL); + if (!tmp) { + kfree(ifaces); + ifaces = NULL; + nip = -ENOMEM; + goto unlock_rtnl; + } + ifaces = tmp; } + + ifaces[nip].li_cpt = cpt; + ifaces[nip].li_flags = flags; + ifaces[nip].li_ipaddr = ntohl(ifa->ifa_local); + ifaces[nip].li_netmask = ntohl(ifa->ifa_mask); + strlcpy(ifaces[nip].li_name, ifa->ifa_label, + sizeof(ifaces[nip].li_name)); + nip++; } - lnet_ipaddr_free_enumeration(ipaddrs, nif); + endfor_ifa(in_dev); + } +unlock_rtnl: + rtnl_unlock(); + + if (nip == 0) { + CERROR("lnet: Can't find any usable interfaces, rc = -ENOENT\n"); + nip = -ENOENT; } + + *dev_list = ifaces; return nip; } +EXPORT_SYMBOL(lnet_inet_enumerate); int lnet_parse_ip2nets (char **networksp, char *ip2nets) { + struct lnet_inetdev *ifaces = NULL; __u32 *ipaddrs = NULL; - int nip = lnet_ipaddr_enumerate(&ipaddrs); + int nip; int rc; + int i; + nip = lnet_inet_enumerate(&ifaces, current->nsproxy->net_ns); if (nip < 0) { - LCONSOLE_ERROR_MSG(0x117, "Error %d enumerating local IP " - "interfaces for ip2nets to match\n", nip); + if (nip != -ENOENT) { + LCONSOLE_ERROR_MSG(0x117, + "Error %d enumerating local IP interfaces for ip2nets to match\n", + nip); + } else { + LCONSOLE_ERROR_MSG(0x118, + "No local IP interfaces for ip2nets to match\n"); + } return nip; } - if (nip == 0) { - LCONSOLE_ERROR_MSG(0x118, "No local IP interfaces " - "for ip2nets to match\n"); - return -ENOENT; + LIBCFS_ALLOC(ipaddrs, nip * sizeof(*ipaddrs)); + if (!ipaddrs) { + rc = -ENOMEM; + CERROR("lnet: Can't allocate ipaddrs[%d], rc = %d\n", + nip, rc); + goto out_free_addrs; } - rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip); - lnet_ipaddr_free_enumeration(ipaddrs, nip); + for (i = 0; i < nip; i++) + ipaddrs[i] = ifaces[i].li_ipaddr; + rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip); if (rc < 0) { LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc); - return rc; - } - - if (rc == 0) { + } else if (rc == 0) { LCONSOLE_ERROR_MSG(0x11a, "ip2nets does not match " "any local IP interfaces\n"); - return -ENOENT; + rc = -ENOENT; } - - return 0; + LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); +out_free_addrs: + kfree(ifaces); + return rc > 0 ? 0 : rc; }