staging: lustre: Dynamic LNet Configuration (DLC)
This is the first patch of a set of patches that enables DLC. This patch adds some cleanup in the config.c as well as some preparatory changes in peer.c to enable dynamic network configuration Signed-off-by: Amir Shehata <amir.shehata@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2456 Change-Id: I8c8bbf3b55acf4d76f22a8be587b553a70d31889 Reviewed-on: http://review.whamcloud.com/9830 Reviewed-by: Liang Zhen <liang.zhen@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
4407f6101f
commit
21602c7db4
|
@ -685,7 +685,7 @@ int lnet_parse_networks(struct list_head *nilist, char *networks);
|
||||||
int lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt);
|
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,
|
lnet_peer_t *lnet_find_peer_locked(struct lnet_peer_table *ptable,
|
||||||
lnet_nid_t nid);
|
lnet_nid_t nid);
|
||||||
void lnet_peer_tables_cleanup(void);
|
void lnet_peer_tables_cleanup(lnet_ni_t *ni);
|
||||||
void lnet_peer_tables_destroy(void);
|
void lnet_peer_tables_destroy(void);
|
||||||
int lnet_peer_tables_create(void);
|
int lnet_peer_tables_create(void);
|
||||||
void lnet_debug_peer(lnet_nid_t nid);
|
void lnet_debug_peer(lnet_nid_t nid);
|
||||||
|
|
|
@ -351,6 +351,8 @@ typedef struct lnet_peer {
|
||||||
struct lnet_peer_table {
|
struct lnet_peer_table {
|
||||||
int pt_version; /* /proc validity stamp */
|
int pt_version; /* /proc validity stamp */
|
||||||
int pt_number; /* # peers extant */
|
int pt_number; /* # peers extant */
|
||||||
|
/* # zombies to go to deathrow (and not there yet) */
|
||||||
|
int pt_zombies;
|
||||||
struct list_head pt_deathrow; /* zombie peers */
|
struct list_head pt_deathrow; /* zombie peers */
|
||||||
struct list_head *pt_hash; /* NID->peer hash */
|
struct list_head *pt_hash; /* NID->peer hash */
|
||||||
};
|
};
|
||||||
|
@ -616,9 +618,6 @@ typedef struct {
|
||||||
/* registered LNDs */
|
/* registered LNDs */
|
||||||
struct list_head ln_lnds;
|
struct list_head ln_lnds;
|
||||||
|
|
||||||
/* space for network names */
|
|
||||||
char *ln_network_tokens;
|
|
||||||
int ln_network_tokens_nob;
|
|
||||||
/* test protocol compatibility flags */
|
/* test protocol compatibility flags */
|
||||||
int ln_testprotocompat;
|
int ln_testprotocompat;
|
||||||
|
|
||||||
|
|
|
@ -892,7 +892,7 @@ lnet_shutdown_lndnis(void)
|
||||||
* Clear the peer table and wait for all peers to go (they hold refs on
|
* Clear the peer table and wait for all peers to go (they hold refs on
|
||||||
* their NIs)
|
* their NIs)
|
||||||
*/
|
*/
|
||||||
lnet_peer_tables_cleanup();
|
lnet_peer_tables_cleanup(NULL);
|
||||||
|
|
||||||
lnet_net_lock(LNET_LOCK_EX);
|
lnet_net_lock(LNET_LOCK_EX);
|
||||||
/*
|
/*
|
||||||
|
@ -952,12 +952,6 @@ lnet_shutdown_lndnis(void)
|
||||||
|
|
||||||
the_lnet.ln_shutdown = 0;
|
the_lnet.ln_shutdown = 0;
|
||||||
lnet_net_unlock(LNET_LOCK_EX);
|
lnet_net_unlock(LNET_LOCK_EX);
|
||||||
|
|
||||||
if (the_lnet.ln_network_tokens) {
|
|
||||||
LIBCFS_FREE(the_lnet.ln_network_tokens,
|
|
||||||
the_lnet.ln_network_tokens_nob);
|
|
||||||
the_lnet.ln_network_tokens = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -96,6 +96,8 @@ lnet_net_unique(__u32 net, struct list_head *nilist)
|
||||||
void
|
void
|
||||||
lnet_ni_free(struct lnet_ni *ni)
|
lnet_ni_free(struct lnet_ni *ni)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (ni->ni_refs)
|
if (ni->ni_refs)
|
||||||
cfs_percpt_free(ni->ni_refs);
|
cfs_percpt_free(ni->ni_refs);
|
||||||
|
|
||||||
|
@ -105,6 +107,10 @@ lnet_ni_free(struct lnet_ni *ni)
|
||||||
if (ni->ni_cpts)
|
if (ni->ni_cpts)
|
||||||
cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts);
|
cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts);
|
||||||
|
|
||||||
|
for (i = 0; i < LNET_MAX_INTERFACES && ni->ni_interfaces[i]; i++) {
|
||||||
|
LIBCFS_FREE(ni->ni_interfaces[i],
|
||||||
|
strlen(ni->ni_interfaces[i]) + 1);
|
||||||
|
}
|
||||||
LIBCFS_FREE(ni, sizeof(*ni));
|
LIBCFS_FREE(ni, sizeof(*ni));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,8 +205,6 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
the_lnet.ln_network_tokens = tokens;
|
|
||||||
the_lnet.ln_network_tokens_nob = tokensize;
|
|
||||||
memcpy(tokens, networks, tokensize);
|
memcpy(tokens, networks, tokensize);
|
||||||
tmp = tokens;
|
tmp = tokens;
|
||||||
str = tokens;
|
str = tokens;
|
||||||
|
@ -321,7 +325,23 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
ni->ni_interfaces[niface++] = iface;
|
/*
|
||||||
|
* Allocate a separate piece of memory and copy
|
||||||
|
* into it the string, so we don't have
|
||||||
|
* a depencency on the tokens string. This way we
|
||||||
|
* can free the tokens at the end of the function.
|
||||||
|
* The newly allocated ni_interfaces[] can be
|
||||||
|
* freed when freeing the NI
|
||||||
|
*/
|
||||||
|
LIBCFS_ALLOC(ni->ni_interfaces[niface],
|
||||||
|
strlen(iface) + 1);
|
||||||
|
if (!ni->ni_interfaces[niface]) {
|
||||||
|
CERROR("Can't allocate net interface name\n");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
strncpy(ni->ni_interfaces[niface], iface,
|
||||||
|
strlen(iface));
|
||||||
|
niface++;
|
||||||
iface = comma;
|
iface = comma;
|
||||||
} while (iface);
|
} while (iface);
|
||||||
|
|
||||||
|
@ -346,6 +366,8 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
|
||||||
}
|
}
|
||||||
|
|
||||||
LASSERT(!list_empty(nilist));
|
LASSERT(!list_empty(nilist));
|
||||||
|
|
||||||
|
LIBCFS_FREE(tokens, tokensize);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed_syntax:
|
failed_syntax:
|
||||||
|
@ -362,7 +384,6 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
|
||||||
cfs_expr_list_free(el);
|
cfs_expr_list_free(el);
|
||||||
|
|
||||||
LIBCFS_FREE(tokens, tokensize);
|
LIBCFS_FREE(tokens, tokensize);
|
||||||
the_lnet.ln_network_tokens = NULL;
|
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,62 +103,116 @@ lnet_peer_tables_destroy(void)
|
||||||
the_lnet.ln_peer_tables = NULL;
|
the_lnet.ln_peer_tables = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lnet_peer_table_cleanup_locked(lnet_ni_t *ni, struct lnet_peer_table *ptable)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
lnet_peer_t *lp;
|
||||||
|
lnet_peer_t *tmp;
|
||||||
|
|
||||||
|
for (i = 0; i < LNET_PEER_HASH_SIZE; i++) {
|
||||||
|
list_for_each_entry_safe(lp, tmp, &ptable->pt_hash[i],
|
||||||
|
lp_hashlist) {
|
||||||
|
if (ni && ni != lp->lp_ni)
|
||||||
|
continue;
|
||||||
|
list_del_init(&lp->lp_hashlist);
|
||||||
|
/* Lose hash table's ref */
|
||||||
|
ptable->pt_zombies++;
|
||||||
|
lnet_peer_decref_locked(lp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lnet_peer_table_deathrow_wait_locked(struct lnet_peer_table *ptable,
|
||||||
|
int cpt_locked)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 3; ptable->pt_zombies; i++) {
|
||||||
|
lnet_net_unlock(cpt_locked);
|
||||||
|
|
||||||
|
if (is_power_of_2(i)) {
|
||||||
|
CDEBUG(D_WARNING,
|
||||||
|
"Waiting for %d zombies on peer table\n",
|
||||||
|
ptable->pt_zombies);
|
||||||
|
}
|
||||||
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
|
schedule_timeout(cfs_time_seconds(1) >> 1);
|
||||||
|
lnet_net_lock(cpt_locked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lnet_peer_table_del_rtrs_locked(lnet_ni_t *ni, struct lnet_peer_table *ptable,
|
||||||
|
int cpt_locked)
|
||||||
|
{
|
||||||
|
lnet_peer_t *lp;
|
||||||
|
lnet_peer_t *tmp;
|
||||||
|
lnet_nid_t lp_nid;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < LNET_PEER_HASH_SIZE; i++) {
|
||||||
|
list_for_each_entry_safe(lp, tmp, &ptable->pt_hash[i],
|
||||||
|
lp_hashlist) {
|
||||||
|
if (ni != lp->lp_ni)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!lp->lp_rtr_refcount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
lp_nid = lp->lp_nid;
|
||||||
|
|
||||||
|
lnet_net_unlock(cpt_locked);
|
||||||
|
lnet_del_route(LNET_NIDNET(LNET_NID_ANY), lp_nid);
|
||||||
|
lnet_net_lock(cpt_locked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lnet_peer_tables_cleanup(void)
|
lnet_peer_tables_cleanup(lnet_ni_t *ni)
|
||||||
{
|
{
|
||||||
struct lnet_peer_table *ptable;
|
struct lnet_peer_table *ptable;
|
||||||
|
struct list_head deathrow;
|
||||||
|
lnet_peer_t *lp;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
|
||||||
|
|
||||||
LASSERT(the_lnet.ln_shutdown); /* i.e. no new peers */
|
INIT_LIST_HEAD(&deathrow);
|
||||||
|
|
||||||
|
LASSERT(the_lnet.ln_shutdown || ni);
|
||||||
|
/*
|
||||||
|
* If just deleting the peers for a NI, get rid of any routes these
|
||||||
|
* peers are gateways for.
|
||||||
|
*/
|
||||||
cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) {
|
cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) {
|
||||||
lnet_net_lock(i);
|
lnet_net_lock(i);
|
||||||
|
lnet_peer_table_del_rtrs_locked(ni, ptable, i);
|
||||||
for (j = 0; j < LNET_PEER_HASH_SIZE; j++) {
|
|
||||||
struct list_head *peers = &ptable->pt_hash[j];
|
|
||||||
|
|
||||||
while (!list_empty(peers)) {
|
|
||||||
lnet_peer_t *lp = list_entry(peers->next,
|
|
||||||
lnet_peer_t,
|
|
||||||
lp_hashlist);
|
|
||||||
list_del_init(&lp->lp_hashlist);
|
|
||||||
/* lose hash table's ref */
|
|
||||||
lnet_peer_decref_locked(lp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lnet_net_unlock(i);
|
lnet_net_unlock(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the process of moving the applicable peers to
|
||||||
|
* deathrow.
|
||||||
|
*/
|
||||||
cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) {
|
cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) {
|
||||||
LIST_HEAD(deathrow);
|
|
||||||
lnet_peer_t *lp;
|
|
||||||
|
|
||||||
lnet_net_lock(i);
|
lnet_net_lock(i);
|
||||||
|
lnet_peer_table_cleanup_locked(ni, ptable);
|
||||||
for (j = 3; ptable->pt_number; j++) {
|
|
||||||
lnet_net_unlock(i);
|
|
||||||
|
|
||||||
if (!(j & (j - 1))) {
|
|
||||||
CDEBUG(D_WARNING,
|
|
||||||
"Waiting for %d peers on peer table\n",
|
|
||||||
ptable->pt_number);
|
|
||||||
}
|
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
|
||||||
schedule_timeout(cfs_time_seconds(1) / 2);
|
|
||||||
lnet_net_lock(i);
|
|
||||||
}
|
|
||||||
list_splice_init(&ptable->pt_deathrow, &deathrow);
|
|
||||||
|
|
||||||
lnet_net_unlock(i);
|
lnet_net_unlock(i);
|
||||||
|
}
|
||||||
|
|
||||||
while (!list_empty(&deathrow)) {
|
/* Cleanup all entries on deathrow. */
|
||||||
lp = list_entry(deathrow.next,
|
cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) {
|
||||||
lnet_peer_t, lp_hashlist);
|
lnet_net_lock(i);
|
||||||
list_del(&lp->lp_hashlist);
|
lnet_peer_table_deathrow_wait_locked(ptable, i);
|
||||||
LIBCFS_FREE(lp, sizeof(*lp));
|
list_splice_init(&ptable->pt_deathrow, &deathrow);
|
||||||
}
|
lnet_net_unlock(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!list_empty(&deathrow)) {
|
||||||
|
lp = list_entry(deathrow.next, lnet_peer_t, lp_hashlist);
|
||||||
|
list_del(&lp->lp_hashlist);
|
||||||
|
LIBCFS_FREE(lp, sizeof(*lp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +235,8 @@ lnet_destroy_peer_locked(lnet_peer_t *lp)
|
||||||
lp->lp_ni = NULL;
|
lp->lp_ni = NULL;
|
||||||
|
|
||||||
list_add(&lp->lp_hashlist, &ptable->pt_deathrow);
|
list_add(&lp->lp_hashlist, &ptable->pt_deathrow);
|
||||||
|
LASSERT(ptable->pt_zombies > 0);
|
||||||
|
ptable->pt_zombies--;
|
||||||
}
|
}
|
||||||
|
|
||||||
lnet_peer_t *
|
lnet_peer_t *
|
||||||
|
|
Loading…
Reference in a new issue