staging: lustre: DLC Feature dynamic net config

This is the third patch of a set of patches that enables DLC.

This patch adds the following features to LNET.  Currently these
features are not driven by user space.
- Adding/Deleting Networks dynamically
Two new functions were added:
 - lnet_dyn_add_ni()
    add an NI. if the NI is already added then fail with
    appropriate error code
 - lnet_dyn_del_ni()
    delete an existing NI.  If NI doesn't exist fail with
    appropriate failure code.
These functions shall be called from IOCTL.

Signed-off-by: Amir Shehata <amir.shehata@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2456
Reviewed-on: http://review.whamcloud.com/9832
Reviewed-by: James Simmons <uja.ornl@gmail.com>
Reviewed-by: Doug Oucharek <doug.s.oucharek@intel.com>
Reviewed-by: Liang Zhen <liang.zhen@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Amir Shehata
2016-02-15 10:25:54 -05:00
committed by Greg Kroah-Hartman
parent 86ef6250fc
commit 6c9e5a55cb
3 changed files with 524 additions and 298 deletions

View File

@@ -681,12 +681,10 @@ void lnet_router_checker_stop(void);
void lnet_router_ni_update_locked(lnet_peer_t *gw, __u32 net);
void lnet_swap_pinginfo(lnet_ping_info_t *info);
int lnet_ping_target_init(void);
void lnet_ping_target_fini(void);
int lnet_parse_ip2nets(char **networksp, char *ip2nets);
int lnet_parse_routes(char *route_str, int *im_a_router);
int lnet_parse_networks(struct list_head *nilist, char *networks);
int lnet_net_unique(__u32 net, struct list_head *nilist);
int lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt);
lnet_peer_t *lnet_find_peer_locked(struct lnet_peer_table *ptable,

View File

@@ -533,6 +533,11 @@ lnet_prepare(lnet_pid_t requested_pid)
struct lnet_res_container **recs;
int rc = 0;
if (requested_pid == LNET_PID_ANY) {
/* Don't instantiate LNET just for me */
return -ENETDOWN;
}
LASSERT(!the_lnet.ln_refcount);
the_lnet.ln_routing = 0;
@@ -819,6 +824,229 @@ lnet_count_acceptor_nis(void)
return count;
}
static lnet_ping_info_t *
lnet_ping_info_create(int num_ni)
{
lnet_ping_info_t *ping_info;
unsigned int infosz;
infosz = offsetof(lnet_ping_info_t, pi_ni[num_ni]);
LIBCFS_ALLOC(ping_info, infosz);
if (!ping_info) {
CERROR("Can't allocate ping info[%d]\n", num_ni);
return NULL;
}
ping_info->pi_nnis = num_ni;
ping_info->pi_pid = the_lnet.ln_pid;
ping_info->pi_magic = LNET_PROTO_PING_MAGIC;
ping_info->pi_features = LNET_PING_FEAT_NI_STATUS;
return ping_info;
}
static inline int
lnet_get_ni_count(void)
{
struct lnet_ni *ni;
int count = 0;
lnet_net_lock(0);
list_for_each_entry(ni, &the_lnet.ln_nis, ni_list)
count++;
lnet_net_unlock(0);
return count;
}
static inline void
lnet_ping_info_free(lnet_ping_info_t *pinfo)
{
LIBCFS_FREE(pinfo,
offsetof(lnet_ping_info_t,
pi_ni[pinfo->pi_nnis]));
}
static void
lnet_ping_info_destroy(void)
{
struct lnet_ni *ni;
lnet_net_lock(LNET_LOCK_EX);
list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) {
lnet_ni_lock(ni);
ni->ni_status = NULL;
lnet_ni_unlock(ni);
}
lnet_ping_info_free(the_lnet.ln_ping_info);
the_lnet.ln_ping_info = NULL;
lnet_net_unlock(LNET_LOCK_EX);
}
static void
lnet_ping_event_handler(lnet_event_t *event)
{
lnet_ping_info_t *pinfo = event->md.user_ptr;
if (event->unlinked)
pinfo->pi_features = LNET_PING_FEAT_INVAL;
}
static int
lnet_ping_info_setup(lnet_ping_info_t **ppinfo, lnet_handle_md_t *md_handle,
int ni_count, bool set_eq)
{
lnet_process_id_t id = {LNET_NID_ANY, LNET_PID_ANY};
lnet_handle_me_t me_handle;
lnet_md_t md = {0};
int rc, rc2;
if (set_eq) {
rc = LNetEQAlloc(0, lnet_ping_event_handler,
&the_lnet.ln_ping_target_eq);
if (rc) {
CERROR("Can't allocate ping EQ: %d\n", rc);
return rc;
}
}
*ppinfo = lnet_ping_info_create(ni_count);
if (!*ppinfo) {
rc = -ENOMEM;
goto failed_0;
}
rc = LNetMEAttach(LNET_RESERVED_PORTAL, id,
LNET_PROTO_PING_MATCHBITS, 0,
LNET_UNLINK, LNET_INS_AFTER,
&me_handle);
if (rc) {
CERROR("Can't create ping ME: %d\n", rc);
goto failed_1;
}
/* initialize md content */
md.start = *ppinfo;
md.length = offsetof(lnet_ping_info_t,
pi_ni[(*ppinfo)->pi_nnis]);
md.threshold = LNET_MD_THRESH_INF;
md.max_size = 0;
md.options = LNET_MD_OP_GET | LNET_MD_TRUNCATE |
LNET_MD_MANAGE_REMOTE;
md.user_ptr = NULL;
md.eq_handle = the_lnet.ln_ping_target_eq;
md.user_ptr = *ppinfo;
rc = LNetMDAttach(me_handle, md, LNET_RETAIN, md_handle);
if (rc) {
CERROR("Can't attach ping MD: %d\n", rc);
goto failed_2;
}
return 0;
failed_2:
rc2 = LNetMEUnlink(me_handle);
LASSERT(!rc2);
failed_1:
lnet_ping_info_free(*ppinfo);
*ppinfo = NULL;
failed_0:
if (set_eq)
LNetEQFree(the_lnet.ln_ping_target_eq);
return rc;
}
static void
lnet_ping_md_unlink(lnet_ping_info_t *pinfo, lnet_handle_md_t *md_handle)
{
sigset_t blocked = cfs_block_allsigs();
LNetMDUnlink(*md_handle);
LNetInvalidateHandle(md_handle);
/* NB md could be busy; this just starts the unlink */
while (pinfo->pi_features != LNET_PING_FEAT_INVAL) {
CDEBUG(D_NET, "Still waiting for ping MD to unlink\n");
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cfs_time_seconds(1));
}
cfs_restore_sigs(blocked);
}
static void
lnet_ping_info_install_locked(lnet_ping_info_t *ping_info)
{
lnet_ni_status_t *ns;
lnet_ni_t *ni;
int i = 0;
list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) {
LASSERT(i < ping_info->pi_nnis);
ns = &ping_info->pi_ni[i];
ns->ns_nid = ni->ni_nid;
lnet_ni_lock(ni);
ns->ns_status = (ni->ni_status) ?
ni->ni_status->ns_status : LNET_NI_STATUS_UP;
ni->ni_status = ns;
lnet_ni_unlock(ni);
i++;
}
}
static void
lnet_ping_target_update(lnet_ping_info_t *pinfo, lnet_handle_md_t md_handle)
{
lnet_ping_info_t *old_pinfo = NULL;
lnet_handle_md_t old_md;
/* switch the NIs to point to the new ping info created */
lnet_net_lock(LNET_LOCK_EX);
if (!the_lnet.ln_routing)
pinfo->pi_features |= LNET_PING_FEAT_RTE_DISABLED;
lnet_ping_info_install_locked(pinfo);
if (the_lnet.ln_ping_info) {
old_pinfo = the_lnet.ln_ping_info;
old_md = the_lnet.ln_ping_target_md;
}
the_lnet.ln_ping_target_md = md_handle;
the_lnet.ln_ping_info = pinfo;
lnet_net_unlock(LNET_LOCK_EX);
if (old_pinfo) {
/* unlink the old ping info */
lnet_ping_md_unlink(old_pinfo, &old_md);
lnet_ping_info_free(old_pinfo);
}
}
static void
lnet_ping_target_fini(void)
{
int rc;
lnet_ping_md_unlink(the_lnet.ln_ping_info,
&the_lnet.ln_ping_target_md);
rc = LNetEQFree(the_lnet.ln_ping_target_eq);
LASSERT(!rc);
lnet_ping_info_destroy();
}
static int
lnet_ni_tq_credits(lnet_ni_t *ni)
{
@@ -837,64 +1065,12 @@ lnet_ni_tq_credits(lnet_ni_t *ni)
}
static void
lnet_shutdown_lndnis(void)
lnet_clear_zombies_nis_locked(void)
{
int i;
int islo;
lnet_ni_t *ni;
/* NB called holding the global mutex */
/* All quiet on the API front */
LASSERT(!the_lnet.ln_shutdown);
LASSERT(!the_lnet.ln_refcount);
LASSERT(list_empty(&the_lnet.ln_nis_zombie));
lnet_net_lock(LNET_LOCK_EX);
the_lnet.ln_shutdown = 1; /* flag shutdown */
/* Unlink NIs from the global table */
while (!list_empty(&the_lnet.ln_nis)) {
ni = list_entry(the_lnet.ln_nis.next,
lnet_ni_t, ni_list);
/* move it to zombie list and nobody can find it anymore */
list_move(&ni->ni_list, &the_lnet.ln_nis_zombie);
lnet_ni_decref_locked(ni, 0); /* drop ln_nis' ref */
if (!list_empty(&ni->ni_cptlist)) {
list_del_init(&ni->ni_cptlist);
lnet_ni_decref_locked(ni, 0);
}
}
/* Drop the cached eqwait NI. */
if (the_lnet.ln_eq_waitni) {
lnet_ni_decref_locked(the_lnet.ln_eq_waitni, 0);
the_lnet.ln_eq_waitni = NULL;
}
/* Drop the cached loopback NI. */
if (the_lnet.ln_loni) {
lnet_ni_decref_locked(the_lnet.ln_loni, 0);
the_lnet.ln_loni = NULL;
}
lnet_net_unlock(LNET_LOCK_EX);
/*
* Clear lazy portals and drop delayed messages which hold refs
* on their lnet_msg_t::msg_rxpeer
*/
for (i = 0; i < the_lnet.ln_nportals; i++)
LNetClearLazyPortal(i);
/*
* Clear the peer table and wait for all peers to go (they hold refs on
* their NIs)
*/
lnet_peer_tables_cleanup(NULL);
lnet_net_lock(LNET_LOCK_EX);
/*
* Now wait for the NI's I just nuked to show up on ln_zombie_nis
* and shut them down in guaranteed thread context
@@ -949,38 +1125,150 @@ lnet_shutdown_lndnis(void)
lnet_net_lock(LNET_LOCK_EX);
}
}
static void
lnet_shutdown_lndnis(void)
{
lnet_ni_t *ni;
int i;
/* NB called holding the global mutex */
/* All quiet on the API front */
LASSERT(!the_lnet.ln_shutdown);
LASSERT(!the_lnet.ln_refcount);
LASSERT(list_empty(&the_lnet.ln_nis_zombie));
lnet_net_lock(LNET_LOCK_EX);
the_lnet.ln_shutdown = 1; /* flag shutdown */
/* Unlink NIs from the global table */
while (!list_empty(&the_lnet.ln_nis)) {
ni = list_entry(the_lnet.ln_nis.next,
lnet_ni_t, ni_list);
/* move it to zombie list and nobody can find it anymore */
list_move(&ni->ni_list, &the_lnet.ln_nis_zombie);
lnet_ni_decref_locked(ni, 0); /* drop ln_nis' ref */
if (!list_empty(&ni->ni_cptlist)) {
list_del_init(&ni->ni_cptlist);
lnet_ni_decref_locked(ni, 0);
}
}
/* Drop the cached eqwait NI. */
if (the_lnet.ln_eq_waitni) {
lnet_ni_decref_locked(the_lnet.ln_eq_waitni, 0);
the_lnet.ln_eq_waitni = NULL;
}
/* Drop the cached loopback NI. */
if (the_lnet.ln_loni) {
lnet_ni_decref_locked(the_lnet.ln_loni, 0);
the_lnet.ln_loni = NULL;
}
lnet_net_unlock(LNET_LOCK_EX);
/*
* Clear lazy portals and drop delayed messages which hold refs
* on their lnet_msg_t::msg_rxpeer
*/
for (i = 0; i < the_lnet.ln_nportals; i++)
LNetClearLazyPortal(i);
/*
* Clear the peer table and wait for all peers to go (they hold refs on
* their NIs)
*/
lnet_peer_tables_cleanup(NULL);
lnet_net_lock(LNET_LOCK_EX);
lnet_clear_zombies_nis_locked();
the_lnet.ln_shutdown = 0;
lnet_net_unlock(LNET_LOCK_EX);
}
int
lnet_shutdown_lndni(__u32 net)
{
lnet_ping_info_t *pinfo;
lnet_handle_md_t md_handle;
lnet_ni_t *found_ni = NULL;
int ni_count;
int rc;
if (LNET_NETTYP(net) == LOLND)
return -EINVAL;
ni_count = lnet_get_ni_count();
/* create and link a new ping info, before removing the old one */
rc = lnet_ping_info_setup(&pinfo, &md_handle, ni_count - 1, false);
if (rc)
return rc;
/* proceed with shutting down the NI */
lnet_net_lock(LNET_LOCK_EX);
found_ni = lnet_net2ni_locked(net, 0);
if (!found_ni) {
lnet_net_unlock(LNET_LOCK_EX);
lnet_ping_md_unlink(pinfo, &md_handle);
lnet_ping_info_free(pinfo);
return -EINVAL;
}
/*
* decrement the reference counter on found_ni which was
* incremented when we called lnet_net2ni_locked()
*/
lnet_ni_decref_locked(found_ni, 0);
/* Move ni to zombie list so nobody can find it anymore */
list_move(&found_ni->ni_list, &the_lnet.ln_nis_zombie);
/* Drop the lock reference for the ln_nis ref. */
lnet_ni_decref_locked(found_ni, 0);
if (!list_empty(&found_ni->ni_cptlist)) {
list_del_init(&found_ni->ni_cptlist);
lnet_ni_decref_locked(found_ni, 0);
}
lnet_net_unlock(LNET_LOCK_EX);
/* Do peer table cleanup for this ni */
lnet_peer_tables_cleanup(found_ni);
lnet_net_lock(LNET_LOCK_EX);
lnet_clear_zombies_nis_locked();
lnet_net_unlock(LNET_LOCK_EX);
lnet_ping_target_update(pinfo, md_handle);
return 0;
}
static int
lnet_startup_lndnis(void)
lnet_startup_lndnis(struct list_head *nilist, __s32 peer_timeout,
__s32 peer_cr, __s32 peer_buf_cr, __s32 credits,
int *ni_count)
{
lnd_t *lnd;
struct lnet_ni *ni;
struct lnet_tx_queue *tq;
struct list_head nilist;
int i;
int rc = 0;
__u32 lnd_type;
int nicount = 0;
char *nets = lnet_get_networks();
INIT_LIST_HEAD(&nilist);
if (!nets)
goto failed;
rc = lnet_parse_networks(&nilist, nets);
if (rc)
goto failed;
while (!list_empty(&nilist)) {
ni = list_entry(nilist.next, lnet_ni_t, ni_list);
while (!list_empty(nilist)) {
ni = list_entry(nilist->next, lnet_ni_t, ni_list);
lnd_type = LNET_NETTYP(LNET_NIDNET(ni->ni_nid));
LASSERT(libcfs_isknown_lnd(lnd_type));
if (!libcfs_isknown_lnd(lnd_type))
goto failed;
if (lnd_type == CIBLND ||
lnd_type == OPENIBLND ||
@@ -991,6 +1279,24 @@ lnet_startup_lndnis(void)
goto failed;
}
/* Make sure this new NI is unique. */
lnet_net_lock(LNET_LOCK_EX);
if (!lnet_net_unique(LNET_NIDNET(ni->ni_nid),
&the_lnet.ln_nis)) {
if (lnd_type == LOLND) {
lnet_net_unlock(LNET_LOCK_EX);
list_del(&ni->ni_list);
lnet_ni_free(ni);
continue;
}
CERROR("Net %s is not unique\n",
libcfs_net2str(LNET_NIDNET(ni->ni_nid)));
lnet_net_unlock(LNET_LOCK_EX);
goto failed;
}
lnet_net_unlock(LNET_LOCK_EX);
mutex_lock(&the_lnet.ln_lnd_mutex);
lnd = lnet_find_lnd_by_type(lnd_type);
@@ -1029,6 +1335,25 @@ lnet_startup_lndnis(void)
goto failed;
}
/*
* If given some LND tunable parameters, parse those now to
* override the values in the NI structure.
*/
if (peer_buf_cr >= 0)
ni->ni_peerrtrcredits = peer_buf_cr;
if (peer_timeout >= 0)
ni->ni_peertimeout = peer_timeout;
/*
* TODO
* Note: For now, don't allow the user to change
* peertxcredits as this number is used in the
* IB LND to control queue depth.
* if (peer_cr != -1)
* ni->ni_peertxcredits = peer_cr;
*/
if (credits >= 0)
ni->ni_maxtxcredits = credits;
LASSERT(ni->ni_peertimeout <= 0 || lnd->lnd_query);
list_del(&ni->ni_list);
@@ -1045,6 +1370,14 @@ lnet_startup_lndnis(void)
lnet_net_unlock(LNET_LOCK_EX);
/* increment the ni_count here to account for the LOLND as
* well. If we increment past this point then the number
* of count will be missing the LOLND, and then ping and
* will not report the LOLND
*/
if (ni_count)
(*ni_count)++;
if (lnd->lnd_type == LOLND) {
lnet_ni_addref(ni);
LASSERT(!the_lnet.ln_loni);
@@ -1070,29 +1403,16 @@ lnet_startup_lndnis(void)
libcfs_nid2str(ni->ni_nid), ni->ni_peertxcredits,
lnet_ni_tq_credits(ni) * LNET_CPT_NUMBER,
ni->ni_peerrtrcredits, ni->ni_peertimeout);
nicount++;
}
if (the_lnet.ln_eq_waitni && nicount > 1) {
lnd_type = the_lnet.ln_eq_waitni->ni_lnd->lnd_type;
LCONSOLE_ERROR_MSG(0x109, "LND %s can only run single-network\n",
libcfs_lnd2str(lnd_type));
goto failed;
}
return 0;
failed:
lnet_shutdown_lndnis();
while (!list_empty(&nilist)) {
ni = list_entry(nilist.next, lnet_ni_t, ni_list);
failed:
while (!list_empty(nilist)) {
ni = list_entry(nilist->next, lnet_ni_t, ni_list);
list_del(&ni->ni_list);
lnet_ni_free(ni);
}
return -ENETDOWN;
return -EINVAL;
}
/**
@@ -1208,6 +1528,15 @@ LNetNIInit(lnet_pid_t requested_pid)
{
int im_a_router = 0;
int rc;
int ni_count = 0;
int lnd_type;
struct lnet_ni *ni;
lnet_ping_info_t *pinfo;
lnet_handle_md_t md_handle;
struct list_head net_head;
char *nets;
INIT_LIST_HEAD(&net_head);
mutex_lock(&the_lnet.ln_api_mutex);
@@ -1216,23 +1545,31 @@ LNetNIInit(lnet_pid_t requested_pid)
if (the_lnet.ln_refcount > 0) {
rc = the_lnet.ln_refcount++;
goto out;
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
}
if (requested_pid == LNET_PID_ANY) {
/* Don't instantiate LNET just for me */
rc = -ENETDOWN;
goto failed0;
}
nets = lnet_get_networks();
rc = lnet_prepare(requested_pid);
if (rc)
goto failed0;
rc = lnet_startup_lndnis();
rc = lnet_parse_networks(&net_head, nets);
if (rc < 0)
goto failed1;
rc = lnet_startup_lndnis(&net_head, -1, -1, -1, -1, &ni_count);
if (rc)
goto failed1;
if (the_lnet.ln_eq_waitni && ni_count > 1) {
lnd_type = the_lnet.ln_eq_waitni->ni_lnd->lnd_type;
LCONSOLE_ERROR_MSG(0x109, "LND %s can only run single-network\n",
libcfs_lnd2str(lnd_type));
goto failed2;
}
rc = lnet_parse_routes(lnet_get_routes(), &im_a_router);
if (rc)
goto failed2;
@@ -1252,26 +1589,30 @@ LNetNIInit(lnet_pid_t requested_pid)
the_lnet.ln_refcount = 1;
/* Now I may use my own API functions... */
/*
* NB router checker needs the_lnet.ln_ping_info in
* lnet_router_checker -> lnet_update_ni_status_locked
*/
rc = lnet_ping_target_init();
rc = lnet_ping_info_setup(&pinfo, &md_handle, ni_count, true);
if (rc)
goto failed3;
lnet_ping_target_update(pinfo, md_handle);
rc = lnet_router_checker_start();
if (rc)
goto failed4;
lnet_router_debugfs_init();
goto out;
mutex_unlock(&the_lnet.ln_api_mutex);
return 0;
failed4:
lnet_ping_target_fini();
failed3:
the_lnet.ln_refcount = 0;
lnet_ping_md_unlink(pinfo, &md_handle);
lnet_ping_info_free(pinfo);
failed3:
lnet_acceptor_stop();
rc = LNetEQFree(the_lnet.ln_ping_target_eq);
LASSERT(!rc);
failed2:
lnet_destroy_routes();
lnet_shutdown_lndnis();
@@ -1279,8 +1620,12 @@ LNetNIInit(lnet_pid_t requested_pid)
lnet_unprepare();
failed0:
LASSERT(rc < 0);
out:
mutex_unlock(&the_lnet.ln_api_mutex);
while (!list_empty(&net_head)) {
ni = list_entry(net_head.next, struct lnet_ni, ni_list);
list_del_init(&ni->ni_list);
lnet_ni_free(ni);
}
return rc;
}
EXPORT_SYMBOL(LNetNIInit);
@@ -1325,6 +1670,71 @@ LNetNIFini(void)
}
EXPORT_SYMBOL(LNetNIFini);
int
lnet_dyn_add_ni(lnet_pid_t requested_pid, char *nets,
__s32 peer_timeout, __s32 peer_cr, __s32 peer_buf_cr,
__s32 credits)
{
lnet_ping_info_t *pinfo;
lnet_handle_md_t md_handle;
struct lnet_ni *ni;
struct list_head net_head;
int rc;
INIT_LIST_HEAD(&net_head);
/* Create a ni structure for the network string */
rc = lnet_parse_networks(&net_head, nets);
if (rc < 0)
return rc;
mutex_lock(&the_lnet.ln_api_mutex);
if (rc > 1) {
rc = -EINVAL; /* only add one interface per call */
goto failed0;
}
rc = lnet_ping_info_setup(&pinfo, &md_handle, 1 + lnet_get_ni_count(),
false);
if (rc)
goto failed0;
rc = lnet_startup_lndnis(&net_head, peer_timeout, peer_cr,
peer_buf_cr, credits, NULL);
if (rc)
goto failed1;
lnet_ping_target_update(pinfo, md_handle);
mutex_unlock(&the_lnet.ln_api_mutex);
return 0;
failed1:
lnet_ping_md_unlink(pinfo, &md_handle);
lnet_ping_info_free(pinfo);
failed0:
mutex_unlock(&the_lnet.ln_api_mutex);
while (!list_empty(&net_head)) {
ni = list_entry(net_head.next, struct lnet_ni, ni_list);
list_del_init(&ni->ni_list);
lnet_ni_free(ni);
}
return rc;
}
int
lnet_dyn_del_ni(__u32 net)
{
int rc;
mutex_lock(&the_lnet.ln_api_mutex);
rc = lnet_shutdown_lndni(net);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
}
/**
* LNet ioctl handler.
*
@@ -1339,7 +1749,6 @@ LNetCtl(unsigned int cmd, void *arg)
unsigned long secs_passed;
LASSERT(the_lnet.ln_init);
LASSERT(the_lnet.ln_refcount > 0);
switch (cmd) {
case IOC_LIBCFS_GET_NI:
@@ -1351,12 +1760,17 @@ LNetCtl(unsigned int cmd, void *arg)
return lnet_fail_nid(data->ioc_nid, data->ioc_count);
case IOC_LIBCFS_ADD_ROUTE:
mutex_lock(&the_lnet.ln_api_mutex);
rc = lnet_add_route(data->ioc_net, data->ioc_count,
data->ioc_nid, data->ioc_priority);
return (rc) ? rc : lnet_check_routes();
mutex_unlock(&the_lnet.ln_api_mutex);
return rc ? rc : lnet_check_routes();
case IOC_LIBCFS_DEL_ROUTE:
return lnet_del_route(data->ioc_net, data->ioc_nid);
mutex_lock(&the_lnet.ln_api_mutex);
rc = lnet_del_route(data->ioc_net, data->ioc_nid);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
case IOC_LIBCFS_GET_ROUTE:
return lnet_get_route(data->ioc_count,
@@ -1471,194 +1885,6 @@ LNetSnprintHandle(char *str, int len, lnet_handle_any_t h)
}
EXPORT_SYMBOL(LNetSnprintHandle);
static int
lnet_create_ping_info(void)
{
int i;
int n;
int rc;
unsigned int infosz;
lnet_ni_t *ni;
lnet_process_id_t id;
lnet_ping_info_t *pinfo;
for (n = 0; ; n++) {
rc = LNetGetId(n, &id);
if (rc == -ENOENT)
break;
LASSERT(!rc);
}
infosz = offsetof(lnet_ping_info_t, pi_ni[n]);
LIBCFS_ALLOC(pinfo, infosz);
if (!pinfo) {
CERROR("Can't allocate ping info[%d]\n", n);
return -ENOMEM;
}
pinfo->pi_nnis = n;
pinfo->pi_pid = the_lnet.ln_pid;
pinfo->pi_magic = LNET_PROTO_PING_MAGIC;
pinfo->pi_features = LNET_PING_FEAT_NI_STATUS;
if (!the_lnet.ln_routing)
pinfo->pi_features |= LNET_PING_FEAT_RTE_DISABLED;
for (i = 0; i < n; i++) {
lnet_ni_status_t *ns = &pinfo->pi_ni[i];
rc = LNetGetId(i, &id);
LASSERT(!rc);
ns->ns_nid = id.nid;
ns->ns_status = LNET_NI_STATUS_UP;
lnet_net_lock(0);
ni = lnet_nid2ni_locked(id.nid, 0);
LASSERT(ni);
lnet_ni_lock(ni);
LASSERT(!ni->ni_status);
ni->ni_status = ns;
lnet_ni_unlock(ni);
lnet_ni_decref_locked(ni, 0);
lnet_net_unlock(0);
}
the_lnet.ln_ping_info = pinfo;
return 0;
}
static void
lnet_destroy_ping_info(void)
{
struct lnet_ni *ni;
lnet_net_lock(0);
list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) {
lnet_ni_lock(ni);
ni->ni_status = NULL;
lnet_ni_unlock(ni);
}
lnet_net_unlock(0);
LIBCFS_FREE(the_lnet.ln_ping_info,
offsetof(lnet_ping_info_t,
pi_ni[the_lnet.ln_ping_info->pi_nnis]));
the_lnet.ln_ping_info = NULL;
}
int
lnet_ping_target_init(void)
{
lnet_md_t md = { NULL };
lnet_handle_me_t meh;
lnet_process_id_t id;
int rc;
int rc2;
int infosz;
rc = lnet_create_ping_info();
if (rc)
return rc;
/*
* 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) {
CERROR("Can't allocate ping EQ: %d\n", rc);
goto failed_0;
}
memset(&id, 0, sizeof(lnet_process_id_t));
id.nid = LNET_NID_ANY;
id.pid = LNET_PID_ANY;
rc = LNetMEAttach(LNET_RESERVED_PORTAL, id,
LNET_PROTO_PING_MATCHBITS, 0,
LNET_UNLINK, LNET_INS_AFTER,
&meh);
if (rc) {
CERROR("Can't create ping ME: %d\n", rc);
goto failed_1;
}
/* initialize md content */
infosz = offsetof(lnet_ping_info_t,
pi_ni[the_lnet.ln_ping_info->pi_nnis]);
md.start = the_lnet.ln_ping_info;
md.length = infosz;
md.threshold = LNET_MD_THRESH_INF;
md.max_size = 0;
md.options = LNET_MD_OP_GET | LNET_MD_TRUNCATE |
LNET_MD_MANAGE_REMOTE;
md.user_ptr = NULL;
md.eq_handle = the_lnet.ln_ping_target_eq;
rc = LNetMDAttach(meh, md,
LNET_RETAIN,
&the_lnet.ln_ping_target_md);
if (rc) {
CERROR("Can't attach ping MD: %d\n", rc);
goto failed_2;
}
return 0;
failed_2:
rc2 = LNetMEUnlink(meh);
LASSERT(!rc2);
failed_1:
rc2 = LNetEQFree(the_lnet.ln_ping_target_eq);
LASSERT(!rc2);
failed_0:
lnet_destroy_ping_info();
return rc;
}
void
lnet_ping_target_fini(void)
{
lnet_event_t event;
int rc;
int which;
int timeout_ms = 1000;
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) {
/* 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);
lnet_destroy_ping_info();
cfs_restore_sigs(blocked);
}
static int lnet_ping(lnet_process_id_t id, int timeout_ms,
lnet_process_id_t __user *ids, int n_ids)
{
@@ -1670,7 +1896,7 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms,
int unlinked = 0;
int replied = 0;
const int a_long_time = 60000; /* mS */
int infosz = offsetof(lnet_ping_info_t, pi_ni[n_ids]);
int infosz;
lnet_ping_info_t *info;
lnet_process_id_t tmpid;
int i;
@@ -1679,6 +1905,8 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms,
int rc2;
sigset_t blocked;
infosz = offsetof(lnet_ping_info_t, pi_ni[n_ids]);
if (n_ids <= 0 ||
id.nid == LNET_NID_ANY ||
timeout_ms > 500000 || /* arbitrary limit! */

View File

@@ -77,7 +77,7 @@ lnet_issep(char c)
}
}
static int
int
lnet_net_unique(__u32 net, struct list_head *nilist)
{
struct list_head *tmp;