diff options
Diffstat (limited to 'drivers/staging/lustre/lnet/lnet')
18 files changed, 3967 insertions, 1821 deletions
diff --git a/drivers/staging/lustre/lnet/lnet/Makefile b/drivers/staging/lustre/lnet/lnet/Makefile index e276fe2bf8f3..4c81fa19429a 100644 --- a/drivers/staging/lustre/lnet/lnet/Makefile +++ b/drivers/staging/lustre/lnet/lnet/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_LNET) += lnet.o -lnet-y := api-ni.o config.o nidstrings.o \ +lnet-y := api-ni.o config.o nidstrings.o net_fault.o \ lib-me.o lib-msg.o lib-eq.o lib-md.o lib-ptl.o \ lib-socket.o lib-move.o module.o lo.o \ router.o router_proc.o acceptor.o peer.o diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c index fed57d90028d..1452bb3ad9eb 100644 --- a/drivers/staging/lustre/lnet/lnet/acceptor.c +++ b/drivers/staging/lustre/lnet/lnet/acceptor.c @@ -36,6 +36,7 @@ #define DEBUG_SUBSYSTEM S_LNET #include <linux/completion.h> +#include <net/sock.h> #include "../../include/linux/lnet/lib-lnet.h" static int accept_port = 988; @@ -46,7 +47,9 @@ static struct { int pta_shutdown; struct socket *pta_sock; struct completion pta_signal; -} lnet_acceptor_state; +} lnet_acceptor_state = { + .pta_shutdown = 1 +}; int lnet_acceptor_port(void) @@ -78,9 +81,11 @@ static char *accept_type; static int lnet_acceptor_get_tunables(void) { - /* Userland acceptor uses 'accept_type' instead of 'accept', due to + /* + * Userland acceptor uses 'accept_type' instead of 'accept', due to * conflict with 'accept(2)', but kernel acceptor still uses 'accept' - * for compatibility. Hence the trick. */ + * for compatibility. Hence the trick. + */ accept_type = accept; return 0; } @@ -140,7 +145,7 @@ EXPORT_SYMBOL(lnet_connect_console_error); int lnet_connect(struct socket **sockp, lnet_nid_t peer_nid, - __u32 local_ip, __u32 peer_ip, int peer_port) + __u32 local_ip, __u32 peer_ip, int peer_port) { lnet_acceptor_connreq_t cr; struct socket *sock; @@ -157,7 +162,7 @@ lnet_connect(struct socket **sockp, lnet_nid_t peer_nid, rc = lnet_sock_connect(&sock, &fatal, local_ip, port, peer_ip, peer_port); - if (rc != 0) { + if (rc) { if (fatal) goto failed; continue; @@ -169,14 +174,14 @@ lnet_connect(struct socket **sockp, lnet_nid_t peer_nid, cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION; cr.acr_nid = peer_nid; - if (the_lnet.ln_testprotocompat != 0) { + if (the_lnet.ln_testprotocompat) { /* single-shot proto check */ lnet_net_lock(LNET_LOCK_EX); - if ((the_lnet.ln_testprotocompat & 4) != 0) { + if (the_lnet.ln_testprotocompat & 4) { cr.acr_version++; the_lnet.ln_testprotocompat &= ~4; } - if ((the_lnet.ln_testprotocompat & 8) != 0) { + if (the_lnet.ln_testprotocompat & 8) { cr.acr_magic = LNET_PROTO_MAGIC; the_lnet.ln_testprotocompat &= ~8; } @@ -184,7 +189,7 @@ lnet_connect(struct socket **sockp, lnet_nid_t peer_nid, } rc = lnet_sock_write(sock, &cr, sizeof(cr), accept_timeout); - if (rc != 0) + if (rc) goto failed_sock; *sockp = sock; @@ -202,8 +207,6 @@ lnet_connect(struct socket **sockp, lnet_nid_t peer_nid, } EXPORT_SYMBOL(lnet_connect); -/* Below is the code common for both kernel and MT user-space */ - static int lnet_accept(struct socket *sock, __u32 magic) { @@ -218,23 +221,23 @@ lnet_accept(struct socket *sock, __u32 magic) LASSERT(sizeof(cr) <= 16); /* not too big for the stack */ rc = lnet_sock_getaddr(sock, 1, &peer_ip, &peer_port); - LASSERT(rc == 0); /* we succeeded before */ + LASSERT(!rc); /* we succeeded before */ if (!lnet_accept_magic(magic, LNET_PROTO_ACCEPTOR_MAGIC)) { - if (lnet_accept_magic(magic, LNET_PROTO_MAGIC)) { - /* future version compatibility! + /* + * future version compatibility! * When LNET unifies protocols over all LNDs, the first - * thing sent will be a version query. I send back - * LNET_PROTO_ACCEPTOR_MAGIC to tell her I'm "old" */ - + * thing sent will be a version query. I send back + * LNET_PROTO_ACCEPTOR_MAGIC to tell her I'm "old" + */ memset(&cr, 0, sizeof(cr)); cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC; cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION; rc = lnet_sock_write(sock, &cr, sizeof(cr), accept_timeout); - if (rc != 0) + if (rc) CERROR("Error sending magic+version in response to LNET magic from %pI4h: %d\n", &peer_ip, rc); return -EPROTO; @@ -254,9 +257,9 @@ lnet_accept(struct socket *sock, __u32 magic) rc = lnet_sock_read(sock, &cr.acr_version, sizeof(cr.acr_version), accept_timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading connection request version from %pI4h\n", - rc, &peer_ip); + rc, &peer_ip); return -EIO; } @@ -264,10 +267,12 @@ lnet_accept(struct socket *sock, __u32 magic) __swab32s(&cr.acr_version); if (cr.acr_version != LNET_PROTO_ACCEPTOR_VERSION) { - /* future version compatibility! + /* + * future version compatibility! * An acceptor-specific protocol rev will first send a version * query. I send back my current version to tell her I'm - * "old". */ + * "old". + */ int peer_version = cr.acr_version; memset(&cr, 0, sizeof(cr)); @@ -275,7 +280,7 @@ lnet_accept(struct socket *sock, __u32 magic) cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION; rc = lnet_sock_write(sock, &cr, sizeof(cr), accept_timeout); - if (rc != 0) + if (rc) CERROR("Error sending magic+version in response to version %d from %pI4h: %d\n", peer_version, &peer_ip, rc); return -EPROTO; @@ -285,9 +290,9 @@ lnet_accept(struct socket *sock, __u32 magic) sizeof(cr) - offsetof(lnet_acceptor_connreq_t, acr_nid), accept_timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading connection request from %pI4h\n", - rc, &peer_ip); + rc, &peer_ip); return -EIO; } @@ -295,20 +300,20 @@ lnet_accept(struct socket *sock, __u32 magic) __swab64s(&cr.acr_nid); ni = lnet_net2ni(LNET_NIDNET(cr.acr_nid)); - if (ni == NULL || /* no matching net */ + if (!ni || /* no matching net */ ni->ni_nid != cr.acr_nid) { /* right NET, wrong NID! */ - if (ni != NULL) + if (ni) lnet_ni_decref(ni); LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %pI4h for %s: No matching NI\n", &peer_ip, libcfs_nid2str(cr.acr_nid)); return -EPERM; } - if (ni->ni_lnd->lnd_accept == NULL) { + if (!ni->ni_lnd->lnd_accept) { /* This catches a request for the loopback LND */ lnet_ni_decref(ni); LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %pI4h for %s: NI doesn not accept IP connections\n", - &peer_ip, libcfs_nid2str(cr.acr_nid)); + &peer_ip, libcfs_nid2str(cr.acr_nid)); return -EPERM; } @@ -331,13 +336,13 @@ lnet_acceptor(void *arg) int peer_port; int secure = (int)((long_ptr_t)arg); - LASSERT(lnet_acceptor_state.pta_sock == NULL); + LASSERT(!lnet_acceptor_state.pta_sock); cfs_block_allsigs(); rc = lnet_sock_listen(&lnet_acceptor_state.pta_sock, 0, accept_port, accept_backlog); - if (rc != 0) { + if (rc) { if (rc == -EADDRINUSE) LCONSOLE_ERROR_MSG(0x122, "Can't start acceptor on port %d: port already in use\n", accept_port); @@ -354,13 +359,12 @@ lnet_acceptor(void *arg) lnet_acceptor_state.pta_shutdown = rc; complete(&lnet_acceptor_state.pta_signal); - if (rc != 0) + if (rc) return rc; while (!lnet_acceptor_state.pta_shutdown) { - rc = lnet_sock_accept(&newsock, lnet_acceptor_state.pta_sock); - if (rc != 0) { + if (rc) { if (rc != -EAGAIN) { CWARN("Accept error %d: pausing...\n", rc); set_current_state(TASK_UNINTERRUPTIBLE); @@ -376,7 +380,7 @@ lnet_acceptor(void *arg) } rc = lnet_sock_getaddr(newsock, 1, &peer_ip, &peer_port); - if (rc != 0) { + if (rc) { CERROR("Can't determine new connection's address\n"); goto failed; } @@ -389,14 +393,14 @@ lnet_acceptor(void *arg) rc = lnet_sock_read(newsock, &magic, sizeof(magic), accept_timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading connection request from %pI4h\n", - rc, &peer_ip); + rc, &peer_ip); goto failed; } rc = lnet_accept(newsock, magic); - if (rc != 0) + if (rc) goto failed; continue; @@ -436,14 +440,19 @@ accept2secure(const char *acc, long *sec) int lnet_acceptor_start(void) { + struct task_struct *task; int rc; long rc2; long secure; - LASSERT(lnet_acceptor_state.pta_sock == NULL); + /* if acceptor is already running return immediately */ + if (!lnet_acceptor_state.pta_shutdown) + return 0; + + LASSERT(!lnet_acceptor_state.pta_sock); rc = lnet_acceptor_get_tunables(); - if (rc != 0) + if (rc) return rc; init_completion(&lnet_acceptor_state.pta_signal); @@ -451,13 +460,13 @@ lnet_acceptor_start(void) if (rc <= 0) return rc; - if (lnet_count_acceptor_nis() == 0) /* not required */ + if (!lnet_count_acceptor_nis()) /* not required */ return 0; - rc2 = PTR_ERR(kthread_run(lnet_acceptor, - (void *)(ulong_ptr_t)secure, - "acceptor_%03ld", secure)); - if (IS_ERR_VALUE(rc2)) { + task = kthread_run(lnet_acceptor, (void *)(ulong_ptr_t)secure, + "acceptor_%03ld", secure); + if (IS_ERR(task)) { + rc2 = PTR_ERR(task); CERROR("Can't start acceptor thread: %ld\n", rc2); return -ESRCH; @@ -468,11 +477,11 @@ lnet_acceptor_start(void) if (!lnet_acceptor_state.pta_shutdown) { /* started OK */ - LASSERT(lnet_acceptor_state.pta_sock != NULL); + LASSERT(lnet_acceptor_state.pta_sock); return 0; } - LASSERT(lnet_acceptor_state.pta_sock == NULL); + LASSERT(!lnet_acceptor_state.pta_sock); return -ENETDOWN; } @@ -480,11 +489,17 @@ lnet_acceptor_start(void) void lnet_acceptor_stop(void) { - if (lnet_acceptor_state.pta_sock == NULL) /* not running */ + struct sock *sk; + + if (lnet_acceptor_state.pta_shutdown) /* not running */ return; lnet_acceptor_state.pta_shutdown = 1; - wake_up_all(sk_sleep(lnet_acceptor_state.pta_sock->sk)); + + sk = lnet_acceptor_state.pta_sock->sk; + + /* awake any sleepers using safe method */ + sk->sk_state_change(sk); /* block until acceptor signals exit */ wait_for_completion(&lnet_acceptor_state.pta_signal); diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 362282fa00bf..8764755544c9 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -39,6 +39,7 @@ #include <linux/ktime.h> #include "../../include/linux/lnet/lib-lnet.h" +#include "../../include/linux/lnet/lib-dlc.h" #define D_LNI D_CONSOLE @@ -61,6 +62,9 @@ static int rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT; module_param(rnet_htable_size, int, 0444); MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table"); +static int lnet_ping(lnet_process_id_t id, int timeout_ms, + lnet_process_id_t __user *ids, int n_ids); + static char * lnet_get_routes(void) { @@ -73,17 +77,17 @@ lnet_get_networks(void) char *nets; int rc; - if (*networks != 0 && *ip2nets != 0) { + if (*networks && *ip2nets) { LCONSOLE_ERROR_MSG(0x101, "Please specify EITHER 'networks' or 'ip2nets' but not both at once\n"); return NULL; } - if (*ip2nets != 0) { + if (*ip2nets) { rc = lnet_parse_ip2nets(&nets, ip2nets); - return (rc == 0) ? nets : NULL; + return !rc ? nets : NULL; } - if (*networks != 0) + if (*networks) return networks; return "tcp"; @@ -94,6 +98,7 @@ lnet_init_locks(void) { spin_lock_init(&the_lnet.ln_eq_wait_lock); init_waitqueue_head(&the_lnet.ln_eq_waitq); + init_waitqueue_head(&the_lnet.ln_rc_waitq); mutex_init(&the_lnet.ln_lnd_mutex); mutex_init(&the_lnet.ln_api_mutex); } @@ -104,10 +109,10 @@ lnet_create_remote_nets_table(void) int i; struct list_head *hash; - LASSERT(the_lnet.ln_remote_nets_hash == NULL); + LASSERT(!the_lnet.ln_remote_nets_hash); LASSERT(the_lnet.ln_remote_nets_hbits > 0); LIBCFS_ALLOC(hash, LNET_REMOTE_NETS_HASH_SIZE * sizeof(*hash)); - if (hash == NULL) { + if (!hash) { CERROR("Failed to create remote nets hash table\n"); return -ENOMEM; } @@ -123,7 +128,7 @@ lnet_destroy_remote_nets_table(void) { int i; - if (the_lnet.ln_remote_nets_hash == NULL) + if (!the_lnet.ln_remote_nets_hash) return; for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++) @@ -138,12 +143,12 @@ lnet_destroy_remote_nets_table(void) static void lnet_destroy_locks(void) { - if (the_lnet.ln_res_lock != NULL) { + if (the_lnet.ln_res_lock) { cfs_percpt_lock_free(the_lnet.ln_res_lock); the_lnet.ln_res_lock = NULL; } - if (the_lnet.ln_net_lock != NULL) { + if (the_lnet.ln_net_lock) { cfs_percpt_lock_free(the_lnet.ln_net_lock); the_lnet.ln_net_lock = NULL; } @@ -155,11 +160,11 @@ lnet_create_locks(void) lnet_init_locks(); the_lnet.ln_res_lock = cfs_percpt_lock_alloc(lnet_cpt_table()); - if (the_lnet.ln_res_lock == NULL) + if (!the_lnet.ln_res_lock) goto failed; the_lnet.ln_net_lock = cfs_percpt_lock_alloc(lnet_cpt_table()); - if (the_lnet.ln_net_lock == NULL) + if (!the_lnet.ln_net_lock) goto failed; return 0; @@ -171,10 +176,12 @@ lnet_create_locks(void) static void lnet_assert_wire_constants(void) { - /* Wire protocol assertions generated by 'wirecheck' + /* + * Wire protocol assertions generated by 'wirecheck' * running on Linux robert.bartonsoftware.com 2.6.8-1.521 * #1 Mon Aug 16 09:01:18 EDT 2004 i686 athlon i386 GNU/Linux - * with gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) */ + * with gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) + */ /* Constants... */ CLASSERT(LNET_PROTO_TCP_MAGIC == 0xeebc0ded); @@ -284,9 +291,8 @@ lnet_register_lnd(lnd_t *lnd) { mutex_lock(&the_lnet.ln_lnd_mutex); - LASSERT(the_lnet.ln_init); LASSERT(libcfs_isknown_lnd(lnd->lnd_type)); - LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == NULL); + LASSERT(!lnet_find_lnd_by_type(lnd->lnd_type)); list_add_tail(&lnd->lnd_list, &the_lnet.ln_lnds); lnd->lnd_refcount = 0; @@ -302,9 +308,8 @@ lnet_unregister_lnd(lnd_t *lnd) { mutex_lock(&the_lnet.ln_lnd_mutex); - LASSERT(the_lnet.ln_init); LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == lnd); - LASSERT(lnd->lnd_refcount == 0); + LASSERT(!lnd->lnd_refcount); list_del(&lnd->lnd_list); CDEBUG(D_NET, "%s LND unregistered\n", libcfs_lnd2str(lnd->lnd_type)); @@ -335,7 +340,6 @@ lnet_counters_get(lnet_counters_t *counters) counters->recv_length += ctr->recv_length; counters->route_length += ctr->route_length; counters->drop_length += ctr->drop_length; - } lnet_net_unlock(LNET_LOCK_EX); } @@ -375,7 +379,7 @@ lnet_res_container_cleanup(struct lnet_res_container *rec) { int count = 0; - if (rec->rec_type == 0) /* not set yet, it's uninitialized */ + if (!rec->rec_type) /* not set yet, it's uninitialized */ return; while (!list_empty(&rec->rec_active)) { @@ -395,14 +399,16 @@ lnet_res_container_cleanup(struct lnet_res_container *rec) } if (count > 0) { - /* Found alive MD/ME/EQ, user really should unlink/free + /* + * Found alive MD/ME/EQ, user really should unlink/free * all of them before finalize LNet, but if someone didn't, - * we have to recycle garbage for him */ + * we have to recycle garbage for him + */ CERROR("%d active elements on exit of %s container\n", count, lnet_res_type2str(rec->rec_type)); } - if (rec->rec_lh_hash != NULL) { + if (rec->rec_lh_hash) { LIBCFS_FREE(rec->rec_lh_hash, LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0])); rec->rec_lh_hash = NULL; @@ -417,7 +423,7 @@ lnet_res_container_setup(struct lnet_res_container *rec, int cpt, int type) int rc = 0; int i; - LASSERT(rec->rec_type == 0); + LASSERT(!rec->rec_type); rec->rec_type = type; INIT_LIST_HEAD(&rec->rec_active); @@ -426,7 +432,7 @@ lnet_res_container_setup(struct lnet_res_container *rec, int cpt, int type) /* Arbitrary choice of hash table size */ LIBCFS_CPT_ALLOC(rec->rec_lh_hash, lnet_cpt_table(), cpt, LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0])); - if (rec->rec_lh_hash == NULL) { + if (!rec->rec_lh_hash) { rc = -ENOMEM; goto out; } @@ -464,7 +470,7 @@ lnet_res_containers_create(int type) int i; recs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*rec)); - if (recs == NULL) { + if (!recs) { CERROR("Failed to allocate %s resource containers\n", lnet_res_type2str(type)); return NULL; @@ -472,7 +478,7 @@ lnet_res_containers_create(int type) cfs_percpt_for_each(rec, i, recs) { rc = lnet_res_container_setup(rec, i, type); - if (rc != 0) { + if (rc) { lnet_res_containers_destroy(recs); return NULL; } @@ -518,7 +524,7 @@ lnet_res_lh_initialize(struct lnet_res_container *rec, lnet_libhandle_t *lh) list_add(&lh->lh_hash_chain, &rec->rec_lh_hash[hash]); } -int lnet_unprepare(void); +static int lnet_unprepare(void); static int lnet_prepare(lnet_pid_t requested_pid) @@ -527,11 +533,16 @@ lnet_prepare(lnet_pid_t requested_pid) struct lnet_res_container **recs; int rc = 0; - LASSERT(the_lnet.ln_refcount == 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; - LASSERT((requested_pid & LNET_PID_USERFLAG) == 0); + LASSERT(!(requested_pid & LNET_PID_USERFLAG)); the_lnet.ln_pid = requested_pid; INIT_LIST_HEAD(&the_lnet.ln_test_peers); @@ -539,9 +550,11 @@ lnet_prepare(lnet_pid_t requested_pid) INIT_LIST_HEAD(&the_lnet.ln_nis_cpt); INIT_LIST_HEAD(&the_lnet.ln_nis_zombie); INIT_LIST_HEAD(&the_lnet.ln_routers); + INIT_LIST_HEAD(&the_lnet.ln_drop_rules); + INIT_LIST_HEAD(&the_lnet.ln_delay_rules); rc = lnet_create_remote_nets_table(); - if (rc != 0) + if (rc) goto failed; /* * NB the interface cookie in wire handles guards against delayed @@ -551,27 +564,27 @@ lnet_prepare(lnet_pid_t requested_pid) the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(), sizeof(lnet_counters_t)); - if (the_lnet.ln_counters == NULL) { + if (!the_lnet.ln_counters) { CERROR("Failed to allocate counters for LNet\n"); rc = -ENOMEM; goto failed; } rc = lnet_peer_tables_create(); - if (rc != 0) + if (rc) goto failed; rc = lnet_msg_containers_create(); - if (rc != 0) + if (rc) goto failed; rc = lnet_res_container_setup(&the_lnet.ln_eq_container, 0, LNET_COOKIE_TYPE_EQ); - if (rc != 0) + if (rc) goto failed; recs = lnet_res_containers_create(LNET_COOKIE_TYPE_ME); - if (recs == NULL) { + if (!recs) { rc = -ENOMEM; goto failed; } @@ -579,7 +592,7 @@ lnet_prepare(lnet_pid_t requested_pid) the_lnet.ln_me_containers = recs; recs = lnet_res_containers_create(LNET_COOKIE_TYPE_MD); - if (recs == NULL) { + if (!recs) { rc = -ENOMEM; goto failed; } @@ -587,7 +600,7 @@ lnet_prepare(lnet_pid_t requested_pid) the_lnet.ln_md_containers = recs; rc = lnet_portals_create(); - if (rc != 0) { + if (rc) { CERROR("Failed to create portals for LNet: %d\n", rc); goto failed; } @@ -599,17 +612,18 @@ lnet_prepare(lnet_pid_t requested_pid) return rc; } -int +static int lnet_unprepare(void) { - /* NB no LNET_LOCK since this is the last reference. All LND instances + /* + * NB no LNET_LOCK since this is the last reference. All LND instances * have shut down already, so it is safe to unlink and free all * descriptors, even those that appear committed to a network op (eg MD - * with non-zero pending count) */ - + * with non-zero pending count) + */ lnet_fail_nid(LNET_NID_ANY, 0); - LASSERT(the_lnet.ln_refcount == 0); + LASSERT(!the_lnet.ln_refcount); LASSERT(list_empty(&the_lnet.ln_test_peers)); LASSERT(list_empty(&the_lnet.ln_nis)); LASSERT(list_empty(&the_lnet.ln_nis_cpt)); @@ -617,12 +631,12 @@ lnet_unprepare(void) lnet_portals_destroy(); - if (the_lnet.ln_md_containers != NULL) { + if (the_lnet.ln_md_containers) { lnet_res_containers_destroy(the_lnet.ln_md_containers); the_lnet.ln_md_containers = NULL; } - if (the_lnet.ln_me_containers != NULL) { + if (the_lnet.ln_me_containers) { lnet_res_containers_destroy(the_lnet.ln_me_containers); the_lnet.ln_me_containers = NULL; } @@ -631,9 +645,9 @@ lnet_unprepare(void) lnet_msg_containers_destroy(); lnet_peer_tables_destroy(); - lnet_rtrpools_free(); + lnet_rtrpools_free(0); - if (the_lnet.ln_counters != NULL) { + if (the_lnet.ln_counters) { cfs_percpt_free(the_lnet.ln_counters); the_lnet.ln_counters = NULL; } @@ -709,7 +723,7 @@ lnet_cpt_of_nid_locked(lnet_nid_t nid) if (LNET_NIDNET(ni->ni_nid) != LNET_NIDNET(nid)) continue; - LASSERT(ni->ni_cpts != NULL); + LASSERT(ni->ni_cpts); return ni->ni_cpts[lnet_nid_cpt_hash (nid, ni->ni_ncpts)]; } @@ -747,12 +761,12 @@ lnet_islocalnet(__u32 net) cpt = lnet_net_lock_current(); ni = lnet_net2ni_locked(net, cpt); - if (ni != NULL) + if (ni) lnet_ni_decref_locked(ni, cpt); lnet_net_unlock(cpt); - return ni != NULL; + return !!ni; } lnet_ni_t * @@ -783,11 +797,11 @@ lnet_islocalnid(lnet_nid_t nid) cpt = lnet_net_lock_current(); ni = lnet_nid2ni_locked(nid, cpt); - if (ni != NULL) + if (ni) lnet_ni_decref_locked(ni, cpt); lnet_net_unlock(cpt); - return ni != NULL; + return !!ni; } int @@ -803,7 +817,7 @@ lnet_count_acceptor_nis(void) list_for_each(tmp, &the_lnet.ln_nis) { ni = list_entry(tmp, lnet_ni_t, ni_list); - if (ni->ni_lnd->lnd_accept != NULL) + if (ni->ni_lnd->lnd_accept) count++; } @@ -812,90 +826,280 @@ lnet_count_acceptor_nis(void) return count; } -static int -lnet_ni_tq_credits(lnet_ni_t *ni) +static lnet_ping_info_t * +lnet_ping_info_create(int num_ni) { - int credits; + lnet_ping_info_t *ping_info; + unsigned int infosz; - LASSERT(ni->ni_ncpts >= 1); + 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; + } - if (ni->ni_ncpts == 1) - return ni->ni_maxtxcredits; + 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; - credits = ni->ni_maxtxcredits / ni->ni_ncpts; - credits = max(credits, 8 * ni->ni_peertxcredits); - credits = min(credits, ni->ni_maxtxcredits); + return ping_info; +} - return credits; +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_shutdown_lndnis(void) +lnet_ping_info_destroy(void) { - int i; - int islo; - lnet_ni_t *ni; + struct lnet_ni *ni; - /* NB called holding the global mutex */ + lnet_net_lock(LNET_LOCK_EX); - /* All quiet on the API front */ - LASSERT(!the_lnet.ln_shutdown); - LASSERT(the_lnet.ln_refcount == 0); - LASSERT(list_empty(&the_lnet.ln_nis_zombie)); + 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_lock(LNET_LOCK_EX); - the_lnet.ln_shutdown = 1; /* flag shutdown */ + lnet_ping_info_free(the_lnet.ln_ping_info); + the_lnet.ln_ping_info = NULL; - /* 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); + 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 = { NULL }; + 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; } } - /* Drop the cached eqwait NI. */ - if (the_lnet.ln_eq_waitni != NULL) { - lnet_ni_decref_locked(the_lnet.ln_eq_waitni, 0); - the_lnet.ln_eq_waitni = NULL; + *ppinfo = lnet_ping_info_create(ni_count); + if (!*ppinfo) { + rc = -ENOMEM; + goto failed_0; } - /* Drop the cached loopback NI. */ - if (the_lnet.ln_loni != NULL) { - lnet_ni_decref_locked(the_lnet.ln_loni, 0); - the_lnet.ln_loni = NULL; + 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; } - lnet_net_unlock(LNET_LOCK_EX); + /* 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; - /* 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); + 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); +} - /* Clear the peer table and wait for all peers to go (they hold refs on - * their NIs) */ - lnet_peer_tables_cleanup(); +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); - /* Now wait for the NI's I just nuked to show up on ln_zombie_nis - * and shut them down in guaranteed thread context */ + + 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) +{ + int credits; + + LASSERT(ni->ni_ncpts >= 1); + + if (ni->ni_ncpts == 1) + return ni->ni_maxtxcredits; + + credits = ni->ni_maxtxcredits / ni->ni_ncpts; + credits = max(credits, 8 * ni->ni_peertxcredits); + credits = min(credits, ni->ni_maxtxcredits); + + return credits; +} + +static void +lnet_ni_unlink_locked(lnet_ni_t *ni) +{ + if (!list_empty(&ni->ni_cptlist)) { + list_del_init(&ni->ni_cptlist); + lnet_ni_decref_locked(ni, 0); + } + + /* move it to zombie list and nobody can find it anymore */ + LASSERT(!list_empty(&ni->ni_list)); + list_move(&ni->ni_list, &the_lnet.ln_nis_zombie); + lnet_ni_decref_locked(ni, 0); /* drop ln_nis' ref */ +} + +static void +lnet_clear_zombies_nis_locked(void) +{ + int i; + int islo; + lnet_ni_t *ni; + lnet_ni_t *temp; + + /* + * Now wait for the NI's I just nuked to show up on ln_zombie_nis + * and shut them down in guaranteed thread context + */ i = 2; - while (!list_empty(&the_lnet.ln_nis_zombie)) { + list_for_each_entry_safe(ni, temp, &the_lnet.ln_nis_zombie, ni_list) { int *ref; int j; - ni = list_entry(the_lnet.ln_nis_zombie.next, - lnet_ni_t, ni_list); list_del_init(&ni->ni_list); cfs_percpt_for_each(ref, j, ni->ni_refs) { - if (*ref == 0) + if (!*ref) continue; /* still busy, add it back to zombie list */ list_add(&ni->ni_list, &the_lnet.ln_nis_zombie); @@ -921,11 +1125,12 @@ lnet_shutdown_lndnis(void) islo = ni->ni_lnd->lnd_type == LOLND; LASSERT(!in_interrupt()); - (ni->ni_lnd->lnd_shutdown)(ni); - - /* can't deref lnd anymore now; it might have unregistered - * itself... */ + ni->ni_lnd->lnd_shutdown(ni); + /* + * can't deref lnd anymore now; it might have unregistered + * itself... + */ if (!islo) CDEBUG(D_LNI, "Removed LNI %s\n", libcfs_nid2str(ni->ni_nid)); @@ -935,176 +1140,263 @@ lnet_shutdown_lndnis(void) lnet_net_lock(LNET_LOCK_EX); } +} + +static void +lnet_shutdown_lndnis(void) +{ + lnet_ni_t *ni; + lnet_ni_t *temp; + 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 */ + list_for_each_entry_safe(ni, temp, &the_lnet.ln_nis, ni_list) { + lnet_ni_unlink_locked(ni); + } + /* 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); +} - if (the_lnet.ln_network_tokens != NULL) { - LIBCFS_FREE(the_lnet.ln_network_tokens, - the_lnet.ln_network_tokens_nob); - the_lnet.ln_network_tokens = NULL; - } +/* shutdown down the NI and release refcount */ +static void +lnet_shutdown_lndni(struct lnet_ni *ni) +{ + int i; + + lnet_net_lock(LNET_LOCK_EX); + lnet_ni_unlink_locked(ni); + lnet_net_unlock(LNET_LOCK_EX); + + /* clear messages for this NI on the lazy portal */ + for (i = 0; i < the_lnet.ln_nportals; i++) + lnet_clear_lazy_portal(ni, i, "Shutting down NI"); + + /* Do peer table cleanup for this ni */ + lnet_peer_tables_cleanup(ni); + + lnet_net_lock(LNET_LOCK_EX); + lnet_clear_zombies_nis_locked(); + lnet_net_unlock(LNET_LOCK_EX); } static int -lnet_startup_lndnis(void) +lnet_startup_lndni(struct lnet_ni *ni, __s32 peer_timeout, + __s32 peer_cr, __s32 peer_buf_cr, __s32 credits) { + int rc = -EINVAL; + int lnd_type; 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); + lnd_type = LNET_NETTYP(LNET_NIDNET(ni->ni_nid)); - if (nets == NULL) - goto failed; + LASSERT(libcfs_isknown_lnd(lnd_type)); - rc = lnet_parse_networks(&nilist, nets); - if (rc != 0) - goto failed; + if (lnd_type == CIBLND || lnd_type == OPENIBLND || + lnd_type == IIBLND || lnd_type == VIBLND) { + CERROR("LND %s obsoleted\n", libcfs_lnd2str(lnd_type)); + goto failed0; + } - while (!list_empty(&nilist)) { - ni = list_entry(nilist.next, lnet_ni_t, ni_list); - lnd_type = LNET_NETTYP(LNET_NIDNET(ni->ni_nid)); + /* Make sure this new NI is unique. */ + lnet_net_lock(LNET_LOCK_EX); + rc = lnet_net_unique(LNET_NIDNET(ni->ni_nid), &the_lnet.ln_nis); + lnet_net_unlock(LNET_LOCK_EX); + if (!rc) { + if (lnd_type == LOLND) { + lnet_ni_free(ni); + return 0; + } - LASSERT(libcfs_isknown_lnd(lnd_type)); + CERROR("Net %s is not unique\n", + libcfs_net2str(LNET_NIDNET(ni->ni_nid))); + rc = -EEXIST; + goto failed0; + } - if (lnd_type == CIBLND || - lnd_type == OPENIBLND || - lnd_type == IIBLND || - lnd_type == VIBLND) { - CERROR("LND %s obsoleted\n", - libcfs_lnd2str(lnd_type)); - goto failed; - } + mutex_lock(&the_lnet.ln_lnd_mutex); + lnd = lnet_find_lnd_by_type(lnd_type); + if (!lnd) { + mutex_unlock(&the_lnet.ln_lnd_mutex); + rc = request_module("%s", libcfs_lnd2modname(lnd_type)); mutex_lock(&the_lnet.ln_lnd_mutex); - lnd = lnet_find_lnd_by_type(lnd_type); - if (lnd == NULL) { + lnd = lnet_find_lnd_by_type(lnd_type); + if (!lnd) { mutex_unlock(&the_lnet.ln_lnd_mutex); - rc = request_module("%s", - libcfs_lnd2modname(lnd_type)); - mutex_lock(&the_lnet.ln_lnd_mutex); - - lnd = lnet_find_lnd_by_type(lnd_type); - if (lnd == NULL) { - mutex_unlock(&the_lnet.ln_lnd_mutex); - CERROR("Can't load LND %s, module %s, rc=%d\n", - libcfs_lnd2str(lnd_type), - libcfs_lnd2modname(lnd_type), rc); - goto failed; - } + CERROR("Can't load LND %s, module %s, rc=%d\n", + libcfs_lnd2str(lnd_type), + libcfs_lnd2modname(lnd_type), rc); + rc = -EINVAL; + goto failed0; } + } - lnet_net_lock(LNET_LOCK_EX); - lnd->lnd_refcount++; - lnet_net_unlock(LNET_LOCK_EX); - - ni->ni_lnd = lnd; - - rc = (lnd->lnd_startup)(ni); - - mutex_unlock(&the_lnet.ln_lnd_mutex); + lnet_net_lock(LNET_LOCK_EX); + lnd->lnd_refcount++; + lnet_net_unlock(LNET_LOCK_EX); - if (rc != 0) { - LCONSOLE_ERROR_MSG(0x105, "Error %d starting up LNI %s\n", - rc, libcfs_lnd2str(lnd->lnd_type)); - lnet_net_lock(LNET_LOCK_EX); - lnd->lnd_refcount--; - lnet_net_unlock(LNET_LOCK_EX); - goto failed; - } + ni->ni_lnd = lnd; - LASSERT(ni->ni_peertimeout <= 0 || lnd->lnd_query != NULL); + rc = lnd->lnd_startup(ni); - list_del(&ni->ni_list); + mutex_unlock(&the_lnet.ln_lnd_mutex); + if (rc) { + LCONSOLE_ERROR_MSG(0x105, "Error %d starting up LNI %s\n", + rc, libcfs_lnd2str(lnd->lnd_type)); lnet_net_lock(LNET_LOCK_EX); - /* refcount for ln_nis */ - lnet_ni_addref_locked(ni, 0); - list_add_tail(&ni->ni_list, &the_lnet.ln_nis); - if (ni->ni_cpts != NULL) { - list_add_tail(&ni->ni_cptlist, - &the_lnet.ln_nis_cpt); - lnet_ni_addref_locked(ni, 0); - } - + lnd->lnd_refcount--; lnet_net_unlock(LNET_LOCK_EX); + goto failed0; + } - if (lnd->lnd_type == LOLND) { - lnet_ni_addref(ni); - LASSERT(the_lnet.ln_loni == NULL); - the_lnet.ln_loni = ni; - continue; - } + /* + * 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; - if (ni->ni_peertxcredits == 0 || - ni->ni_maxtxcredits == 0) { - LCONSOLE_ERROR_MSG(0x107, "LNI %s has no %scredits\n", - libcfs_lnd2str(lnd->lnd_type), - ni->ni_peertxcredits == 0 ? - "" : "per-peer "); - goto failed; - } + LASSERT(ni->ni_peertimeout <= 0 || lnd->lnd_query); - cfs_percpt_for_each(tq, i, ni->ni_tx_queues) { - tq->tq_credits_min = - tq->tq_credits_max = - tq->tq_credits = lnet_ni_tq_credits(ni); - } + lnet_net_lock(LNET_LOCK_EX); + /* refcount for ln_nis */ + lnet_ni_addref_locked(ni, 0); + list_add_tail(&ni->ni_list, &the_lnet.ln_nis); + if (ni->ni_cpts) { + lnet_ni_addref_locked(ni, 0); + list_add_tail(&ni->ni_cptlist, &the_lnet.ln_nis_cpt); + } + + lnet_net_unlock(LNET_LOCK_EX); - CDEBUG(D_LNI, "Added LNI %s [%d/%d/%d/%d]\n", - libcfs_nid2str(ni->ni_nid), ni->ni_peertxcredits, - lnet_ni_tq_credits(ni) * LNET_CPT_NUMBER, - ni->ni_peerrtrcredits, ni->ni_peertimeout); + if (lnd->lnd_type == LOLND) { + lnet_ni_addref(ni); + LASSERT(!the_lnet.ln_loni); + the_lnet.ln_loni = ni; + return 0; + } - nicount++; + if (!ni->ni_peertxcredits || !ni->ni_maxtxcredits) { + LCONSOLE_ERROR_MSG(0x107, "LNI %s has no %scredits\n", + libcfs_lnd2str(lnd->lnd_type), + !ni->ni_peertxcredits ? + "" : "per-peer "); + /* + * shutdown the NI since if we get here then it must've already + * been started + */ + lnet_shutdown_lndni(ni); + return -EINVAL; } - if (the_lnet.ln_eq_waitni != NULL && 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; + cfs_percpt_for_each(tq, i, ni->ni_tx_queues) { + tq->tq_credits_min = + tq->tq_credits_max = + tq->tq_credits = lnet_ni_tq_credits(ni); } + CDEBUG(D_LNI, "Added LNI %s [%d/%d/%d/%d]\n", + libcfs_nid2str(ni->ni_nid), ni->ni_peertxcredits, + lnet_ni_tq_credits(ni) * LNET_CPT_NUMBER, + ni->ni_peerrtrcredits, ni->ni_peertimeout); + return 0; +failed0: + lnet_ni_free(ni); + return rc; +} - failed: - lnet_shutdown_lndnis(); +static int +lnet_startup_lndnis(struct list_head *nilist) +{ + struct lnet_ni *ni; + int rc; + int ni_count = 0; - 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); list_del(&ni->ni_list); - lnet_ni_free(ni); + rc = lnet_startup_lndni(ni, -1, -1, -1, -1); + + if (rc < 0) + goto failed; + + ni_count++; } - return -ENETDOWN; + return ni_count; +failed: + lnet_shutdown_lndnis(); + + return rc; } /** * Initialize LNet library. * - * Only userspace program needs to call this function - it's automatically - * called in the kernel at module loading time. Caller has to call lnet_fini() - * after a call to lnet_init(), if and only if the latter returned 0. It must - * be called exactly once. + * Automatically called at module loading time. Caller has to call + * lnet_lib_exit() after a call to lnet_lib_init(), if and only if the + * latter returned 0. It must be called exactly once. * - * \return 0 on success, and -ve on failures. + * \retval 0 on success + * \retval -ve on failures. */ -int -lnet_init(void) +int lnet_lib_init(void) { int rc; lnet_assert_wire_constants(); - LASSERT(!the_lnet.ln_init); memset(&the_lnet, 0, sizeof(the_lnet)); @@ -1117,28 +1409,29 @@ lnet_init(void) /* we are under risk of consuming all lh_cookie */ CERROR("Can't have %d CPTs for LNet (max allowed is %d), please change setting of CPT-table and retry\n", the_lnet.ln_cpt_number, LNET_CPT_MAX); - return -1; + return -E2BIG; } while ((1 << the_lnet.ln_cpt_bits) < the_lnet.ln_cpt_number) the_lnet.ln_cpt_bits++; rc = lnet_create_locks(); - if (rc != 0) { + if (rc) { CERROR("Can't create LNet global locks: %d\n", rc); - return -1; + return rc; } the_lnet.ln_refcount = 0; - the_lnet.ln_init = 1; LNetInvalidateHandle(&the_lnet.ln_rc_eqh); INIT_LIST_HEAD(&the_lnet.ln_lnds); INIT_LIST_HEAD(&the_lnet.ln_rcd_zombie); INIT_LIST_HEAD(&the_lnet.ln_rcd_deathrow); - /* The hash table size is the number of bits it takes to express the set + /* + * The hash table size is the number of bits it takes to express the set * ln_num_routes, minus 1 (better to under estimate than over so we - * don't waste memory). */ + * don't waste memory). + */ if (rnet_htable_size <= 0) rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT; else if (rnet_htable_size > LNET_REMOTE_NETS_HASH_MAX) @@ -1146,9 +1439,11 @@ lnet_init(void) the_lnet.ln_remote_nets_hbits = max_t(int, 1, order_base_2(rnet_htable_size) - 1); - /* All LNDs apart from the LOLND are in separate modules. They + /* + * All LNDs apart from the LOLND are in separate modules. They * register themselves when their module loads, and unregister - * themselves when their module is unloaded. */ + * themselves when their module is unloaded. + */ lnet_register_lnd(&the_lolnd); return 0; } @@ -1156,30 +1451,22 @@ lnet_init(void) /** * Finalize LNet library. * - * Only userspace program needs to call this function. It can be called - * at most once. - * - * \pre lnet_init() called with success. + * \pre lnet_lib_init() called with success. * \pre All LNet users called LNetNIFini() for matching LNetNIInit() calls. */ -void -lnet_fini(void) +void lnet_lib_exit(void) { - LASSERT(the_lnet.ln_init); - LASSERT(the_lnet.ln_refcount == 0); + LASSERT(!the_lnet.ln_refcount); while (!list_empty(&the_lnet.ln_lnds)) lnet_unregister_lnd(list_entry(the_lnet.ln_lnds.next, - lnd_t, lnd_list)); + lnd_t, lnd_list)); lnet_destroy_locks(); - - the_lnet.ln_init = 0; } /** * Set LNet PID and start LNet interfaces, routing, and forwarding. * - * Userspace program should call this after a successful call to lnet_init(). * Users must call this function at least once before any other functions. * For each successful call there must be a corresponding call to * LNetNIFini(). For subsequent calls to LNetNIInit(), \a requested_pid is @@ -1197,77 +1484,114 @@ LNetNIInit(lnet_pid_t requested_pid) { int im_a_router = 0; int rc; + int ni_count; + lnet_ping_info_t *pinfo; + lnet_handle_md_t md_handle; + struct list_head net_head; + + INIT_LIST_HEAD(&net_head); mutex_lock(&the_lnet.ln_api_mutex); - LASSERT(the_lnet.ln_init); CDEBUG(D_OTHER, "refs %d\n", the_lnet.ln_refcount); 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; + rc = lnet_prepare(requested_pid); + if (rc) { + mutex_unlock(&the_lnet.ln_api_mutex); + return rc; } - rc = lnet_prepare(requested_pid); - if (rc != 0) - goto failed0; + /* Add in the loopback network */ + if (!lnet_ni_alloc(LNET_MKNET(LOLND, 0), NULL, &net_head)) { + rc = -ENOMEM; + goto err_empty_list; + } - rc = lnet_startup_lndnis(); - if (rc != 0) - goto failed1; + /* + * If LNet is being initialized via DLC it is possible + * that the user requests not to load module parameters (ones which + * are supported by DLC) on initialization. Therefore, make sure not + * to load networks, routes and forwarding from module parameters + * in this case. On cleanup in case of failure only clean up + * routes if it has been loaded + */ + if (!the_lnet.ln_nis_from_mod_params) { + rc = lnet_parse_networks(&net_head, lnet_get_networks()); + if (rc < 0) + goto err_empty_list; + } + + ni_count = lnet_startup_lndnis(&net_head); + if (ni_count < 0) { + rc = ni_count; + goto err_empty_list; + } - rc = lnet_parse_routes(lnet_get_routes(), &im_a_router); - if (rc != 0) - goto failed2; + if (!the_lnet.ln_nis_from_mod_params) { + rc = lnet_parse_routes(lnet_get_routes(), &im_a_router); + if (rc) + goto err_shutdown_lndnis; - rc = lnet_check_routes(); - if (rc != 0) - goto failed2; + rc = lnet_check_routes(); + if (rc) + goto err_destory_routes; - rc = lnet_rtrpools_alloc(im_a_router); - if (rc != 0) - goto failed2; + rc = lnet_rtrpools_alloc(im_a_router); + if (rc) + goto err_destory_routes; + } rc = lnet_acceptor_start(); - if (rc != 0) - goto failed2; + if (rc) + goto err_destory_routes; 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(); - if (rc != 0) - goto failed3; + rc = lnet_ping_info_setup(&pinfo, &md_handle, ni_count, true); + if (rc) + goto err_acceptor_stop; + + lnet_ping_target_update(pinfo, md_handle); rc = lnet_router_checker_start(); - if (rc != 0) - goto failed4; + if (rc) + goto err_stop_ping; + lnet_fault_init(); lnet_router_debugfs_init(); - goto out; - failed4: + mutex_unlock(&the_lnet.ln_api_mutex); + + return 0; + +err_stop_ping: lnet_ping_target_fini(); - failed3: +err_acceptor_stop: the_lnet.ln_refcount = 0; lnet_acceptor_stop(); - failed2: - lnet_destroy_routes(); +err_destory_routes: + if (!the_lnet.ln_nis_from_mod_params) + lnet_destroy_routes(); +err_shutdown_lndnis: lnet_shutdown_lndnis(); - failed1: +err_empty_list: lnet_unprepare(); - failed0: LASSERT(rc < 0); - out: mutex_unlock(&the_lnet.ln_api_mutex); + while (!list_empty(&net_head)) { + struct lnet_ni *ni; + + 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); @@ -1286,7 +1610,6 @@ LNetNIFini(void) { mutex_lock(&the_lnet.ln_api_mutex); - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); if (the_lnet.ln_refcount != 1) { @@ -1294,6 +1617,7 @@ LNetNIFini(void) } else { LASSERT(!the_lnet.ln_niinit_self); + lnet_fault_fini(); lnet_router_debugfs_fini(); lnet_router_checker_stop(); lnet_ping_target_fini(); @@ -1313,30 +1637,233 @@ LNetNIFini(void) EXPORT_SYMBOL(LNetNIFini); /** - * This is an ugly hack to export IOC_LIBCFS_DEBUG_PEER and - * IOC_LIBCFS_PORTALS_COMPATIBILITY commands to users, by tweaking the LNet - * internal ioctl handler. + * Grabs the ni data from the ni structure and fills the out + * parameters * - * IOC_LIBCFS_PORTALS_COMPATIBILITY is now deprecated, don't use it. - * - * \param cmd IOC_LIBCFS_DEBUG_PEER to print debugging data about a peer. - * The data will be printed to system console. Don't use it excessively. - * \param arg A pointer to lnet_process_id_t, process ID of the peer. + * \param[in] ni network interface structure + * \param[out] cpt_count the number of cpts the ni is on + * \param[out] nid Network Interface ID + * \param[out] peer_timeout NI peer timeout + * \param[out] peer_tx_crdits NI peer transmit credits + * \param[out] peer_rtr_credits NI peer router credits + * \param[out] max_tx_credits NI max transmit credit + * \param[out] net_config Network configuration + */ +static void +lnet_fill_ni_info(struct lnet_ni *ni, __u32 *cpt_count, __u64 *nid, + int *peer_timeout, int *peer_tx_credits, + int *peer_rtr_credits, int *max_tx_credits, + struct lnet_ioctl_net_config *net_config) +{ + int i; + + if (!ni) + return; + + if (!net_config) + return; + + BUILD_BUG_ON(ARRAY_SIZE(ni->ni_interfaces) != + ARRAY_SIZE(net_config->ni_interfaces)); + + for (i = 0; i < ARRAY_SIZE(ni->ni_interfaces); i++) { + if (!ni->ni_interfaces[i]) + break; + + strncpy(net_config->ni_interfaces[i], + ni->ni_interfaces[i], + sizeof(net_config->ni_interfaces[i])); + } + + *nid = ni->ni_nid; + *peer_timeout = ni->ni_peertimeout; + *peer_tx_credits = ni->ni_peertxcredits; + *peer_rtr_credits = ni->ni_peerrtrcredits; + *max_tx_credits = ni->ni_maxtxcredits; + + net_config->ni_status = ni->ni_status->ns_status; + + if (ni->ni_cpts) { + int num_cpts = min(ni->ni_ncpts, LNET_MAX_SHOW_NUM_CPT); + + for (i = 0; i < num_cpts; i++) + net_config->ni_cpts[i] = ni->ni_cpts[i]; + + *cpt_count = num_cpts; + } +} + +int +lnet_get_net_config(int idx, __u32 *cpt_count, __u64 *nid, int *peer_timeout, + int *peer_tx_credits, int *peer_rtr_credits, + int *max_tx_credits, + struct lnet_ioctl_net_config *net_config) +{ + struct lnet_ni *ni; + struct list_head *tmp; + int cpt, i = 0; + int rc = -ENOENT; + + cpt = lnet_net_lock_current(); + + list_for_each(tmp, &the_lnet.ln_nis) { + if (i++ != idx) + continue; + + ni = list_entry(tmp, lnet_ni_t, ni_list); + lnet_ni_lock(ni); + lnet_fill_ni_info(ni, cpt_count, nid, peer_timeout, + peer_tx_credits, peer_rtr_credits, + max_tx_credits, net_config); + lnet_ni_unlock(ni); + rc = 0; + break; + } + + lnet_net_unlock(cpt); + return rc; +} + +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; + lnet_remotenet_t *rnet; + 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 ? -EINVAL : rc; + + mutex_lock(&the_lnet.ln_api_mutex); + + if (rc > 1) { + rc = -EINVAL; /* only add one interface per call */ + goto failed0; + } + + ni = list_entry(net_head.next, struct lnet_ni, ni_list); + + lnet_net_lock(LNET_LOCK_EX); + rnet = lnet_find_net_locked(LNET_NIDNET(ni->ni_nid)); + lnet_net_unlock(LNET_LOCK_EX); + /* + * make sure that the net added doesn't invalidate the current + * configuration LNet is keeping + */ + if (rnet) { + CERROR("Adding net %s will invalidate routing configuration\n", + nets); + rc = -EUSERS; + goto failed0; + } + + rc = lnet_ping_info_setup(&pinfo, &md_handle, 1 + lnet_get_ni_count(), + false); + if (rc) + goto failed0; + + list_del_init(&ni->ni_list); + + rc = lnet_startup_lndni(ni, peer_timeout, peer_cr, + peer_buf_cr, credits); + if (rc) + goto failed1; + + if (ni->ni_lnd->lnd_accept) { + rc = lnet_acceptor_start(); + if (rc < 0) { + /* shutdown the ni that we just started */ + CERROR("Failed to start up acceptor thread\n"); + lnet_shutdown_lndni(ni); + 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) +{ + lnet_ni_t *ni; + lnet_ping_info_t *pinfo; + lnet_handle_md_t md_handle; + int rc; + + /* don't allow userspace to shutdown the LOLND */ + if (LNET_NETTYP(net) == LOLND) + return -EINVAL; + + mutex_lock(&the_lnet.ln_api_mutex); + /* create and link a new ping info, before removing the old one */ + rc = lnet_ping_info_setup(&pinfo, &md_handle, + lnet_get_ni_count() - 1, false); + if (rc) + goto out; + + ni = lnet_net2ni(net); + if (!ni) { + rc = -EINVAL; + goto failed; + } + + /* decrement the reference counter taken by lnet_net2ni() */ + lnet_ni_decref_locked(ni, 0); + + lnet_shutdown_lndni(ni); + + if (!lnet_count_acceptor_nis()) + lnet_acceptor_stop(); + + lnet_ping_target_update(pinfo, md_handle); + goto out; +failed: + lnet_ping_md_unlink(pinfo, &md_handle); + lnet_ping_info_free(pinfo); +out: + mutex_unlock(&the_lnet.ln_api_mutex); + + return rc; +} + +/** + * LNet ioctl handler. * - * \return Always return 0 when called by users directly (i.e., not via ioctl). */ int LNetCtl(unsigned int cmd, void *arg) { struct libcfs_ioctl_data *data = arg; + struct lnet_ioctl_config_data *config; lnet_process_id_t id = {0}; lnet_ni_t *ni; int rc; unsigned long secs_passed; - LASSERT(the_lnet.ln_init); - LASSERT(the_lnet.ln_refcount > 0); - switch (cmd) { case IOC_LIBCFS_GET_NI: rc = LNetGetId(data->ioc_count, &id); @@ -1347,26 +1874,149 @@ LNetCtl(unsigned int cmd, void *arg) return lnet_fail_nid(data->ioc_nid, data->ioc_count); case IOC_LIBCFS_ADD_ROUTE: - rc = lnet_add_route(data->ioc_net, data->ioc_count, - data->ioc_nid, data->ioc_priority); - return (rc != 0) ? rc : lnet_check_routes(); + config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + + mutex_lock(&the_lnet.ln_api_mutex); + rc = lnet_add_route(config->cfg_net, + config->cfg_config_u.cfg_route.rtr_hop, + config->cfg_nid, + config->cfg_config_u.cfg_route.rtr_priority); + if (!rc) { + rc = lnet_check_routes(); + if (rc) + lnet_del_route(config->cfg_net, + config->cfg_nid); + } + mutex_unlock(&the_lnet.ln_api_mutex); + return rc; case IOC_LIBCFS_DEL_ROUTE: - return lnet_del_route(data->ioc_net, data->ioc_nid); + config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + + mutex_lock(&the_lnet.ln_api_mutex); + rc = lnet_del_route(config->cfg_net, config->cfg_nid); + mutex_unlock(&the_lnet.ln_api_mutex); + return rc; case IOC_LIBCFS_GET_ROUTE: - return lnet_get_route(data->ioc_count, - &data->ioc_net, &data->ioc_count, - &data->ioc_nid, &data->ioc_flags, - &data->ioc_priority); + config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + + return lnet_get_route(config->cfg_count, + &config->cfg_net, + &config->cfg_config_u.cfg_route.rtr_hop, + &config->cfg_nid, + &config->cfg_config_u.cfg_route.rtr_flags, + &config->cfg_config_u.cfg_route.rtr_priority); + + case IOC_LIBCFS_GET_NET: { + struct lnet_ioctl_net_config *net_config; + size_t total = sizeof(*config) + sizeof(*net_config); + + config = arg; + + if (config->cfg_hdr.ioc_len < total) + return -EINVAL; + + net_config = (struct lnet_ioctl_net_config *) + config->cfg_bulk; + if (!net_config) + return -EINVAL; + + return lnet_get_net_config(config->cfg_count, + &config->cfg_ncpts, + &config->cfg_nid, + &config->cfg_config_u.cfg_net.net_peer_timeout, + &config->cfg_config_u.cfg_net.net_peer_tx_credits, + &config->cfg_config_u.cfg_net.net_peer_rtr_credits, + &config->cfg_config_u.cfg_net.net_max_tx_credits, + net_config); + } + + case IOC_LIBCFS_GET_LNET_STATS: { + struct lnet_ioctl_lnet_stats *lnet_stats = arg; + + if (lnet_stats->st_hdr.ioc_len < sizeof(*lnet_stats)) + return -EINVAL; + + lnet_counters_get(&lnet_stats->st_cntrs); + return 0; + } + + case IOC_LIBCFS_CONFIG_RTR: + config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + + mutex_lock(&the_lnet.ln_api_mutex); + if (config->cfg_config_u.cfg_buffers.buf_enable) { + rc = lnet_rtrpools_enable(); + mutex_unlock(&the_lnet.ln_api_mutex); + return rc; + } + lnet_rtrpools_disable(); + mutex_unlock(&the_lnet.ln_api_mutex); + return 0; + + case IOC_LIBCFS_ADD_BUF: + config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + + mutex_lock(&the_lnet.ln_api_mutex); + rc = lnet_rtrpools_adjust(config->cfg_config_u.cfg_buffers.buf_tiny, + config->cfg_config_u.cfg_buffers.buf_small, + config->cfg_config_u.cfg_buffers.buf_large); + mutex_unlock(&the_lnet.ln_api_mutex); + return rc; + + case IOC_LIBCFS_GET_BUF: { + struct lnet_ioctl_pool_cfg *pool_cfg; + size_t total = sizeof(*config) + sizeof(*pool_cfg); + + config = arg; + + if (config->cfg_hdr.ioc_len < total) + return -EINVAL; + + pool_cfg = (struct lnet_ioctl_pool_cfg *)config->cfg_bulk; + return lnet_get_rtr_pool_cfg(config->cfg_count, pool_cfg); + } + + case IOC_LIBCFS_GET_PEER_INFO: { + struct lnet_ioctl_peer *peer_info = arg; + + if (peer_info->pr_hdr.ioc_len < sizeof(*peer_info)) + return -EINVAL; + + return lnet_get_peer_info(peer_info->pr_count, + &peer_info->pr_nid, + peer_info->pr_lnd_u.pr_peer_credits.cr_aliveness, + &peer_info->pr_lnd_u.pr_peer_credits.cr_ncpt, + &peer_info->pr_lnd_u.pr_peer_credits.cr_refcount, + &peer_info->pr_lnd_u.pr_peer_credits.cr_ni_peer_tx_credits, + &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_tx_credits, + &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_rtr_credits, + &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_min_rtr_credits, + &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_tx_qnob); + } + case IOC_LIBCFS_NOTIFY_ROUTER: secs_passed = (ktime_get_real_seconds() - data->ioc_u64[0]); - return lnet_notify(NULL, data->ioc_nid, data->ioc_flags, - jiffies - secs_passed * HZ); + secs_passed *= msecs_to_jiffies(MSEC_PER_SEC); - case IOC_LIBCFS_PORTALS_COMPATIBILITY: - /* This can be removed once lustre stops calling it */ - return 0; + return lnet_notify(NULL, data->ioc_nid, data->ioc_flags, + jiffies - secs_passed); case IOC_LIBCFS_LNET_DIST: rc = LNetDist(data->ioc_nid, &data->ioc_nid, &data->ioc_u32[1]); @@ -1382,46 +2032,26 @@ LNetCtl(unsigned int cmd, void *arg) lnet_net_unlock(LNET_LOCK_EX); return 0; + case IOC_LIBCFS_LNET_FAULT: + return lnet_fault_ctl(data->ioc_flags, data); + case IOC_LIBCFS_PING: id.nid = data->ioc_nid; id.pid = data->ioc_u32[0]; rc = lnet_ping(id, data->ioc_u32[1], /* timeout */ - (lnet_process_id_t *)data->ioc_pbuf1, - data->ioc_plen1/sizeof(lnet_process_id_t)); + data->ioc_pbuf1, + data->ioc_plen1 / sizeof(lnet_process_id_t)); if (rc < 0) return rc; data->ioc_count = rc; return 0; - case IOC_LIBCFS_DEBUG_PEER: { - /* CAVEAT EMPTOR: this one designed for calling directly; not - * via an ioctl */ - id = *((lnet_process_id_t *) arg); - - lnet_debug_peer(id.nid); - - ni = lnet_net2ni(LNET_NIDNET(id.nid)); - if (ni == NULL) { - CDEBUG(D_WARNING, "No NI for %s\n", libcfs_id2str(id)); - } else { - if (ni->ni_lnd->lnd_ctl == NULL) { - CDEBUG(D_WARNING, "No ctl for %s\n", - libcfs_id2str(id)); - } else { - (void)ni->ni_lnd->lnd_ctl(ni, cmd, arg); - } - - lnet_ni_decref(ni); - } - return 0; - } - default: ni = lnet_net2ni(data->ioc_net); - if (ni == NULL) + if (!ni) return -EINVAL; - if (ni->ni_lnd->lnd_ctl == NULL) + if (!ni->ni_lnd->lnd_ctl) rc = -EINVAL; else rc = ni->ni_lnd->lnd_ctl(ni, cmd, arg); @@ -1433,6 +2063,12 @@ LNetCtl(unsigned int cmd, void *arg) } EXPORT_SYMBOL(LNetCtl); +void LNetDebugPeer(lnet_process_id_t id) +{ + lnet_debug_peer(id.nid); +} +EXPORT_SYMBOL(LNetDebugPeer); + /** * Retrieve the lnet_process_id_t ID of LNet interface at \a index. Note that * all interfaces share a same PID, as requested by LNetNIInit(). @@ -1452,16 +2088,12 @@ LNetGetId(unsigned int index, lnet_process_id_t *id) int cpt; int rc = -ENOENT; - LASSERT(the_lnet.ln_init); - - /* LNetNI initilization failed? */ - if (the_lnet.ln_refcount == 0) - return rc; + LASSERT(the_lnet.ln_refcount > 0); cpt = lnet_net_lock_current(); list_for_each(tmp, &the_lnet.ln_nis) { - if (index-- != 0) + if (index--) continue; ni = list_entry(tmp, lnet_ni_t, ni_list); @@ -1488,192 +2120,8 @@ 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 == 0); - } - - infosz = offsetof(lnet_ping_info_t, pi_ni[n]); - LIBCFS_ALLOC(pinfo, infosz); - if (pinfo == NULL) { - 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; - - for (i = 0; i < n; i++) { - lnet_ni_status_t *ns = &pinfo->pi_ni[i]; - - rc = LNetGetId(i, &id); - LASSERT(rc == 0); - - 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 != NULL); - - lnet_ni_lock(ni); - LASSERT(ni->ni_status == NULL); - 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 != 0) - 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 != 0) { - 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 != 0) { - 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 != 0) { - CERROR("Can't attach ping MD: %d\n", rc); - goto failed_2; - } - - return 0; - - failed_2: - rc2 = LNetMEUnlink(meh); - LASSERT(rc2 == 0); - failed_1: - rc2 = LNetEQFree(the_lnet.ln_ping_target_eq); - LASSERT(rc2 == 0); - 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 == 0) { - /* 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 == 0); - lnet_destroy_ping_info(); - cfs_restore_sigs(blocked); -} - -int -lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_ids) +static int lnet_ping(lnet_process_id_t id, int timeout_ms, + lnet_process_id_t __user *ids, int n_ids) { lnet_handle_eq_t eqh; lnet_handle_md_t mdh; @@ -1683,7 +2131,7 @@ lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_id 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; @@ -1692,6 +2140,8 @@ lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_id 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! */ @@ -1699,15 +2149,15 @@ lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_id return -EINVAL; if (id.pid == LNET_PID_ANY) - id.pid = LUSTRE_SRV_LNET_PID; + id.pid = LNET_PID_LUSTRE; LIBCFS_ALLOC(info, infosz); - if (info == NULL) + if (!info) return -ENOMEM; /* NB 2 events max (including any unlink event) */ rc = LNetEQAlloc(2, LNET_EQ_HANDLER_NONE, &eqh); - if (rc != 0) { + if (rc) { CERROR("Can't allocate EQ: %d\n", rc); goto out_0; } @@ -1722,7 +2172,7 @@ lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_id md.eq_handle = eqh; rc = LNetMDBind(md, LNET_UNLINK, &mdh); - if (rc != 0) { + if (rc) { CERROR("Can't bind MD: %d\n", rc); goto out_1; } @@ -1731,11 +2181,11 @@ lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_id LNET_RESERVED_PORTAL, LNET_PROTO_PING_MATCHBITS, 0); - if (rc != 0) { + if (rc) { /* Don't CERROR; this could be deliberate! */ rc2 = LNetMDUnlink(mdh); - LASSERT(rc2 == 0); + LASSERT(!rc2); /* NB must wait for the UNLINK event below... */ unlinked = 1; @@ -1759,11 +2209,11 @@ lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_id LASSERT(rc2 != -EOVERFLOW); /* can't miss anything */ - if (rc2 <= 0 || event.status != 0) { + if (rc2 <= 0 || event.status) { /* timeout or error */ - if (!replied && rc == 0) + if (!replied && !rc) rc = (rc2 < 0) ? rc2 : - (rc2 == 0) ? -ETIMEDOUT : + !rc2 ? -ETIMEDOUT : event.status; if (!unlinked) { @@ -1772,7 +2222,7 @@ lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_id /* No assertion (racing with network) */ unlinked = 1; timeout_ms = a_long_time; - } else if (rc2 == 0) { + } else if (!rc2) { /* timed out waiting for unlink */ CWARN("ping %s: late network completion\n", libcfs_id2str(id)); @@ -1812,7 +2262,7 @@ lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_id goto out_1; } - if ((info->pi_features & LNET_PING_FEAT_NI_STATUS) == 0) { + if (!(info->pi_features & LNET_PING_FEAT_NI_STATUS)) { CERROR("%s: ping w/o NI status: 0x%x\n", libcfs_id2str(id), info->pi_features); goto out_1; @@ -1846,9 +2296,9 @@ lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_id out_1: rc2 = LNetEQFree(eqh); - if (rc2 != 0) + if (rc2) CERROR("rc2 %d\n", rc2); - LASSERT(rc2 == 0); + LASSERT(!rc2); out_0: LIBCFS_FREE(info, infosz); diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index 284a3c271bc6..449069c9e649 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -37,15 +37,15 @@ #define DEBUG_SUBSYSTEM S_LNET #include "../../include/linux/lnet/lib-lnet.h" -struct lnet_text_buf_t { /* tmp struct for parsing routes */ +struct lnet_text_buf { /* tmp struct for parsing routes */ struct list_head ltb_list; /* stash on lists */ int ltb_size; /* allocated size */ char ltb_text[0]; /* text buffer */ }; static int lnet_tbnob; /* track text buf allocation */ -#define LNET_MAX_TEXTBUF_NOB (64<<10) /* bound allocation */ -#define LNET_SINGLE_TEXTBUF_NOB (4<<10) +#define LNET_MAX_TEXTBUF_NOB (64 << 10) /* bound allocation */ +#define LNET_SINGLE_TEXTBUF_NOB (4 << 10) static void lnet_syntax(char *name, char *str, int offset, int width) @@ -54,9 +54,9 @@ lnet_syntax(char *name, char *str, int offset, int width) static char dashes[LNET_SINGLE_TEXTBUF_NOB]; memset(dots, '.', sizeof(dots)); - dots[sizeof(dots)-1] = 0; + dots[sizeof(dots) - 1] = 0; memset(dashes, '-', sizeof(dashes)); - dashes[sizeof(dashes)-1] = 0; + dashes[sizeof(dashes) - 1] = 0; LCONSOLE_ERROR_MSG(0x10f, "Error parsing '%s=\"%s\"'\n", name, str); LCONSOLE_ERROR_MSG(0x110, "here...........%.*s..%.*s|%.*s|\n", @@ -77,7 +77,7 @@ lnet_issep(char c) } } -static int +int lnet_net_unique(__u32 net, struct list_head *nilist) { struct list_head *tmp; @@ -96,19 +96,25 @@ lnet_net_unique(__u32 net, struct list_head *nilist) void lnet_ni_free(struct lnet_ni *ni) { - if (ni->ni_refs != NULL) + int i; + + if (ni->ni_refs) cfs_percpt_free(ni->ni_refs); - if (ni->ni_tx_queues != NULL) + if (ni->ni_tx_queues) cfs_percpt_free(ni->ni_tx_queues); - if (ni->ni_cpts != NULL) + if (ni->ni_cpts) 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)); } -static lnet_ni_t * +lnet_ni_t * lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist) { struct lnet_tx_queue *tq; @@ -123,7 +129,7 @@ lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist) } LIBCFS_ALLOC(ni, sizeof(*ni)); - if (ni == NULL) { + if (!ni) { CERROR("Out of memory creating network %s\n", libcfs_net2str(net)); return NULL; @@ -133,18 +139,18 @@ lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist) INIT_LIST_HEAD(&ni->ni_cptlist); ni->ni_refs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*ni->ni_refs[0])); - if (ni->ni_refs == NULL) + if (!ni->ni_refs) goto failed; ni->ni_tx_queues = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*ni->ni_tx_queues[0])); - if (ni->ni_tx_queues == NULL) + if (!ni->ni_tx_queues) goto failed; cfs_percpt_for_each(tq, i, ni->ni_tx_queues) INIT_LIST_HEAD(&tq->tq_delayed); - if (el == NULL) { + if (!el) { ni->ni_cpts = NULL; ni->ni_ncpts = LNET_CPT_NUMBER; } else { @@ -178,13 +184,19 @@ int lnet_parse_networks(struct list_head *nilist, char *networks) { struct cfs_expr_list *el = NULL; - int tokensize = strlen(networks) + 1; + int tokensize; char *tokens; char *str; char *tmp; struct lnet_ni *ni; __u32 net; int nnets = 0; + struct list_head *temp_node; + + if (!networks) { + CERROR("networks string is undefined\n"); + return -EINVAL; + } if (strlen(networks) > LNET_SINGLE_TEXTBUF_NOB) { /* _WAY_ conservative */ @@ -193,23 +205,19 @@ lnet_parse_networks(struct list_head *nilist, char *networks) return -EINVAL; } + tokensize = strlen(networks) + 1; + LIBCFS_ALLOC(tokens, tokensize); - if (tokens == NULL) { + if (!tokens) { CERROR("Can't allocate net tokens\n"); return -ENOMEM; } - the_lnet.ln_network_tokens = tokens; - the_lnet.ln_network_tokens_nob = tokensize; memcpy(tokens, networks, tokensize); - str = tmp = tokens; - - /* Add in the loopback network */ - ni = lnet_ni_alloc(LNET_MKNET(LOLND, 0), NULL, nilist); - if (ni == NULL) - goto failed; + tmp = tokens; + str = tokens; - while (str != NULL && *str != 0) { + while (str && *str) { char *comma = strchr(str, ','); char *bracket = strchr(str, '('); char *square = strchr(str, '['); @@ -217,26 +225,29 @@ lnet_parse_networks(struct list_head *nilist, char *networks) int niface; int rc; - /* NB we don't check interface conflicts here; it's the LNDs - * responsibility (if it cares at all) */ - - if (square != NULL && (comma == NULL || square < comma)) { - /* i.e: o2ib0(ib0)[1,2], number between square - * brackets are CPTs this NI needs to be bond */ - if (bracket != NULL && bracket > square) { + /* + * NB we don't check interface conflicts here; it's the LNDs + * responsibility (if it cares at all) + */ + if (square && (!comma || square < comma)) { + /* + * i.e: o2ib0(ib0)[1,2], number between square + * brackets are CPTs this NI needs to be bond + */ + if (bracket && bracket > square) { tmp = square; goto failed_syntax; } tmp = strchr(square, ']'); - if (tmp == NULL) { + if (!tmp) { tmp = square; goto failed_syntax; } rc = cfs_expr_list_parse(square, tmp - square + 1, 0, LNET_CPT_NUMBER - 1, &el); - if (rc != 0) { + if (rc) { tmp = square; goto failed_syntax; } @@ -245,12 +256,10 @@ lnet_parse_networks(struct list_head *nilist, char *networks) *square++ = ' '; } - if (bracket == NULL || - (comma != NULL && comma < bracket)) { - + if (!bracket || (comma && comma < bracket)) { /* no interface list specified */ - if (comma != NULL) + if (comma) *comma++ = 0; net = libcfs_str2net(cfs_trimwhite(str)); @@ -262,10 +271,10 @@ lnet_parse_networks(struct list_head *nilist, char *networks) } if (LNET_NETTYP(net) != LOLND && /* LO is implicit */ - lnet_ni_alloc(net, el, nilist) == NULL) + !lnet_ni_alloc(net, el, nilist)) goto failed; - if (el != NULL) { + if (el) { cfs_expr_list_free(el); el = NULL; } @@ -281,12 +290,11 @@ lnet_parse_networks(struct list_head *nilist, char *networks) goto failed_syntax; } - nnets++; ni = lnet_ni_alloc(net, el, nilist); - if (ni == NULL) + if (!ni) goto failed; - if (el != NULL) { + if (el) { cfs_expr_list_free(el); el = NULL; } @@ -295,7 +303,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) iface = bracket + 1; bracket = strchr(iface, ')'); - if (bracket == NULL) { + if (!bracket) { tmp = iface; goto failed_syntax; } @@ -303,11 +311,11 @@ lnet_parse_networks(struct list_head *nilist, char *networks) *bracket = 0; do { comma = strchr(iface, ','); - if (comma != NULL) + if (comma) *comma++ = 0; iface = cfs_trimwhite(iface); - if (*iface == 0) { + if (!*iface) { tmp = iface; goto failed_syntax; } @@ -319,16 +327,32 @@ lnet_parse_networks(struct list_head *nilist, char *networks) 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; - } while (iface != NULL); + } while (iface); str = bracket + 1; comma = strchr(bracket + 1, ','); - if (comma != NULL) { + if (comma) { *comma = 0; str = cfs_trimwhite(str); - if (*str != 0) { + if (*str) { tmp = str; goto failed_syntax; } @@ -337,14 +361,17 @@ lnet_parse_networks(struct list_head *nilist, char *networks) } str = cfs_trimwhite(str); - if (*str != 0) { + if (*str) { tmp = str; goto failed_syntax; } } - LASSERT(!list_empty(nilist)); - return 0; + list_for_each(temp_node, nilist) + nnets++; + + LIBCFS_FREE(tokens, tokensize); + return nnets; failed_syntax: lnet_syntax("networks", networks, (int)(tmp - tokens), strlen(tmp)); @@ -356,23 +383,22 @@ lnet_parse_networks(struct list_head *nilist, char *networks) lnet_ni_free(ni); } - if (el != NULL) + if (el) cfs_expr_list_free(el); LIBCFS_FREE(tokens, tokensize); - the_lnet.ln_network_tokens = NULL; return -EINVAL; } -static struct lnet_text_buf_t * +static struct lnet_text_buf * lnet_new_text_buf(int str_len) { - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; int nob; /* NB allocate space for the terminating 0 */ - nob = offsetof(struct lnet_text_buf_t, ltb_text[str_len + 1]); + nob = offsetof(struct lnet_text_buf, ltb_text[str_len + 1]); if (nob > LNET_SINGLE_TEXTBUF_NOB) { /* _way_ conservative for "route net gateway..." */ CERROR("text buffer too big\n"); @@ -385,7 +411,7 @@ lnet_new_text_buf(int str_len) } LIBCFS_ALLOC(ltb, nob); - if (ltb == NULL) + if (!ltb) return NULL; ltb->ltb_size = nob; @@ -395,7 +421,7 @@ lnet_new_text_buf(int str_len) } static void -lnet_free_text_buf(struct lnet_text_buf_t *ltb) +lnet_free_text_buf(struct lnet_text_buf *ltb) { lnet_tbnob -= ltb->ltb_size; LIBCFS_FREE(ltb, ltb->ltb_size); @@ -404,10 +430,10 @@ lnet_free_text_buf(struct lnet_text_buf_t *ltb) static void lnet_free_text_bufs(struct list_head *tbs) { - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; while (!list_empty(tbs)) { - ltb = list_entry(tbs->next, struct lnet_text_buf_t, ltb_list); + ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list); list_del(<b->ltb_list); lnet_free_text_buf(ltb); @@ -421,7 +447,7 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) char *sep; int nob; int i; - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; INIT_LIST_HEAD(&pending); @@ -432,16 +458,16 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) str++; /* scan for separator or comment */ - for (sep = str; *sep != 0; sep++) + for (sep = str; *sep; sep++) if (lnet_issep(*sep) || *sep == '#') break; nob = (int)(sep - str); if (nob > 0) { ltb = lnet_new_text_buf(nob); - if (ltb == NULL) { + if (!ltb) { lnet_free_text_bufs(&pending); - return -1; + return -ENOMEM; } for (i = 0; i < nob; i++) @@ -459,10 +485,10 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) /* scan for separator */ do { sep++; - } while (*sep != 0 && !lnet_issep(*sep)); + } while (*sep && !lnet_issep(*sep)); } - if (*sep == 0) + if (!*sep) break; str = sep + 1; @@ -479,18 +505,18 @@ lnet_expand1tb(struct list_head *list, { int len1 = (int)(sep1 - str); int len2 = strlen(sep2 + 1); - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; LASSERT(*sep1 == '['); LASSERT(*sep2 == ']'); ltb = lnet_new_text_buf(len1 + itemlen + len2); - if (ltb == NULL) + if (!ltb) return -ENOMEM; memcpy(ltb->ltb_text, str, len1); memcpy(<b->ltb_text[len1], item, itemlen); - memcpy(<b->ltb_text[len1+itemlen], sep2 + 1, len2); + memcpy(<b->ltb_text[len1 + itemlen], sep2 + 1, len2); ltb->ltb_text[len1 + itemlen + len2] = 0; list_add_tail(<b->ltb_list, list); @@ -516,15 +542,14 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) INIT_LIST_HEAD(&pending); sep = strchr(str, '['); - if (sep == NULL) /* nothing to expand */ + if (!sep) /* nothing to expand */ return 0; sep2 = strchr(sep, ']'); - if (sep2 == NULL) + if (!sep2) goto failed; for (parsed = sep; parsed < sep2; parsed = enditem) { - enditem = ++parsed; while (enditem < sep2 && *enditem != ',') enditem++; @@ -534,17 +559,13 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) if (sscanf(parsed, "%d-%d/%d%n", &lo, &hi, &stride, &scanned) < 3) { - if (sscanf(parsed, "%d-%d%n", &lo, &hi, &scanned) < 2) { - /* simple string enumeration */ - if (lnet_expand1tb( - &pending, str, sep, sep2, - parsed, - (int)(enditem - parsed)) != 0) { + if (lnet_expand1tb(&pending, str, sep, sep2, + parsed, + (int)(enditem - parsed))) { goto failed; } - continue; } @@ -557,18 +578,17 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) goto failed; if (hi < 0 || lo < 0 || stride < 0 || hi < lo || - (hi - lo) % stride != 0) + (hi - lo) % stride) goto failed; for (i = lo; i <= hi; i += stride) { - snprintf(num, sizeof(num), "%d", i); nob = strlen(num); if (nob + 1 == sizeof(num)) goto failed; if (lnet_expand1tb(&pending, str, sep, sep2, - num, nob) != 0) + num, nob)) goto failed; } } @@ -578,7 +598,7 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) failed: lnet_free_text_bufs(&pending); - return -1; + return -EINVAL; } static int @@ -602,17 +622,19 @@ lnet_parse_priority(char *str, unsigned int *priority, char **token) int len; sep = strchr(str, LNET_PRIORITY_SEPARATOR); - if (sep == NULL) { + if (!sep) { *priority = 0; return 0; } len = strlen(sep + 1); - if ((sscanf((sep+1), "%u%n", priority, &nob) < 1) || (len != nob)) { - /* Update the caller's token pointer so it treats the found - priority as the token to report in the error message. */ + if ((sscanf((sep + 1), "%u%n", priority, &nob) < 1) || (len != nob)) { + /* + * Update the caller's token pointer so it treats the found + * priority as the token to report in the error message. + */ *token += sep - str + 1; - return -1; + return -EINVAL; } CDEBUG(D_NET, "gateway %s, priority %d, nob %d\n", str, *priority, nob); @@ -636,13 +658,13 @@ lnet_parse_route(char *str, int *im_a_router) struct list_head *tmp2; __u32 net; lnet_nid_t nid; - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; int rc; char *sep; char *token = str; int ntokens = 0; int myrc = -1; - unsigned int hops; + __u32 hops; int got_hops = 0; unsigned int priority = 0; @@ -658,7 +680,7 @@ lnet_parse_route(char *str, int *im_a_router) /* scan for token start */ while (isspace(*sep)) sep++; - if (*sep == 0) { + if (!*sep) { if (ntokens < (got_hops ? 3 : 2)) goto token_error; break; @@ -668,9 +690,9 @@ lnet_parse_route(char *str, int *im_a_router) token = sep++; /* scan for token end */ - while (*sep != 0 && !isspace(*sep)) + while (*sep && !isspace(*sep)) sep++; - if (*sep != 0) + if (*sep) *sep++ = 0; if (ntokens == 1) { @@ -684,7 +706,7 @@ lnet_parse_route(char *str, int *im_a_router) } ltb = lnet_new_text_buf(strlen(token)); - if (ltb == NULL) + if (!ltb) goto out; strcpy(ltb->ltb_text, token); @@ -692,8 +714,7 @@ lnet_parse_route(char *str, int *im_a_router) list_add_tail(tmp1, tmp2); while (tmp1 != tmp2) { - ltb = list_entry(tmp1, struct lnet_text_buf_t, - ltb_list); + ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list); rc = lnet_str2tbs_expand(tmp1->next, ltb->ltb_text); if (rc < 0) @@ -726,20 +747,23 @@ lnet_parse_route(char *str, int *im_a_router) } } + /** + * if there are no hops set then we want to flag this value as + * unset since hops is an optional parameter + */ if (!got_hops) - hops = 1; + hops = LNET_UNDEFINED_HOPS; LASSERT(!list_empty(&nets)); LASSERT(!list_empty(&gateways)); list_for_each(tmp1, &nets) { - ltb = list_entry(tmp1, struct lnet_text_buf_t, ltb_list); + ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list); net = libcfs_str2net(ltb->ltb_text); LASSERT(net != LNET_NIDNET(LNET_NID_ANY)); list_for_each(tmp2, &gateways) { - ltb = list_entry(tmp2, struct lnet_text_buf_t, - ltb_list); + ltb = list_entry(tmp2, struct lnet_text_buf, ltb_list); nid = libcfs_str2nid(ltb->ltb_text); LASSERT(nid != LNET_NID_ANY); @@ -749,7 +773,7 @@ lnet_parse_route(char *str, int *im_a_router) } rc = lnet_add_route(net, hops, nid, priority); - if (rc != 0) { + if (rc && rc != -EEXIST && rc != -EHOSTUNREACH) { CERROR("Can't create route to %s via %s\n", libcfs_net2str(net), libcfs_nid2str(nid)); @@ -772,10 +796,10 @@ lnet_parse_route(char *str, int *im_a_router) static int lnet_parse_route_tbs(struct list_head *tbs, int *im_a_router) { - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; while (!list_empty(tbs)) { - ltb = list_entry(tbs->next, struct lnet_text_buf_t, ltb_list); + ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list); if (lnet_parse_route(ltb->ltb_text, im_a_router) < 0) { lnet_free_text_bufs(tbs); @@ -806,7 +830,7 @@ lnet_parse_routes(char *routes, int *im_a_router) rc = lnet_parse_route_tbs(&tbs, im_a_router); } - LASSERT(lnet_tbnob == 0); + LASSERT(!lnet_tbnob); return rc; } @@ -818,7 +842,7 @@ lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip) int i; rc = cfs_ip_addr_parse(token, len, &list); - if (rc != 0) + if (rc) return rc; for (rc = i = 0; !rc && i < nip; i++) @@ -851,18 +875,18 @@ lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip) /* scan for token start */ while (isspace(*sep)) sep++; - if (*sep == 0) + if (!*sep) break; token = sep++; /* scan for token end */ - while (*sep != 0 && !isspace(*sep)) + while (*sep && !isspace(*sep)) sep++; - if (*sep != 0) + if (*sep) *sep++ = 0; - if (ntokens++ == 0) { + if (!ntokens++) { net = token; continue; } @@ -876,7 +900,8 @@ lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip) return rc; } - matched |= (rc != 0); + if (rc) + matched |= 1; } if (!matched) @@ -892,12 +917,12 @@ lnet_netspec2net(char *netspec) char *bracket = strchr(netspec, '('); __u32 net; - if (bracket != NULL) + if (bracket) *bracket = 0; net = libcfs_str2net(netspec); - if (bracket != NULL) + if (bracket) *bracket = '('; return net; @@ -909,8 +934,8 @@ lnet_splitnets(char *source, struct list_head *nets) int offset = 0; int offset2; int len; - struct lnet_text_buf_t *tb; - struct lnet_text_buf_t *tb2; + struct lnet_text_buf *tb; + struct lnet_text_buf *tb2; struct list_head *t; char *sep; char *bracket; @@ -919,15 +944,13 @@ lnet_splitnets(char *source, struct list_head *nets) LASSERT(!list_empty(nets)); LASSERT(nets->next == nets->prev); /* single entry */ - tb = list_entry(nets->next, struct lnet_text_buf_t, ltb_list); + tb = list_entry(nets->next, struct lnet_text_buf, ltb_list); for (;;) { sep = strchr(tb->ltb_text, ','); bracket = strchr(tb->ltb_text, '('); - if (sep != NULL && - bracket != NULL && - bracket < sep) { + if (sep && bracket && bracket < sep) { /* netspec lists interfaces... */ offset2 = offset + (int)(bracket - tb->ltb_text); @@ -935,16 +958,16 @@ lnet_splitnets(char *source, struct list_head *nets) bracket = strchr(bracket + 1, ')'); - if (bracket == NULL || - !(bracket[1] == ',' || bracket[1] == 0)) { + if (!bracket || + !(bracket[1] == ',' || !bracket[1])) { lnet_syntax("ip2nets", source, offset2, len); return -EINVAL; } - sep = (bracket[1] == 0) ? NULL : bracket + 1; + sep = !bracket[1] ? NULL : bracket + 1; } - if (sep != NULL) + if (sep) *sep++ = 0; net = lnet_netspec2net(tb->ltb_text); @@ -955,7 +978,7 @@ lnet_splitnets(char *source, struct list_head *nets) } list_for_each(t, nets) { - tb2 = list_entry(t, struct lnet_text_buf_t, ltb_list); + tb2 = list_entry(t, struct lnet_text_buf, ltb_list); if (tb2 == tb) continue; @@ -968,13 +991,13 @@ lnet_splitnets(char *source, struct list_head *nets) } } - if (sep == NULL) + if (!sep) return 0; offset += (int)(sep - tb->ltb_text); len = strlen(sep); tb2 = lnet_new_text_buf(len); - if (tb2 == NULL) + if (!tb2) return -ENOMEM; strncpy(tb2->ltb_text, sep, len); @@ -996,8 +1019,9 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) struct list_head current_nets; struct list_head *t; struct list_head *t2; - struct lnet_text_buf_t *tb; - struct lnet_text_buf_t *tb2; + struct lnet_text_buf *tb; + struct lnet_text_buf *temp; + struct lnet_text_buf *tb2; __u32 net1; __u32 net2; int len; @@ -1008,7 +1032,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) INIT_LIST_HEAD(&raw_entries); if (lnet_str2tbs_sep(&raw_entries, ip2nets) < 0) { CERROR("Error parsing ip2nets\n"); - LASSERT(lnet_tbnob == 0); + LASSERT(!lnet_tbnob); return -EINVAL; } @@ -1019,12 +1043,9 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) len = 0; rc = 0; - while (!list_empty(&raw_entries)) { - tb = list_entry(raw_entries.next, struct lnet_text_buf_t, - ltb_list); - + list_for_each_entry_safe(tb, temp, &raw_entries, ltb_list) { strncpy(source, tb->ltb_text, sizeof(source)); - source[sizeof(source)-1] = '\0'; + source[sizeof(source) - 1] = '\0'; /* replace ltb_text with the network(s) add on match */ rc = lnet_match_network_tokens(tb->ltb_text, ipaddrs, nip); @@ -1033,7 +1054,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) list_del(&tb->ltb_list); - if (rc == 0) { /* no match */ + if (!rc) { /* no match */ lnet_free_text_buf(tb); continue; } @@ -1047,13 +1068,13 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) dup = 0; list_for_each(t, ¤t_nets) { - tb = list_entry(t, struct lnet_text_buf_t, ltb_list); + tb = list_entry(t, struct lnet_text_buf, ltb_list); net1 = lnet_netspec2net(tb->ltb_text); LASSERT(net1 != LNET_NIDNET(LNET_NID_ANY)); list_for_each(t2, &matched_nets) { - tb2 = list_entry(t2, struct lnet_text_buf_t, - ltb_list); + tb2 = list_entry(t2, struct lnet_text_buf, + ltb_list); net2 = lnet_netspec2net(tb2->ltb_text); LASSERT(net2 != LNET_NIDNET(LNET_NID_ANY)); @@ -1073,13 +1094,13 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) } list_for_each_safe(t, t2, ¤t_nets) { - tb = list_entry(t, struct lnet_text_buf_t, ltb_list); + tb = list_entry(t, struct lnet_text_buf, ltb_list); list_del(&tb->ltb_list); list_add_tail(&tb->ltb_list, &matched_nets); len += snprintf(networks + len, sizeof(networks) - len, - "%s%s", (len == 0) ? "" : ",", + "%s%s", !len ? "" : ",", tb->ltb_text); if (len >= sizeof(networks)) { @@ -1096,7 +1117,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) lnet_free_text_bufs(&raw_entries); lnet_free_text_bufs(&matched_nets); lnet_free_text_bufs(¤t_nets); - LASSERT(lnet_tbnob == 0); + LASSERT(!lnet_tbnob); if (rc < 0) return rc; @@ -1122,7 +1143,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp) return nif; LIBCFS_ALLOC(ipaddrs, nif * sizeof(*ipaddrs)); - if (ipaddrs == NULL) { + if (!ipaddrs) { CERROR("Can't allocate ipaddrs[%d]\n", nif); lnet_ipif_free_enumeration(ifnames, nif); return -ENOMEM; @@ -1133,7 +1154,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp) continue; rc = lnet_ipif_query(ifnames[i], &up, &ipaddrs[nip], &netmask); - if (rc != 0) { + if (rc) { CWARN("Can't query interface %s: %d\n", ifnames[i], rc); continue; @@ -1155,7 +1176,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp) } else { if (nip > 0) { LIBCFS_ALLOC(ipaddrs2, nip * sizeof(*ipaddrs2)); - if (ipaddrs2 == NULL) { + if (!ipaddrs2) { CERROR("Can't allocate ipaddrs[%d]\n", nip); nip = -ENOMEM; } else { @@ -1184,7 +1205,7 @@ lnet_parse_ip2nets(char **networksp, char *ip2nets) return nip; } - if (nip == 0) { + if (!nip) { LCONSOLE_ERROR_MSG(0x118, "No local IP interfaces for ip2nets to match\n"); return -ENOENT; @@ -1198,7 +1219,7 @@ lnet_parse_ip2nets(char **networksp, char *ip2nets) return rc; } - if (rc == 0) { + if (!rc) { LCONSOLE_ERROR_MSG(0x11a, "ip2nets does not match any local IP interfaces\n"); return -ENOENT; diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c index 64f94a690081..adbcadbab1be 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-eq.c +++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c @@ -72,33 +72,38 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, { lnet_eq_t *eq; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); - /* We need count to be a power of 2 so that when eq_{enq,deq}_seq + /* + * We need count to be a power of 2 so that when eq_{enq,deq}_seq * overflow, they don't skip entries, so the queue has the same - * apparent capacity at all times */ + * apparent capacity at all times + */ + if (count) + count = roundup_pow_of_two(count); - count = roundup_pow_of_two(count); - - if (callback != LNET_EQ_HANDLER_NONE && count != 0) + if (callback != LNET_EQ_HANDLER_NONE && count) CWARN("EQ callback is guaranteed to get every event, do you still want to set eqcount %d for polling event which will have locking overhead? Please contact with developer to confirm\n", count); - /* count can be 0 if only need callback, we can eliminate - * overhead of enqueue event */ - if (count == 0 && callback == LNET_EQ_HANDLER_NONE) + /* + * count can be 0 if only need callback, we can eliminate + * overhead of enqueue event + */ + if (!count && callback == LNET_EQ_HANDLER_NONE) return -EINVAL; eq = lnet_eq_alloc(); - if (eq == NULL) + if (!eq) return -ENOMEM; - if (count != 0) { + if (count) { LIBCFS_ALLOC(eq->eq_events, count * sizeof(lnet_event_t)); - if (eq->eq_events == NULL) + if (!eq->eq_events) goto failed; - /* NB allocator has set all event sequence numbers to 0, - * so all them should be earlier than eq_deq_seq */ + /* + * NB allocator has set all event sequence numbers to 0, + * so all them should be earlier than eq_deq_seq + */ } eq->eq_deq_seq = 1; @@ -108,13 +113,15 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, eq->eq_refs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*eq->eq_refs[0])); - if (eq->eq_refs == NULL) + if (!eq->eq_refs) goto failed; /* MUST hold both exclusive lnet_res_lock */ lnet_res_lock(LNET_LOCK_EX); - /* NB: hold lnet_eq_wait_lock for EQ link/unlink, so we can do - * both EQ lookup and poll event with only lnet_eq_wait_lock */ + /* + * NB: hold lnet_eq_wait_lock for EQ link/unlink, so we can do + * both EQ lookup and poll event with only lnet_eq_wait_lock + */ lnet_eq_wait_lock(); lnet_res_lh_initialize(&the_lnet.ln_eq_container, &eq->eq_lh); @@ -127,10 +134,10 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, return 0; failed: - if (eq->eq_events != NULL) + if (eq->eq_events) LIBCFS_FREE(eq->eq_events, count * sizeof(lnet_event_t)); - if (eq->eq_refs != NULL) + if (eq->eq_refs) cfs_percpt_free(eq->eq_refs); lnet_eq_free(eq); @@ -159,23 +166,24 @@ LNetEQFree(lnet_handle_eq_t eqh) int size = 0; int i; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); lnet_res_lock(LNET_LOCK_EX); - /* NB: hold lnet_eq_wait_lock for EQ link/unlink, so we can do - * both EQ lookup and poll event with only lnet_eq_wait_lock */ + /* + * NB: hold lnet_eq_wait_lock for EQ link/unlink, so we can do + * both EQ lookup and poll event with only lnet_eq_wait_lock + */ lnet_eq_wait_lock(); eq = lnet_handle2eq(&eqh); - if (eq == NULL) { + if (!eq) { rc = -ENOENT; goto out; } cfs_percpt_for_each(ref, i, eq->eq_refs) { LASSERT(*ref >= 0); - if (*ref == 0) + if (!*ref) continue; CDEBUG(D_NET, "Event equeue (%d: %d) busy on destroy.\n", @@ -196,9 +204,9 @@ LNetEQFree(lnet_handle_eq_t eqh) lnet_eq_wait_unlock(); lnet_res_unlock(LNET_LOCK_EX); - if (events != NULL) + if (events) LIBCFS_FREE(events, size * sizeof(lnet_event_t)); - if (refs != NULL) + if (refs) cfs_percpt_free(refs); return rc; @@ -211,7 +219,7 @@ lnet_eq_enqueue_event(lnet_eq_t *eq, lnet_event_t *ev) /* MUST called with resource lock hold but w/o lnet_eq_wait_lock */ int index; - if (eq->eq_size == 0) { + if (!eq->eq_size) { LASSERT(eq->eq_callback != LNET_EQ_HANDLER_NONE); eq->eq_callback(ev); return; @@ -255,8 +263,10 @@ lnet_eq_dequeue_event(lnet_eq_t *eq, lnet_event_t *ev) if (eq->eq_deq_seq == new_event->sequence) { rc = 1; } else { - /* don't complain with CERROR: some EQs are sized small - * anyway; if it's important, the caller should complain */ + /* + * don't complain with CERROR: some EQs are sized small + * anyway; if it's important, the caller should complain + */ CDEBUG(D_NET, "Event Queue Overflow: eq seq %lu ev seq %lu\n", eq->eq_deq_seq, new_event->sequence); rc = -EOVERFLOW; @@ -309,8 +319,8 @@ __must_hold(&the_lnet.ln_eq_wait_lock) wait_queue_t wl; unsigned long now; - if (tms == 0) - return -1; /* don't want to wait and no new event */ + if (!tms) + return -ENXIO; /* don't want to wait and no new event */ init_waitqueue_entry(&wl, current); set_current_state(TASK_INTERRUPTIBLE); @@ -320,7 +330,6 @@ __must_hold(&the_lnet.ln_eq_wait_lock) if (tms < 0) { schedule(); - } else { now = jiffies; schedule_timeout(msecs_to_jiffies(tms)); @@ -329,7 +338,7 @@ __must_hold(&the_lnet.ln_eq_wait_lock) tms = 0; } - wait = tms != 0; /* might need to call here again */ + wait = tms; /* might need to call here again */ *timeout_ms = tms; lnet_eq_wait_lock(); @@ -372,7 +381,6 @@ LNetEQPoll(lnet_handle_eq_t *eventqs, int neq, int timeout_ms, int rc; int i; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); if (neq < 1) @@ -384,20 +392,20 @@ LNetEQPoll(lnet_handle_eq_t *eventqs, int neq, int timeout_ms, for (i = 0; i < neq; i++) { lnet_eq_t *eq = lnet_handle2eq(&eventqs[i]); - if (eq == NULL) { + if (!eq) { lnet_eq_wait_unlock(); return -ENOENT; } rc = lnet_eq_dequeue_event(eq, event); - if (rc != 0) { + if (rc) { lnet_eq_wait_unlock(); *which = i; return rc; } } - if (wait == 0) + if (!wait) break; /* diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index 758f5bedef7e..c74514f99f90 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -46,16 +46,18 @@ void lnet_md_unlink(lnet_libmd_t *md) { - if ((md->md_flags & LNET_MD_FLAG_ZOMBIE) == 0) { + if (!(md->md_flags & LNET_MD_FLAG_ZOMBIE)) { /* first unlink attempt... */ lnet_me_t *me = md->md_me; md->md_flags |= LNET_MD_FLAG_ZOMBIE; - /* Disassociate from ME (if any), + /* + * Disassociate from ME (if any), * and unlink it if it was created - * with LNET_UNLINK */ - if (me != NULL) { + * with LNET_UNLINK + */ + if (me) { /* detach MD from portal */ lnet_ptl_detach_md(me, md); if (me->me_unlink == LNET_UNLINK) @@ -66,14 +68,14 @@ lnet_md_unlink(lnet_libmd_t *md) lnet_res_lh_invalidate(&md->md_lh); } - if (md->md_refcount != 0) { + if (md->md_refcount) { CDEBUG(D_NET, "Queueing unlink of md %p\n", md); return; } CDEBUG(D_NET, "Unlinking md %p\n", md); - if (md->md_eq != NULL) { + if (md->md_eq) { int cpt = lnet_cpt_of_cookie(md->md_lh.lh_cookie); LASSERT(*md->md_eq->eq_refs[cpt] > 0); @@ -103,12 +105,12 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) lmd->md_refcount = 0; lmd->md_flags = (unlink == LNET_UNLINK) ? LNET_MD_FLAG_AUTO_UNLINK : 0; - if ((umd->options & LNET_MD_IOVEC) != 0) { - - if ((umd->options & LNET_MD_KIOV) != 0) /* Can't specify both */ + if (umd->options & LNET_MD_IOVEC) { + if (umd->options & LNET_MD_KIOV) /* Can't specify both */ return -EINVAL; - lmd->md_niov = niov = umd->length; + niov = umd->length; + lmd->md_niov = umd->length; memcpy(lmd->md_iov.iov, umd->start, niov * sizeof(lmd->md_iov.iov[0])); @@ -123,13 +125,14 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) lmd->md_length = total_length; - if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* use max size */ + if ((umd->options & LNET_MD_MAX_SIZE) && /* use max size */ (umd->max_size < 0 || umd->max_size > total_length)) /* illegal max_size */ return -EINVAL; - } else if ((umd->options & LNET_MD_KIOV) != 0) { - lmd->md_niov = niov = umd->length; + } else if (umd->options & LNET_MD_KIOV) { + niov = umd->length; + lmd->md_niov = umd->length; memcpy(lmd->md_iov.kiov, umd->start, niov * sizeof(lmd->md_iov.kiov[0])); @@ -144,17 +147,18 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) lmd->md_length = total_length; - if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* max size used */ + if ((umd->options & LNET_MD_MAX_SIZE) && /* max size used */ (umd->max_size < 0 || umd->max_size > total_length)) /* illegal max_size */ return -EINVAL; } else { /* contiguous */ lmd->md_length = umd->length; - lmd->md_niov = niov = 1; + niov = 1; + lmd->md_niov = 1; lmd->md_iov.iov[0].iov_base = umd->start; lmd->md_iov.iov[0].iov_len = umd->length; - if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* max size used */ + if ((umd->options & LNET_MD_MAX_SIZE) && /* max size used */ (umd->max_size < 0 || umd->max_size > (int)umd->length)) /* illegal max_size */ return -EINVAL; @@ -169,22 +173,26 @@ lnet_md_link(lnet_libmd_t *md, lnet_handle_eq_t eq_handle, int cpt) { struct lnet_res_container *container = the_lnet.ln_md_containers[cpt]; - /* NB we are passed an allocated, but inactive md. + /* + * NB we are passed an allocated, but inactive md. * if we return success, caller may lnet_md_unlink() it. * otherwise caller may only lnet_md_free() it. */ - /* This implementation doesn't know how to create START events or + /* + * This implementation doesn't know how to create START events or * disable END events. Best to LASSERT our caller is compliant so - * we find out quickly... */ - /* TODO - reevaluate what should be here in light of + * we find out quickly... + */ + /* + * TODO - reevaluate what should be here in light of * the removal of the start and end events * maybe there we shouldn't even allow LNET_EQ_NONE!) - * LASSERT (eq == NULL); + * LASSERT(!eq); */ if (!LNetHandleIsInvalid(eq_handle)) { md->md_eq = lnet_handle2eq(&eq_handle); - if (md->md_eq == NULL) + if (!md->md_eq) return -ENOENT; (*md->md_eq->eq_refs[cpt])++; @@ -208,8 +216,8 @@ lnet_md_deconstruct(lnet_libmd_t *lmd, lnet_md_t *umd) * and that's all. */ umd->start = lmd->md_start; - umd->length = ((lmd->md_options & - (LNET_MD_IOVEC | LNET_MD_KIOV)) == 0) ? + umd->length = !(lmd->md_options & + (LNET_MD_IOVEC | LNET_MD_KIOV)) ? lmd->md_length : lmd->md_niov; umd->threshold = lmd->md_threshold; umd->max_size = lmd->md_max_size; @@ -221,13 +229,13 @@ lnet_md_deconstruct(lnet_libmd_t *lmd, lnet_md_t *umd) static int lnet_md_validate(lnet_md_t *umd) { - if (umd->start == NULL && umd->length != 0) { + if (!umd->start && umd->length) { CERROR("MD start pointer can not be NULL with length %u\n", umd->length); return -EINVAL; } - if ((umd->options & (LNET_MD_KIOV | LNET_MD_IOVEC)) != 0 && + if ((umd->options & (LNET_MD_KIOV | LNET_MD_IOVEC)) && umd->length > LNET_MAX_IOV) { CERROR("Invalid option: too many fragments %u, %d max\n", umd->length, LNET_MAX_IOV); @@ -273,41 +281,42 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, int cpt; int rc; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); - if (lnet_md_validate(&umd) != 0) + if (lnet_md_validate(&umd)) return -EINVAL; - if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT)) == 0) { + if (!(umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT))) { CERROR("Invalid option: no MD_OP set\n"); return -EINVAL; } md = lnet_md_alloc(&umd); - if (md == NULL) + if (!md) return -ENOMEM; rc = lnet_md_build(md, &umd, unlink); cpt = lnet_cpt_of_cookie(meh.cookie); lnet_res_lock(cpt); - if (rc != 0) + if (rc) goto failed; me = lnet_handle2me(&meh); - if (me == NULL) + if (!me) rc = -ENOENT; - else if (me->me_md != NULL) + else if (me->me_md) rc = -EBUSY; else rc = lnet_md_link(md, umd.eq_handle, cpt); - if (rc != 0) + if (rc) goto failed; - /* attach this MD to portal of ME and check if it matches any - * blocked msgs on this portal */ + /* + * attach this MD to portal of ME and check if it matches any + * blocked msgs on this portal + */ lnet_ptl_attach_md(me, md, &matches, &drops); lnet_md2handle(handle, md); @@ -350,29 +359,28 @@ LNetMDBind(lnet_md_t umd, lnet_unlink_t unlink, lnet_handle_md_t *handle) int cpt; int rc; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); - if (lnet_md_validate(&umd) != 0) + if (lnet_md_validate(&umd)) return -EINVAL; - if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT)) != 0) { + if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT))) { CERROR("Invalid option: GET|PUT illegal on active MDs\n"); return -EINVAL; } md = lnet_md_alloc(&umd); - if (md == NULL) + if (!md) return -ENOMEM; rc = lnet_md_build(md, &umd, unlink); cpt = lnet_res_lock_current(); - if (rc != 0) + if (rc) goto failed; rc = lnet_md_link(md, umd.eq_handle, cpt); - if (rc != 0) + if (rc) goto failed; lnet_md2handle(handle, md); @@ -425,23 +433,24 @@ LNetMDUnlink(lnet_handle_md_t mdh) lnet_libmd_t *md; int cpt; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); cpt = lnet_cpt_of_cookie(mdh.cookie); lnet_res_lock(cpt); md = lnet_handle2md(&mdh); - if (md == NULL) { + if (!md) { lnet_res_unlock(cpt); return -ENOENT; } md->md_flags |= LNET_MD_FLAG_ABORTED; - /* If the MD is busy, lnet_md_unlink just marks it for deletion, and + /* + * If the MD is busy, lnet_md_unlink just marks it for deletion, and * when the LND is done, the completion event flags that the MD was - * unlinked. Otherwise, we enqueue an event now... */ - if (md->md_eq != NULL && md->md_refcount == 0) { + * unlinked. Otherwise, we enqueue an event now... + */ + if (md->md_eq && !md->md_refcount) { lnet_build_unlink_event(md, &ev); lnet_eq_enqueue_event(md->md_eq, &ev); } diff --git a/drivers/staging/lustre/lnet/lnet/lib-me.c b/drivers/staging/lustre/lnet/lnet/lib-me.c index 42fc99ef9f80..e671aed373df 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-me.c +++ b/drivers/staging/lustre/lnet/lnet/lib-me.c @@ -83,7 +83,6 @@ LNetMEAttach(unsigned int portal, struct lnet_me *me; struct list_head *head; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); if ((int)portal >= the_lnet.ln_nportals) @@ -91,11 +90,11 @@ LNetMEAttach(unsigned int portal, mtable = lnet_mt_of_attach(portal, match_id, match_bits, ignore_bits, pos); - if (mtable == NULL) /* can't match portal type */ + if (!mtable) /* can't match portal type */ return -EPERM; me = lnet_me_alloc(); - if (me == NULL) + if (!me) return -ENOMEM; lnet_res_lock(mtable->mt_cpt); @@ -109,7 +108,7 @@ LNetMEAttach(unsigned int portal, lnet_res_lh_initialize(the_lnet.ln_me_containers[mtable->mt_cpt], &me->me_lh); - if (ignore_bits != 0) + if (ignore_bits) head = &mtable->mt_mhash[LNET_MT_HASH_IGNORE]; else head = lnet_mt_match_head(mtable, match_id, match_bits); @@ -156,14 +155,13 @@ LNetMEInsert(lnet_handle_me_t current_meh, struct lnet_portal *ptl; int cpt; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); if (pos == LNET_INS_LOCAL) return -EPERM; new_me = lnet_me_alloc(); - if (new_me == NULL) + if (!new_me) return -ENOMEM; cpt = lnet_cpt_of_cookie(current_meh.cookie); @@ -171,7 +169,7 @@ LNetMEInsert(lnet_handle_me_t current_meh, lnet_res_lock(cpt); current_me = lnet_handle2me(¤t_meh); - if (current_me == NULL) { + if (!current_me) { lnet_me_free(new_me); lnet_res_unlock(cpt); @@ -233,22 +231,21 @@ LNetMEUnlink(lnet_handle_me_t meh) lnet_event_t ev; int cpt; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); cpt = lnet_cpt_of_cookie(meh.cookie); lnet_res_lock(cpt); me = lnet_handle2me(&meh); - if (me == NULL) { + if (!me) { lnet_res_unlock(cpt); return -ENOENT; } md = me->me_md; - if (md != NULL) { + if (md) { md->md_flags |= LNET_MD_FLAG_ABORTED; - if (md->md_eq != NULL && md->md_refcount == 0) { + if (md->md_eq && !md->md_refcount) { lnet_build_unlink_event(md, &ev); lnet_eq_enqueue_event(md->md_eq, &ev); } @@ -267,7 +264,7 @@ lnet_me_unlink(lnet_me_t *me) { list_del(&me->me_list); - if (me->me_md != NULL) { + if (me->me_md) { lnet_libmd_t *md = me->me_md; /* detach MD from portal of this ME */ diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index fb8f7be043ec..0009a8de77d5 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -50,17 +50,16 @@ int lnet_fail_nid(lnet_nid_t nid, unsigned int threshold) { lnet_test_peer_t *tp; + lnet_test_peer_t *temp; struct list_head *el; struct list_head *next; struct list_head cull; - LASSERT(the_lnet.ln_init); - /* NB: use lnet_net_lock(0) to serialize operations on test peers */ - if (threshold != 0) { + if (threshold) { /* Adding a new entry */ LIBCFS_ALLOC(tp, sizeof(*tp)); - if (tp == NULL) + if (!tp) return -ENOMEM; tp->tp_nid = nid; @@ -80,7 +79,7 @@ lnet_fail_nid(lnet_nid_t nid, unsigned int threshold) list_for_each_safe(el, next, &the_lnet.ln_test_peers) { tp = list_entry(el, lnet_test_peer_t, tp_list); - if (tp->tp_threshold == 0 || /* needs culling anyway */ + if (!tp->tp_threshold || /* needs culling anyway */ nid == LNET_NID_ANY || /* removing all entries */ tp->tp_nid == nid) { /* matched this one */ list_del(&tp->tp_list); @@ -90,9 +89,7 @@ lnet_fail_nid(lnet_nid_t nid, unsigned int threshold) lnet_net_unlock(0); - while (!list_empty(&cull)) { - tp = list_entry(cull.next, lnet_test_peer_t, tp_list); - + list_for_each_entry_safe(tp, temp, &cull, tp_list) { list_del(&tp->tp_list); LIBCFS_FREE(tp, sizeof(*tp)); } @@ -103,6 +100,7 @@ static int fail_peer(lnet_nid_t nid, int outgoing) { lnet_test_peer_t *tp; + lnet_test_peer_t *temp; struct list_head *el; struct list_head *next; struct list_head cull; @@ -116,12 +114,14 @@ fail_peer(lnet_nid_t nid, int outgoing) list_for_each_safe(el, next, &the_lnet.ln_test_peers) { tp = list_entry(el, lnet_test_peer_t, tp_list); - if (tp->tp_threshold == 0) { + if (!tp->tp_threshold) { /* zombie entry */ if (outgoing) { - /* only cull zombies on outgoing tests, + /* + * only cull zombies on outgoing tests, * since we may be at interrupt priority on - * incoming messages. */ + * incoming messages. + */ list_del(&tp->tp_list); list_add(&tp->tp_list, &cull); } @@ -135,7 +135,7 @@ fail_peer(lnet_nid_t nid, int outgoing) if (tp->tp_threshold != LNET_MD_THRESH_INF) { tp->tp_threshold--; if (outgoing && - tp->tp_threshold == 0) { + !tp->tp_threshold) { /* see above */ list_del(&tp->tp_list); list_add(&tp->tp_list, &cull); @@ -147,8 +147,7 @@ fail_peer(lnet_nid_t nid, int outgoing) lnet_net_unlock(0); - while (!list_empty(&cull)) { - tp = list_entry(cull.next, lnet_test_peer_t, tp_list); + list_for_each_entry_safe(tp, temp, &cull, tp_list) { list_del(&tp->tp_list); LIBCFS_FREE(tp, sizeof(*tp)); @@ -162,6 +161,7 @@ lnet_iov_nob(unsigned int niov, struct kvec *iov) { unsigned int nob = 0; + LASSERT(!niov || iov); while (niov-- > 0) nob += (iov++)->iov_len; @@ -171,13 +171,13 @@ EXPORT_SYMBOL(lnet_iov_nob); void lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, - unsigned int nsiov, struct kvec *siov, unsigned int soffset, - unsigned int nob) + unsigned int nsiov, struct kvec *siov, unsigned int soffset, + unsigned int nob) { /* NB diov, siov are READ-ONLY */ unsigned int this_nob; - if (nob == 0) + if (!nob) return; /* skip complete frags before 'doffset' */ @@ -206,7 +206,7 @@ lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, this_nob = min(this_nob, nob); memcpy((char *)diov->iov_base + doffset, - (char *)siov->iov_base + soffset, this_nob); + (char *)siov->iov_base + soffset, this_nob); nob -= this_nob; if (diov->iov_len > doffset + this_nob) { @@ -230,16 +230,18 @@ EXPORT_SYMBOL(lnet_copy_iov2iov); int lnet_extract_iov(int dst_niov, struct kvec *dst, - int src_niov, struct kvec *src, - unsigned int offset, unsigned int len) + int src_niov, struct kvec *src, + unsigned int offset, unsigned int len) { - /* Initialise 'dst' to the subset of 'src' starting at 'offset', + /* + * Initialise 'dst' to the subset of 'src' starting at 'offset', * for exactly 'len' bytes, and return the number of entries. - * NB not destructive to 'src' */ + * NB not destructive to 'src' + */ unsigned int frag_len; unsigned int niov; - if (len == 0) /* no data => */ + if (!len) /* no data => */ return 0; /* no frags */ LASSERT(src_niov > 0); @@ -280,6 +282,7 @@ lnet_kiov_nob(unsigned int niov, lnet_kiov_t *kiov) { unsigned int nob = 0; + LASSERT(!niov || kiov); while (niov-- > 0) nob += (kiov++)->kiov_len; @@ -297,7 +300,7 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, char *daddr = NULL; char *saddr = NULL; - if (nob == 0) + if (!nob) return; LASSERT(!in_interrupt()); @@ -325,17 +328,18 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, siov->kiov_len - soffset); this_nob = min(this_nob, nob); - if (daddr == NULL) + if (!daddr) daddr = ((char *)kmap(diov->kiov_page)) + diov->kiov_offset + doffset; - if (saddr == NULL) + if (!saddr) saddr = ((char *)kmap(siov->kiov_page)) + siov->kiov_offset + soffset; - /* Vanishing risk of kmap deadlock when mapping 2 pages. + /* + * Vanishing risk of kmap deadlock when mapping 2 pages. * However in practice at least one of the kiovs will be mapped - * kernel pages and the map/unmap will be NOOPs */ - + * kernel pages and the map/unmap will be NOOPs + */ memcpy(daddr, saddr, this_nob); nob -= this_nob; @@ -362,9 +366,9 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, } } while (nob > 0); - if (daddr != NULL) + if (daddr) kunmap(diov->kiov_page); - if (saddr != NULL) + if (saddr) kunmap(siov->kiov_page); } EXPORT_SYMBOL(lnet_copy_kiov2kiov); @@ -378,7 +382,7 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, unsigned int this_nob; char *addr = NULL; - if (nob == 0) + if (!nob) return; LASSERT(!in_interrupt()); @@ -406,7 +410,7 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, (__kernel_size_t) kiov->kiov_len - kiovoffset); this_nob = min(this_nob, nob); - if (addr == NULL) + if (!addr) addr = ((char *)kmap(kiov->kiov_page)) + kiov->kiov_offset + kiovoffset; @@ -434,7 +438,7 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, } while (nob > 0); - if (addr != NULL) + if (addr) kunmap(kiov->kiov_page); } EXPORT_SYMBOL(lnet_copy_kiov2iov); @@ -449,7 +453,7 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, unsigned int this_nob; char *addr = NULL; - if (nob == 0) + if (!nob) return; LASSERT(!in_interrupt()); @@ -477,7 +481,7 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, iov->iov_len - iovoffset); this_nob = min(this_nob, nob); - if (addr == NULL) + if (!addr) addr = ((char *)kmap(kiov->kiov_page)) + kiov->kiov_offset + kiovoffset; @@ -504,23 +508,25 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, } } while (nob > 0); - if (addr != NULL) + if (addr) kunmap(kiov->kiov_page); } EXPORT_SYMBOL(lnet_copy_iov2kiov); int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, - int src_niov, lnet_kiov_t *src, - unsigned int offset, unsigned int len) + int src_niov, lnet_kiov_t *src, + unsigned int offset, unsigned int len) { - /* Initialise 'dst' to the subset of 'src' starting at 'offset', + /* + * Initialise 'dst' to the subset of 'src' starting at 'offset', * for exactly 'len' bytes, and return the number of entries. - * NB not destructive to 'src' */ + * NB not destructive to 'src' + */ unsigned int frag_len; unsigned int niov; - if (len == 0) /* no data => */ + if (!len) /* no data => */ return 0; /* no frags */ LASSERT(src_niov > 0); @@ -543,7 +549,7 @@ lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, if (len <= frag_len) { dst->kiov_len = len; LASSERT(dst->kiov_offset + dst->kiov_len - <= PAGE_CACHE_SIZE); + <= PAGE_CACHE_SIZE); return niov; } @@ -560,7 +566,7 @@ lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, } EXPORT_SYMBOL(lnet_extract_kiov); -static void +void lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, unsigned int offset, unsigned int mlen, unsigned int rlen) { @@ -570,9 +576,9 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, int rc; LASSERT(!in_interrupt()); - LASSERT(mlen == 0 || msg != NULL); + LASSERT(!mlen || msg); - if (msg != NULL) { + if (msg) { LASSERT(msg->msg_receiving); LASSERT(!msg->msg_sending); LASSERT(rlen == msg->msg_len); @@ -582,18 +588,18 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, msg->msg_receiving = 0; - if (mlen != 0) { + if (mlen) { niov = msg->msg_niov; iov = msg->msg_iov; kiov = msg->msg_kiov; LASSERT(niov > 0); - LASSERT((iov == NULL) != (kiov == NULL)); + LASSERT(!iov != !kiov); } } - rc = (ni->ni_lnd->lnd_recv)(ni, private, msg, delayed, - niov, iov, kiov, offset, mlen, rlen); + rc = ni->ni_lnd->lnd_recv(ni, private, msg, delayed, + niov, iov, kiov, offset, mlen, rlen); if (rc < 0) lnet_finalize(ni, msg, rc); } @@ -605,13 +611,13 @@ lnet_setpayloadbuffer(lnet_msg_t *msg) LASSERT(msg->msg_len > 0); LASSERT(!msg->msg_routing); - LASSERT(md != NULL); - LASSERT(msg->msg_niov == 0); - LASSERT(msg->msg_iov == NULL); - LASSERT(msg->msg_kiov == NULL); + LASSERT(md); + LASSERT(!msg->msg_niov); + LASSERT(!msg->msg_iov); + LASSERT(!msg->msg_kiov); msg->msg_niov = md->md_niov; - if ((md->md_options & LNET_MD_KIOV) != 0) + if (md->md_options & LNET_MD_KIOV) msg->msg_kiov = md->md_iov.kiov; else msg->msg_iov = md->md_iov.iov; @@ -626,7 +632,7 @@ lnet_prep_send(lnet_msg_t *msg, int type, lnet_process_id_t target, msg->msg_len = len; msg->msg_offset = offset; - if (len != 0) + if (len) lnet_setpayloadbuffer(msg); memset(&msg->msg_hdr, 0, sizeof(msg->msg_hdr)); @@ -646,9 +652,9 @@ lnet_ni_send(lnet_ni_t *ni, lnet_msg_t *msg) LASSERT(!in_interrupt()); LASSERT(LNET_NETTYP(LNET_NIDNET(ni->ni_nid)) == LOLND || - (msg->msg_txcredit && msg->msg_peertxcredit)); + (msg->msg_txcredit && msg->msg_peertxcredit)); - rc = (ni->ni_lnd->lnd_send)(ni, priv, msg); + rc = ni->ni_lnd->lnd_send(ni, priv, msg); if (rc < 0) lnet_finalize(ni, msg, rc); } @@ -661,12 +667,12 @@ lnet_ni_eager_recv(lnet_ni_t *ni, lnet_msg_t *msg) LASSERT(!msg->msg_sending); LASSERT(msg->msg_receiving); LASSERT(!msg->msg_rx_ready_delay); - LASSERT(ni->ni_lnd->lnd_eager_recv != NULL); + LASSERT(ni->ni_lnd->lnd_eager_recv); msg->msg_rx_ready_delay = 1; - rc = (ni->ni_lnd->lnd_eager_recv)(ni, msg->msg_private, msg, - &msg->msg_private); - if (rc != 0) { + rc = ni->ni_lnd->lnd_eager_recv(ni, msg->msg_private, msg, + &msg->msg_private); + if (rc) { CERROR("recv from %s / send to %s aborted: eager_recv failed %d\n", libcfs_nid2str(msg->msg_rxpeer->lp_nid), libcfs_id2str(msg->msg_target), rc); @@ -683,15 +689,15 @@ lnet_ni_query_locked(lnet_ni_t *ni, lnet_peer_t *lp) unsigned long last_alive = 0; LASSERT(lnet_peer_aliveness_enabled(lp)); - LASSERT(ni->ni_lnd->lnd_query != NULL); + LASSERT(ni->ni_lnd->lnd_query); lnet_net_unlock(lp->lp_cpt); - (ni->ni_lnd->lnd_query)(ni, lp->lp_nid, &last_alive); + ni->ni_lnd->lnd_query(ni, lp->lp_nid, &last_alive); lnet_net_lock(lp->lp_cpt); lp->lp_last_query = cfs_time_current(); - if (last_alive != 0) /* NI has updated timestamp */ + if (last_alive) /* NI has updated timestamp */ lp->lp_last_alive = last_alive; } @@ -720,14 +726,16 @@ lnet_peer_is_alive(lnet_peer_t *lp, unsigned long now) * case, and moreover lp_last_alive at peer creation is assumed. */ if (alive && !lp->lp_alive && - !(lnet_isrouter(lp) && lp->lp_alive_count == 0)) + !(lnet_isrouter(lp) && !lp->lp_alive_count)) lnet_notify_locked(lp, 0, 1, lp->lp_last_alive); return alive; } -/* NB: returns 1 when alive, 0 when dead, negative when error; - * may drop the lnet_net_lock */ +/* + * NB: returns 1 when alive, 0 when dead, negative when error; + * may drop the lnet_net_lock + */ static int lnet_peer_alive_locked(lnet_peer_t *lp) { @@ -739,9 +747,11 @@ lnet_peer_alive_locked(lnet_peer_t *lp) if (lnet_peer_is_alive(lp, now)) return 1; - /* Peer appears dead, but we should avoid frequent NI queries (at - * most once per lnet_queryinterval seconds). */ - if (lp->lp_last_query != 0) { + /* + * Peer appears dead, but we should avoid frequent NI queries (at + * most once per lnet_queryinterval seconds). + */ + if (lp->lp_last_query) { static const int lnet_queryinterval = 1; unsigned long next_query = @@ -775,10 +785,10 @@ lnet_peer_alive_locked(lnet_peer_t *lp) * lnet_send() is going to lnet_net_unlock immediately after this, so * it sets do_send FALSE and I don't do the unlock/send/lock bit. * - * \retval 0 If \a msg sent or OK to send. - * \retval EAGAIN If \a msg blocked for credit. - * \retval EHOSTUNREACH If the next hop of the message appears dead. - * \retval ECANCELED If the MD of the message has been unlinked. + * \retval LNET_CREDIT_OK If \a msg sent or OK to send. + * \retval LNET_CREDIT_WAIT If \a msg blocked for credit. + * \retval -EHOSTUNREACH If the next hop of the message appears dead. + * \retval -ECANCELED If the MD of the message has been unlinked. */ static int lnet_post_send_locked(lnet_msg_t *msg, int do_send) @@ -794,8 +804,8 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) LASSERT(msg->msg_tx_committed); /* NB 'lp' is always the next hop */ - if ((msg->msg_target.pid & LNET_PID_USERFLAG) == 0 && - lnet_peer_alive_locked(lp) == 0) { + if (!(msg->msg_target.pid & LNET_PID_USERFLAG) && + !lnet_peer_alive_locked(lp)) { the_lnet.ln_counters[cpt]->drop_count++; the_lnet.ln_counters[cpt]->drop_length += msg->msg_len; lnet_net_unlock(cpt); @@ -806,11 +816,11 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) lnet_finalize(ni, msg, -EHOSTUNREACH); lnet_net_lock(cpt); - return EHOSTUNREACH; + return -EHOSTUNREACH; } - if (msg->msg_md != NULL && - (msg->msg_md->md_flags & LNET_MD_FLAG_ABORTED) != 0) { + if (msg->msg_md && + (msg->msg_md->md_flags & LNET_MD_FLAG_ABORTED)) { lnet_net_unlock(cpt); CNETERR("Aborting message for %s: LNetM[DE]Unlink() already called on the MD/ME.\n", @@ -819,12 +829,12 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) lnet_finalize(ni, msg, -ECANCELED); lnet_net_lock(cpt); - return ECANCELED; + return -ECANCELED; } if (!msg->msg_peertxcredit) { LASSERT((lp->lp_txcredits < 0) == - !list_empty(&lp->lp_txq)); + !list_empty(&lp->lp_txq)); msg->msg_peertxcredit = 1; lp->lp_txqnob += msg->msg_len + sizeof(lnet_hdr_t); @@ -836,7 +846,7 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) if (lp->lp_txcredits < 0) { msg->msg_tx_delayed = 1; list_add_tail(&msg->msg_list, &lp->lp_txq); - return EAGAIN; + return LNET_CREDIT_WAIT; } } @@ -853,7 +863,7 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) if (tq->tq_credits < 0) { msg->msg_tx_delayed = 1; list_add_tail(&msg->msg_list, &tq->tq_delayed); - return EAGAIN; + return LNET_CREDIT_WAIT; } } @@ -862,7 +872,7 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) lnet_ni_send(ni, msg); lnet_net_lock(cpt); } - return 0; + return LNET_CREDIT_OK; } static lnet_rtrbufpool_t * @@ -888,16 +898,19 @@ lnet_msg2bufpool(lnet_msg_t *msg) static int lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv) { - /* lnet_parse is going to lnet_net_unlock immediately after this, so it - * sets do_recv FALSE and I don't do the unlock/send/lock bit. I - * return EAGAIN if msg blocked and 0 if received or OK to receive */ + /* + * lnet_parse is going to lnet_net_unlock immediately after this, so it + * sets do_recv FALSE and I don't do the unlock/send/lock bit. + * I return LNET_CREDIT_WAIT if msg blocked and LNET_CREDIT_OK if + * received or OK to receive + */ lnet_peer_t *lp = msg->msg_rxpeer; lnet_rtrbufpool_t *rbp; lnet_rtrbuf_t *rb; - LASSERT(msg->msg_iov == NULL); - LASSERT(msg->msg_kiov == NULL); - LASSERT(msg->msg_niov == 0); + LASSERT(!msg->msg_iov); + LASSERT(!msg->msg_kiov); + LASSERT(!msg->msg_niov); LASSERT(msg->msg_routing); LASSERT(msg->msg_receiving); LASSERT(!msg->msg_sending); @@ -907,7 +920,7 @@ lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv) if (!msg->msg_peerrtrcredit) { LASSERT((lp->lp_rtrcredits < 0) == - !list_empty(&lp->lp_rtrq)); + !list_empty(&lp->lp_rtrq)); msg->msg_peerrtrcredit = 1; lp->lp_rtrcredits--; @@ -919,16 +932,13 @@ lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv) LASSERT(msg->msg_rx_ready_delay); msg->msg_rx_delayed = 1; list_add_tail(&msg->msg_list, &lp->lp_rtrq); - return EAGAIN; + return LNET_CREDIT_WAIT; } } rbp = lnet_msg2bufpool(msg); if (!msg->msg_rtrcredit) { - LASSERT((rbp->rbp_credits < 0) == - !list_empty(&rbp->rbp_msgs)); - msg->msg_rtrcredit = 1; rbp->rbp_credits--; if (rbp->rbp_credits < rbp->rbp_mincredits) @@ -939,7 +949,7 @@ lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv) LASSERT(msg->msg_rx_ready_delay); msg->msg_rx_delayed = 1; list_add_tail(&msg->msg_list, &rbp->rbp_msgs); - return EAGAIN; + return LNET_CREDIT_WAIT; } } @@ -958,7 +968,7 @@ lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv) 0, msg->msg_len, msg->msg_len); lnet_net_lock(cpt); } - return 0; + return LNET_CREDIT_OK; } void @@ -980,7 +990,7 @@ lnet_return_tx_credits_locked(lnet_msg_t *msg) tq->tq_credits++; if (tq->tq_credits <= 0) { msg2 = list_entry(tq->tq_delayed.next, - lnet_msg_t, msg_list); + lnet_msg_t, msg_list); list_del(&msg2->msg_list); LASSERT(msg2->msg_txpeer->lp_ni == ni); @@ -1003,7 +1013,7 @@ lnet_return_tx_credits_locked(lnet_msg_t *msg) txpeer->lp_txcredits++; if (txpeer->lp_txcredits <= 0) { msg2 = list_entry(txpeer->lp_txq.next, - lnet_msg_t, msg_list); + lnet_msg_t, msg_list); list_del(&msg2->msg_list); LASSERT(msg2->msg_txpeer == txpeer); @@ -1013,13 +1023,50 @@ lnet_return_tx_credits_locked(lnet_msg_t *msg) } } - if (txpeer != NULL) { + if (txpeer) { msg->msg_txpeer = NULL; lnet_peer_decref_locked(txpeer); } } void +lnet_schedule_blocked_locked(lnet_rtrbufpool_t *rbp) +{ + lnet_msg_t *msg; + + if (list_empty(&rbp->rbp_msgs)) + return; + msg = list_entry(rbp->rbp_msgs.next, + lnet_msg_t, msg_list); + list_del(&msg->msg_list); + + (void)lnet_post_routed_recv_locked(msg, 1); +} + +void +lnet_drop_routed_msgs_locked(struct list_head *list, int cpt) +{ + struct list_head drop; + lnet_msg_t *msg; + lnet_msg_t *tmp; + + INIT_LIST_HEAD(&drop); + + list_splice_init(list, &drop); + + lnet_net_unlock(cpt); + + list_for_each_entry_safe(msg, tmp, &drop, msg_list) { + lnet_ni_recv(msg->msg_rxpeer->lp_ni, msg->msg_private, NULL, + 0, 0, 0, msg->msg_hdr.payload_length); + list_del_init(&msg->msg_list); + lnet_finalize(NULL, msg, -ECANCELED); + } + + lnet_net_lock(cpt); +} + +void lnet_return_rx_credits_locked(lnet_msg_t *msg) { lnet_peer_t *rxpeer = msg->msg_rxpeer; @@ -1030,34 +1077,51 @@ lnet_return_rx_credits_locked(lnet_msg_t *msg) lnet_rtrbuf_t *rb; lnet_rtrbufpool_t *rbp; - /* NB If a msg ever blocks for a buffer in rbp_msgs, it stays + /* + * NB If a msg ever blocks for a buffer in rbp_msgs, it stays * there until it gets one allocated, or aborts the wait - * itself */ - LASSERT(msg->msg_kiov != NULL); + * itself + */ + LASSERT(msg->msg_kiov); rb = list_entry(msg->msg_kiov, lnet_rtrbuf_t, rb_kiov[0]); rbp = rb->rb_pool; - LASSERT(rbp == lnet_msg2bufpool(msg)); msg->msg_kiov = NULL; msg->msg_rtrcredit = 0; - LASSERT((rbp->rbp_credits < 0) == - !list_empty(&rbp->rbp_msgs)); + LASSERT(rbp == lnet_msg2bufpool(msg)); + LASSERT((rbp->rbp_credits > 0) == !list_empty(&rbp->rbp_bufs)); - list_add(&rb->rb_list, &rbp->rbp_bufs); - rbp->rbp_credits++; - if (rbp->rbp_credits <= 0) { - msg2 = list_entry(rbp->rbp_msgs.next, - lnet_msg_t, msg_list); - list_del(&msg2->msg_list); + /* + * If routing is now turned off, we just drop this buffer and + * don't bother trying to return credits. + */ + if (!the_lnet.ln_routing) { + lnet_destroy_rtrbuf(rb, rbp->rbp_npages); + goto routing_off; + } - (void) lnet_post_routed_recv_locked(msg2, 1); + /* + * It is possible that a user has lowered the desired number of + * buffers in this pool. Make sure we never put back + * more buffers than the stated number. + */ + if (unlikely(rbp->rbp_credits >= rbp->rbp_req_nbuffers)) { + /* Discard this buffer so we don't have too many. */ + lnet_destroy_rtrbuf(rb, rbp->rbp_npages); + rbp->rbp_nbuffers--; + } else { + list_add(&rb->rb_list, &rbp->rbp_bufs); + rbp->rbp_credits++; + if (rbp->rbp_credits <= 0) + lnet_schedule_blocked_locked(rbp); } } +routing_off: if (msg->msg_peerrtrcredit) { /* give back peer router credits */ msg->msg_peerrtrcredit = 0; @@ -1066,15 +1130,22 @@ lnet_return_rx_credits_locked(lnet_msg_t *msg) !list_empty(&rxpeer->lp_rtrq)); rxpeer->lp_rtrcredits++; - if (rxpeer->lp_rtrcredits <= 0) { + /* + * drop all messages which are queued to be routed on that + * peer. + */ + if (!the_lnet.ln_routing) { + lnet_drop_routed_msgs_locked(&rxpeer->lp_rtrq, + msg->msg_rx_cpt); + } else if (rxpeer->lp_rtrcredits <= 0) { msg2 = list_entry(rxpeer->lp_rtrq.next, - lnet_msg_t, msg_list); + lnet_msg_t, msg_list); list_del(&msg2->msg_list); (void) lnet_post_routed_recv_locked(msg2, 1); } } - if (rxpeer != NULL) { + if (rxpeer) { msg->msg_rxpeer = NULL; lnet_peer_decref_locked(rxpeer); } @@ -1085,94 +1156,99 @@ lnet_compare_routes(lnet_route_t *r1, lnet_route_t *r2) { lnet_peer_t *p1 = r1->lr_gateway; lnet_peer_t *p2 = r2->lr_gateway; + int r1_hops = (r1->lr_hops == LNET_UNDEFINED_HOPS) ? 1 : r1->lr_hops; + int r2_hops = (r2->lr_hops == LNET_UNDEFINED_HOPS) ? 1 : r2->lr_hops; if (r1->lr_priority < r2->lr_priority) return 1; if (r1->lr_priority > r2->lr_priority) - return -1; + return -ERANGE; - if (r1->lr_hops < r2->lr_hops) + if (r1_hops < r2_hops) return 1; - if (r1->lr_hops > r2->lr_hops) - return -1; + if (r1_hops > r2_hops) + return -ERANGE; if (p1->lp_txqnob < p2->lp_txqnob) return 1; if (p1->lp_txqnob > p2->lp_txqnob) - return -1; + return -ERANGE; if (p1->lp_txcredits > p2->lp_txcredits) return 1; if (p1->lp_txcredits < p2->lp_txcredits) - return -1; + return -ERANGE; if (r1->lr_seq - r2->lr_seq <= 0) return 1; - return -1; + return -ERANGE; } static lnet_peer_t * lnet_find_route_locked(lnet_ni_t *ni, lnet_nid_t target, lnet_nid_t rtr_nid) { lnet_remotenet_t *rnet; - lnet_route_t *rtr; - lnet_route_t *rtr_best; - lnet_route_t *rtr_last; + lnet_route_t *route; + lnet_route_t *best_route; + lnet_route_t *last_route; struct lnet_peer *lp_best; struct lnet_peer *lp; int rc; - /* If @rtr_nid is not LNET_NID_ANY, return the gateway with - * rtr_nid nid, otherwise find the best gateway I can use */ - + /* + * If @rtr_nid is not LNET_NID_ANY, return the gateway with + * rtr_nid nid, otherwise find the best gateway I can use + */ rnet = lnet_find_net_locked(LNET_NIDNET(target)); - if (rnet == NULL) + if (!rnet) return NULL; lp_best = NULL; - rtr_best = rtr_last = NULL; - list_for_each_entry(rtr, &rnet->lrn_routes, lr_list) { - lp = rtr->lr_gateway; + best_route = NULL; + last_route = NULL; + list_for_each_entry(route, &rnet->lrn_routes, lr_list) { + lp = route->lr_gateway; - if (!lp->lp_alive || /* gateway is down */ - ((lp->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) != 0 && - rtr->lr_downis != 0)) /* NI to target is down */ + if (!lnet_is_route_alive(route)) continue; - if (ni != NULL && lp->lp_ni != ni) + if (ni && lp->lp_ni != ni) continue; if (lp->lp_nid == rtr_nid) /* it's pre-determined router */ return lp; - if (lp_best == NULL) { - rtr_best = rtr_last = rtr; + if (!lp_best) { + best_route = route; + last_route = route; lp_best = lp; continue; } /* no protection on below fields, but it's harmless */ - if (rtr_last->lr_seq - rtr->lr_seq < 0) - rtr_last = rtr; + if (last_route->lr_seq - route->lr_seq < 0) + last_route = route; - rc = lnet_compare_routes(rtr, rtr_best); + rc = lnet_compare_routes(route, best_route); if (rc < 0) continue; - rtr_best = rtr; + best_route = route; lp_best = lp; } - /* set sequence number on the best router to the latest sequence + 1 + /* + * set sequence number on the best router to the latest sequence + 1 * so we can round-robin all routers, it's race and inaccurate but - * harmless and functional */ - if (rtr_best != NULL) - rtr_best->lr_seq = rtr_last->lr_seq + 1; + * harmless and functional + */ + if (best_route) + best_route->lr_seq = last_route->lr_seq + 1; return lp_best; } @@ -1187,11 +1263,13 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) int cpt2; int rc; - /* NB: rtr_nid is set to LNET_NID_ANY for all current use-cases, + /* + * NB: rtr_nid is set to LNET_NID_ANY for all current use-cases, * but we might want to use pre-determined router for ACK/REPLY - * in the future */ - /* NB: ni != NULL == interface pre-determined (ACK/REPLY) */ - LASSERT(msg->msg_txpeer == NULL); + * in the future + */ + /* NB: ni == interface pre-determined (ACK/REPLY) */ + LASSERT(!msg->msg_txpeer); LASSERT(!msg->msg_sending); LASSERT(!msg->msg_target_is_router); LASSERT(!msg->msg_receiving); @@ -1212,7 +1290,7 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) src_ni = NULL; } else { src_ni = lnet_nid2ni_locked(src_nid, cpt); - if (src_ni == NULL) { + if (!src_ni) { lnet_net_unlock(cpt); LCONSOLE_WARN("Can't send to %s: src %s is not a local nid\n", libcfs_nid2str(dst_nid), @@ -1225,8 +1303,8 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) /* Is this for someone on a local network? */ local_ni = lnet_net2ni_locked(LNET_NIDNET(dst_nid), cpt); - if (local_ni != NULL) { - if (src_ni == NULL) { + if (local_ni) { + if (!src_ni) { src_ni = local_ni; src_nid = src_ni->ni_nid; } else if (src_ni == local_ni) { @@ -1261,7 +1339,7 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) rc = lnet_nid2peer_locked(&lp, dst_nid, cpt); /* lp has ref on src_ni; lose mine */ lnet_ni_decref_locked(src_ni, cpt); - if (rc != 0) { + if (rc) { lnet_net_unlock(cpt); LCONSOLE_WARN("Error %d finding peer %s\n", rc, libcfs_nid2str(dst_nid)); @@ -1272,8 +1350,8 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) } else { /* sending to a remote network */ lp = lnet_find_route_locked(src_ni, dst_nid, rtr_nid); - if (lp == NULL) { - if (src_ni != NULL) + if (!lp) { + if (src_ni) lnet_ni_decref_locked(src_ni, cpt); lnet_net_unlock(cpt); @@ -1283,14 +1361,16 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) return -EHOSTUNREACH; } - /* rtr_nid is LNET_NID_ANY or NID of pre-determined router, + /* + * rtr_nid is LNET_NID_ANY or NID of pre-determined router, * it's possible that rtr_nid isn't LNET_NID_ANY and lp isn't * pre-determined router, this can happen if router table - * was changed when we release the lock */ + * was changed when we release the lock + */ if (rtr_nid != lp->lp_nid) { cpt2 = lnet_cpt_of_nid_locked(lp->lp_nid); if (cpt2 != cpt) { - if (src_ni != NULL) + if (src_ni) lnet_ni_decref_locked(src_ni, cpt); lnet_net_unlock(cpt); @@ -1304,7 +1384,7 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) libcfs_nid2str(dst_nid), libcfs_nid2str(lp->lp_nid), lnet_msgtyp2str(msg->msg_type), msg->msg_len); - if (src_ni == NULL) { + if (!src_ni) { src_ni = lp->lp_ni; src_nid = src_ni->ni_nid; } else { @@ -1324,30 +1404,30 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) msg->msg_target_is_router = 1; msg->msg_target.nid = lp->lp_nid; - msg->msg_target.pid = LUSTRE_SRV_LNET_PID; + msg->msg_target.pid = LNET_PID_LUSTRE; } /* 'lp' is our best choice of peer */ LASSERT(!msg->msg_peertxcredit); LASSERT(!msg->msg_txcredit); - LASSERT(msg->msg_txpeer == NULL); + LASSERT(!msg->msg_txpeer); msg->msg_txpeer = lp; /* msg takes my ref on lp */ rc = lnet_post_send_locked(msg, 0); lnet_net_unlock(cpt); - if (rc == EHOSTUNREACH || rc == ECANCELED) - return -rc; + if (rc < 0) + return rc; - if (rc == 0) + if (rc == LNET_CREDIT_OK) lnet_ni_send(src_ni, msg); - return 0; /* rc == 0 or EAGAIN */ + return 0; /* rc == LNET_CREDIT_OK or LNET_CREDIT_WAIT */ } -static void +void lnet_drop_message(lnet_ni_t *ni, int cpt, void *private, unsigned int nob) { lnet_net_lock(cpt); @@ -1363,15 +1443,17 @@ lnet_recv_put(lnet_ni_t *ni, lnet_msg_t *msg) { lnet_hdr_t *hdr = &msg->msg_hdr; - if (msg->msg_wanted != 0) + if (msg->msg_wanted) lnet_setpayloadbuffer(msg); lnet_build_msg_event(msg, LNET_EVENT_PUT); - /* Must I ACK? If so I'll grab the ack_wmd out of the header and put - * it back into the ACK during lnet_finalize() */ - msg->msg_ack = (!lnet_is_wire_handle_none(&hdr->msg.put.ack_wmd) && - (msg->msg_md->md_options & LNET_MD_ACK_DISABLE) == 0); + /* + * Must I ACK? If so I'll grab the ack_wmd out of the header and put + * it back into the ACK during lnet_finalize() + */ + msg->msg_ack = !lnet_is_wire_handle_none(&hdr->msg.put.ack_wmd) && + !(msg->msg_md->md_options & LNET_MD_ACK_DISABLE); lnet_ni_recv(ni, msg->msg_private, msg, msg->msg_rx_delayed, msg->msg_offset, msg->msg_wanted, hdr->payload_length); @@ -1382,6 +1464,7 @@ lnet_parse_put(lnet_ni_t *ni, lnet_msg_t *msg) { lnet_hdr_t *hdr = &msg->msg_hdr; struct lnet_match_info info; + bool ready_delay; int rc; /* Convert put fields to host byte order */ @@ -1397,7 +1480,8 @@ lnet_parse_put(lnet_ni_t *ni, lnet_msg_t *msg) info.mi_roffset = hdr->msg.put.offset; info.mi_mbits = hdr->msg.put.match_bits; - msg->msg_rx_ready_delay = ni->ni_lnd->lnd_eager_recv == NULL; + msg->msg_rx_ready_delay = !ni->ni_lnd->lnd_eager_recv; + ready_delay = msg->msg_rx_ready_delay; again: rc = lnet_ptl_match_md(&info, msg); @@ -1410,12 +1494,18 @@ lnet_parse_put(lnet_ni_t *ni, lnet_msg_t *msg) return 0; case LNET_MATCHMD_NONE: - if (msg->msg_rx_delayed) /* attached on delayed list */ + /** + * no eager_recv or has already called it, should + * have been attached on delayed list + */ + if (ready_delay) return 0; rc = lnet_ni_eager_recv(ni, msg); - if (rc == 0) + if (!rc) { + ready_delay = true; goto again; + } /* fall through */ case LNET_MATCHMD_DROP: @@ -1423,7 +1513,7 @@ lnet_parse_put(lnet_ni_t *ni, lnet_msg_t *msg) libcfs_id2str(info.mi_id), info.mi_portal, info.mi_mbits, info.mi_roffset, info.mi_rlength, rc); - return ENOENT; /* +ve: OK but no match */ + return -ENOENT; /* -ve: OK but no match */ } } @@ -1454,7 +1544,7 @@ lnet_parse_get(lnet_ni_t *ni, lnet_msg_t *msg, int rdma_get) CNETERR("Dropping GET from %s portal %d match %llu offset %d length %d\n", libcfs_id2str(info.mi_id), info.mi_portal, info.mi_mbits, info.mi_roffset, info.mi_rlength); - return ENOENT; /* +ve: OK but no match */ + return -ENOENT; /* -ve: OK but no match */ } LASSERT(rc == LNET_MATCHMD_OK); @@ -1510,33 +1600,33 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg_t *msg) /* NB handles only looked up by creator (no flips) */ md = lnet_wire_handle2md(&hdr->msg.reply.dst_wmd); - if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) { + if (!md || !md->md_threshold || md->md_me) { CNETERR("%s: Dropping REPLY from %s for %s MD %#llx.%#llx\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(src), - (md == NULL) ? "invalid" : "inactive", + !md ? "invalid" : "inactive", hdr->msg.reply.dst_wmd.wh_interface_cookie, hdr->msg.reply.dst_wmd.wh_object_cookie); - if (md != NULL && md->md_me != NULL) + if (md && md->md_me) CERROR("REPLY MD also attached to portal %d\n", md->md_me->me_portal); lnet_res_unlock(cpt); - return ENOENT; /* +ve: OK but no match */ + return -ENOENT; /* -ve: OK but no match */ } - LASSERT(md->md_offset == 0); + LASSERT(!md->md_offset); rlength = hdr->payload_length; mlength = min_t(uint, rlength, md->md_length); if (mlength < rlength && - (md->md_options & LNET_MD_TRUNCATE) == 0) { + !(md->md_options & LNET_MD_TRUNCATE)) { CNETERR("%s: Dropping REPLY from %s length %d for MD %#llx would overflow (%d)\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(src), rlength, hdr->msg.reply.dst_wmd.wh_object_cookie, mlength); lnet_res_unlock(cpt); - return ENOENT; /* +ve: OK but no match */ + return -ENOENT; /* -ve: OK but no match */ } CDEBUG(D_NET, "%s: Reply from %s of length %d/%d into md %#llx\n", @@ -1545,7 +1635,7 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg_t *msg) lnet_msg_attach_md(msg, md, 0, mlength); - if (mlength != 0) + if (mlength) lnet_setpayloadbuffer(msg); lnet_res_unlock(cpt); @@ -1576,20 +1666,20 @@ lnet_parse_ack(lnet_ni_t *ni, lnet_msg_t *msg) /* NB handles only looked up by creator (no flips) */ md = lnet_wire_handle2md(&hdr->msg.ack.dst_wmd); - if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) { + if (!md || !md->md_threshold || md->md_me) { /* Don't moan; this is expected */ CDEBUG(D_NET, "%s: Dropping ACK from %s to %s MD %#llx.%#llx\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(src), - (md == NULL) ? "invalid" : "inactive", + !md ? "invalid" : "inactive", hdr->msg.ack.dst_wmd.wh_interface_cookie, hdr->msg.ack.dst_wmd.wh_object_cookie); - if (md != NULL && md->md_me != NULL) + if (md && md->md_me) CERROR("Source MD also attached to portal %d\n", md->md_me->me_portal); lnet_res_unlock(cpt); - return ENOENT; /* +ve! */ + return -ENOENT; /* -ve! */ } CDEBUG(D_NET, "%s: ACK from %s into md %#llx\n", @@ -1606,14 +1696,22 @@ lnet_parse_ack(lnet_ni_t *ni, lnet_msg_t *msg) return 0; } -static int +/** + * \retval LNET_CREDIT_OK If \a msg is forwarded + * \retval LNET_CREDIT_WAIT If \a msg is blocked because w/o buffer + * \retval -ve error code + */ +int lnet_parse_forward_locked(lnet_ni_t *ni, lnet_msg_t *msg) { int rc = 0; + if (!the_lnet.ln_routing) + return -ECANCELED; + if (msg->msg_rxpeer->lp_rtrcredits <= 0 || lnet_msg2bufpool(msg)->rbp_credits <= 0) { - if (ni->ni_lnd->lnd_eager_recv == NULL) { + if (!ni->ni_lnd->lnd_eager_recv) { msg->msg_rx_ready_delay = 1; } else { lnet_net_unlock(msg->msg_rx_cpt); @@ -1622,11 +1720,38 @@ lnet_parse_forward_locked(lnet_ni_t *ni, lnet_msg_t *msg) } } - if (rc == 0) + if (!rc) rc = lnet_post_routed_recv_locked(msg, 0); return rc; } +int +lnet_parse_local(lnet_ni_t *ni, lnet_msg_t *msg) +{ + int rc; + + switch (msg->msg_type) { + case LNET_MSG_ACK: + rc = lnet_parse_ack(ni, msg); + break; + case LNET_MSG_PUT: + rc = lnet_parse_put(ni, msg); + break; + case LNET_MSG_GET: + rc = lnet_parse_get(ni, msg, msg->msg_rdma_get); + break; + case LNET_MSG_REPLY: + rc = lnet_parse_reply(ni, msg); + break; + default: /* prevent an unused label if !kernel */ + LASSERT(0); + return -EPROTO; + } + + LASSERT(!rc || rc == -ENOENT); + return rc; +} + char * lnet_msgtyp2str(int type) { @@ -1702,7 +1827,6 @@ lnet_print_hdr(lnet_hdr_t *hdr) hdr->msg.reply.dst_wmd.wh_object_cookie, hdr->payload_length); } - } int @@ -1765,20 +1889,20 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, if (the_lnet.ln_routing && ni->ni_last_alive != ktime_get_real_seconds()) { - lnet_ni_lock(ni); - /* NB: so far here is the only place to set NI status to "up */ + lnet_ni_lock(ni); ni->ni_last_alive = ktime_get_real_seconds(); - if (ni->ni_status != NULL && + if (ni->ni_status && ni->ni_status->ns_status == LNET_NI_STATUS_DOWN) ni->ni_status->ns_status = LNET_NI_STATUS_UP; lnet_ni_unlock(ni); } - /* Regard a bad destination NID as a protocol error. Senders should + /* + * Regard a bad destination NID as a protocol error. Senders should * know what they're doing; if they don't they're misconfigured, buggy - * or malicious so we chop them off at the knees :) */ - + * or malicious so we chop them off at the knees :) + */ if (!for_me) { if (LNET_NIDNET(dest_nid) == LNET_NIDNET(ni->ni_nid)) { /* should have gone direct */ @@ -1790,8 +1914,10 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, } if (lnet_islocalnid(dest_nid)) { - /* dest is another local NI; sender should have used - * this node's NID on its own network */ + /* + * dest is another local NI; sender should have used + * this node's NID on its own network + */ CERROR("%s, src %s: Bad dest nid %s (it's my nid but on a different network)\n", libcfs_nid2str(from_nid), libcfs_nid2str(src_nid), @@ -1816,9 +1942,10 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, } } - /* Message looks OK; we're not going to return an error, so we MUST - * call back lnd_recv() come what may... */ - + /* + * Message looks OK; we're not going to return an error, so we MUST + * call back lnd_recv() come what may... + */ if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */ fail_peer(src_nid, 0)) { /* shall we now? */ CERROR("%s, src %s: Dropping %s to simulate failure\n", @@ -1827,8 +1954,16 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, goto drop; } + if (!list_empty(&the_lnet.ln_drop_rules) && + lnet_drop_rule_match(hdr)) { + CDEBUG(D_NET, "%s, src %s, dst %s: Dropping %s to simulate silent message loss\n", + libcfs_nid2str(from_nid), libcfs_nid2str(src_nid), + libcfs_nid2str(dest_nid), lnet_msgtyp2str(type)); + goto drop; + } + msg = lnet_msg_alloc(); - if (msg == NULL) { + if (!msg) { CERROR("%s, src %s: Dropping %s (out of memory)\n", libcfs_nid2str(from_nid), libcfs_nid2str(src_nid), lnet_msgtyp2str(type)); @@ -1838,11 +1973,12 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, /* msg zeroed in lnet_msg_alloc; * i.e. flags all clear, pointers NULL etc */ - msg->msg_type = type; msg->msg_private = private; msg->msg_receiving = 1; - msg->msg_len = msg->msg_wanted = payload_length; + msg->msg_rdma_get = rdma_req; + msg->msg_wanted = payload_length; + msg->msg_len = payload_length; msg->msg_offset = 0; msg->msg_hdr = *hdr; /* for building message event */ @@ -1864,7 +2000,7 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, lnet_net_lock(cpt); rc = lnet_nid2peer_locked(&msg->msg_rxpeer, from_nid, cpt); - if (rc != 0) { + if (rc) { lnet_net_unlock(cpt); CERROR("%s, src %s: Dropping %s (error %d looking up sender)\n", libcfs_nid2str(from_nid), libcfs_nid2str(src_nid), @@ -1888,13 +2024,21 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, lnet_msg_commit(msg, cpt); + /* message delay simulation */ + if (unlikely(!list_empty(&the_lnet.ln_delay_rules) && + lnet_delay_rule_match_locked(hdr, msg))) { + lnet_net_unlock(cpt); + return 0; + } + if (!for_me) { rc = lnet_parse_forward_locked(ni, msg); lnet_net_unlock(cpt); if (rc < 0) goto free_drop; - if (rc == 0) { + + if (rc == LNET_CREDIT_OK) { lnet_ni_recv(ni, msg->msg_private, msg, 0, 0, payload_length, payload_length); } @@ -1903,32 +2047,13 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, lnet_net_unlock(cpt); - switch (type) { - case LNET_MSG_ACK: - rc = lnet_parse_ack(ni, msg); - break; - case LNET_MSG_PUT: - rc = lnet_parse_put(ni, msg); - break; - case LNET_MSG_GET: - rc = lnet_parse_get(ni, msg, rdma_req); - break; - case LNET_MSG_REPLY: - rc = lnet_parse_reply(ni, msg); - break; - default: - LASSERT(0); - rc = -EPROTO; - goto free_drop; /* prevent an unused label if !kernel */ - } - - if (rc == 0) - return 0; - - LASSERT(rc == ENOENT); + rc = lnet_parse_local(ni, msg); + if (rc) + goto free_drop; + return 0; free_drop: - LASSERT(msg->msg_md == NULL); + LASSERT(!msg->msg_md); lnet_finalize(ni, msg, rc); drop: @@ -1950,9 +2075,9 @@ lnet_drop_delayed_msg_list(struct list_head *head, char *reason) id.nid = msg->msg_hdr.src_nid; id.pid = msg->msg_hdr.src_pid; - LASSERT(msg->msg_md == NULL); + LASSERT(!msg->msg_md); LASSERT(msg->msg_rx_delayed); - LASSERT(msg->msg_rxpeer != NULL); + LASSERT(msg->msg_rxpeer); LASSERT(msg->msg_hdr.type == LNET_MSG_PUT); CWARN("Dropping delayed PUT from %s portal %d match %llu offset %d length %d: %s\n", @@ -1962,10 +2087,11 @@ lnet_drop_delayed_msg_list(struct list_head *head, char *reason) msg->msg_hdr.msg.put.offset, msg->msg_hdr.payload_length, reason); - /* NB I can't drop msg's ref on msg_rxpeer until after I've + /* + * NB I can't drop msg's ref on msg_rxpeer until after I've * called lnet_drop_message(), so I just hang onto msg as well - * until that's done */ - + * until that's done + */ lnet_drop_message(msg->msg_rxpeer->lp_ni, msg->msg_rxpeer->lp_cpt, msg->msg_private, msg->msg_len); @@ -1988,15 +2114,16 @@ lnet_recv_delayed_msg_list(struct list_head *head) msg = list_entry(head->next, lnet_msg_t, msg_list); list_del(&msg->msg_list); - /* md won't disappear under me, since each msg - * holds a ref on it */ - + /* + * md won't disappear under me, since each msg + * holds a ref on it + */ id.nid = msg->msg_hdr.src_nid; id.pid = msg->msg_hdr.src_pid; LASSERT(msg->msg_rx_delayed); - LASSERT(msg->msg_md != NULL); - LASSERT(msg->msg_rxpeer != NULL); + LASSERT(msg->msg_md); + LASSERT(msg->msg_rxpeer); LASSERT(msg->msg_hdr.type == LNET_MSG_PUT); CDEBUG(D_NET, "Resuming delayed PUT from %s portal %d match %llu offset %d length %d.\n", @@ -2064,7 +2191,6 @@ LNetPut(lnet_nid_t self, lnet_handle_md_t mdh, lnet_ack_req_t ack, int cpt; int rc; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */ @@ -2075,7 +2201,7 @@ LNetPut(lnet_nid_t self, lnet_handle_md_t mdh, lnet_ack_req_t ack, } msg = lnet_msg_alloc(); - if (msg == NULL) { + if (!msg) { CERROR("Dropping PUT to %s: ENOMEM on lnet_msg_t\n", libcfs_id2str(target)); return -ENOMEM; @@ -2086,11 +2212,11 @@ LNetPut(lnet_nid_t self, lnet_handle_md_t mdh, lnet_ack_req_t ack, lnet_res_lock(cpt); md = lnet_handle2md(&mdh); - if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) { + if (!md || !md->md_threshold || md->md_me) { CERROR("Dropping PUT (%llu:%d:%s): MD (%d) invalid\n", match_bits, portal, libcfs_id2str(target), - md == NULL ? -1 : md->md_threshold); - if (md != NULL && md->md_me != NULL) + !md ? -1 : md->md_threshold); + if (md && md->md_me) CERROR("Source MD also attached to portal %d\n", md->md_me->me_portal); lnet_res_unlock(cpt); @@ -2128,9 +2254,9 @@ LNetPut(lnet_nid_t self, lnet_handle_md_t mdh, lnet_ack_req_t ack, lnet_build_msg_event(msg, LNET_EVENT_SEND); rc = lnet_send(self, msg, LNET_NID_ANY); - if (rc != 0) { + if (rc) { CNETERR("Error sending PUT to %s: %d\n", - libcfs_id2str(target), rc); + libcfs_id2str(target), rc); lnet_finalize(NULL, msg, rc); } @@ -2142,13 +2268,14 @@ EXPORT_SYMBOL(LNetPut); lnet_msg_t * lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg) { - /* The LND can DMA direct to the GET md (i.e. no REPLY msg). This + /* + * The LND can DMA direct to the GET md (i.e. no REPLY msg). This * returns a msg for the LND to pass to lnet_finalize() when the sink * data has been received. * * CAVEAT EMPTOR: 'getmsg' is the original GET, which is freed when - * lnet_finalize() is called on it, so the LND must call this first */ - + * lnet_finalize() is called on it, so the LND must call this first + */ struct lnet_msg *msg = lnet_msg_alloc(); struct lnet_libmd *getmd = getmsg->msg_md; lnet_process_id_t peer_id = getmsg->msg_target; @@ -2157,26 +2284,26 @@ lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg) LASSERT(!getmsg->msg_target_is_router); LASSERT(!getmsg->msg_routing); + if (!msg) { + CERROR("%s: Dropping REPLY from %s: can't allocate msg\n", + libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id)); + goto drop; + } + cpt = lnet_cpt_of_cookie(getmd->md_lh.lh_cookie); lnet_res_lock(cpt); LASSERT(getmd->md_refcount > 0); - if (msg == NULL) { - CERROR("%s: Dropping REPLY from %s: can't allocate msg\n", - libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id)); - goto drop; - } - - if (getmd->md_threshold == 0) { + if (!getmd->md_threshold) { CERROR("%s: Dropping REPLY from %s for inactive MD %p\n", - libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id), - getmd); + libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id), + getmd); lnet_res_unlock(cpt); goto drop; } - LASSERT(getmd->md_offset == 0); + LASSERT(!getmd->md_offset); CDEBUG(D_NET, "%s: Reply from %s md %p\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id), getmd); @@ -2209,7 +2336,7 @@ lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg) the_lnet.ln_counters[cpt]->drop_length += getmd->md_length; lnet_net_unlock(cpt); - if (msg != NULL) + if (msg) lnet_msg_free(msg); return NULL; @@ -2219,14 +2346,18 @@ EXPORT_SYMBOL(lnet_create_reply_msg); void lnet_set_reply_msg_len(lnet_ni_t *ni, lnet_msg_t *reply, unsigned int len) { - /* Set the REPLY length, now the RDMA that elides the REPLY message has - * completed and I know it. */ - LASSERT(reply != NULL); + /* + * Set the REPLY length, now the RDMA that elides the REPLY message has + * completed and I know it. + */ + LASSERT(reply); LASSERT(reply->msg_type == LNET_MSG_GET); LASSERT(reply->msg_ev.type == LNET_EVENT_REPLY); - /* NB I trusted my peer to RDMA. If she tells me she's written beyond - * the end of my buffer, I might as well be dead. */ + /* + * NB I trusted my peer to RDMA. If she tells me she's written beyond + * the end of my buffer, I might as well be dead. + */ LASSERT(len <= reply->msg_ev.mlength); reply->msg_ev.mlength = len; @@ -2264,7 +2395,6 @@ LNetGet(lnet_nid_t self, lnet_handle_md_t mdh, int cpt; int rc; - LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */ @@ -2275,7 +2405,7 @@ LNetGet(lnet_nid_t self, lnet_handle_md_t mdh, } msg = lnet_msg_alloc(); - if (msg == NULL) { + if (!msg) { CERROR("Dropping GET to %s: ENOMEM on lnet_msg_t\n", libcfs_id2str(target)); return -ENOMEM; @@ -2285,11 +2415,11 @@ LNetGet(lnet_nid_t self, lnet_handle_md_t mdh, lnet_res_lock(cpt); md = lnet_handle2md(&mdh); - if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) { + if (!md || !md->md_threshold || md->md_me) { CERROR("Dropping GET (%llu:%d:%s): MD (%d) invalid\n", match_bits, portal, libcfs_id2str(target), - md == NULL ? -1 : md->md_threshold); - if (md != NULL && md->md_me != NULL) + !md ? -1 : md->md_threshold); + if (md && md->md_me) CERROR("REPLY MD also attached to portal %d\n", md->md_me->me_portal); @@ -2323,7 +2453,7 @@ LNetGet(lnet_nid_t self, lnet_handle_md_t mdh, rc = lnet_send(self, msg, LNET_NID_ANY); if (rc < 0) { CNETERR("Error sending GET to %s: %d\n", - libcfs_id2str(target), rc); + libcfs_id2str(target), rc); lnet_finalize(NULL, msg, rc); } @@ -2358,12 +2488,12 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) __u32 order = 2; struct list_head *rn_list; - /* if !local_nid_dist_zero, I don't return a distance of 0 ever + /* + * if !local_nid_dist_zero, I don't return a distance of 0 ever * (when lustre sees a distance of 0, it substitutes 0@lo), so I * keep order 0 free for 0@lo and order 1 free for a local NID - * match */ - - LASSERT(the_lnet.ln_init); + * match + */ LASSERT(the_lnet.ln_refcount > 0); cpt = lnet_net_lock_current(); @@ -2372,9 +2502,9 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) ni = list_entry(e, lnet_ni_t, ni_list); if (ni->ni_nid == dstnid) { - if (srcnidp != NULL) + if (srcnidp) *srcnidp = dstnid; - if (orderp != NULL) { + if (orderp) { if (LNET_NETTYP(LNET_NIDNET(dstnid)) == LOLND) *orderp = 0; else @@ -2386,9 +2516,9 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) } if (LNET_NIDNET(ni->ni_nid) == dstnet) { - if (srcnidp != NULL) + if (srcnidp) *srcnidp = ni->ni_nid; - if (orderp != NULL) + if (orderp) *orderp = order; lnet_net_unlock(cpt); return 1; @@ -2404,21 +2534,28 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) if (rnet->lrn_net == dstnet) { lnet_route_t *route; lnet_route_t *shortest = NULL; + __u32 shortest_hops = LNET_UNDEFINED_HOPS; + __u32 route_hops; LASSERT(!list_empty(&rnet->lrn_routes)); list_for_each_entry(route, &rnet->lrn_routes, - lr_list) { - if (shortest == NULL || - route->lr_hops < shortest->lr_hops) + lr_list) { + route_hops = route->lr_hops; + if (route_hops == LNET_UNDEFINED_HOPS) + route_hops = 1; + if (!shortest || + route_hops < shortest_hops) { shortest = route; + shortest_hops = route_hops; + } } - LASSERT(shortest != NULL); - hops = shortest->lr_hops; - if (srcnidp != NULL) + LASSERT(shortest); + hops = shortest_hops; + if (srcnidp) *srcnidp = shortest->lr_gateway->lp_ni->ni_nid; - if (orderp != NULL) + if (orderp) *orderp = order; lnet_net_unlock(cpt); return hops + 1; diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index 43977e8dffbb..f879d7f28708 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -74,7 +74,6 @@ lnet_build_msg_event(lnet_msg_t *msg, lnet_event_kind_t ev_type) ev->initiator.nid = LNET_NID_ANY; ev->initiator.pid = the_lnet.ln_pid; ev->sender = LNET_NID_ANY; - } else { /* event for passive message */ ev->target.pid = hdr->dest_pid; @@ -173,7 +172,7 @@ lnet_msg_decommit_tx(lnet_msg_t *msg, int status) lnet_event_t *ev = &msg->msg_ev; LASSERT(msg->msg_tx_committed); - if (status != 0) + if (status) goto out; counters = the_lnet.ln_counters[msg->msg_tx_cpt]; @@ -181,7 +180,7 @@ lnet_msg_decommit_tx(lnet_msg_t *msg, int status) default: /* routed message */ LASSERT(msg->msg_routing); LASSERT(msg->msg_rx_committed); - LASSERT(ev->type == 0); + LASSERT(!ev->type); counters->route_length += msg->msg_len; counters->route_count++; @@ -203,8 +202,10 @@ lnet_msg_decommit_tx(lnet_msg_t *msg, int status) case LNET_EVENT_GET: LASSERT(msg->msg_rx_committed); - /* overwritten while sending reply, we should never be - * here for optimized GET */ + /* + * overwritten while sending reply, we should never be + * here for optimized GET + */ LASSERT(msg->msg_type == LNET_MSG_REPLY); msg->msg_type = LNET_MSG_GET; /* fix type */ break; @@ -225,13 +226,13 @@ lnet_msg_decommit_rx(lnet_msg_t *msg, int status) LASSERT(!msg->msg_tx_committed); /* decommitted or never committed */ LASSERT(msg->msg_rx_committed); - if (status != 0) + if (status) goto out; counters = the_lnet.ln_counters[msg->msg_rx_cpt]; switch (ev->type) { default: - LASSERT(ev->type == 0); + LASSERT(!ev->type); LASSERT(msg->msg_routing); goto out; @@ -240,10 +241,12 @@ lnet_msg_decommit_rx(lnet_msg_t *msg, int status) break; case LNET_EVENT_GET: - /* type is "REPLY" if it's an optimized GET on passive side, + /* + * type is "REPLY" if it's an optimized GET on passive side, * because optimized GET will never be committed for sending, * so message type wouldn't be changed back to "GET" by - * lnet_msg_decommit_tx(), see details in lnet_parse_get() */ + * lnet_msg_decommit_tx(), see details in lnet_parse_get() + */ LASSERT(msg->msg_type == LNET_MSG_REPLY || msg->msg_type == LNET_MSG_GET); counters->send_length += msg->msg_wanted; @@ -254,8 +257,10 @@ lnet_msg_decommit_rx(lnet_msg_t *msg, int status) break; case LNET_EVENT_REPLY: - /* type is "GET" if it's an optimized GET on active side, - * see details in lnet_create_reply_msg() */ + /* + * type is "GET" if it's an optimized GET on active side, + * see details in lnet_create_reply_msg() + */ LASSERT(msg->msg_type == LNET_MSG_GET || msg->msg_type == LNET_MSG_REPLY); break; @@ -309,10 +314,12 @@ lnet_msg_attach_md(lnet_msg_t *msg, lnet_libmd_t *md, unsigned int offset, unsigned int mlen) { /* NB: @offset and @len are only useful for receiving */ - /* Here, we attach the MD on lnet_msg and mark it busy and + /* + * Here, we attach the MD on lnet_msg and mark it busy and * decrementing its threshold. Come what may, the lnet_msg "owns" * the MD until a call to lnet_msg_detach_md or lnet_finalize() - * signals completion. */ + * signals completion. + */ LASSERT(!msg->msg_routing); msg->msg_md = md; @@ -343,7 +350,7 @@ lnet_msg_detach_md(lnet_msg_t *msg, int status) LASSERT(md->md_refcount >= 0); unlink = lnet_md_unlinkable(md); - if (md->md_eq != NULL) { + if (md->md_eq) { msg->msg_ev.status = status; msg->msg_ev.unlinked = unlink; lnet_eq_enqueue_event(md->md_eq, &msg->msg_ev); @@ -364,7 +371,7 @@ lnet_complete_msg_locked(lnet_msg_t *msg, int cpt) LASSERT(msg->msg_onactivelist); - if (status == 0 && msg->msg_ack) { + if (!status && msg->msg_ack) { /* Only send an ACK if the PUT completed successfully */ lnet_msg_decommit(msg, cpt, 0); @@ -383,8 +390,10 @@ lnet_complete_msg_locked(lnet_msg_t *msg, int cpt) msg->msg_hdr.msg.ack.match_bits = msg->msg_ev.match_bits; msg->msg_hdr.msg.ack.mlength = cpu_to_le32(msg->msg_ev.mlength); - /* NB: we probably want to use NID of msg::msg_from as 3rd - * parameter (router NID) if it's routed message */ + /* + * NB: we probably want to use NID of msg::msg_from as 3rd + * parameter (router NID) if it's routed message + */ rc = lnet_send(msg->msg_ev.target.nid, msg, LNET_NID_ANY); lnet_net_lock(cpt); @@ -401,7 +410,7 @@ lnet_complete_msg_locked(lnet_msg_t *msg, int cpt) */ return rc; - } else if (status == 0 && /* OK so far */ + } else if (!status && /* OK so far */ (msg->msg_routing && !msg->msg_sending)) { /* not forwarded */ LASSERT(!msg->msg_receiving); /* called back recv already */ @@ -442,7 +451,7 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) LASSERT(!in_interrupt()); - if (msg == NULL) + if (!msg) return; #if 0 CDEBUG(D_WARNING, "%s msg->%s Flags:%s%s%s%s%s%s%s%s%s%s%s txp %s rxp %s\n", @@ -458,12 +467,12 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) msg->msg_rtrcredit ? "F" : "", msg->msg_peerrtrcredit ? "f" : "", msg->msg_onactivelist ? "!" : "", - msg->msg_txpeer == NULL ? "<none>" : libcfs_nid2str(msg->msg_txpeer->lp_nid), - msg->msg_rxpeer == NULL ? "<none>" : libcfs_nid2str(msg->msg_rxpeer->lp_nid)); + !msg->msg_txpeer ? "<none>" : libcfs_nid2str(msg->msg_txpeer->lp_nid), + !msg->msg_rxpeer ? "<none>" : libcfs_nid2str(msg->msg_rxpeer->lp_nid)); #endif msg->msg_ev.status = status; - if (msg->msg_md != NULL) { + if (msg->msg_md) { cpt = lnet_cpt_of_cookie(msg->msg_md->md_lh.lh_cookie); lnet_res_lock(cpt); @@ -491,15 +500,16 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) container = the_lnet.ln_msg_containers[cpt]; list_add_tail(&msg->msg_list, &container->msc_finalizing); - /* Recursion breaker. Don't complete the message here if I am (or - * enough other threads are) already completing messages */ - + /* + * Recursion breaker. Don't complete the message here if I am (or + * enough other threads are) already completing messages + */ my_slot = -1; for (i = 0; i < container->msc_nfinalizers; i++) { if (container->msc_finalizers[i] == current) break; - if (my_slot < 0 && container->msc_finalizers[i] == NULL) + if (my_slot < 0 && !container->msc_finalizers[i]) my_slot = i; } @@ -512,21 +522,29 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) while (!list_empty(&container->msc_finalizing)) { msg = list_entry(container->msc_finalizing.next, - lnet_msg_t, msg_list); + lnet_msg_t, msg_list); list_del(&msg->msg_list); - /* NB drops and regains the lnet lock if it actually does - * anything, so my finalizing friends can chomp along too */ + /* + * NB drops and regains the lnet lock if it actually does + * anything, so my finalizing friends can chomp along too + */ rc = lnet_complete_msg_locked(msg, cpt); - if (rc != 0) + if (rc) break; } + if (unlikely(!list_empty(&the_lnet.ln_delay_rules))) { + lnet_net_unlock(cpt); + lnet_delay_rule_check(); + lnet_net_lock(cpt); + } + container->msc_finalizers[my_slot] = NULL; lnet_net_unlock(cpt); - if (rc != 0) + if (rc) goto again; } EXPORT_SYMBOL(lnet_finalize); @@ -536,12 +554,12 @@ lnet_msg_container_cleanup(struct lnet_msg_container *container) { int count = 0; - if (container->msc_init == 0) + if (!container->msc_init) return; while (!list_empty(&container->msc_active)) { lnet_msg_t *msg = list_entry(container->msc_active.next, - lnet_msg_t, msg_activelist); + lnet_msg_t, msg_activelist); LASSERT(msg->msg_onactivelist); msg->msg_onactivelist = 0; @@ -553,41 +571,23 @@ lnet_msg_container_cleanup(struct lnet_msg_container *container) if (count > 0) CERROR("%d active msg on exit\n", count); - if (container->msc_finalizers != NULL) { + if (container->msc_finalizers) { LIBCFS_FREE(container->msc_finalizers, container->msc_nfinalizers * sizeof(*container->msc_finalizers)); container->msc_finalizers = NULL; } -#ifdef LNET_USE_LIB_FREELIST - lnet_freelist_fini(&container->msc_freelist); -#endif container->msc_init = 0; } int lnet_msg_container_setup(struct lnet_msg_container *container, int cpt) { - int rc; - container->msc_init = 1; INIT_LIST_HEAD(&container->msc_active); INIT_LIST_HEAD(&container->msc_finalizing); -#ifdef LNET_USE_LIB_FREELIST - memset(&container->msc_freelist, 0, sizeof(lnet_freelist_t)); - - rc = lnet_freelist_init(&container->msc_freelist, - LNET_FL_MAX_MSGS, sizeof(lnet_msg_t)); - if (rc != 0) { - CERROR("Failed to init freelist for message container\n"); - lnet_msg_container_cleanup(container); - return rc; - } -#else - rc = 0; -#endif /* number of CPUs */ container->msc_nfinalizers = cfs_cpt_weight(lnet_cpt_table(), cpt); @@ -595,13 +595,13 @@ lnet_msg_container_setup(struct lnet_msg_container *container, int cpt) container->msc_nfinalizers * sizeof(*container->msc_finalizers)); - if (container->msc_finalizers == NULL) { + if (!container->msc_finalizers) { CERROR("Failed to allocate message finalizers\n"); lnet_msg_container_cleanup(container); return -ENOMEM; } - return rc; + return 0; } void @@ -610,7 +610,7 @@ lnet_msg_containers_destroy(void) struct lnet_msg_container *container; int i; - if (the_lnet.ln_msg_containers == NULL) + if (!the_lnet.ln_msg_containers) return; cfs_percpt_for_each(container, i, the_lnet.ln_msg_containers) @@ -630,14 +630,14 @@ lnet_msg_containers_create(void) the_lnet.ln_msg_containers = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*container)); - if (the_lnet.ln_msg_containers == NULL) { + if (!the_lnet.ln_msg_containers) { CERROR("Failed to allocate cpu-partition data for network\n"); return -ENOMEM; } cfs_percpt_for_each(container, i, the_lnet.ln_msg_containers) { rc = lnet_msg_container_setup(container, i); - if (rc != 0) { + if (rc) { lnet_msg_containers_destroy(); return rc; } diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c index bd7b071b2873..3947e8b711c0 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c +++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c @@ -13,11 +13,6 @@ * General Public License version 2 for more details (a copy is included * in the LICENSE file that accompanied this code). * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA - * * GPL HEADER END */ /* @@ -50,7 +45,7 @@ lnet_ptl_match_type(unsigned int index, lnet_process_id_t match_id, struct lnet_portal *ptl = the_lnet.ln_portals[index]; int unique; - unique = ignore_bits == 0 && + unique = !ignore_bits && match_id.nid != LNET_NID_ANY && match_id.pid != LNET_PID_ANY; @@ -139,8 +134,10 @@ static int lnet_try_match_md(lnet_libmd_t *md, struct lnet_match_info *info, struct lnet_msg *msg) { - /* ALWAYS called holding the lnet_res_lock, and can't lnet_res_unlock; - * lnet_match_blocked_msg() relies on this to avoid races */ + /* + * ALWAYS called holding the lnet_res_lock, and can't lnet_res_unlock; + * lnet_match_blocked_msg() relies on this to avoid races + */ unsigned int offset; unsigned int mlength; lnet_me_t *me = md->md_me; @@ -150,7 +147,7 @@ lnet_try_match_md(lnet_libmd_t *md, return LNET_MATCHMD_NONE | LNET_MATCHMD_EXHAUSTED; /* mismatched MD op */ - if ((md->md_options & info->mi_opc) == 0) + if (!(md->md_options & info->mi_opc)) return LNET_MATCHMD_NONE; /* mismatched ME nid/pid? */ @@ -163,17 +160,17 @@ lnet_try_match_md(lnet_libmd_t *md, return LNET_MATCHMD_NONE; /* mismatched ME matchbits? */ - if (((me->me_match_bits ^ info->mi_mbits) & ~me->me_ignore_bits) != 0) + if ((me->me_match_bits ^ info->mi_mbits) & ~me->me_ignore_bits) return LNET_MATCHMD_NONE; /* Hurrah! This _is_ a match; check it out... */ - if ((md->md_options & LNET_MD_MANAGE_REMOTE) == 0) + if (!(md->md_options & LNET_MD_MANAGE_REMOTE)) offset = md->md_offset; else offset = info->mi_roffset; - if ((md->md_options & LNET_MD_MAX_SIZE) != 0) { + if (md->md_options & LNET_MD_MAX_SIZE) { mlength = md->md_max_size; LASSERT(md->md_offset + mlength <= md->md_length); } else { @@ -182,7 +179,7 @@ lnet_try_match_md(lnet_libmd_t *md, if (info->mi_rlength <= mlength) { /* fits in allowed space */ mlength = info->mi_rlength; - } else if ((md->md_options & LNET_MD_TRUNCATE) == 0) { + } else if (!(md->md_options & LNET_MD_TRUNCATE)) { /* this packet _really_ is too big */ CERROR("Matching packet from %s, match %llu length %d too big: %d left, %d allowed\n", libcfs_id2str(info->mi_id), info->mi_mbits, @@ -203,10 +200,12 @@ lnet_try_match_md(lnet_libmd_t *md, if (!lnet_md_exhausted(md)) return LNET_MATCHMD_OK; - /* Auto-unlink NOW, so the ME gets unlinked if required. + /* + * Auto-unlink NOW, so the ME gets unlinked if required. * We bumped md->md_refcount above so the MD just gets flagged - * for unlink when it is finalized. */ - if ((md->md_flags & LNET_MD_FLAG_AUTO_UNLINK) != 0) + * for unlink when it is finalized. + */ + if (md->md_flags & LNET_MD_FLAG_AUTO_UNLINK) lnet_md_unlink(md); return LNET_MATCHMD_OK | LNET_MATCHMD_EXHAUSTED; @@ -239,7 +238,7 @@ lnet_mt_of_attach(unsigned int index, lnet_process_id_t id, ptl = the_lnet.ln_portals[index]; mtable = lnet_match2mt(ptl, id, mbits); - if (mtable != NULL) /* unique portal or only one match-table */ + if (mtable) /* unique portal or only one match-table */ return mtable; /* it's a wildcard portal */ @@ -248,8 +247,10 @@ lnet_mt_of_attach(unsigned int index, lnet_process_id_t id, return NULL; case LNET_INS_BEFORE: case LNET_INS_AFTER: - /* posted by no affinity thread, always hash to specific - * match-table to avoid buffer stealing which is heavy */ + /* + * posted by no affinity thread, always hash to specific + * match-table to avoid buffer stealing which is heavy + */ return ptl->ptl_mtables[ptl->ptl_index % LNET_CPT_NUMBER]; case LNET_INS_LOCAL: /* posted by cpu-affinity thread */ @@ -274,7 +275,7 @@ lnet_mt_of_match(struct lnet_match_info *info, struct lnet_msg *msg) LASSERT(lnet_ptl_is_wildcard(ptl) || lnet_ptl_is_unique(ptl)); mtable = lnet_match2mt(ptl, info->mi_id, info->mi_mbits); - if (mtable != NULL) + if (mtable) return mtable; /* it's a wildcard portal */ @@ -298,10 +299,12 @@ lnet_mt_of_match(struct lnet_match_info *info, struct lnet_msg *msg) /* is there any active entry for this portal? */ nmaps = ptl->ptl_mt_nmaps; /* map to an active mtable to avoid heavy "stealing" */ - if (nmaps != 0) { - /* NB: there is possibility that ptl_mt_maps is being + if (nmaps) { + /* + * NB: there is possibility that ptl_mt_maps is being * changed because we are not under protection of - * lnet_ptl_lock, but it shouldn't hurt anything */ + * lnet_ptl_lock, but it shouldn't hurt anything + */ cpt = ptl->ptl_mt_maps[rotor % nmaps]; } } @@ -331,7 +334,7 @@ lnet_mt_test_exhausted(struct lnet_match_table *mtable, int pos) bmap = &mtable->mt_exhausted[pos >> LNET_MT_BITS_U64]; pos &= (1 << LNET_MT_BITS_U64) - 1; - return ((*bmap) & (1ULL << pos)) != 0; + return (*bmap & (1ULL << pos)); } static void @@ -357,16 +360,15 @@ lnet_mt_match_head(struct lnet_match_table *mtable, lnet_process_id_t id, __u64 mbits) { struct lnet_portal *ptl = the_lnet.ln_portals[mtable->mt_portal]; + unsigned long hash = mbits; - if (lnet_ptl_is_wildcard(ptl)) { - return &mtable->mt_mhash[mbits & LNET_MT_HASH_MASK]; - } else { - unsigned long hash = mbits + id.nid + id.pid; + if (!lnet_ptl_is_wildcard(ptl)) { + hash += id.nid + id.pid; LASSERT(lnet_ptl_is_unique(ptl)); hash = hash_long(hash, LNET_MT_HASH_BITS); - return &mtable->mt_mhash[hash]; } + return &mtable->mt_mhash[hash & LNET_MT_HASH_MASK]; } int @@ -391,18 +393,20 @@ lnet_mt_match_md(struct lnet_match_table *mtable, list_for_each_entry_safe(me, tmp, head, me_list) { /* ME attached but MD not attached yet */ - if (me->me_md == NULL) + if (!me->me_md) continue; LASSERT(me == me->me_md->md_me); rc = lnet_try_match_md(me->me_md, info, msg); - if ((rc & LNET_MATCHMD_EXHAUSTED) == 0) + if (!(rc & LNET_MATCHMD_EXHAUSTED)) exhausted = 0; /* mlist is not empty */ - if ((rc & LNET_MATCHMD_FINISH) != 0) { - /* don't return EXHAUSTED bit because we don't know - * whether the mlist is empty or not */ + if (rc & LNET_MATCHMD_FINISH) { + /* + * don't return EXHAUSTED bit because we don't know + * whether the mlist is empty or not + */ return rc & ~LNET_MATCHMD_EXHAUSTED; } } @@ -413,7 +417,7 @@ lnet_mt_match_md(struct lnet_match_table *mtable, exhausted = 0; } - if (exhausted == 0 && head == &mtable->mt_mhash[LNET_MT_HASH_IGNORE]) { + if (!exhausted && head == &mtable->mt_mhash[LNET_MT_HASH_IGNORE]) { head = lnet_mt_match_head(mtable, info->mi_id, info->mi_mbits); goto again; /* re-check MEs w/o ignore-bits */ } @@ -430,8 +434,10 @@ lnet_ptl_match_early(struct lnet_portal *ptl, struct lnet_msg *msg) { int rc; - /* message arrived before any buffer posting on this portal, - * simply delay or drop this message */ + /* + * message arrived before any buffer posting on this portal, + * simply delay or drop this message + */ if (likely(lnet_ptl_is_wildcard(ptl) || lnet_ptl_is_unique(ptl))) return 0; @@ -446,7 +452,7 @@ lnet_ptl_match_early(struct lnet_portal *ptl, struct lnet_msg *msg) if (msg->msg_rx_ready_delay) { msg->msg_rx_delayed = 1; list_add_tail(&msg->msg_list, - &ptl->ptl_msg_delayed); + &ptl->ptl_msg_delayed); } rc = LNET_MATCHMD_NONE; } else { @@ -465,9 +471,13 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, int rc = 0; int i; - /* steal buffer from other CPTs, and delay it if nothing to steal, - * this function is more expensive than a regular match, but we - * don't expect it can happen a lot */ + /** + * Steal buffer from other CPTs, and delay msg if nothing to + * steal. This function is more expensive than a regular + * match, but we don't expect it can happen a lot. The return + * code contains one of LNET_MATCHMD_OK, LNET_MATCHMD_DROP, or + * LNET_MATCHMD_NONE. + */ LASSERT(lnet_ptl_is_wildcard(ptl)); for (i = 0; i < LNET_CPT_NUMBER; i++) { @@ -476,56 +486,77 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, cpt = (first + i) % LNET_CPT_NUMBER; mtable = ptl->ptl_mtables[cpt]; - if (i != 0 && i != LNET_CPT_NUMBER - 1 && !mtable->mt_enabled) + if (i && i != LNET_CPT_NUMBER - 1 && !mtable->mt_enabled) continue; lnet_res_lock(cpt); lnet_ptl_lock(ptl); - if (i == 0) { /* the first try, attach on stealing list */ + if (!i) { + /* The first try, add to stealing list. */ list_add_tail(&msg->msg_list, - &ptl->ptl_msg_stealing); + &ptl->ptl_msg_stealing); } - if (!list_empty(&msg->msg_list)) { /* on stealing list */ + if (!list_empty(&msg->msg_list)) { + /* On stealing list. */ rc = lnet_mt_match_md(mtable, info, msg); - if ((rc & LNET_MATCHMD_EXHAUSTED) != 0 && + if ((rc & LNET_MATCHMD_EXHAUSTED) && mtable->mt_enabled) lnet_ptl_disable_mt(ptl, cpt); - if ((rc & LNET_MATCHMD_FINISH) != 0) + if (rc & LNET_MATCHMD_FINISH) { + /* Match found, remove from stealing list. */ + list_del_init(&msg->msg_list); + } else if (i == LNET_CPT_NUMBER - 1 || /* (1) */ + !ptl->ptl_mt_nmaps || /* (2) */ + (ptl->ptl_mt_nmaps == 1 && /* (3) */ + ptl->ptl_mt_maps[0] == cpt)) { + /** + * No match found, and this is either + * (1) the last cpt to check, or + * (2) there is no active cpt, or + * (3) this is the only active cpt. + * There is nothing to steal: delay or + * drop the message. + */ list_del_init(&msg->msg_list); - } else { - /* could be matched by lnet_ptl_attach_md() - * which is called by another thread */ - rc = msg->msg_md == NULL ? - LNET_MATCHMD_DROP : LNET_MATCHMD_OK; - } - - if (!list_empty(&msg->msg_list) && /* not matched yet */ - (i == LNET_CPT_NUMBER - 1 || /* the last CPT */ - ptl->ptl_mt_nmaps == 0 || /* no active CPT */ - (ptl->ptl_mt_nmaps == 1 && /* the only active CPT */ - ptl->ptl_mt_maps[0] == cpt))) { - /* nothing to steal, delay or drop */ - list_del_init(&msg->msg_list); - - if (lnet_ptl_is_lazy(ptl)) { - msg->msg_rx_delayed = 1; - list_add_tail(&msg->msg_list, - &ptl->ptl_msg_delayed); - rc = LNET_MATCHMD_NONE; + if (lnet_ptl_is_lazy(ptl)) { + msg->msg_rx_delayed = 1; + list_add_tail(&msg->msg_list, + &ptl->ptl_msg_delayed); + rc = LNET_MATCHMD_NONE; + } else { + rc = LNET_MATCHMD_DROP; + } } else { - rc = LNET_MATCHMD_DROP; + /* Do another iteration. */ + rc = 0; } + } else { + /** + * No longer on stealing list: another thread + * matched the message in lnet_ptl_attach_md(). + * We are now expected to handle the message. + */ + rc = !msg->msg_md ? + LNET_MATCHMD_DROP : LNET_MATCHMD_OK; } lnet_ptl_unlock(ptl); lnet_res_unlock(cpt); - if ((rc & LNET_MATCHMD_FINISH) != 0 || msg->msg_rx_delayed) + /** + * Note that test (1) above ensures that we always + * exit the loop through this break statement. + * + * LNET_MATCHMD_NONE means msg was added to the + * delayed queue, and we may no longer reference it + * after lnet_ptl_unlock() and lnet_res_unlock(). + */ + if (rc & (LNET_MATCHMD_FINISH | LNET_MATCHMD_NONE)) break; } @@ -551,7 +582,7 @@ lnet_ptl_match_md(struct lnet_match_info *info, struct lnet_msg *msg) ptl = the_lnet.ln_portals[info->mi_portal]; rc = lnet_ptl_match_early(ptl, msg); - if (rc != 0) /* matched or delayed early message */ + if (rc) /* matched or delayed early message */ return rc; mtable = lnet_mt_of_match(info, msg); @@ -563,13 +594,13 @@ lnet_ptl_match_md(struct lnet_match_info *info, struct lnet_msg *msg) } rc = lnet_mt_match_md(mtable, info, msg); - if ((rc & LNET_MATCHMD_EXHAUSTED) != 0 && mtable->mt_enabled) { + if ((rc & LNET_MATCHMD_EXHAUSTED) && mtable->mt_enabled) { lnet_ptl_lock(ptl); lnet_ptl_disable_mt(ptl, mtable->mt_cpt); lnet_ptl_unlock(ptl); } - if ((rc & LNET_MATCHMD_FINISH) != 0) /* matched or dropping */ + if (rc & LNET_MATCHMD_FINISH) /* matched or dropping */ goto out1; if (!msg->msg_rx_ready_delay) @@ -587,13 +618,14 @@ lnet_ptl_match_md(struct lnet_match_info *info, struct lnet_msg *msg) lnet_ptl_unlock(ptl); lnet_res_unlock(mtable->mt_cpt); - + rc = LNET_MATCHMD_NONE; } else { lnet_res_unlock(mtable->mt_cpt); rc = lnet_ptl_match_delay(ptl, info, msg); } - if (msg->msg_rx_delayed) { + /* LNET_MATCHMD_NONE means msg was added to the delay queue */ + if (rc & LNET_MATCHMD_NONE) { CDEBUG(D_NET, "Delaying %s from %s ptl %d MB %#llx off %d len %d\n", info->mi_opc == LNET_MD_OP_PUT ? "PUT" : "GET", @@ -630,7 +662,7 @@ lnet_ptl_attach_md(lnet_me_t *me, lnet_libmd_t *md, int exhausted = 0; int cpt; - LASSERT(md->md_refcount == 0); /* a brand new MD */ + LASSERT(!md->md_refcount); /* a brand new MD */ me->me_md = md; md->md_me = me; @@ -664,15 +696,15 @@ lnet_ptl_attach_md(lnet_me_t *me, lnet_libmd_t *md, rc = lnet_try_match_md(md, &info, msg); - exhausted = (rc & LNET_MATCHMD_EXHAUSTED) != 0; - if ((rc & LNET_MATCHMD_NONE) != 0) { + exhausted = (rc & LNET_MATCHMD_EXHAUSTED); + if (rc & LNET_MATCHMD_NONE) { if (exhausted) break; continue; } /* Hurrah! This _is_ a match */ - LASSERT((rc & LNET_MATCHMD_FINISH) != 0); + LASSERT(rc & LNET_MATCHMD_FINISH); list_del_init(&msg->msg_list); if (head == &ptl->ptl_msg_stealing) { @@ -682,7 +714,7 @@ lnet_ptl_attach_md(lnet_me_t *me, lnet_libmd_t *md, continue; } - if ((rc & LNET_MATCHMD_OK) != 0) { + if (rc & LNET_MATCHMD_OK) { list_add_tail(&msg->msg_list, matches); CDEBUG(D_NET, "Resuming delayed PUT from %s portal %d match %llu offset %d length %d.\n", @@ -717,7 +749,7 @@ lnet_ptl_cleanup(struct lnet_portal *ptl) struct lnet_match_table *mtable; int i; - if (ptl->ptl_mtables == NULL) /* uninitialized portal */ + if (!ptl->ptl_mtables) /* uninitialized portal */ return; LASSERT(list_empty(&ptl->ptl_msg_delayed)); @@ -727,7 +759,7 @@ lnet_ptl_cleanup(struct lnet_portal *ptl) lnet_me_t *me; int j; - if (mtable->mt_mhash == NULL) /* uninitialized match-table */ + if (!mtable->mt_mhash) /* uninitialized match-table */ continue; mhash = mtable->mt_mhash; @@ -735,7 +767,7 @@ lnet_ptl_cleanup(struct lnet_portal *ptl) for (j = 0; j < LNET_MT_HASH_SIZE + 1; j++) { while (!list_empty(&mhash[j])) { me = list_entry(mhash[j].next, - lnet_me_t, me_list); + lnet_me_t, me_list); CERROR("Active ME %p on exit\n", me); list_del(&me->me_list); lnet_me_free(me); @@ -759,7 +791,7 @@ lnet_ptl_setup(struct lnet_portal *ptl, int index) ptl->ptl_mtables = cfs_percpt_alloc(lnet_cpt_table(), sizeof(struct lnet_match_table)); - if (ptl->ptl_mtables == NULL) { + if (!ptl->ptl_mtables) { CERROR("Failed to create match table for portal %d\n", index); return -ENOMEM; } @@ -772,7 +804,7 @@ lnet_ptl_setup(struct lnet_portal *ptl, int index) /* the extra entry is for MEs with ignore bits */ LIBCFS_CPT_ALLOC(mhash, lnet_cpt_table(), i, sizeof(*mhash) * (LNET_MT_HASH_SIZE + 1)); - if (mhash == NULL) { + if (!mhash) { CERROR("Failed to create match hash for portal %d\n", index); goto failed; @@ -800,7 +832,7 @@ lnet_portals_destroy(void) { int i; - if (the_lnet.ln_portals == NULL) + if (!the_lnet.ln_portals) return; for (i = 0; i < the_lnet.ln_nportals; i++) @@ -820,7 +852,7 @@ lnet_portals_create(void) the_lnet.ln_nportals = MAX_PORTALS; the_lnet.ln_portals = cfs_array_alloc(the_lnet.ln_nportals, size); - if (the_lnet.ln_portals == NULL) { + if (!the_lnet.ln_portals) { CERROR("Failed to allocate portals table\n"); return -ENOMEM; } @@ -886,17 +918,8 @@ LNetSetLazyPortal(int portal) } EXPORT_SYMBOL(LNetSetLazyPortal); -/** - * Turn off the lazy portal attribute. Delayed requests on the portal, - * if any, will be all dropped when this function returns. - * - * \param portal Index of the portal to disable the lazy attribute on. - * - * \retval 0 On success. - * \retval -EINVAL If \a portal is not a valid index. - */ int -LNetClearLazyPortal(int portal) +lnet_clear_lazy_portal(struct lnet_ni *ni, int portal, char *reason) { struct lnet_portal *ptl; LIST_HEAD(zombies); @@ -915,21 +938,48 @@ LNetClearLazyPortal(int portal) return 0; } - if (the_lnet.ln_shutdown) - CWARN("Active lazy portal %d on exit\n", portal); - else - CDEBUG(D_NET, "clearing portal %d lazy\n", portal); + if (ni) { + struct lnet_msg *msg, *tmp; + + /* grab all messages which are on the NI passed in */ + list_for_each_entry_safe(msg, tmp, &ptl->ptl_msg_delayed, + msg_list) { + if (msg->msg_rxpeer->lp_ni == ni) + list_move(&msg->msg_list, &zombies); + } + } else { + if (the_lnet.ln_shutdown) + CWARN("Active lazy portal %d on exit\n", portal); + else + CDEBUG(D_NET, "clearing portal %d lazy\n", portal); - /* grab all the blocked messages atomically */ - list_splice_init(&ptl->ptl_msg_delayed, &zombies); + /* grab all the blocked messages atomically */ + list_splice_init(&ptl->ptl_msg_delayed, &zombies); - lnet_ptl_unsetopt(ptl, LNET_PTL_LAZY); + lnet_ptl_unsetopt(ptl, LNET_PTL_LAZY); + } lnet_ptl_unlock(ptl); lnet_res_unlock(LNET_LOCK_EX); - lnet_drop_delayed_msg_list(&zombies, "Clearing lazy portal attr"); + lnet_drop_delayed_msg_list(&zombies, reason); return 0; } + +/** + * Turn off the lazy portal attribute. Delayed requests on the portal, + * if any, will be all dropped when this function returns. + * + * \param portal Index of the portal to disable the lazy attribute on. + * + * \retval 0 On success. + * \retval -EINVAL If \a portal is not a valid index. + */ +int +LNetClearLazyPortal(int portal) +{ + return lnet_clear_lazy_portal(NULL, portal, + "Clearing lazy portal attr"); +} EXPORT_SYMBOL(LNetClearLazyPortal); diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c index 589ecc84d1b8..cc0c2753dd63 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-socket.c +++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c @@ -64,7 +64,7 @@ lnet_sock_ioctl(int cmd, unsigned long arg) int rc; rc = sock_create(PF_INET, SOCK_STREAM, 0, &sock); - if (rc != 0) { + if (rc) { CERROR("Can't create socket: %d\n", rc); return rc; } @@ -99,14 +99,17 @@ lnet_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask) CLASSERT(sizeof(ifr.ifr_name) >= IFNAMSIZ); - strcpy(ifr.ifr_name, name); + if (strlen(name) > sizeof(ifr.ifr_name) - 1) + return -E2BIG; + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + rc = lnet_sock_ioctl(SIOCGIFFLAGS, (unsigned long)&ifr); - if (rc != 0) { + if (rc) { CERROR("Can't get flags for interface %s\n", name); return rc; } - if ((ifr.ifr_flags & IFF_UP) == 0) { + if (!(ifr.ifr_flags & IFF_UP)) { CDEBUG(D_NET, "Interface %s down\n", name); *up = 0; *ip = *mask = 0; @@ -114,10 +117,13 @@ lnet_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask) } *up = 1; - strcpy(ifr.ifr_name, name); + if (strlen(name) > sizeof(ifr.ifr_name) - 1) + return -E2BIG; + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_addr.sa_family = AF_INET; rc = lnet_sock_ioctl(SIOCGIFADDR, (unsigned long)&ifr); - if (rc != 0) { + if (rc) { CERROR("Can't get IP address for interface %s\n", name); return rc; } @@ -125,10 +131,13 @@ lnet_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask) val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; *ip = ntohl(val); - strcpy(ifr.ifr_name, name); + if (strlen(name) > sizeof(ifr.ifr_name) - 1) + return -E2BIG; + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_addr.sa_family = AF_INET; rc = lnet_sock_ioctl(SIOCGIFNETMASK, (unsigned long)&ifr); - if (rc != 0) { + if (rc) { CERROR("Can't get netmask for interface %s\n", name); return rc; } @@ -159,13 +168,13 @@ lnet_ipif_enumerate(char ***namesp) for (;;) { if (nalloc * sizeof(*ifr) > PAGE_CACHE_SIZE) { toobig = 1; - nalloc = PAGE_CACHE_SIZE/sizeof(*ifr); + nalloc = PAGE_CACHE_SIZE / sizeof(*ifr); CWARN("Too many interfaces: only enumerating first %d\n", nalloc); } LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr)); - if (ifr == NULL) { + if (!ifr) { CERROR("ENOMEM enumerating up to %d interfaces\n", nalloc); rc = -ENOMEM; @@ -181,9 +190,9 @@ lnet_ipif_enumerate(char ***namesp) goto out1; } - LASSERT(rc == 0); + LASSERT(!rc); - nfound = ifc.ifc_len/sizeof(*ifr); + nfound = ifc.ifc_len / sizeof(*ifr); LASSERT(nfound <= nalloc); if (nfound < nalloc || toobig) @@ -193,11 +202,11 @@ lnet_ipif_enumerate(char ***namesp) nalloc *= 2; } - if (nfound == 0) + if (!nfound) goto out1; LIBCFS_ALLOC(names, nfound * sizeof(*names)); - if (names == NULL) { + if (!names) { rc = -ENOMEM; goto out1; } @@ -213,7 +222,7 @@ lnet_ipif_enumerate(char ***namesp) } LIBCFS_ALLOC(names[i], IFNAMSIZ); - if (names[i] == NULL) { + if (!names[i]) { rc = -ENOMEM; goto out2; } @@ -242,7 +251,7 @@ lnet_ipif_free_enumeration(char **names, int n) LASSERT(n > 0); - for (i = 0; i < n && names[i] != NULL; i++) + for (i = 0; i < n && names[i]; i++) LIBCFS_FREE(names[i], IFNAMSIZ); LIBCFS_FREE(names, n * sizeof(*names)); @@ -253,32 +262,30 @@ int lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) { int rc; - long ticks = timeout * HZ; + long jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC); unsigned long then; struct timeval tv; LASSERT(nob > 0); - /* Caller may pass a zero timeout if she thinks the socket buffer is - * empty enough to take the whole message immediately */ - + /* + * Caller may pass a zero timeout if she thinks the socket buffer is + * empty enough to take the whole message immediately + */ for (;;) { struct kvec iov = { .iov_base = buffer, .iov_len = nob }; struct msghdr msg = { - .msg_flags = (timeout == 0) ? MSG_DONTWAIT : 0 + .msg_flags = !timeout ? MSG_DONTWAIT : 0 }; - if (timeout != 0) { + if (timeout) { /* Set send timeout to remaining time */ - tv = (struct timeval) { - .tv_sec = ticks / HZ, - .tv_usec = ((ticks % HZ) * 1000000) / HZ - }; + jiffies_to_timeval(jiffies_left, &tv); rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); - if (rc != 0) { + if (rc) { CERROR("Can't set socket send timeout %ld.%06d: %d\n", (long)tv.tv_sec, (int)tv.tv_usec, rc); return rc; @@ -287,7 +294,7 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) then = jiffies; rc = kernel_sendmsg(sock, &msg, &iov, 1, nob); - ticks -= jiffies - then; + jiffies_left -= jiffies - then; if (rc == nob) return 0; @@ -295,12 +302,12 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) if (rc < 0) return rc; - if (rc == 0) { + if (!rc) { CERROR("Unexpected zero rc\n"); return -ECONNABORTED; } - if (ticks <= 0) + if (jiffies_left <= 0) return -EAGAIN; buffer = ((char *)buffer) + rc; @@ -314,12 +321,12 @@ int lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout) { int rc; - long ticks = timeout * HZ; + long jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC); unsigned long then; struct timeval tv; LASSERT(nob > 0); - LASSERT(ticks > 0); + LASSERT(jiffies_left > 0); for (;;) { struct kvec iov = { @@ -331,13 +338,10 @@ lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout) }; /* Set receive timeout to remaining time */ - tv = (struct timeval) { - .tv_sec = ticks / HZ, - .tv_usec = ((ticks % HZ) * 1000000) / HZ - }; + jiffies_to_timeval(jiffies_left, &tv); rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); - if (rc != 0) { + if (rc) { CERROR("Can't set socket recv timeout %ld.%06d: %d\n", (long)tv.tv_sec, (int)tv.tv_usec, rc); return rc; @@ -345,21 +349,21 @@ lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout) then = jiffies; rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0); - ticks -= jiffies - then; + jiffies_left -= jiffies - then; if (rc < 0) return rc; - if (rc == 0) + if (!rc) return -ECONNRESET; buffer = ((char *)buffer) + rc; nob -= rc; - if (nob == 0) + if (!nob) return 0; - if (ticks <= 0) + if (jiffies_left <= 0) return -ETIMEDOUT; } } @@ -379,7 +383,7 @@ lnet_sock_create(struct socket **sockp, int *fatal, __u32 local_ip, rc = sock_create(PF_INET, SOCK_STREAM, 0, &sock); *sockp = sock; - if (rc != 0) { + if (rc) { CERROR("Can't create socket: %d\n", rc); return rc; } @@ -387,16 +391,16 @@ lnet_sock_create(struct socket **sockp, int *fatal, __u32 local_ip, option = 1; rc = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option)); - if (rc != 0) { + if (rc) { CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc); goto failed; } - if (local_ip != 0 || local_port != 0) { + if (local_ip || local_port) { memset(&locaddr, 0, sizeof(locaddr)); locaddr.sin_family = AF_INET; locaddr.sin_port = htons(local_port); - locaddr.sin_addr.s_addr = (local_ip == 0) ? + locaddr.sin_addr.s_addr = !local_ip ? INADDR_ANY : htonl(local_ip); rc = kernel_bind(sock, (struct sockaddr *)&locaddr, @@ -406,7 +410,7 @@ lnet_sock_create(struct socket **sockp, int *fatal, __u32 local_ip, *fatal = 0; goto failed; } - if (rc != 0) { + if (rc) { CERROR("Error trying to bind to port %d: %d\n", local_port, rc); goto failed; @@ -425,22 +429,22 @@ lnet_sock_setbuf(struct socket *sock, int txbufsize, int rxbufsize) int option; int rc; - if (txbufsize != 0) { + if (txbufsize) { option = txbufsize; rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&option, sizeof(option)); - if (rc != 0) { + if (rc) { CERROR("Can't set send buffer %d: %d\n", option, rc); return rc; } } - if (rxbufsize != 0) { + if (rxbufsize) { option = rxbufsize; rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, - (char *)&option, sizeof(option)); - if (rc != 0) { + (char *)&option, sizeof(option)); + if (rc) { CERROR("Can't set receive buffer %d: %d\n", option, rc); return rc; @@ -461,16 +465,16 @@ lnet_sock_getaddr(struct socket *sock, bool remote, __u32 *ip, int *port) rc = kernel_getpeername(sock, (struct sockaddr *)&sin, &len); else rc = kernel_getsockname(sock, (struct sockaddr *)&sin, &len); - if (rc != 0) { + if (rc) { CERROR("Error %d getting sock %s IP/port\n", rc, remote ? "peer" : "local"); return rc; } - if (ip != NULL) + if (ip) *ip = ntohl(sin.sin_addr.s_addr); - if (port != NULL) + if (port) *port = ntohs(sin.sin_port); return 0; @@ -480,10 +484,10 @@ EXPORT_SYMBOL(lnet_sock_getaddr); int lnet_sock_getbuf(struct socket *sock, int *txbufsize, int *rxbufsize) { - if (txbufsize != NULL) + if (txbufsize) *txbufsize = sock->sk->sk_sndbuf; - if (rxbufsize != NULL) + if (rxbufsize) *rxbufsize = sock->sk->sk_rcvbuf; return 0; @@ -498,7 +502,7 @@ lnet_sock_listen(struct socket **sockp, __u32 local_ip, int local_port, int rc; rc = lnet_sock_create(sockp, &fatal, local_ip, local_port); - if (rc != 0) { + if (rc) { if (!fatal) CERROR("Can't create socket: port %d already in use\n", local_port); @@ -506,14 +510,13 @@ lnet_sock_listen(struct socket **sockp, __u32 local_ip, int local_port, } rc = kernel_listen(*sockp, backlog); - if (rc == 0) + if (!rc) return 0; CERROR("Can't set listen backlog %d: %d\n", backlog, rc); sock_release(*sockp); return rc; } -EXPORT_SYMBOL(lnet_sock_listen); int lnet_sock_accept(struct socket **newsockp, struct socket *sock) @@ -522,10 +525,10 @@ lnet_sock_accept(struct socket **newsockp, struct socket *sock) struct socket *newsock; int rc; - init_waitqueue_entry(&wait, current); - - /* XXX this should add a ref to sock->ops->owner, if - * TCP could be a module */ + /* + * XXX this should add a ref to sock->ops->owner, if + * TCP could be a module + */ rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock); if (rc) { CERROR("Can't allocate socket\n"); @@ -537,15 +540,15 @@ lnet_sock_accept(struct socket **newsockp, struct socket *sock) rc = sock->ops->accept(sock, newsock, O_NONBLOCK); if (rc == -EAGAIN) { /* Nothing ready, so wait for activity */ - set_current_state(TASK_INTERRUPTIBLE); + init_waitqueue_entry(&wait, current); add_wait_queue(sk_sleep(sock->sk), &wait); + set_current_state(TASK_INTERRUPTIBLE); schedule(); remove_wait_queue(sk_sleep(sock->sk), &wait); - set_current_state(TASK_RUNNING); rc = sock->ops->accept(sock, newsock, O_NONBLOCK); } - if (rc != 0) + if (rc) goto failed; *newsockp = newsock; @@ -555,7 +558,6 @@ failed: sock_release(newsock); return rc; } -EXPORT_SYMBOL(lnet_sock_accept); int lnet_sock_connect(struct socket **sockp, int *fatal, __u32 local_ip, @@ -565,7 +567,7 @@ lnet_sock_connect(struct socket **sockp, int *fatal, __u32 local_ip, int rc; rc = lnet_sock_create(sockp, fatal, local_ip, local_port); - if (rc != 0) + if (rc) return rc; memset(&srvaddr, 0, sizeof(srvaddr)); @@ -575,13 +577,15 @@ lnet_sock_connect(struct socket **sockp, int *fatal, __u32 local_ip, rc = kernel_connect(*sockp, (struct sockaddr *)&srvaddr, sizeof(srvaddr), 0); - if (rc == 0) + if (!rc) return 0; - /* EADDRNOTAVAIL probably means we're already connected to the same + /* + * EADDRNOTAVAIL probably means we're already connected to the same * peer/port on the same local port on a differently typed * connection. Let our caller retry with a different local - * port... */ + * port... + */ *fatal = !(rc == -EADDRNOTAVAIL); CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET, @@ -591,4 +595,3 @@ lnet_sock_connect(struct socket **sockp, int *fatal, __u32 local_ip, sock_release(*sockp); return rc; } -EXPORT_SYMBOL(lnet_sock_connect); diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c index 2a137f46800f..468eda611bf8 100644 --- a/drivers/staging/lustre/lnet/lnet/lo.c +++ b/drivers/staging/lustre/lnet/lnet/lo.c @@ -46,15 +46,15 @@ lolnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) static int lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, - int delayed, unsigned int niov, - struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) + int delayed, unsigned int niov, + struct kvec *iov, lnet_kiov_t *kiov, + unsigned int offset, unsigned int mlen, unsigned int rlen) { lnet_msg_t *sendmsg = private; - if (lntmsg != NULL) { /* not discarding */ - if (sendmsg->msg_iov != NULL) { - if (iov != NULL) + if (lntmsg) { /* not discarding */ + if (sendmsg->msg_iov) { + if (iov) lnet_copy_iov2iov(niov, iov, offset, sendmsg->msg_niov, sendmsg->msg_iov, @@ -65,7 +65,7 @@ lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, sendmsg->msg_iov, sendmsg->msg_offset, mlen); } else { - if (iov != NULL) + if (iov) lnet_copy_kiov2iov(niov, iov, offset, sendmsg->msg_niov, sendmsg->msg_kiov, diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c index c93c00752a4c..93037c1168ca 100644 --- a/drivers/staging/lustre/lnet/lnet/module.c +++ b/drivers/staging/lustre/lnet/lnet/module.c @@ -36,6 +36,7 @@ #define DEBUG_SUBSYSTEM S_LNET #include "../../include/linux/lnet/lib-lnet.h" +#include "../../include/linux/lnet/lib-dlc.h" static int config_on_load; module_param(config_on_load, int, 0444); @@ -52,13 +53,21 @@ lnet_configure(void *arg) mutex_lock(&lnet_config_mutex); if (!the_lnet.ln_niinit_self) { - rc = LNetNIInit(LUSTRE_SRV_LNET_PID); + rc = try_module_get(THIS_MODULE); + + if (rc != 1) + goto out; + + rc = LNetNIInit(LNET_PID_LUSTRE); if (rc >= 0) { the_lnet.ln_niinit_self = 1; rc = 0; + } else { + module_put(THIS_MODULE); } } +out: mutex_unlock(&lnet_config_mutex); return rc; } @@ -73,6 +82,7 @@ lnet_unconfigure(void) if (the_lnet.ln_niinit_self) { the_lnet.ln_niinit_self = 0; LNetNIFini(); + module_put(THIS_MODULE); } mutex_lock(&the_lnet.ln_api_mutex); @@ -80,28 +90,93 @@ lnet_unconfigure(void) mutex_unlock(&the_lnet.ln_api_mutex); mutex_unlock(&lnet_config_mutex); - return (refcount == 0) ? 0 : -EBUSY; + return !refcount ? 0 : -EBUSY; } static int -lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_data *data) +lnet_dyn_configure(struct libcfs_ioctl_hdr *hdr) +{ + struct lnet_ioctl_config_data *conf = + (struct lnet_ioctl_config_data *)hdr; + int rc; + + if (conf->cfg_hdr.ioc_len < sizeof(*conf)) + return -EINVAL; + + mutex_lock(&lnet_config_mutex); + if (!the_lnet.ln_niinit_self) { + rc = -EINVAL; + goto out_unlock; + } + rc = lnet_dyn_add_ni(LNET_PID_LUSTRE, + conf->cfg_config_u.cfg_net.net_intf, + conf->cfg_config_u.cfg_net.net_peer_timeout, + conf->cfg_config_u.cfg_net.net_peer_tx_credits, + conf->cfg_config_u.cfg_net.net_peer_rtr_credits, + conf->cfg_config_u.cfg_net.net_max_tx_credits); +out_unlock: + mutex_unlock(&lnet_config_mutex); + + return rc; +} + +static int +lnet_dyn_unconfigure(struct libcfs_ioctl_hdr *hdr) +{ + struct lnet_ioctl_config_data *conf = + (struct lnet_ioctl_config_data *)hdr; + int rc; + + if (conf->cfg_hdr.ioc_len < sizeof(*conf)) + return -EINVAL; + + mutex_lock(&lnet_config_mutex); + if (!the_lnet.ln_niinit_self) { + rc = -EINVAL; + goto out_unlock; + } + rc = lnet_dyn_del_ni(conf->cfg_net); +out_unlock: + mutex_unlock(&lnet_config_mutex); + + return rc; +} + +static int +lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_hdr *hdr) { int rc; switch (cmd) { - case IOC_LIBCFS_CONFIGURE: + case IOC_LIBCFS_CONFIGURE: { + struct libcfs_ioctl_data *data = + (struct libcfs_ioctl_data *)hdr; + + if (data->ioc_hdr.ioc_len < sizeof(*data)) + return -EINVAL; + + the_lnet.ln_nis_from_mod_params = data->ioc_flags; return lnet_configure(NULL); + } case IOC_LIBCFS_UNCONFIGURE: return lnet_unconfigure(); + case IOC_LIBCFS_ADD_NET: + return lnet_dyn_configure(hdr); + + case IOC_LIBCFS_DEL_NET: + return lnet_dyn_unconfigure(hdr); + default: - /* Passing LNET_PID_ANY only gives me a ref if the net is up + /* + * Passing LNET_PID_ANY only gives me a ref if the net is up * already; I'll need it to ensure the net can't go down while - * I'm called into it */ + * I'm called into it + */ rc = LNetNIInit(LNET_PID_ANY); if (rc >= 0) { - rc = LNetCtl(cmd, data); + rc = LNetCtl(cmd, hdr); LNetNIFini(); } return rc; @@ -110,46 +185,46 @@ lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_data *data) static DECLARE_IOCTL_HANDLER(lnet_ioctl_handler, lnet_ioctl); -static int __init -init_lnet(void) +static int __init lnet_init(void) { int rc; mutex_init(&lnet_config_mutex); - rc = lnet_init(); - if (rc != 0) { - CERROR("lnet_init: error %d\n", rc); + rc = lnet_lib_init(); + if (rc) { + CERROR("lnet_lib_init: error %d\n", rc); return rc; } rc = libcfs_register_ioctl(&lnet_ioctl_handler); - LASSERT(rc == 0); + LASSERT(!rc); if (config_on_load) { - /* Have to schedule a separate thread to avoid deadlocking - * in modload */ + /* + * Have to schedule a separate thread to avoid deadlocking + * in modload + */ (void) kthread_run(lnet_configure, NULL, "lnet_initd"); } return 0; } -static void __exit -fini_lnet(void) +static void __exit lnet_exit(void) { int rc; rc = libcfs_deregister_ioctl(&lnet_ioctl_handler); - LASSERT(rc == 0); + LASSERT(!rc); - lnet_fini(); + lnet_lib_exit(); } MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>"); -MODULE_DESCRIPTION("LNet v3.1"); +MODULE_DESCRIPTION("Lustre Networking layer"); +MODULE_VERSION(LNET_VERSION); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.0.0"); -module_init(init_lnet); -module_exit(fini_lnet); +module_init(lnet_init); +module_exit(lnet_exit); diff --git a/drivers/staging/lustre/lnet/lnet/net_fault.c b/drivers/staging/lustre/lnet/lnet/net_fault.c new file mode 100644 index 000000000000..7d76f28d3a7a --- /dev/null +++ b/drivers/staging/lustre/lnet/lnet/net_fault.c @@ -0,0 +1,1025 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2014, Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Seagate, Inc. + * + * lnet/lnet/net_fault.c + * + * Lustre network fault simulation + * + * Author: liang.zhen@intel.com + */ + +#define DEBUG_SUBSYSTEM S_LNET + +#include "../../include/linux/lnet/lib-lnet.h" +#include "../../include/linux/lnet/lnetctl.h" + +#define LNET_MSG_MASK (LNET_PUT_BIT | LNET_ACK_BIT | \ + LNET_GET_BIT | LNET_REPLY_BIT) + +struct lnet_drop_rule { + /** link chain on the_lnet.ln_drop_rules */ + struct list_head dr_link; + /** attributes of this rule */ + struct lnet_fault_attr dr_attr; + /** lock to protect \a dr_drop_at and \a dr_stat */ + spinlock_t dr_lock; + /** + * the message sequence to drop, which means message is dropped when + * dr_stat.drs_count == dr_drop_at + */ + unsigned long dr_drop_at; + /** + * seconds to drop the next message, it's exclusive with dr_drop_at + */ + unsigned long dr_drop_time; + /** baseline to caculate dr_drop_time */ + unsigned long dr_time_base; + /** statistic of dropped messages */ + struct lnet_fault_stat dr_stat; +}; + +static bool +lnet_fault_nid_match(lnet_nid_t nid, lnet_nid_t msg_nid) +{ + if (nid == msg_nid || nid == LNET_NID_ANY) + return true; + + if (LNET_NIDNET(nid) != LNET_NIDNET(msg_nid)) + return false; + + /* 255.255.255.255@net is wildcard for all addresses in a network */ + return LNET_NIDADDR(nid) == LNET_NIDADDR(LNET_NID_ANY); +} + +static bool +lnet_fault_attr_match(struct lnet_fault_attr *attr, lnet_nid_t src, + lnet_nid_t dst, unsigned int type, unsigned int portal) +{ + if (!lnet_fault_nid_match(attr->fa_src, src) || + !lnet_fault_nid_match(attr->fa_dst, dst)) + return false; + + if (!(attr->fa_msg_mask & (1 << type))) + return false; + + /** + * NB: ACK and REPLY have no portal, but they should have been + * rejected by message mask + */ + if (attr->fa_ptl_mask && /* has portal filter */ + !(attr->fa_ptl_mask & (1ULL << portal))) + return false; + + return true; +} + +static int +lnet_fault_attr_validate(struct lnet_fault_attr *attr) +{ + if (!attr->fa_msg_mask) + attr->fa_msg_mask = LNET_MSG_MASK; /* all message types */ + + if (!attr->fa_ptl_mask) /* no portal filter */ + return 0; + + /* NB: only PUT and GET can be filtered if portal filter has been set */ + attr->fa_msg_mask &= LNET_GET_BIT | LNET_PUT_BIT; + if (!attr->fa_msg_mask) { + CDEBUG(D_NET, "can't find valid message type bits %x\n", + attr->fa_msg_mask); + return -EINVAL; + } + return 0; +} + +static void +lnet_fault_stat_inc(struct lnet_fault_stat *stat, unsigned int type) +{ + /* NB: fs_counter is NOT updated by this function */ + switch (type) { + case LNET_MSG_PUT: + stat->fs_put++; + return; + case LNET_MSG_ACK: + stat->fs_ack++; + return; + case LNET_MSG_GET: + stat->fs_get++; + return; + case LNET_MSG_REPLY: + stat->fs_reply++; + return; + } +} + +/** + * LNet message drop simulation + */ + +/** + * Add a new drop rule to LNet + * There is no check for duplicated drop rule, all rules will be checked for + * incoming message. + */ +static int +lnet_drop_rule_add(struct lnet_fault_attr *attr) +{ + struct lnet_drop_rule *rule; + + if (attr->u.drop.da_rate & attr->u.drop.da_interval) { + CDEBUG(D_NET, "please provide either drop rate or drop interval, but not both at the same time %d/%d\n", + attr->u.drop.da_rate, attr->u.drop.da_interval); + return -EINVAL; + } + + if (lnet_fault_attr_validate(attr)) + return -EINVAL; + + CFS_ALLOC_PTR(rule); + if (!rule) + return -ENOMEM; + + spin_lock_init(&rule->dr_lock); + + rule->dr_attr = *attr; + if (attr->u.drop.da_interval) { + rule->dr_time_base = cfs_time_shift(attr->u.drop.da_interval); + rule->dr_drop_time = cfs_time_shift(cfs_rand() % + attr->u.drop.da_interval); + } else { + rule->dr_drop_at = cfs_rand() % attr->u.drop.da_rate; + } + + lnet_net_lock(LNET_LOCK_EX); + list_add(&rule->dr_link, &the_lnet.ln_drop_rules); + lnet_net_unlock(LNET_LOCK_EX); + + CDEBUG(D_NET, "Added drop rule: src %s, dst %s, rate %d, interval %d\n", + libcfs_nid2str(attr->fa_src), libcfs_nid2str(attr->fa_src), + attr->u.drop.da_rate, attr->u.drop.da_interval); + return 0; +} + +/** + * Remove matched drop rules from lnet, all rules that can match \a src and + * \a dst will be removed. + * If \a src is zero, then all rules have \a dst as destination will be remove + * If \a dst is zero, then all rules have \a src as source will be removed + * If both of them are zero, all rules will be removed + */ +static int +lnet_drop_rule_del(lnet_nid_t src, lnet_nid_t dst) +{ + struct lnet_drop_rule *rule; + struct lnet_drop_rule *tmp; + struct list_head zombies; + int n = 0; + + INIT_LIST_HEAD(&zombies); + + lnet_net_lock(LNET_LOCK_EX); + list_for_each_entry_safe(rule, tmp, &the_lnet.ln_drop_rules, dr_link) { + if (rule->dr_attr.fa_src != src && src) + continue; + + if (rule->dr_attr.fa_dst != dst && dst) + continue; + + list_move(&rule->dr_link, &zombies); + } + lnet_net_unlock(LNET_LOCK_EX); + + list_for_each_entry_safe(rule, tmp, &zombies, dr_link) { + CDEBUG(D_NET, "Remove drop rule: src %s->dst: %s (1/%d, %d)\n", + libcfs_nid2str(rule->dr_attr.fa_src), + libcfs_nid2str(rule->dr_attr.fa_dst), + rule->dr_attr.u.drop.da_rate, + rule->dr_attr.u.drop.da_interval); + + list_del(&rule->dr_link); + CFS_FREE_PTR(rule); + n++; + } + + return n; +} + +/** + * List drop rule at position of \a pos + */ +static int +lnet_drop_rule_list(int pos, struct lnet_fault_attr *attr, + struct lnet_fault_stat *stat) +{ + struct lnet_drop_rule *rule; + int cpt; + int i = 0; + int rc = -ENOENT; + + cpt = lnet_net_lock_current(); + list_for_each_entry(rule, &the_lnet.ln_drop_rules, dr_link) { + if (i++ < pos) + continue; + + spin_lock(&rule->dr_lock); + *attr = rule->dr_attr; + *stat = rule->dr_stat; + spin_unlock(&rule->dr_lock); + rc = 0; + break; + } + + lnet_net_unlock(cpt); + return rc; +} + +/** + * reset counters for all drop rules + */ +static void +lnet_drop_rule_reset(void) +{ + struct lnet_drop_rule *rule; + int cpt; + + cpt = lnet_net_lock_current(); + + list_for_each_entry(rule, &the_lnet.ln_drop_rules, dr_link) { + struct lnet_fault_attr *attr = &rule->dr_attr; + + spin_lock(&rule->dr_lock); + + memset(&rule->dr_stat, 0, sizeof(rule->dr_stat)); + if (attr->u.drop.da_rate) { + rule->dr_drop_at = cfs_rand() % attr->u.drop.da_rate; + } else { + rule->dr_drop_time = cfs_time_shift(cfs_rand() % + attr->u.drop.da_interval); + rule->dr_time_base = cfs_time_shift(attr->u.drop.da_interval); + } + spin_unlock(&rule->dr_lock); + } + + lnet_net_unlock(cpt); +} + +/** + * check source/destination NID, portal, message type and drop rate, + * decide whether should drop this message or not + */ +static bool +drop_rule_match(struct lnet_drop_rule *rule, lnet_nid_t src, + lnet_nid_t dst, unsigned int type, unsigned int portal) +{ + struct lnet_fault_attr *attr = &rule->dr_attr; + bool drop; + + if (!lnet_fault_attr_match(attr, src, dst, type, portal)) + return false; + + /* match this rule, check drop rate now */ + spin_lock(&rule->dr_lock); + if (rule->dr_drop_time) { /* time based drop */ + unsigned long now = cfs_time_current(); + + rule->dr_stat.fs_count++; + drop = cfs_time_aftereq(now, rule->dr_drop_time); + if (drop) { + if (cfs_time_after(now, rule->dr_time_base)) + rule->dr_time_base = now; + + rule->dr_drop_time = rule->dr_time_base + + cfs_time_seconds(cfs_rand() % + attr->u.drop.da_interval); + rule->dr_time_base += cfs_time_seconds(attr->u.drop.da_interval); + + CDEBUG(D_NET, "Drop Rule %s->%s: next drop : %lu\n", + libcfs_nid2str(attr->fa_src), + libcfs_nid2str(attr->fa_dst), + rule->dr_drop_time); + } + + } else { /* rate based drop */ + drop = rule->dr_stat.fs_count++ == rule->dr_drop_at; + + if (!do_div(rule->dr_stat.fs_count, attr->u.drop.da_rate)) { + rule->dr_drop_at = rule->dr_stat.fs_count + + cfs_rand() % attr->u.drop.da_rate; + CDEBUG(D_NET, "Drop Rule %s->%s: next drop: %lu\n", + libcfs_nid2str(attr->fa_src), + libcfs_nid2str(attr->fa_dst), rule->dr_drop_at); + } + } + + if (drop) { /* drop this message, update counters */ + lnet_fault_stat_inc(&rule->dr_stat, type); + rule->dr_stat.u.drop.ds_dropped++; + } + + spin_unlock(&rule->dr_lock); + return drop; +} + +/** + * Check if message from \a src to \a dst can match any existed drop rule + */ +bool +lnet_drop_rule_match(lnet_hdr_t *hdr) +{ + struct lnet_drop_rule *rule; + lnet_nid_t src = le64_to_cpu(hdr->src_nid); + lnet_nid_t dst = le64_to_cpu(hdr->dest_nid); + unsigned int typ = le32_to_cpu(hdr->type); + unsigned int ptl = -1; + bool drop = false; + int cpt; + + /** + * NB: if Portal is specified, then only PUT and GET will be + * filtered by drop rule + */ + if (typ == LNET_MSG_PUT) + ptl = le32_to_cpu(hdr->msg.put.ptl_index); + else if (typ == LNET_MSG_GET) + ptl = le32_to_cpu(hdr->msg.get.ptl_index); + + cpt = lnet_net_lock_current(); + list_for_each_entry(rule, &the_lnet.ln_drop_rules, dr_link) { + drop = drop_rule_match(rule, src, dst, typ, ptl); + if (drop) + break; + } + + lnet_net_unlock(cpt); + return drop; +} + +/** + * LNet Delay Simulation + */ +/** timestamp (second) to send delayed message */ +#define msg_delay_send msg_ev.hdr_data + +struct lnet_delay_rule { + /** link chain on the_lnet.ln_delay_rules */ + struct list_head dl_link; + /** link chain on delay_dd.dd_sched_rules */ + struct list_head dl_sched_link; + /** attributes of this rule */ + struct lnet_fault_attr dl_attr; + /** lock to protect \a below members */ + spinlock_t dl_lock; + /** refcount of delay rule */ + atomic_t dl_refcount; + /** + * the message sequence to delay, which means message is delayed when + * dl_stat.fs_count == dl_delay_at + */ + unsigned long dl_delay_at; + /** + * seconds to delay the next message, it's exclusive with dl_delay_at + */ + unsigned long dl_delay_time; + /** baseline to caculate dl_delay_time */ + unsigned long dl_time_base; + /** jiffies to send the next delayed message */ + unsigned long dl_msg_send; + /** delayed message list */ + struct list_head dl_msg_list; + /** statistic of delayed messages */ + struct lnet_fault_stat dl_stat; + /** timer to wakeup delay_daemon */ + struct timer_list dl_timer; +}; + +struct delay_daemon_data { + /** serialise rule add/remove */ + struct mutex dd_mutex; + /** protect rules on \a dd_sched_rules */ + spinlock_t dd_lock; + /** scheduled delay rules (by timer) */ + struct list_head dd_sched_rules; + /** daemon thread sleeps at here */ + wait_queue_head_t dd_waitq; + /** controller (lctl command) wait at here */ + wait_queue_head_t dd_ctl_waitq; + /** daemon is running */ + unsigned int dd_running; + /** daemon stopped */ + unsigned int dd_stopped; +}; + +static struct delay_daemon_data delay_dd; + +static unsigned long +round_timeout(unsigned long timeout) +{ + return cfs_time_seconds((unsigned int) + cfs_duration_sec(cfs_time_sub(timeout, 0)) + 1); +} + +static void +delay_rule_decref(struct lnet_delay_rule *rule) +{ + if (atomic_dec_and_test(&rule->dl_refcount)) { + LASSERT(list_empty(&rule->dl_sched_link)); + LASSERT(list_empty(&rule->dl_msg_list)); + LASSERT(list_empty(&rule->dl_link)); + + CFS_FREE_PTR(rule); + } +} + +/** + * check source/destination NID, portal, message type and delay rate, + * decide whether should delay this message or not + */ +static bool +delay_rule_match(struct lnet_delay_rule *rule, lnet_nid_t src, + lnet_nid_t dst, unsigned int type, unsigned int portal, + struct lnet_msg *msg) +{ + struct lnet_fault_attr *attr = &rule->dl_attr; + bool delay; + + if (!lnet_fault_attr_match(attr, src, dst, type, portal)) + return false; + + /* match this rule, check delay rate now */ + spin_lock(&rule->dl_lock); + if (rule->dl_delay_time) { /* time based delay */ + unsigned long now = cfs_time_current(); + + rule->dl_stat.fs_count++; + delay = cfs_time_aftereq(now, rule->dl_delay_time); + if (delay) { + if (cfs_time_after(now, rule->dl_time_base)) + rule->dl_time_base = now; + + rule->dl_delay_time = rule->dl_time_base + + cfs_time_seconds(cfs_rand() % + attr->u.delay.la_interval); + rule->dl_time_base += cfs_time_seconds(attr->u.delay.la_interval); + + CDEBUG(D_NET, "Delay Rule %s->%s: next delay : %lu\n", + libcfs_nid2str(attr->fa_src), + libcfs_nid2str(attr->fa_dst), + rule->dl_delay_time); + } + + } else { /* rate based delay */ + delay = rule->dl_stat.fs_count++ == rule->dl_delay_at; + /* generate the next random rate sequence */ + if (!do_div(rule->dl_stat.fs_count, attr->u.delay.la_rate)) { + rule->dl_delay_at = rule->dl_stat.fs_count + + cfs_rand() % attr->u.delay.la_rate; + CDEBUG(D_NET, "Delay Rule %s->%s: next delay: %lu\n", + libcfs_nid2str(attr->fa_src), + libcfs_nid2str(attr->fa_dst), rule->dl_delay_at); + } + } + + if (!delay) { + spin_unlock(&rule->dl_lock); + return false; + } + + /* delay this message, update counters */ + lnet_fault_stat_inc(&rule->dl_stat, type); + rule->dl_stat.u.delay.ls_delayed++; + + list_add_tail(&msg->msg_list, &rule->dl_msg_list); + msg->msg_delay_send = round_timeout( + cfs_time_shift(attr->u.delay.la_latency)); + if (rule->dl_msg_send == -1) { + rule->dl_msg_send = msg->msg_delay_send; + mod_timer(&rule->dl_timer, rule->dl_msg_send); + } + + spin_unlock(&rule->dl_lock); + return true; +} + +/** + * check if \a msg can match any Delay Rule, receiving of this message + * will be delayed if there is a match. + */ +bool +lnet_delay_rule_match_locked(lnet_hdr_t *hdr, struct lnet_msg *msg) +{ + struct lnet_delay_rule *rule; + lnet_nid_t src = le64_to_cpu(hdr->src_nid); + lnet_nid_t dst = le64_to_cpu(hdr->dest_nid); + unsigned int typ = le32_to_cpu(hdr->type); + unsigned int ptl = -1; + + /* NB: called with hold of lnet_net_lock */ + + /** + * NB: if Portal is specified, then only PUT and GET will be + * filtered by delay rule + */ + if (typ == LNET_MSG_PUT) + ptl = le32_to_cpu(hdr->msg.put.ptl_index); + else if (typ == LNET_MSG_GET) + ptl = le32_to_cpu(hdr->msg.get.ptl_index); + + list_for_each_entry(rule, &the_lnet.ln_delay_rules, dl_link) { + if (delay_rule_match(rule, src, dst, typ, ptl, msg)) + return true; + } + + return false; +} + +/** check out delayed messages for send */ +static void +delayed_msg_check(struct lnet_delay_rule *rule, bool all, + struct list_head *msg_list) +{ + struct lnet_msg *msg; + struct lnet_msg *tmp; + unsigned long now = cfs_time_current(); + + if (!all && rule->dl_msg_send > now) + return; + + spin_lock(&rule->dl_lock); + list_for_each_entry_safe(msg, tmp, &rule->dl_msg_list, msg_list) { + if (!all && msg->msg_delay_send > now) + break; + + msg->msg_delay_send = 0; + list_move_tail(&msg->msg_list, msg_list); + } + + if (list_empty(&rule->dl_msg_list)) { + del_timer(&rule->dl_timer); + rule->dl_msg_send = -1; + + } else if (!list_empty(msg_list)) { + /* + * dequeued some timedout messages, update timer for the + * next delayed message on rule + */ + msg = list_entry(rule->dl_msg_list.next, + struct lnet_msg, msg_list); + rule->dl_msg_send = msg->msg_delay_send; + mod_timer(&rule->dl_timer, rule->dl_msg_send); + } + spin_unlock(&rule->dl_lock); +} + +static void +delayed_msg_process(struct list_head *msg_list, bool drop) +{ + struct lnet_msg *msg; + + while (!list_empty(msg_list)) { + struct lnet_ni *ni; + int cpt; + int rc; + + msg = list_entry(msg_list->next, struct lnet_msg, msg_list); + LASSERT(msg->msg_rxpeer); + + ni = msg->msg_rxpeer->lp_ni; + cpt = msg->msg_rx_cpt; + + list_del_init(&msg->msg_list); + if (drop) { + rc = -ECANCELED; + + } else if (!msg->msg_routing) { + rc = lnet_parse_local(ni, msg); + if (!rc) + continue; + + } else { + lnet_net_lock(cpt); + rc = lnet_parse_forward_locked(ni, msg); + lnet_net_unlock(cpt); + + switch (rc) { + case LNET_CREDIT_OK: + lnet_ni_recv(ni, msg->msg_private, msg, 0, + 0, msg->msg_len, msg->msg_len); + case LNET_CREDIT_WAIT: + continue; + default: /* failures */ + break; + } + } + + lnet_drop_message(ni, cpt, msg->msg_private, msg->msg_len); + lnet_finalize(ni, msg, rc); + } +} + +/** + * Process delayed messages for scheduled rules + * This function can either be called by delay_rule_daemon, or by lnet_finalise + */ +void +lnet_delay_rule_check(void) +{ + struct lnet_delay_rule *rule; + struct list_head msgs; + + INIT_LIST_HEAD(&msgs); + while (1) { + if (list_empty(&delay_dd.dd_sched_rules)) + break; + + spin_lock_bh(&delay_dd.dd_lock); + if (list_empty(&delay_dd.dd_sched_rules)) { + spin_unlock_bh(&delay_dd.dd_lock); + break; + } + + rule = list_entry(delay_dd.dd_sched_rules.next, + struct lnet_delay_rule, dl_sched_link); + list_del_init(&rule->dl_sched_link); + spin_unlock_bh(&delay_dd.dd_lock); + + delayed_msg_check(rule, false, &msgs); + delay_rule_decref(rule); /* -1 for delay_dd.dd_sched_rules */ + } + + if (!list_empty(&msgs)) + delayed_msg_process(&msgs, false); +} + +/** daemon thread to handle delayed messages */ +static int +lnet_delay_rule_daemon(void *arg) +{ + delay_dd.dd_running = 1; + wake_up(&delay_dd.dd_ctl_waitq); + + while (delay_dd.dd_running) { + wait_event_interruptible(delay_dd.dd_waitq, + !delay_dd.dd_running || + !list_empty(&delay_dd.dd_sched_rules)); + lnet_delay_rule_check(); + } + + /* in case more rules have been enqueued after my last check */ + lnet_delay_rule_check(); + delay_dd.dd_stopped = 1; + wake_up(&delay_dd.dd_ctl_waitq); + + return 0; +} + +static void +delay_timer_cb(unsigned long arg) +{ + struct lnet_delay_rule *rule = (struct lnet_delay_rule *)arg; + + spin_lock_bh(&delay_dd.dd_lock); + if (list_empty(&rule->dl_sched_link) && delay_dd.dd_running) { + atomic_inc(&rule->dl_refcount); + list_add_tail(&rule->dl_sched_link, &delay_dd.dd_sched_rules); + wake_up(&delay_dd.dd_waitq); + } + spin_unlock_bh(&delay_dd.dd_lock); +} + +/** + * Add a new delay rule to LNet + * There is no check for duplicated delay rule, all rules will be checked for + * incoming message. + */ +int +lnet_delay_rule_add(struct lnet_fault_attr *attr) +{ + struct lnet_delay_rule *rule; + int rc = 0; + + if (attr->u.delay.la_rate & attr->u.delay.la_interval) { + CDEBUG(D_NET, "please provide either delay rate or delay interval, but not both at the same time %d/%d\n", + attr->u.delay.la_rate, attr->u.delay.la_interval); + return -EINVAL; + } + + if (!attr->u.delay.la_latency) { + CDEBUG(D_NET, "delay latency cannot be zero\n"); + return -EINVAL; + } + + if (lnet_fault_attr_validate(attr)) + return -EINVAL; + + CFS_ALLOC_PTR(rule); + if (!rule) + return -ENOMEM; + + mutex_lock(&delay_dd.dd_mutex); + if (!delay_dd.dd_running) { + struct task_struct *task; + + /** + * NB: although LND threads will process delayed message + * in lnet_finalize, but there is no guarantee that LND + * threads will be waken up if no other message needs to + * be handled. + * Only one daemon thread, performance is not the concern + * of this simualation module. + */ + task = kthread_run(lnet_delay_rule_daemon, NULL, "lnet_dd"); + if (IS_ERR(task)) { + rc = PTR_ERR(task); + goto failed; + } + wait_event(delay_dd.dd_ctl_waitq, delay_dd.dd_running); + } + + init_timer(&rule->dl_timer); + rule->dl_timer.function = delay_timer_cb; + rule->dl_timer.data = (unsigned long)rule; + + spin_lock_init(&rule->dl_lock); + INIT_LIST_HEAD(&rule->dl_msg_list); + INIT_LIST_HEAD(&rule->dl_sched_link); + + rule->dl_attr = *attr; + if (attr->u.delay.la_interval) { + rule->dl_time_base = cfs_time_shift(attr->u.delay.la_interval); + rule->dl_delay_time = cfs_time_shift(cfs_rand() % + attr->u.delay.la_interval); + } else { + rule->dl_delay_at = cfs_rand() % attr->u.delay.la_rate; + } + + rule->dl_msg_send = -1; + + lnet_net_lock(LNET_LOCK_EX); + atomic_set(&rule->dl_refcount, 1); + list_add(&rule->dl_link, &the_lnet.ln_delay_rules); + lnet_net_unlock(LNET_LOCK_EX); + + CDEBUG(D_NET, "Added delay rule: src %s, dst %s, rate %d\n", + libcfs_nid2str(attr->fa_src), libcfs_nid2str(attr->fa_src), + attr->u.delay.la_rate); + + mutex_unlock(&delay_dd.dd_mutex); + return 0; +failed: + mutex_unlock(&delay_dd.dd_mutex); + CFS_FREE_PTR(rule); + return rc; +} + +/** + * Remove matched Delay Rules from lnet, if \a shutdown is true or both \a src + * and \a dst are zero, all rules will be removed, otherwise only matched rules + * will be removed. + * If \a src is zero, then all rules have \a dst as destination will be remove + * If \a dst is zero, then all rules have \a src as source will be removed + * + * When a delay rule is removed, all delayed messages of this rule will be + * processed immediately. + */ +int +lnet_delay_rule_del(lnet_nid_t src, lnet_nid_t dst, bool shutdown) +{ + struct lnet_delay_rule *rule; + struct lnet_delay_rule *tmp; + struct list_head rule_list; + struct list_head msg_list; + int n = 0; + bool cleanup; + + INIT_LIST_HEAD(&rule_list); + INIT_LIST_HEAD(&msg_list); + + if (shutdown) { + src = 0; + dst = 0; + } + + mutex_lock(&delay_dd.dd_mutex); + lnet_net_lock(LNET_LOCK_EX); + + list_for_each_entry_safe(rule, tmp, &the_lnet.ln_delay_rules, dl_link) { + if (rule->dl_attr.fa_src != src && src) + continue; + + if (rule->dl_attr.fa_dst != dst && dst) + continue; + + CDEBUG(D_NET, "Remove delay rule: src %s->dst: %s (1/%d, %d)\n", + libcfs_nid2str(rule->dl_attr.fa_src), + libcfs_nid2str(rule->dl_attr.fa_dst), + rule->dl_attr.u.delay.la_rate, + rule->dl_attr.u.delay.la_interval); + /* refcount is taken over by rule_list */ + list_move(&rule->dl_link, &rule_list); + } + + /* check if we need to shutdown delay_daemon */ + cleanup = list_empty(&the_lnet.ln_delay_rules) && + !list_empty(&rule_list); + lnet_net_unlock(LNET_LOCK_EX); + + list_for_each_entry_safe(rule, tmp, &rule_list, dl_link) { + list_del_init(&rule->dl_link); + + del_timer_sync(&rule->dl_timer); + delayed_msg_check(rule, true, &msg_list); + delay_rule_decref(rule); /* -1 for the_lnet.ln_delay_rules */ + n++; + } + + if (cleanup) { /* no more delay rule, shutdown delay_daemon */ + LASSERT(delay_dd.dd_running); + delay_dd.dd_running = 0; + wake_up(&delay_dd.dd_waitq); + + while (!delay_dd.dd_stopped) + wait_event(delay_dd.dd_ctl_waitq, delay_dd.dd_stopped); + } + mutex_unlock(&delay_dd.dd_mutex); + + if (!list_empty(&msg_list)) + delayed_msg_process(&msg_list, shutdown); + + return n; +} + +/** + * List Delay Rule at position of \a pos + */ +int +lnet_delay_rule_list(int pos, struct lnet_fault_attr *attr, + struct lnet_fault_stat *stat) +{ + struct lnet_delay_rule *rule; + int cpt; + int i = 0; + int rc = -ENOENT; + + cpt = lnet_net_lock_current(); + list_for_each_entry(rule, &the_lnet.ln_delay_rules, dl_link) { + if (i++ < pos) + continue; + + spin_lock(&rule->dl_lock); + *attr = rule->dl_attr; + *stat = rule->dl_stat; + spin_unlock(&rule->dl_lock); + rc = 0; + break; + } + + lnet_net_unlock(cpt); + return rc; +} + +/** + * reset counters for all Delay Rules + */ +void +lnet_delay_rule_reset(void) +{ + struct lnet_delay_rule *rule; + int cpt; + + cpt = lnet_net_lock_current(); + + list_for_each_entry(rule, &the_lnet.ln_delay_rules, dl_link) { + struct lnet_fault_attr *attr = &rule->dl_attr; + + spin_lock(&rule->dl_lock); + + memset(&rule->dl_stat, 0, sizeof(rule->dl_stat)); + if (attr->u.delay.la_rate) { + rule->dl_delay_at = cfs_rand() % attr->u.delay.la_rate; + } else { + rule->dl_delay_time = cfs_time_shift(cfs_rand() % + attr->u.delay.la_interval); + rule->dl_time_base = cfs_time_shift(attr->u.delay.la_interval); + } + spin_unlock(&rule->dl_lock); + } + + lnet_net_unlock(cpt); +} + +int +lnet_fault_ctl(int opc, struct libcfs_ioctl_data *data) +{ + struct lnet_fault_attr *attr; + struct lnet_fault_stat *stat; + + attr = (struct lnet_fault_attr *)data->ioc_inlbuf1; + + switch (opc) { + default: + return -EINVAL; + + case LNET_CTL_DROP_ADD: + if (!attr) + return -EINVAL; + + return lnet_drop_rule_add(attr); + + case LNET_CTL_DROP_DEL: + if (!attr) + return -EINVAL; + + data->ioc_count = lnet_drop_rule_del(attr->fa_src, + attr->fa_dst); + return 0; + + case LNET_CTL_DROP_RESET: + lnet_drop_rule_reset(); + return 0; + + case LNET_CTL_DROP_LIST: + stat = (struct lnet_fault_stat *)data->ioc_inlbuf2; + if (!attr || !stat) + return -EINVAL; + + return lnet_drop_rule_list(data->ioc_count, attr, stat); + + case LNET_CTL_DELAY_ADD: + if (!attr) + return -EINVAL; + + return lnet_delay_rule_add(attr); + + case LNET_CTL_DELAY_DEL: + if (!attr) + return -EINVAL; + + data->ioc_count = lnet_delay_rule_del(attr->fa_src, + attr->fa_dst, false); + return 0; + + case LNET_CTL_DELAY_RESET: + lnet_delay_rule_reset(); + return 0; + + case LNET_CTL_DELAY_LIST: + stat = (struct lnet_fault_stat *)data->ioc_inlbuf2; + if (!attr || !stat) + return -EINVAL; + + return lnet_delay_rule_list(data->ioc_count, attr, stat); + } +} + +int +lnet_fault_init(void) +{ + CLASSERT(LNET_PUT_BIT == 1 << LNET_MSG_PUT); + CLASSERT(LNET_ACK_BIT == 1 << LNET_MSG_ACK); + CLASSERT(LNET_GET_BIT == 1 << LNET_MSG_GET); + CLASSERT(LNET_REPLY_BIT == 1 << LNET_MSG_REPLY); + + mutex_init(&delay_dd.dd_mutex); + spin_lock_init(&delay_dd.dd_lock); + init_waitqueue_head(&delay_dd.dd_waitq); + init_waitqueue_head(&delay_dd.dd_ctl_waitq); + INIT_LIST_HEAD(&delay_dd.dd_sched_rules); + + return 0; +} + +void +lnet_fault_fini(void) +{ + lnet_drop_rule_del(0, 0); + lnet_delay_rule_del(0, 0, true); + + LASSERT(list_empty(&the_lnet.ln_drop_rules)); + LASSERT(list_empty(&the_lnet.ln_delay_rules)); + LASSERT(list_empty(&delay_dd.dd_sched_rules)); +} diff --git a/drivers/staging/lustre/lnet/lnet/nidstrings.c b/drivers/staging/lustre/lnet/lnet/nidstrings.c index 80f585afa259..ebf468fbc64f 100644 --- a/drivers/staging/lustre/lnet/lnet/nidstrings.c +++ b/drivers/staging/lustre/lnet/lnet/nidstrings.c @@ -170,7 +170,7 @@ parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange) } LIBCFS_ALLOC(addrrange, sizeof(struct addrrange)); - if (addrrange == NULL) + if (!addrrange) return -ENOMEM; list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges); INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges); @@ -203,16 +203,18 @@ add_nidrange(const struct cfs_lstr *src, return NULL; nf = libcfs_namenum2netstrfns(src->ls_str); - if (nf == NULL) + if (!nf) return NULL; endlen = src->ls_len - strlen(nf->nf_name); - if (endlen == 0) + if (!endlen) /* network name only, e.g. "elan" or "tcp" */ netnum = 0; else { - /* e.g. "elan25" or "tcp23", refuse to parse if + /* + * e.g. "elan25" or "tcp23", refuse to parse if * network name is not appended with decimal or - * hexadecimal number */ + * hexadecimal number + */ if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name), endlen, &netnum, 0, MAX_NUMERIC_VALUE)) return NULL; @@ -227,7 +229,7 @@ add_nidrange(const struct cfs_lstr *src, } LIBCFS_ALLOC(nr, sizeof(struct nidrange)); - if (nr == NULL) + if (!nr) return NULL; list_add_tail(&nr->nr_link, nidlist); INIT_LIST_HEAD(&nr->nr_addrranges); @@ -253,22 +255,21 @@ parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist) struct nidrange *nr; tmp = *src; - if (cfs_gettok(src, '@', &addrrange) == 0) + if (!cfs_gettok(src, '@', &addrrange)) goto failed; - if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL) + if (!cfs_gettok(src, '@', &net) || src->ls_str) goto failed; nr = add_nidrange(&net, nidlist); - if (nr == NULL) + if (!nr) goto failed; - if (parse_addrange(&addrrange, nr) != 0) + if (parse_addrange(&addrrange, nr)) goto failed; return 1; failed: - CWARN("can't parse nidrange: \"%.*s\"\n", tmp.ls_len, tmp.ls_str); return 0; } @@ -342,12 +343,12 @@ cfs_parse_nidlist(char *str, int len, struct list_head *nidlist) INIT_LIST_HEAD(nidlist); while (src.ls_str) { rc = cfs_gettok(&src, ' ', &res); - if (rc == 0) { + if (!rc) { cfs_free_nidlist(nidlist); return 0; } rc = parse_nidrange(&res, nidlist); - if (rc == 0) { + if (!rc) { cfs_free_nidlist(nidlist); return 0; } @@ -378,7 +379,7 @@ int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist) return 1; list_for_each_entry(ar, &nr->nr_addrranges, ar_link) if (nr->nr_netstrfns->nf_match_addr(LNET_NIDADDR(nid), - &ar->ar_numaddr_ranges)) + &ar->ar_numaddr_ranges)) return 1; } return 0; @@ -395,7 +396,7 @@ cfs_print_network(char *buffer, int count, struct nidrange *nr) { struct netstrfns *nf = nr->nr_netstrfns; - if (nr->nr_netnum == 0) + if (!nr->nr_netnum) return scnprintf(buffer, count, "@%s", nf->nf_name); else return scnprintf(buffer, count, "@%s%u", @@ -417,7 +418,7 @@ cfs_print_addrranges(char *buffer, int count, struct list_head *addrranges, struct netstrfns *nf = nr->nr_netstrfns; list_for_each_entry(ar, addrranges, ar_link) { - if (i != 0) + if (i) i += scnprintf(buffer + i, count - i, " "); i += nf->nf_print_addrlist(buffer + i, count - i, &ar->ar_numaddr_ranges); @@ -442,10 +443,10 @@ int cfs_print_nidlist(char *buffer, int count, struct list_head *nidlist) return 0; list_for_each_entry(nr, nidlist, nr_link) { - if (i != 0) + if (i) i += scnprintf(buffer + i, count - i, " "); - if (nr->nr_all != 0) { + if (nr->nr_all) { LASSERT(list_empty(&nr->nr_addrranges)); i += scnprintf(buffer + i, count - i, "*"); i += cfs_print_network(buffer + i, count - i, nr); @@ -487,13 +488,13 @@ static void cfs_ip_ar_min_max(struct addrrange *ar, __u32 *min_nid, tmp_ip_addr = ((min_ip[0] << 24) | (min_ip[1] << 16) | (min_ip[2] << 8) | min_ip[3]); - if (min_nid != NULL) + if (min_nid) *min_nid = tmp_ip_addr; tmp_ip_addr = ((max_ip[0] << 24) | (max_ip[1] << 16) | (max_ip[2] << 8) | max_ip[3]); - if (max_nid != NULL) + if (max_nid) *max_nid = tmp_ip_addr; } @@ -515,16 +516,16 @@ static void cfs_num_ar_min_max(struct addrrange *ar, __u32 *min_nid, list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) { list_for_each_entry(re, &el->el_exprs, re_link) { - if (re->re_lo < min_addr || min_addr == 0) + if (re->re_lo < min_addr || !min_addr) min_addr = re->re_lo; if (re->re_hi > max_addr) max_addr = re->re_hi; } } - if (min_nid != NULL) + if (min_nid) *min_nid = min_addr; - if (max_nid != NULL) + if (max_nid) *max_nid = max_addr; } @@ -546,17 +547,17 @@ bool cfs_nidrange_is_contiguous(struct list_head *nidlist) list_for_each_entry(nr, nidlist, nr_link) { nf = nr->nr_netstrfns; - if (lndname == NULL) + if (!lndname) lndname = nf->nf_name; if (netnum == -1) netnum = nr->nr_netnum; - if (strcmp(lndname, nf->nf_name) != 0 || + if (strcmp(lndname, nf->nf_name) || netnum != nr->nr_netnum) return false; } - if (nf == NULL) + if (!nf) return false; if (!nf->nf_is_contiguous(nidlist)) @@ -590,7 +591,7 @@ static bool cfs_num_is_contiguous(struct list_head *nidlist) list_for_each_entry(ar, &nr->nr_addrranges, ar_link) { cfs_num_ar_min_max(ar, ¤t_start_nid, ¤t_end_nid); - if (last_end_nid != 0 && + if (last_end_nid && (current_start_nid - last_end_nid != 1)) return false; last_end_nid = current_end_nid; @@ -600,7 +601,7 @@ static bool cfs_num_is_contiguous(struct list_head *nidlist) re_link) { if (re->re_stride > 1) return false; - else if (last_hi != 0 && + else if (last_hi && re->re_hi - last_hi != 1) return false; last_hi = re->re_hi; @@ -640,7 +641,7 @@ static bool cfs_ip_is_contiguous(struct list_head *nidlist) last_diff = 0; cfs_ip_ar_min_max(ar, ¤t_start_nid, ¤t_end_nid); - if (last_end_nid != 0 && + if (last_end_nid && (current_start_nid - last_end_nid != 1)) return false; last_end_nid = current_end_nid; @@ -724,7 +725,7 @@ static void cfs_num_min_max(struct list_head *nidlist, __u32 *min_nid, list_for_each_entry(ar, &nr->nr_addrranges, ar_link) { cfs_num_ar_min_max(ar, &tmp_min_addr, &tmp_max_addr); - if (tmp_min_addr < min_addr || min_addr == 0) + if (tmp_min_addr < min_addr || !min_addr) min_addr = tmp_min_addr; if (tmp_max_addr > max_addr) max_addr = tmp_min_addr; @@ -756,16 +757,16 @@ static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min_nid, list_for_each_entry(ar, &nr->nr_addrranges, ar_link) { cfs_ip_ar_min_max(ar, &tmp_min_ip_addr, &tmp_max_ip_addr); - if (tmp_min_ip_addr < min_ip_addr || min_ip_addr == 0) + if (tmp_min_ip_addr < min_ip_addr || !min_ip_addr) min_ip_addr = tmp_min_ip_addr; if (tmp_max_ip_addr > max_ip_addr) max_ip_addr = tmp_max_ip_addr; } } - if (min_nid != NULL) + if (min_nid) *min_nid = min_ip_addr; - if (max_nid != NULL) + if (max_nid) *max_nid = max_ip_addr; } @@ -784,12 +785,14 @@ libcfs_ip_addr2str(__u32 addr, char *str, size_t size) (addr >> 8) & 0xff, addr & 0xff); } -/* CAVEAT EMPTOR XscanfX +/* + * CAVEAT EMPTOR XscanfX * I use "%n" at the end of a sscanf format to detect trailing junk. However * sscanf may return immediately if it sees the terminating '0' in a string, so * I initialise the %n variable to the expected length. If sscanf sets it; * fine, if it doesn't, then the scan ended at the end of the string, which is - * fine too :) */ + * fine too :) + */ static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) { @@ -802,9 +805,9 @@ libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) /* numeric IP? */ if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 && n == nob && - (a & ~0xff) == 0 && (b & ~0xff) == 0 && - (c & ~0xff) == 0 && (d & ~0xff) == 0) { - *addr = ((a<<24)|(b<<16)|(c<<8)|d); + !(a & ~0xff) && !(b & ~0xff) && + !(c & ~0xff) && !(d & ~0xff)) { + *addr = ((a << 24) | (b << 16) | (c << 8) | d); return 1; } @@ -824,7 +827,7 @@ cfs_ip_addr_parse(char *str, int len, struct list_head *list) src.ls_len = len; i = 0; - while (src.ls_str != NULL) { + while (src.ls_str) { struct cfs_lstr res; if (!cfs_gettok(&src, '.', &res)) { @@ -833,7 +836,7 @@ cfs_ip_addr_parse(char *str, int len, struct list_head *list) } rc = cfs_expr_list_parse(res.ls_str, res.ls_len, 0, 255, &el); - if (rc != 0) + if (rc) goto out; list_add_tail(&el->el_link, list); @@ -858,7 +861,7 @@ libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list) list_for_each_entry(el, list, el_link) { LASSERT(j++ < 4); - if (i != 0) + if (i) i += scnprintf(buffer + i, count - i, "."); i += cfs_expr_list_print(buffer + i, count - i, el); } @@ -928,7 +931,7 @@ libcfs_num_parse(char *str, int len, struct list_head *list) int rc; rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el); - if (rc == 0) + if (!rc) list_add_tail(&el->el_link, list); return rc; @@ -1060,7 +1063,7 @@ libcfs_name2netstrfns(const char *name) int libcfs_isknown_lnd(__u32 lnd) { - return libcfs_lnd2netstrfns(lnd) != NULL; + return !!libcfs_lnd2netstrfns(lnd); } EXPORT_SYMBOL(libcfs_isknown_lnd); @@ -1069,7 +1072,7 @@ libcfs_lnd2modname(__u32 lnd) { struct netstrfns *nf = libcfs_lnd2netstrfns(lnd); - return (nf == NULL) ? NULL : nf->nf_modname; + return nf ? nf->nf_modname : NULL; } EXPORT_SYMBOL(libcfs_lnd2modname); @@ -1078,10 +1081,10 @@ libcfs_str2lnd(const char *str) { struct netstrfns *nf = libcfs_name2netstrfns(str); - if (nf != NULL) + if (nf) return nf->nf_type; - return -1; + return -ENXIO; } EXPORT_SYMBOL(libcfs_str2lnd); @@ -1091,7 +1094,7 @@ libcfs_lnd2str_r(__u32 lnd, char *buf, size_t buf_size) struct netstrfns *nf; nf = libcfs_lnd2netstrfns(lnd); - if (nf == NULL) + if (!nf) snprintf(buf, buf_size, "?%u?", lnd); else snprintf(buf, buf_size, "%s", nf->nf_name); @@ -1108,9 +1111,9 @@ libcfs_net2str_r(__u32 net, char *buf, size_t buf_size) struct netstrfns *nf; nf = libcfs_lnd2netstrfns(lnd); - if (nf == NULL) + if (!nf) snprintf(buf, buf_size, "<%u:%u>", lnd, nnum); - else if (nnum == 0) + else if (!nnum) snprintf(buf, buf_size, "%s", nf->nf_name); else snprintf(buf, buf_size, "%s%u", nf->nf_name, nnum); @@ -1135,14 +1138,14 @@ libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size) } nf = libcfs_lnd2netstrfns(lnd); - if (nf == NULL) + if (!nf) { snprintf(buf, buf_size, "%x@<%u:%u>", addr, lnd, nnum); - else { + } else { size_t addr_len; nf->nf_addr2str(addr, buf, buf_size); addr_len = strlen(buf); - if (nnum == 0) + if (!nnum) snprintf(buf + addr_len, buf_size - addr_len, "@%s", nf->nf_name); else @@ -1195,7 +1198,7 @@ libcfs_str2net(const char *str) { __u32 net; - if (libcfs_str2net_internal(str, &net) != NULL) + if (libcfs_str2net_internal(str, &net)) return net; return LNET_NIDNET(LNET_NID_ANY); @@ -1210,15 +1213,15 @@ libcfs_str2nid(const char *str) __u32 net; __u32 addr; - if (sep != NULL) { + if (sep) { nf = libcfs_str2net_internal(sep + 1, &net); - if (nf == NULL) + if (!nf) return LNET_NID_ANY; } else { sep = str + strlen(str); net = LNET_MKNET(SOCKLND, 0); nf = libcfs_lnd2netstrfns(SOCKLND); - LASSERT(nf != NULL); + LASSERT(nf); } if (!nf->nf_str2addr(str, (int)(sep - str), &addr)) @@ -1240,8 +1243,8 @@ libcfs_id2str(lnet_process_id_t id) } snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s", - ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "", - (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid)); + id.pid & LNET_PID_USERFLAG ? "U" : "", + id.pid & ~LNET_PID_USERFLAG, libcfs_nid2str(id.nid)); return str; } EXPORT_SYMBOL(libcfs_id2str); diff --git a/drivers/staging/lustre/lnet/lnet/peer.c b/drivers/staging/lustre/lnet/lnet/peer.c index 1fceed3c8fc0..b026feebc03a 100644 --- a/drivers/staging/lustre/lnet/lnet/peer.c +++ b/drivers/staging/lustre/lnet/lnet/peer.c @@ -39,6 +39,7 @@ #define DEBUG_SUBSYSTEM S_LNET #include "../../include/linux/lnet/lib-lnet.h" +#include "../../include/linux/lnet/lib-dlc.h" int lnet_peer_tables_create(void) @@ -50,7 +51,7 @@ lnet_peer_tables_create(void) the_lnet.ln_peer_tables = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*ptable)); - if (the_lnet.ln_peer_tables == NULL) { + if (!the_lnet.ln_peer_tables) { CERROR("Failed to allocate cpu-partition peer tables\n"); return -ENOMEM; } @@ -60,7 +61,7 @@ lnet_peer_tables_create(void) LIBCFS_CPT_ALLOC(hash, lnet_cpt_table(), i, LNET_PEER_HASH_SIZE * sizeof(*hash)); - if (hash == NULL) { + if (!hash) { CERROR("Failed to create peer hash table\n"); lnet_peer_tables_destroy(); return -ENOMEM; @@ -82,12 +83,12 @@ lnet_peer_tables_destroy(void) int i; int j; - if (the_lnet.ln_peer_tables == NULL) + if (!the_lnet.ln_peer_tables) return; cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) { hash = ptable->pt_hash; - if (hash == NULL) /* not initialized */ + if (!hash) /* not initialized */ break; LASSERT(list_empty(&ptable->pt_deathrow)); @@ -103,62 +104,116 @@ lnet_peer_tables_destroy(void) 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 -lnet_peer_tables_cleanup(void) +lnet_peer_tables_cleanup(lnet_ni_t *ni) { struct lnet_peer_table *ptable; + struct list_head deathrow; + lnet_peer_t *lp; + lnet_peer_t *temp; 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) { lnet_net_lock(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_peer_table_del_rtrs_locked(ni, ptable, 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) { - LIST_HEAD(deathrow); - lnet_peer_t *lp; - lnet_net_lock(i); + lnet_peer_table_cleanup_locked(ni, ptable); + lnet_net_unlock(i); + } - for (j = 3; ptable->pt_number != 0; j++) { - lnet_net_unlock(i); - - if ((j & (j - 1)) == 0) { - 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); - } + /* Cleanup all entries on deathrow. */ + cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) { + lnet_net_lock(i); + lnet_peer_table_deathrow_wait_locked(ptable, i); 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)); - } + list_for_each_entry_safe(lp, temp, &deathrow, lp_hashlist) { + list_del(&lp->lp_hashlist); + LIBCFS_FREE(lp, sizeof(*lp)); } } @@ -167,11 +222,11 @@ lnet_destroy_peer_locked(lnet_peer_t *lp) { struct lnet_peer_table *ptable; - LASSERT(lp->lp_refcount == 0); - LASSERT(lp->lp_rtr_refcount == 0); + LASSERT(!lp->lp_refcount); + LASSERT(!lp->lp_rtr_refcount); LASSERT(list_empty(&lp->lp_txq)); LASSERT(list_empty(&lp->lp_hashlist)); - LASSERT(lp->lp_txqnob == 0); + LASSERT(!lp->lp_txqnob); ptable = the_lnet.ln_peer_tables[lp->lp_cpt]; LASSERT(ptable->pt_number > 0); @@ -181,6 +236,8 @@ lnet_destroy_peer_locked(lnet_peer_t *lp) lp->lp_ni = NULL; list_add(&lp->lp_hashlist, &ptable->pt_deathrow); + LASSERT(ptable->pt_zombies > 0); + ptable->pt_zombies--; } lnet_peer_t * @@ -220,14 +277,14 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) ptable = the_lnet.ln_peer_tables[cpt2]; lp = lnet_find_peer_locked(ptable, nid); - if (lp != NULL) { + if (lp) { *lpp = lp; return 0; } if (!list_empty(&ptable->pt_deathrow)) { lp = list_entry(ptable->pt_deathrow.next, - lnet_peer_t, lp_hashlist); + lnet_peer_t, lp_hashlist); list_del(&lp->lp_hashlist); } @@ -238,12 +295,12 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) ptable->pt_number++; lnet_net_unlock(cpt); - if (lp != NULL) + if (lp) memset(lp, 0, sizeof(*lp)); else LIBCFS_CPT_ALLOC(lp, lnet_cpt_table(), cpt2, sizeof(*lp)); - if (lp == NULL) { + if (!lp) { rc = -ENOMEM; lnet_net_lock(cpt); goto out; @@ -276,30 +333,30 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) } lp2 = lnet_find_peer_locked(ptable, nid); - if (lp2 != NULL) { + if (lp2) { *lpp = lp2; goto out; } lp->lp_ni = lnet_net2ni_locked(LNET_NIDNET(nid), cpt2); - if (lp->lp_ni == NULL) { + if (!lp->lp_ni) { rc = -EHOSTUNREACH; goto out; } - lp->lp_txcredits = - lp->lp_mintxcredits = lp->lp_ni->ni_peertxcredits; - lp->lp_rtrcredits = + lp->lp_txcredits = lp->lp_ni->ni_peertxcredits; + lp->lp_mintxcredits = lp->lp_ni->ni_peertxcredits; + lp->lp_rtrcredits = lnet_peer_buffer_credits(lp->lp_ni); lp->lp_minrtrcredits = lnet_peer_buffer_credits(lp->lp_ni); list_add_tail(&lp->lp_hashlist, - &ptable->pt_hash[lnet_nid2peerhash(nid)]); + &ptable->pt_hash[lnet_nid2peerhash(nid)]); ptable->pt_version++; *lpp = lp; return 0; out: - if (lp != NULL) + if (lp) list_add(&lp->lp_hashlist, &ptable->pt_deathrow); ptable->pt_number--; return rc; @@ -317,7 +374,7 @@ lnet_debug_peer(lnet_nid_t nid) lnet_net_lock(cpt); rc = lnet_nid2peer_locked(&lp, nid, cpt); - if (rc != 0) { + if (rc) { lnet_net_unlock(cpt); CDEBUG(D_WARNING, "No peer %s\n", libcfs_nid2str(nid)); return; @@ -336,3 +393,65 @@ lnet_debug_peer(lnet_nid_t nid) lnet_net_unlock(cpt); } + +int +lnet_get_peer_info(__u32 peer_index, __u64 *nid, + char aliveness[LNET_MAX_STR_LEN], + __u32 *cpt_iter, __u32 *refcount, + __u32 *ni_peer_tx_credits, __u32 *peer_tx_credits, + __u32 *peer_rtr_credits, __u32 *peer_min_rtr_credits, + __u32 *peer_tx_qnob) +{ + struct lnet_peer_table *peer_table; + lnet_peer_t *lp; + bool found = false; + int lncpt, j; + + /* get the number of CPTs */ + lncpt = cfs_percpt_number(the_lnet.ln_peer_tables); + + /* + * if the cpt number to be examined is >= the number of cpts in + * the system then indicate that there are no more cpts to examin + */ + if (*cpt_iter >= lncpt) + return -ENOENT; + + /* get the current table */ + peer_table = the_lnet.ln_peer_tables[*cpt_iter]; + /* if the ptable is NULL then there are no more cpts to examine */ + if (!peer_table) + return -ENOENT; + + lnet_net_lock(*cpt_iter); + + for (j = 0; j < LNET_PEER_HASH_SIZE && !found; j++) { + struct list_head *peers = &peer_table->pt_hash[j]; + + list_for_each_entry(lp, peers, lp_hashlist) { + if (peer_index-- > 0) + continue; + + snprintf(aliveness, LNET_MAX_STR_LEN, "NA"); + if (lnet_isrouter(lp) || + lnet_peer_aliveness_enabled(lp)) + snprintf(aliveness, LNET_MAX_STR_LEN, + lp->lp_alive ? "up" : "down"); + + *nid = lp->lp_nid; + *refcount = lp->lp_refcount; + *ni_peer_tx_credits = lp->lp_ni->ni_peertxcredits; + *peer_tx_credits = lp->lp_txcredits; + *peer_rtr_credits = lp->lp_rtrcredits; + *peer_min_rtr_credits = lp->lp_mintxcredits; + *peer_tx_qnob = lp->lp_txqnob; + + found = true; + } + } + lnet_net_unlock(*cpt_iter); + + *cpt_iter = lncpt; + + return found ? 0 : -ENOENT; +} diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index f5faa414d250..61459cf9d58f 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -15,10 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Portals; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * */ #define DEBUG_SUBSYSTEM S_LNET @@ -28,8 +24,11 @@ #define LNET_NRB_TINY (LNET_NRB_TINY_MIN * 4) #define LNET_NRB_SMALL_MIN 4096 /* min value for each CPT */ #define LNET_NRB_SMALL (LNET_NRB_SMALL_MIN * 4) +#define LNET_NRB_SMALL_PAGES 1 #define LNET_NRB_LARGE_MIN 256 /* min value for each CPT */ #define LNET_NRB_LARGE (LNET_NRB_LARGE_MIN * 4) +#define LNET_NRB_LARGE_PAGES ((LNET_MTU + PAGE_CACHE_SIZE - 1) >> \ + PAGE_CACHE_SHIFT) static char *forwarding = ""; module_param(forwarding, charp, 0444); @@ -61,8 +60,10 @@ lnet_peer_buffer_credits(lnet_ni_t *ni) if (peer_buffer_credits > 0) return peer_buffer_credits; - /* As an approximation, allow this peer the same number of router - * buffers as it is allowed outstanding sends */ + /* + * As an approximation, allow this peer the same number of router + * buffers as it is allowed outstanding sends + */ return ni->ni_peertxcredits; } @@ -107,7 +108,7 @@ lnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive, lp->lp_timestamp = when; /* update timestamp */ lp->lp_ping_deadline = 0; /* disable ping timeout */ - if (lp->lp_alive_count != 0 && /* got old news */ + if (lp->lp_alive_count && /* got old news */ (!lp->lp_alive) == (!alive)) { /* new date for old news */ CDEBUG(D_NET, "Old news\n"); return; @@ -131,11 +132,12 @@ lnet_ni_notify_locked(lnet_ni_t *ni, lnet_peer_t *lp) int alive; int notifylnd; - /* Notify only in 1 thread at any time to ensure ordered notification. + /* + * Notify only in 1 thread at any time to ensure ordered notification. * NB individual events can be missed; the only guarantee is that you - * always get the most recent news */ - - if (lp->lp_notifying || ni == NULL) + * always get the most recent news + */ + if (lp->lp_notifying || !ni) return; lp->lp_notifying = 1; @@ -147,13 +149,14 @@ lnet_ni_notify_locked(lnet_ni_t *ni, lnet_peer_t *lp) lp->lp_notifylnd = 0; lp->lp_notify = 0; - if (notifylnd && ni->ni_lnd->lnd_notify != NULL) { + if (notifylnd && ni->ni_lnd->lnd_notify) { lnet_net_unlock(lp->lp_cpt); - /* A new notification could happen now; I'll handle it - * when control returns to me */ - - (ni->ni_lnd->lnd_notify)(ni, lp->lp_nid, alive); + /* + * A new notification could happen now; I'll handle it + * when control returns to me + */ + ni->ni_lnd->lnd_notify(ni, lp->lp_nid, alive); lnet_net_lock(lp->lp_cpt); } @@ -176,7 +179,7 @@ lnet_rtr_addref_locked(lnet_peer_t *lp) /* a simple insertion sort */ list_for_each_prev(pos, &the_lnet.ln_routers) { lnet_peer_t *rtr = list_entry(pos, lnet_peer_t, - lp_rtr_list); + lp_rtr_list); if (rtr->lp_nid < lp->lp_nid) break; @@ -197,12 +200,12 @@ lnet_rtr_decref_locked(lnet_peer_t *lp) /* lnet_net_lock must be exclusively locked */ lp->lp_rtr_refcount--; - if (lp->lp_rtr_refcount == 0) { + if (!lp->lp_rtr_refcount) { LASSERT(list_empty(&lp->lp_routes)); - if (lp->lp_rcd != NULL) { + if (lp->lp_rcd) { list_add(&lp->lp_rcd->rcd_list, - &the_lnet.ln_rcd_deathrow); + &the_lnet.ln_rcd_deathrow); lp->lp_rcd = NULL; } @@ -245,8 +248,10 @@ static void lnet_shuffle_seed(void) cfs_get_random_bytes(seed, sizeof(seed)); - /* Nodes with small feet have little entropy - * the NID for this node gives the most entropy in the low bits */ + /* + * Nodes with small feet have little entropy + * the NID for this node gives the most entropy in the low bits + */ list_for_each(tmp, &the_lnet.ln_nis) { ni = list_entry(tmp, lnet_ni_t, ni_list); lnd_type = LNET_NETTYP(LNET_NIDNET(ni->ni_nid)); @@ -277,7 +282,7 @@ lnet_add_route_to_rnet(lnet_remotenet_t *rnet, lnet_route_t *route) /* len+1 positions to add a new entry, also prevents division by 0 */ offset = cfs_rand() % (len + 1); list_for_each(e, &rnet->lrn_routes) { - if (offset == 0) + if (!offset) break; offset--; } @@ -289,7 +294,7 @@ lnet_add_route_to_rnet(lnet_remotenet_t *rnet, lnet_route_t *route) } int -lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, +lnet_add_route(__u32 net, __u32 hops, lnet_nid_t gateway, unsigned int priority) { struct list_head *e; @@ -300,7 +305,7 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, int add_route; int rc; - CDEBUG(D_NET, "Add route: net %s hops %u priority %u gw %s\n", + CDEBUG(D_NET, "Add route: net %s hops %d priority %u gw %s\n", libcfs_net2str(net), hops, priority, libcfs_nid2str(gateway)); if (gateway == LNET_NID_ANY || @@ -308,21 +313,21 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, net == LNET_NIDNET(LNET_NID_ANY) || LNET_NETTYP(net) == LOLND || LNET_NIDNET(gateway) == net || - hops < 1 || hops > 255) + (hops != LNET_UNDEFINED_HOPS && (hops < 1 || hops > 255))) return -EINVAL; if (lnet_islocalnet(net)) /* it's a local network */ - return 0; /* ignore the route entry */ + return -EEXIST; /* Assume net, route, all new */ LIBCFS_ALLOC(route, sizeof(*route)); LIBCFS_ALLOC(rnet, sizeof(*rnet)); - if (route == NULL || rnet == NULL) { + if (!route || !rnet) { CERROR("Out of memory creating route %s %d %s\n", libcfs_net2str(net), hops, libcfs_nid2str(gateway)); - if (route != NULL) + if (route) LIBCFS_FREE(route, sizeof(*route)); - if (rnet != NULL) + if (rnet) LIBCFS_FREE(rnet, sizeof(*rnet)); return -ENOMEM; } @@ -336,25 +341,24 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, lnet_net_lock(LNET_LOCK_EX); rc = lnet_nid2peer_locked(&route->lr_gateway, gateway, LNET_LOCK_EX); - if (rc != 0) { + if (rc) { lnet_net_unlock(LNET_LOCK_EX); LIBCFS_FREE(route, sizeof(*route)); LIBCFS_FREE(rnet, sizeof(*rnet)); if (rc == -EHOSTUNREACH) /* gateway is not on a local net */ - return 0; /* ignore the route entry */ + return rc; /* ignore the route entry */ CERROR("Error %d creating route %s %d %s\n", rc, libcfs_net2str(net), hops, libcfs_nid2str(gateway)); - return rc; } LASSERT(!the_lnet.ln_shutdown); rnet2 = lnet_find_net_locked(net); - if (rnet2 == NULL) { + if (!rnet2) { /* new network */ list_add_tail(&rnet->lrn_list, lnet_net2rnethash(net)); rnet2 = rnet; @@ -382,8 +386,8 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, lnet_net_unlock(LNET_LOCK_EX); /* XXX Assume alive */ - if (ni->ni_lnd->lnd_notify != NULL) - (ni->ni_lnd->lnd_notify)(ni, gateway, 1); + if (ni->ni_lnd->lnd_notify) + ni->ni_lnd->lnd_notify(ni, gateway, 1); lnet_net_lock(LNET_LOCK_EX); } @@ -391,14 +395,20 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, /* -1 for notify or !add_route */ lnet_peer_decref_locked(route->lr_gateway); lnet_net_unlock(LNET_LOCK_EX); + rc = 0; - if (!add_route) + if (!add_route) { + rc = -EEXIST; LIBCFS_FREE(route, sizeof(*route)); + } if (rnet != rnet2) LIBCFS_FREE(rnet, sizeof(*rnet)); - return 0; + /* indicate to startup the router checker if configured */ + wake_up(&the_lnet.ln_rc_waitq); + + return rc; } int @@ -426,10 +436,9 @@ lnet_check_routes(void) lnet_nid_t nid2; int net; - route = list_entry(e2, lnet_route_t, - lr_list); + route = list_entry(e2, lnet_route_t, lr_list); - if (route2 == NULL) { + if (!route2) { route2 = route; continue; } @@ -472,9 +481,10 @@ lnet_del_route(__u32 net, lnet_nid_t gw_nid) CDEBUG(D_NET, "Del route: net %s : gw %s\n", libcfs_net2str(net), libcfs_nid2str(gw_nid)); - /* NB Caller may specify either all routes via the given gateway - * or a specific route entry actual NIDs) */ - + /* + * NB Caller may specify either all routes via the given gateway + * or a specific route entry actual NIDs) + */ lnet_net_lock(LNET_LOCK_EX); if (net == LNET_NIDNET(LNET_NID_ANY)) rn_list = &the_lnet.ln_remote_nets_hash[0]; @@ -486,7 +496,7 @@ lnet_del_route(__u32 net, lnet_nid_t gw_nid) rnet = list_entry(e1, lnet_remotenet_t, lrn_list); if (!(net == LNET_NIDNET(LNET_NID_ANY) || - net == rnet->lrn_net)) + net == rnet->lrn_net)) continue; list_for_each(e2, &rnet->lrn_routes) { @@ -513,7 +523,7 @@ lnet_del_route(__u32 net, lnet_nid_t gw_nid) LIBCFS_FREE(route, sizeof(*route)); - if (rnet != NULL) + if (rnet) LIBCFS_FREE(rnet, sizeof(*rnet)); rc = 0; @@ -538,6 +548,38 @@ lnet_destroy_routes(void) lnet_del_route(LNET_NIDNET(LNET_NID_ANY), LNET_NID_ANY); } +int lnet_get_rtr_pool_cfg(int idx, struct lnet_ioctl_pool_cfg *pool_cfg) +{ + int i, rc = -ENOENT, j; + + if (!the_lnet.ln_rtrpools) + return rc; + + for (i = 0; i < LNET_NRBPOOLS; i++) { + lnet_rtrbufpool_t *rbp; + + lnet_net_lock(LNET_LOCK_EX); + cfs_percpt_for_each(rbp, j, the_lnet.ln_rtrpools) { + if (i++ != idx) + continue; + + pool_cfg->pl_pools[i].pl_npages = rbp[i].rbp_npages; + pool_cfg->pl_pools[i].pl_nbuffers = rbp[i].rbp_nbuffers; + pool_cfg->pl_pools[i].pl_credits = rbp[i].rbp_credits; + pool_cfg->pl_pools[i].pl_mincredits = rbp[i].rbp_mincredits; + rc = 0; + break; + } + lnet_net_unlock(LNET_LOCK_EX); + } + + lnet_net_lock(LNET_LOCK_EX); + pool_cfg->pl_routing = the_lnet.ln_routing; + lnet_net_unlock(LNET_LOCK_EX); + + return rc; +} + int lnet_get_route(int idx, __u32 *net, __u32 *hops, lnet_nid_t *gateway, __u32 *alive, __u32 *priority) @@ -558,15 +600,14 @@ lnet_get_route(int idx, __u32 *net, __u32 *hops, rnet = list_entry(e1, lnet_remotenet_t, lrn_list); list_for_each(e2, &rnet->lrn_routes) { - route = list_entry(e2, lnet_route_t, - lr_list); + route = list_entry(e2, lnet_route_t, lr_list); - if (idx-- == 0) { + if (!idx--) { *net = rnet->lrn_net; *hops = route->lr_hops; *priority = route->lr_priority; *gateway = route->lr_gateway->lp_nid; - *alive = route->lr_gateway->lp_alive; + *alive = lnet_is_route_alive(route); lnet_net_unlock(cpt); return 0; } @@ -604,7 +645,7 @@ lnet_parse_rc_info(lnet_rc_data_t *rcd) { lnet_ping_info_t *info = rcd->rcd_pinginfo; struct lnet_peer *gw = rcd->rcd_gateway; - lnet_route_t *rtr; + lnet_route_t *rte; if (!gw->lp_alive) return; @@ -621,21 +662,25 @@ lnet_parse_rc_info(lnet_rc_data_t *rcd) } gw->lp_ping_feats = info->pi_features; - if ((gw->lp_ping_feats & LNET_PING_FEAT_MASK) == 0) { + if (!(gw->lp_ping_feats & LNET_PING_FEAT_MASK)) { CDEBUG(D_NET, "%s: Unexpected features 0x%x\n", libcfs_nid2str(gw->lp_nid), gw->lp_ping_feats); return; /* nothing I can understand */ } - if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) == 0) + if (!(gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS)) return; /* can't carry NI status info */ - list_for_each_entry(rtr, &gw->lp_routes, lr_gwlist) { - int ptl_status = LNET_NI_STATUS_INVALID; + list_for_each_entry(rte, &gw->lp_routes, lr_gwlist) { int down = 0; int up = 0; int i; + if (gw->lp_ping_feats & LNET_PING_FEAT_RTE_DISABLED) { + rte->lr_downis = 1; + continue; + } + for (i = 0; i < info->pi_nnis && i < LNET_MAX_RTR_NIS; i++) { lnet_ni_status_t *stat = &info->pi_ni[i]; lnet_nid_t nid = stat->ns_nid; @@ -651,22 +696,15 @@ lnet_parse_rc_info(lnet_rc_data_t *rcd) continue; if (stat->ns_status == LNET_NI_STATUS_DOWN) { - if (LNET_NETTYP(LNET_NIDNET(nid)) != PTLLND) - down++; - else if (ptl_status != LNET_NI_STATUS_UP) - ptl_status = LNET_NI_STATUS_DOWN; + down++; continue; } if (stat->ns_status == LNET_NI_STATUS_UP) { - if (LNET_NIDNET(nid) == rtr->lr_net) { + if (LNET_NIDNET(nid) == rte->lr_net) { up = 1; break; } - /* ptl NIs are considered down only when - * they're all down */ - if (LNET_NETTYP(LNET_NIDNET(nid)) == PTLLND) - ptl_status = LNET_NI_STATUS_UP; continue; } @@ -677,10 +715,17 @@ lnet_parse_rc_info(lnet_rc_data_t *rcd) } if (up) { /* ignore downed NIs if NI for dest network is up */ - rtr->lr_downis = 0; + rte->lr_downis = 0; continue; } - rtr->lr_downis = down + (ptl_status == LNET_NI_STATUS_DOWN); + /** + * if @down is zero and this route is single-hop, it means + * we can't find NI for target network + */ + if (!down && rte->lr_hops == 1) + down = 1; + + rte->lr_downis = down; } } @@ -690,7 +735,7 @@ lnet_router_checker_event(lnet_event_t *event) lnet_rc_data_t *rcd = event->md.user_ptr; struct lnet_peer *lp; - LASSERT(rcd != NULL); + LASSERT(rcd); if (event->unlinked) { LNetInvalidateHandle(&rcd->rcd_mdh); @@ -701,11 +746,13 @@ lnet_router_checker_event(lnet_event_t *event) event->type == LNET_EVENT_REPLY); lp = rcd->rcd_gateway; - LASSERT(lp != NULL); + LASSERT(lp); - /* NB: it's called with holding lnet_res_lock, we have a few - * places need to hold both locks at the same time, please take - * care of lock ordering */ + /* + * NB: it's called with holding lnet_res_lock, we have a few + * places need to hold both locks at the same time, please take + * care of lock ordering + */ lnet_net_lock(lp->lp_cpt); if (!lnet_isrouter(lp) || lp->lp_rcd != rcd) { /* ignore if no longer a router or rcd is replaced */ @@ -714,23 +761,26 @@ lnet_router_checker_event(lnet_event_t *event) if (event->type == LNET_EVENT_SEND) { lp->lp_ping_notsent = 0; - if (event->status == 0) + if (!event->status) goto out; } /* LNET_EVENT_REPLY */ - /* A successful REPLY means the router is up. If _any_ comms + /* + * A successful REPLY means the router is up. If _any_ comms * to the router fail I assume it's down (this will happen if * we ping alive routers to try to detect router death before - * apps get burned). */ + * apps get burned). + */ + lnet_notify_locked(lp, 1, !event->status, cfs_time_current()); - lnet_notify_locked(lp, 1, (event->status == 0), cfs_time_current()); - /* The router checker will wake up very shortly and do the + /* + * The router checker will wake up very shortly and do the * actual notification. * XXX If 'lp' stops being a router before then, it will still - * have the notification pending!!! */ - - if (avoid_asym_router_failure && event->status == 0) + * have the notification pending!!! + */ + if (avoid_asym_router_failure && !event->status) lnet_parse_rc_info(rcd); out: @@ -753,7 +803,7 @@ lnet_wait_known_routerstate(void) list_for_each(entry, &the_lnet.ln_routers) { rtr = list_entry(entry, lnet_peer_t, lp_rtr_list); - if (rtr->lp_alive_count == 0) { + if (!rtr->lp_alive_count) { all_known = 0; break; } @@ -774,7 +824,7 @@ lnet_router_ni_update_locked(lnet_peer_t *gw, __u32 net) { lnet_route_t *rte; - if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) != 0) { + if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS)) { list_for_each_entry(rte, &gw->lp_routes, lr_gwlist) { if (rte->lr_net == net) { rte->lr_downis = 0; @@ -811,13 +861,15 @@ lnet_update_ni_status_locked(void) continue; } - LASSERT(ni->ni_status != NULL); + LASSERT(ni->ni_status); if (ni->ni_status->ns_status != LNET_NI_STATUS_DOWN) { CDEBUG(D_NET, "NI(%s:%d) status changed to down\n", libcfs_nid2str(ni->ni_nid), timeout); - /* NB: so far, this is the only place to set - * NI status to "down" */ + /* + * NB: so far, this is the only place to set + * NI status to "down" + */ ni->ni_status->ns_status = LNET_NI_STATUS_DOWN; } lnet_ni_unlock(ni); @@ -831,7 +883,7 @@ lnet_destroy_rc_data(lnet_rc_data_t *rcd) /* detached from network */ LASSERT(LNetHandleIsInvalid(rcd->rcd_mdh)); - if (rcd->rcd_gateway != NULL) { + if (rcd->rcd_gateway) { int cpt = rcd->rcd_gateway->lp_cpt; lnet_net_lock(cpt); @@ -839,7 +891,7 @@ lnet_destroy_rc_data(lnet_rc_data_t *rcd) lnet_net_unlock(cpt); } - if (rcd->rcd_pinginfo != NULL) + if (rcd->rcd_pinginfo) LIBCFS_FREE(rcd->rcd_pinginfo, LNET_PINGINFO_SIZE); LIBCFS_FREE(rcd, sizeof(*rcd)); @@ -856,14 +908,14 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway) lnet_net_unlock(gateway->lp_cpt); LIBCFS_ALLOC(rcd, sizeof(*rcd)); - if (rcd == NULL) + if (!rcd) goto out; LNetInvalidateHandle(&rcd->rcd_mdh); INIT_LIST_HEAD(&rcd->rcd_list); LIBCFS_ALLOC(pi, LNET_PINGINFO_SIZE); - if (pi == NULL) + if (!pi) goto out; for (i = 0; i < LNET_MAX_RTR_NIS; i++) { @@ -885,11 +937,11 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway) CERROR("Can't bind MD: %d\n", rc); goto out; } - LASSERT(rc == 0); + LASSERT(!rc); lnet_net_lock(gateway->lp_cpt); /* router table changed or someone has created rcd for this gateway */ - if (!lnet_isrouter(gateway) || gateway->lp_rcd != NULL) { + if (!lnet_isrouter(gateway) || gateway->lp_rcd) { lnet_net_unlock(gateway->lp_cpt); goto out; } @@ -902,10 +954,10 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway) return rcd; out: - if (rcd != NULL) { + if (rcd) { if (!LNetHandleIsInvalid(rcd->rcd_mdh)) { rc = LNetMDUnlink(rcd->rcd_mdh); - LASSERT(rc == 0); + LASSERT(!rc); } lnet_destroy_rc_data(rcd); } @@ -936,7 +988,7 @@ lnet_ping_router_locked(lnet_peer_t *rtr) lnet_peer_addref_locked(rtr); - if (rtr->lp_ping_deadline != 0 && /* ping timed out? */ + if (rtr->lp_ping_deadline && /* ping timed out? */ cfs_time_after(now, rtr->lp_ping_deadline)) lnet_notify_locked(rtr, 1, 0, now); @@ -950,10 +1002,10 @@ lnet_ping_router_locked(lnet_peer_t *rtr) return; } - rcd = rtr->lp_rcd != NULL ? + rcd = rtr->lp_rcd ? rtr->lp_rcd : lnet_create_rc_data_locked(rtr); - if (rcd == NULL) + if (!rcd) return; secs = lnet_router_check_interval(rtr); @@ -964,7 +1016,7 @@ lnet_ping_router_locked(lnet_peer_t *rtr) rtr->lp_ping_deadline, rtr->lp_ping_notsent, rtr->lp_alive, rtr->lp_alive_count, rtr->lp_ping_timestamp); - if (secs != 0 && !rtr->lp_ping_notsent && + if (secs && !rtr->lp_ping_notsent && cfs_time_after(now, cfs_time_add(rtr->lp_ping_timestamp, cfs_time_seconds(secs)))) { int rc; @@ -972,7 +1024,7 @@ lnet_ping_router_locked(lnet_peer_t *rtr) lnet_handle_md_t mdh; id.nid = rtr->lp_nid; - id.pid = LUSTRE_SRV_LNET_PID; + id.pid = LNET_PID_LUSTRE; CDEBUG(D_NET, "Check: %s\n", libcfs_id2str(id)); rtr->lp_ping_notsent = 1; @@ -980,7 +1032,7 @@ lnet_ping_router_locked(lnet_peer_t *rtr) mdh = rcd->rcd_mdh; - if (rtr->lp_ping_deadline == 0) { + if (!rtr->lp_ping_deadline) { rtr->lp_ping_deadline = cfs_time_shift(router_ping_timeout); } @@ -991,7 +1043,7 @@ lnet_ping_router_locked(lnet_peer_t *rtr) LNET_PROTO_PING_MATCHBITS, 0); lnet_net_lock(rtr->lp_cpt); - if (rc != 0) + if (rc) rtr->lp_ping_notsent = 0; /* no event pending */ } @@ -1001,8 +1053,9 @@ lnet_ping_router_locked(lnet_peer_t *rtr) int lnet_router_checker_start(void) { + struct task_struct *task; int rc; - int eqsz; + int eqsz = 0; LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_SHUTDOWN); @@ -1012,39 +1065,33 @@ lnet_router_checker_start(void) return -EINVAL; } - if (!the_lnet.ln_routing && - live_router_check_interval <= 0 && - dead_router_check_interval <= 0) - return 0; - sema_init(&the_lnet.ln_rc_signal, 0); - /* EQ size doesn't matter; the callback is guaranteed to get every - * event */ - eqsz = 0; - rc = LNetEQAlloc(eqsz, lnet_router_checker_event, - &the_lnet.ln_rc_eqh); - if (rc != 0) { + + rc = LNetEQAlloc(0, lnet_router_checker_event, &the_lnet.ln_rc_eqh); + if (rc) { CERROR("Can't allocate EQ(%d): %d\n", eqsz, rc); return -ENOMEM; } the_lnet.ln_rc_state = LNET_RC_STATE_RUNNING; - rc = PTR_ERR(kthread_run(lnet_router_checker, - NULL, "router_checker")); - if (IS_ERR_VALUE(rc)) { + task = kthread_run(lnet_router_checker, NULL, "router_checker"); + if (IS_ERR(task)) { + rc = PTR_ERR(task); CERROR("Can't start router checker thread: %d\n", rc); /* block until event callback signals exit */ down(&the_lnet.ln_rc_signal); rc = LNetEQFree(the_lnet.ln_rc_eqh); - LASSERT(rc == 0); + LASSERT(!rc); the_lnet.ln_rc_state = LNET_RC_STATE_SHUTDOWN; return -ENOMEM; } if (check_routers_before_use) { - /* Note that a helpful side-effect of pinging all known routers + /* + * Note that a helpful side-effect of pinging all known routers * at startup is that it makes them drop stale connections they - * may have to a previous instance of me. */ + * may have to a previous instance of me. + */ lnet_wait_known_routerstate(); } @@ -1061,13 +1108,15 @@ lnet_router_checker_stop(void) LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING); the_lnet.ln_rc_state = LNET_RC_STATE_STOPPING; + /* wakeup the RC thread if it's sleeping */ + wake_up(&the_lnet.ln_rc_waitq); /* block until event callback signals exit */ down(&the_lnet.ln_rc_signal); LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_SHUTDOWN); rc = LNetEQFree(the_lnet.ln_rc_eqh); - LASSERT(rc == 0); + LASSERT(!rc); } static void @@ -1091,13 +1140,13 @@ lnet_prune_rc_data(int wait_unlink) if (the_lnet.ln_rc_state != LNET_RC_STATE_RUNNING) { /* router checker is stopping, prune all */ list_for_each_entry(lp, &the_lnet.ln_routers, - lp_rtr_list) { - if (lp->lp_rcd == NULL) + lp_rtr_list) { + if (!lp->lp_rcd) continue; LASSERT(list_empty(&lp->lp_rcd->rcd_list)); list_add(&lp->lp_rcd->rcd_list, - &the_lnet.ln_rcd_deathrow); + &the_lnet.ln_rcd_deathrow); lp->lp_rcd = NULL; } } @@ -1119,7 +1168,7 @@ lnet_prune_rc_data(int wait_unlink) /* release all zombie RCDs */ while (!list_empty(&the_lnet.ln_rcd_zombie)) { list_for_each_entry_safe(rcd, tmp, &the_lnet.ln_rcd_zombie, - rcd_list) { + rcd_list) { if (LNetHandleIsInvalid(rcd->rcd_mdh)) list_move(&rcd->rcd_list, &head); } @@ -1131,7 +1180,7 @@ lnet_prune_rc_data(int wait_unlink) while (!list_empty(&head)) { rcd = list_entry(head.next, - lnet_rc_data_t, rcd_list); + lnet_rc_data_t, rcd_list); list_del_init(&rcd->rcd_list); lnet_destroy_rc_data(rcd); } @@ -1151,6 +1200,33 @@ lnet_prune_rc_data(int wait_unlink) lnet_net_unlock(LNET_LOCK_EX); } +/* + * This function is called to check if the RC should block indefinitely. + * It's called from lnet_router_checker() as well as being passed to + * wait_event_interruptible() to avoid the lost wake_up problem. + * + * When it's called from wait_event_interruptible() it is necessary to + * also not sleep if the rc state is not running to avoid a deadlock + * when the system is shutting down + */ +static inline bool +lnet_router_checker_active(void) +{ + if (the_lnet.ln_rc_state != LNET_RC_STATE_RUNNING) + return true; + + /* + * Router Checker thread needs to run when routing is enabled in + * order to call lnet_update_ni_status_locked() + */ + if (the_lnet.ln_routing) + return true; + + return !list_empty(&the_lnet.ln_routers) && + (live_router_check_interval > 0 || + dead_router_check_interval > 0); +} + static int lnet_router_checker(void *arg) { @@ -1159,8 +1235,6 @@ lnet_router_checker(void *arg) cfs_block_allsigs(); - LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING); - while (the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING) { __u64 version; int cpt; @@ -1199,15 +1273,25 @@ rescan: lnet_prune_rc_data(0); /* don't wait for UNLINK */ - /* Call schedule_timeout() here always adds 1 to load average + /* + * Call schedule_timeout() here always adds 1 to load average * because kernel counts # active tasks as nr_running - * + nr_uninterruptible. */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(cfs_time_seconds(1)); + * + nr_uninterruptible. + */ + /* + * if there are any routes then wakeup every second. If + * there are no routes then sleep indefinitely until woken + * up by a user adding a route + */ + if (!lnet_router_checker_active()) + wait_event_interruptible(the_lnet.ln_rc_waitq, + lnet_router_checker_active()); + else + wait_event_interruptible_timeout(the_lnet.ln_rc_waitq, + false, + cfs_time_seconds(1)); } - LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_STOPPING); - lnet_prune_rc_data(1); /* wait for UNLINK */ the_lnet.ln_rc_state = LNET_RC_STATE_SHUTDOWN; @@ -1216,7 +1300,7 @@ rescan: return 0; } -static void +void lnet_destroy_rtrbuf(lnet_rtrbuf_t *rb, int npages) { int sz = offsetof(lnet_rtrbuf_t, rb_kiov[npages]); @@ -1237,7 +1321,7 @@ lnet_new_rtrbuf(lnet_rtrbufpool_t *rbp, int cpt) int i; LIBCFS_CPT_ALLOC(rb, lnet_cpt_table(), cpt, sz); - if (rb == NULL) + if (!rb) return NULL; rb->rb_pool = rbp; @@ -1246,7 +1330,7 @@ lnet_new_rtrbuf(lnet_rtrbufpool_t *rbp, int cpt) page = alloc_pages_node( cfs_cpt_spread_node(lnet_cpt_table(), cpt), GFP_KERNEL | __GFP_ZERO, 0); - if (page == NULL) { + if (!page) { while (--i >= 0) __free_page(rb->rb_kiov[i].kiov_page); @@ -1263,66 +1347,119 @@ lnet_new_rtrbuf(lnet_rtrbufpool_t *rbp, int cpt) } static void -lnet_rtrpool_free_bufs(lnet_rtrbufpool_t *rbp) +lnet_rtrpool_free_bufs(lnet_rtrbufpool_t *rbp, int cpt) { int npages = rbp->rbp_npages; - int nbuffers = 0; + struct list_head tmp; lnet_rtrbuf_t *rb; + lnet_rtrbuf_t *temp; - if (rbp->rbp_nbuffers == 0) /* not initialized or already freed */ + if (!rbp->rbp_nbuffers) /* not initialized or already freed */ return; - LASSERT(list_empty(&rbp->rbp_msgs)); - LASSERT(rbp->rbp_credits == rbp->rbp_nbuffers); + INIT_LIST_HEAD(&tmp); - while (!list_empty(&rbp->rbp_bufs)) { - LASSERT(rbp->rbp_credits > 0); + lnet_net_lock(cpt); + lnet_drop_routed_msgs_locked(&rbp->rbp_msgs, cpt); + list_splice_init(&rbp->rbp_bufs, &tmp); + rbp->rbp_req_nbuffers = 0; + rbp->rbp_nbuffers = 0; + rbp->rbp_credits = 0; + rbp->rbp_mincredits = 0; + lnet_net_unlock(cpt); - rb = list_entry(rbp->rbp_bufs.next, - lnet_rtrbuf_t, rb_list); + /* Free buffers on the free list. */ + list_for_each_entry_safe(rb, temp, &tmp, rb_list) { list_del(&rb->rb_list); lnet_destroy_rtrbuf(rb, npages); - nbuffers++; } - - LASSERT(rbp->rbp_nbuffers == nbuffers); - LASSERT(rbp->rbp_credits == nbuffers); - - rbp->rbp_nbuffers = rbp->rbp_credits = 0; } static int -lnet_rtrpool_alloc_bufs(lnet_rtrbufpool_t *rbp, int nbufs, int cpt) +lnet_rtrpool_adjust_bufs(lnet_rtrbufpool_t *rbp, int nbufs, int cpt) { + struct list_head rb_list; lnet_rtrbuf_t *rb; - int i; + int num_rb; + int num_buffers = 0; + int old_req_nbufs; + int npages = rbp->rbp_npages; - if (rbp->rbp_nbuffers != 0) { - LASSERT(rbp->rbp_nbuffers == nbufs); + lnet_net_lock(cpt); + /* + * If we are called for less buffers than already in the pool, we + * just lower the req_nbuffers number and excess buffers will be + * thrown away as they are returned to the free list. Credits + * then get adjusted as well. + * If we already have enough buffers allocated to serve the + * increase requested, then we can treat that the same way as we + * do the decrease. + */ + num_rb = nbufs - rbp->rbp_nbuffers; + if (nbufs <= rbp->rbp_req_nbuffers || num_rb <= 0) { + rbp->rbp_req_nbuffers = nbufs; + lnet_net_unlock(cpt); return 0; } + /* + * store the older value of rbp_req_nbuffers and then set it to + * the new request to prevent lnet_return_rx_credits_locked() from + * freeing buffers that we need to keep around + */ + old_req_nbufs = rbp->rbp_req_nbuffers; + rbp->rbp_req_nbuffers = nbufs; + lnet_net_unlock(cpt); - for (i = 0; i < nbufs; i++) { + INIT_LIST_HEAD(&rb_list); + + /* + * allocate the buffers on a local list first. If all buffers are + * allocated successfully then join this list to the rbp buffer + * list. If not then free all allocated buffers. + */ + while (num_rb-- > 0) { rb = lnet_new_rtrbuf(rbp, cpt); + if (!rb) { + CERROR("Failed to allocate %d route bufs of %d pages\n", + nbufs, npages); - if (rb == NULL) { - CERROR("Failed to allocate %d router bufs of %d pages\n", - nbufs, rbp->rbp_npages); - return -ENOMEM; - } + lnet_net_lock(cpt); + rbp->rbp_req_nbuffers = old_req_nbufs; + lnet_net_unlock(cpt); - rbp->rbp_nbuffers++; - rbp->rbp_credits++; - rbp->rbp_mincredits++; - list_add(&rb->rb_list, &rbp->rbp_bufs); + goto failed; + } - /* No allocation "under fire" */ - /* Otherwise we'd need code to schedule blocked msgs etc */ - LASSERT(!the_lnet.ln_routing); + list_add(&rb->rb_list, &rb_list); + num_buffers++; } - LASSERT(rbp->rbp_credits == nbufs); + lnet_net_lock(cpt); + + list_splice_tail(&rb_list, &rbp->rbp_bufs); + rbp->rbp_nbuffers += num_buffers; + rbp->rbp_credits += num_buffers; + rbp->rbp_mincredits = rbp->rbp_credits; + /* + * We need to schedule blocked msg using the newly + * added buffers. + */ + while (!list_empty(&rbp->rbp_bufs) && + !list_empty(&rbp->rbp_msgs)) + lnet_schedule_blocked_locked(rbp); + + lnet_net_unlock(cpt); + return 0; + +failed: + while (!list_empty(&rb_list)) { + rb = list_entry(rb_list.next, lnet_rtrbuf_t, rb_list); + list_del(&rb->rb_list); + lnet_destroy_rtrbuf(rb, npages); + } + + return -ENOMEM; } static void @@ -1337,26 +1474,28 @@ lnet_rtrpool_init(lnet_rtrbufpool_t *rbp, int npages) } void -lnet_rtrpools_free(void) +lnet_rtrpools_free(int keep_pools) { lnet_rtrbufpool_t *rtrp; int i; - if (the_lnet.ln_rtrpools == NULL) /* uninitialized or freed */ + if (!the_lnet.ln_rtrpools) /* uninitialized or freed */ return; cfs_percpt_for_each(rtrp, i, the_lnet.ln_rtrpools) { - lnet_rtrpool_free_bufs(&rtrp[0]); - lnet_rtrpool_free_bufs(&rtrp[1]); - lnet_rtrpool_free_bufs(&rtrp[2]); + lnet_rtrpool_free_bufs(&rtrp[LNET_TINY_BUF_IDX], i); + lnet_rtrpool_free_bufs(&rtrp[LNET_SMALL_BUF_IDX], i); + lnet_rtrpool_free_bufs(&rtrp[LNET_LARGE_BUF_IDX], i); } - cfs_percpt_free(the_lnet.ln_rtrpools); - the_lnet.ln_rtrpools = NULL; + if (!keep_pools) { + cfs_percpt_free(the_lnet.ln_rtrpools); + the_lnet.ln_rtrpools = NULL; + } } static int -lnet_nrb_tiny_calculate(int npages) +lnet_nrb_tiny_calculate(void) { int nrbs = LNET_NRB_TINY; @@ -1364,7 +1503,7 @@ lnet_nrb_tiny_calculate(int npages) LCONSOLE_ERROR_MSG(0x10c, "tiny_router_buffers=%d invalid when routing enabled\n", tiny_router_buffers); - return -1; + return -EINVAL; } if (tiny_router_buffers > 0) @@ -1375,7 +1514,7 @@ lnet_nrb_tiny_calculate(int npages) } static int -lnet_nrb_small_calculate(int npages) +lnet_nrb_small_calculate(void) { int nrbs = LNET_NRB_SMALL; @@ -1383,7 +1522,7 @@ lnet_nrb_small_calculate(int npages) LCONSOLE_ERROR_MSG(0x10c, "small_router_buffers=%d invalid when routing enabled\n", small_router_buffers); - return -1; + return -EINVAL; } if (small_router_buffers > 0) @@ -1394,7 +1533,7 @@ lnet_nrb_small_calculate(int npages) } static int -lnet_nrb_large_calculate(int npages) +lnet_nrb_large_calculate(void) { int nrbs = LNET_NRB_LARGE; @@ -1402,7 +1541,7 @@ lnet_nrb_large_calculate(int npages) LCONSOLE_ERROR_MSG(0x10c, "large_router_buffers=%d invalid when routing enabled\n", large_router_buffers); - return -1; + return -EINVAL; } if (large_router_buffers > 0) @@ -1416,16 +1555,12 @@ int lnet_rtrpools_alloc(int im_a_router) { lnet_rtrbufpool_t *rtrp; - int large_pages; - int small_pages = 1; int nrb_tiny; int nrb_small; int nrb_large; int rc; int i; - large_pages = (LNET_MTU + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - if (!strcmp(forwarding, "")) { /* not set either way */ if (!im_a_router) @@ -1440,41 +1575,46 @@ lnet_rtrpools_alloc(int im_a_router) return -EINVAL; } - nrb_tiny = lnet_nrb_tiny_calculate(0); + nrb_tiny = lnet_nrb_tiny_calculate(); if (nrb_tiny < 0) return -EINVAL; - nrb_small = lnet_nrb_small_calculate(small_pages); + nrb_small = lnet_nrb_small_calculate(); if (nrb_small < 0) return -EINVAL; - nrb_large = lnet_nrb_large_calculate(large_pages); + nrb_large = lnet_nrb_large_calculate(); if (nrb_large < 0) return -EINVAL; the_lnet.ln_rtrpools = cfs_percpt_alloc(lnet_cpt_table(), LNET_NRBPOOLS * sizeof(lnet_rtrbufpool_t)); - if (the_lnet.ln_rtrpools == NULL) { + if (!the_lnet.ln_rtrpools) { LCONSOLE_ERROR_MSG(0x10c, "Failed to initialize router buffe pool\n"); return -ENOMEM; } cfs_percpt_for_each(rtrp, i, the_lnet.ln_rtrpools) { - lnet_rtrpool_init(&rtrp[0], 0); - rc = lnet_rtrpool_alloc_bufs(&rtrp[0], nrb_tiny, i); - if (rc != 0) + lnet_rtrpool_init(&rtrp[LNET_TINY_BUF_IDX], 0); + rc = lnet_rtrpool_adjust_bufs(&rtrp[LNET_TINY_BUF_IDX], + nrb_tiny, i); + if (rc) goto failed; - lnet_rtrpool_init(&rtrp[1], small_pages); - rc = lnet_rtrpool_alloc_bufs(&rtrp[1], nrb_small, i); - if (rc != 0) + lnet_rtrpool_init(&rtrp[LNET_SMALL_BUF_IDX], + LNET_NRB_SMALL_PAGES); + rc = lnet_rtrpool_adjust_bufs(&rtrp[LNET_SMALL_BUF_IDX], + nrb_small, i); + if (rc) goto failed; - lnet_rtrpool_init(&rtrp[2], large_pages); - rc = lnet_rtrpool_alloc_bufs(&rtrp[2], nrb_large, i); - if (rc != 0) + lnet_rtrpool_init(&rtrp[LNET_LARGE_BUF_IDX], + LNET_NRB_LARGE_PAGES); + rc = lnet_rtrpool_adjust_bufs(&rtrp[LNET_LARGE_BUF_IDX], + nrb_large, i); + if (rc) goto failed; } @@ -1485,10 +1625,118 @@ lnet_rtrpools_alloc(int im_a_router) return 0; failed: - lnet_rtrpools_free(); + lnet_rtrpools_free(0); return rc; } +static int +lnet_rtrpools_adjust_helper(int tiny, int small, int large) +{ + int nrb = 0; + int rc = 0; + int i; + lnet_rtrbufpool_t *rtrp; + + /* + * If the provided values for each buffer pool are different than the + * configured values, we need to take action. + */ + if (tiny >= 0) { + tiny_router_buffers = tiny; + nrb = lnet_nrb_tiny_calculate(); + cfs_percpt_for_each(rtrp, i, the_lnet.ln_rtrpools) { + rc = lnet_rtrpool_adjust_bufs(&rtrp[LNET_TINY_BUF_IDX], + nrb, i); + if (rc) + return rc; + } + } + if (small >= 0) { + small_router_buffers = small; + nrb = lnet_nrb_small_calculate(); + cfs_percpt_for_each(rtrp, i, the_lnet.ln_rtrpools) { + rc = lnet_rtrpool_adjust_bufs(&rtrp[LNET_SMALL_BUF_IDX], + nrb, i); + if (rc) + return rc; + } + } + if (large >= 0) { + large_router_buffers = large; + nrb = lnet_nrb_large_calculate(); + cfs_percpt_for_each(rtrp, i, the_lnet.ln_rtrpools) { + rc = lnet_rtrpool_adjust_bufs(&rtrp[LNET_LARGE_BUF_IDX], + nrb, i); + if (rc) + return rc; + } + } + + return 0; +} + +int +lnet_rtrpools_adjust(int tiny, int small, int large) +{ + /* + * this function doesn't revert the changes if adding new buffers + * failed. It's up to the user space caller to revert the + * changes. + */ + if (!the_lnet.ln_routing) + return 0; + + return lnet_rtrpools_adjust_helper(tiny, small, large); +} + +int +lnet_rtrpools_enable(void) +{ + int rc; + + if (the_lnet.ln_routing) + return 0; + + if (!the_lnet.ln_rtrpools) + /* + * If routing is turned off, and we have never + * initialized the pools before, just call the + * standard buffer pool allocation routine as + * if we are just configuring this for the first + * time. + */ + return lnet_rtrpools_alloc(1); + + rc = lnet_rtrpools_adjust_helper(0, 0, 0); + if (rc) + return rc; + + lnet_net_lock(LNET_LOCK_EX); + the_lnet.ln_routing = 1; + + the_lnet.ln_ping_info->pi_features &= ~LNET_PING_FEAT_RTE_DISABLED; + lnet_net_unlock(LNET_LOCK_EX); + + return 0; +} + +void +lnet_rtrpools_disable(void) +{ + if (!the_lnet.ln_routing) + return; + + lnet_net_lock(LNET_LOCK_EX); + the_lnet.ln_routing = 0; + the_lnet.ln_ping_info->pi_features |= LNET_PING_FEAT_RTE_DISABLED; + + tiny_router_buffers = 0; + small_router_buffers = 0; + large_router_buffers = 0; + lnet_net_unlock(LNET_LOCK_EX); + lnet_rtrpools_free(1); +} + int lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) { @@ -1499,28 +1747,28 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) LASSERT(!in_interrupt()); CDEBUG(D_NET, "%s notifying %s: %s\n", - (ni == NULL) ? "userspace" : libcfs_nid2str(ni->ni_nid), - libcfs_nid2str(nid), - alive ? "up" : "down"); + !ni ? "userspace" : libcfs_nid2str(ni->ni_nid), + libcfs_nid2str(nid), + alive ? "up" : "down"); - if (ni != NULL && + if (ni && LNET_NIDNET(ni->ni_nid) != LNET_NIDNET(nid)) { CWARN("Ignoring notification of %s %s by %s (different net)\n", - libcfs_nid2str(nid), alive ? "birth" : "death", - libcfs_nid2str(ni->ni_nid)); + libcfs_nid2str(nid), alive ? "birth" : "death", + libcfs_nid2str(ni->ni_nid)); return -EINVAL; } /* can't do predictions... */ if (cfs_time_after(when, now)) { CWARN("Ignoring prediction from %s of %s %s %ld seconds in the future\n", - (ni == NULL) ? "userspace" : libcfs_nid2str(ni->ni_nid), + !ni ? "userspace" : libcfs_nid2str(ni->ni_nid), libcfs_nid2str(nid), alive ? "up" : "down", cfs_duration_sec(cfs_time_sub(when, now))); return -EINVAL; } - if (ni != NULL && !alive && /* LND telling me she's down */ + if (ni && !alive && /* LND telling me she's down */ !auto_down) { /* auto-down disabled */ CDEBUG(D_NET, "Auto-down disabled\n"); return 0; @@ -1534,23 +1782,26 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) } lp = lnet_find_peer_locked(the_lnet.ln_peer_tables[cpt], nid); - if (lp == NULL) { + if (!lp) { /* nid not found */ lnet_net_unlock(cpt); CDEBUG(D_NET, "%s not found\n", libcfs_nid2str(nid)); return 0; } - /* We can't fully trust LND on reporting exact peer last_alive + /* + * We can't fully trust LND on reporting exact peer last_alive * if he notifies us about dead peer. For example ksocklnd can * call us with when == _time_when_the_node_was_booted_ if - * no connections were successfully established */ - if (ni != NULL && !alive && when < lp->lp_last_alive) + * no connections were successfully established + */ + if (ni && !alive && when < lp->lp_last_alive) when = lp->lp_last_alive; - lnet_notify_locked(lp, ni == NULL, alive, when); + lnet_notify_locked(lp, !ni, alive, when); - lnet_ni_notify_locked(ni, lp); + if (ni) + lnet_ni_notify_locked(ni, lp); lnet_peer_decref_locked(lp); diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index 396c7c4e5c83..65f65a3fc901 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -15,18 +15,16 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Portals; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * */ #define DEBUG_SUBSYSTEM S_LNET #include "../../include/linux/libcfs/libcfs.h" #include "../../include/linux/lnet/lib-lnet.h" -/* This is really lnet_proc.c. You might need to update sanity test 215 - * if any file format is changed. */ +/* + * This is really lnet_proc.c. You might need to update sanity test 215 + * if any file format is changed. + */ #define LNET_LOFFT_BITS (sizeof(loff_t) * 8) /* @@ -75,25 +73,6 @@ #define LNET_PROC_VERSION(v) ((unsigned int)((v) & LNET_PROC_VER_MASK)) -static int proc_call_handler(void *data, int write, loff_t *ppos, - void __user *buffer, size_t *lenp, - int (*handler)(void *data, int write, - loff_t pos, void __user *buffer, int len)) -{ - int rc = handler(data, write, *ppos, buffer, *lenp); - - if (rc < 0) - return rc; - - if (write) { - *ppos += *lenp; - } else { - *lenp = rc; - *ppos += rc; - } - return 0; -} - static int __proc_lnet_stats(void *data, int write, loff_t pos, void __user *buffer, int nob) { @@ -111,11 +90,11 @@ static int __proc_lnet_stats(void *data, int write, /* read */ LIBCFS_ALLOC(ctrs, sizeof(*ctrs)); - if (ctrs == NULL) + if (!ctrs) return -ENOMEM; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) { + if (!tmpstr) { LIBCFS_FREE(ctrs, sizeof(*ctrs)); return -ENOMEM; } @@ -145,8 +124,8 @@ static int __proc_lnet_stats(void *data, int write, static int proc_lnet_stats(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - return proc_call_handler(table->data, write, ppos, buffer, lenp, - __proc_lnet_stats); + return lprocfs_call_handler(table->data, write, ppos, buffer, lenp, + __proc_lnet_stats); } static int proc_lnet_routes(struct ctl_table *table, int write, @@ -167,16 +146,16 @@ static int proc_lnet_routes(struct ctl_table *table, int write, LASSERT(!write); - if (*lenp == 0) + if (!*lenp) return 0; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ - if (*ppos == 0) { + if (!*ppos) { s += snprintf(s, tmpstr + tmpsiz - s, "Routing %s\n", the_lnet.ln_routing ? "enabled" : "disabled"); LASSERT(tmpstr + tmpsiz - s > 0); @@ -206,23 +185,22 @@ static int proc_lnet_routes(struct ctl_table *table, int write, return -ESTALE; } - for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE && route == NULL; - i++) { + for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE && !route; i++) { rn_list = &the_lnet.ln_remote_nets_hash[i]; n = rn_list->next; - while (n != rn_list && route == NULL) { + while (n != rn_list && !route) { rnet = list_entry(n, lnet_remotenet_t, - lrn_list); + lrn_list); r = rnet->lrn_routes.next; while (r != &rnet->lrn_routes) { lnet_route_t *re = list_entry(r, lnet_route_t, - lr_list); - if (skip == 0) { + lr_list); + if (!skip) { route = re; break; } @@ -235,12 +213,12 @@ static int proc_lnet_routes(struct ctl_table *table, int write, } } - if (route != NULL) { + if (route) { __u32 net = rnet->lrn_net; - unsigned int hops = route->lr_hops; + __u32 hops = route->lr_hops; unsigned int priority = route->lr_priority; lnet_nid_t nid = route->lr_gateway->lp_nid; - int alive = route->lr_gateway->lp_alive; + int alive = lnet_is_route_alive(route); s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4u %8u %7s %s\n", @@ -259,9 +237,9 @@ static int proc_lnet_routes(struct ctl_table *table, int write, if (len > *lenp) { /* linux-supplied buffer is too small */ rc = -EINVAL; } else if (len > 0) { /* wrote something */ - if (copy_to_user(buffer, tmpstr, len)) + if (copy_to_user(buffer, tmpstr, len)) { rc = -EFAULT; - else { + } else { off += 1; *ppos = LNET_PROC_POS_MAKE(0, ver, 0, off); } @@ -269,7 +247,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write, LIBCFS_FREE(tmpstr, tmpsiz); - if (rc == 0) + if (!rc) *lenp = len; return rc; @@ -291,16 +269,16 @@ static int proc_lnet_routers(struct ctl_table *table, int write, LASSERT(!write); - if (*lenp == 0) + if (!*lenp) return 0; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ - if (*ppos == 0) { + if (!*ppos) { s += snprintf(s, tmpstr + tmpsiz - s, "%-4s %7s %9s %6s %12s %9s %8s %7s %s\n", "ref", "rtr_ref", "alive_cnt", "state", @@ -330,9 +308,9 @@ static int proc_lnet_routers(struct ctl_table *table, int write, while (r != &the_lnet.ln_routers) { lnet_peer_t *lp = list_entry(r, lnet_peer_t, - lp_rtr_list); + lp_rtr_list); - if (skip == 0) { + if (!skip) { peer = lp; break; } @@ -341,7 +319,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write, r = r->next; } - if (peer != NULL) { + if (peer) { lnet_nid_t nid = peer->lp_nid; unsigned long now = cfs_time_current(); unsigned long deadline = peer->lp_ping_deadline; @@ -356,19 +334,21 @@ static int proc_lnet_routers(struct ctl_table *table, int write, lnet_route_t *rtr; if ((peer->lp_ping_feats & - LNET_PING_FEAT_NI_STATUS) != 0) { + LNET_PING_FEAT_NI_STATUS)) { list_for_each_entry(rtr, &peer->lp_routes, - lr_gwlist) { - /* downis on any route should be the - * number of downis on the gateway */ - if (rtr->lr_downis != 0) { + lr_gwlist) { + /* + * downis on any route should be the + * number of downis on the gateway + */ + if (rtr->lr_downis) { down_ni = rtr->lr_downis; break; } } } - if (deadline == 0) + if (!deadline) s += snprintf(s, tmpstr + tmpsiz - s, "%-4d %7d %9d %6s %12d %9d %8s %7d %s\n", nrefs, nrtrrefs, alive_cnt, @@ -394,9 +374,9 @@ static int proc_lnet_routers(struct ctl_table *table, int write, if (len > *lenp) { /* linux-supplied buffer is too small */ rc = -EINVAL; } else if (len > 0) { /* wrote something */ - if (copy_to_user(buffer, tmpstr, len)) + if (copy_to_user(buffer, tmpstr, len)) { rc = -EFAULT; - else { + } else { off += 1; *ppos = LNET_PROC_POS_MAKE(0, ver, 0, off); } @@ -404,7 +384,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write, LIBCFS_FREE(tmpstr, tmpsiz); - if (rc == 0) + if (!rc) *lenp = len; return rc; @@ -427,7 +407,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, CLASSERT(LNET_PROC_HASH_BITS >= LNET_PEER_HASH_BITS); LASSERT(!write); - if (*lenp == 0) + if (!*lenp) return 0; if (cpt >= LNET_CPT_NUMBER) { @@ -436,12 +416,12 @@ static int proc_lnet_peers(struct ctl_table *table, int write, } LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ - if (*ppos == 0) { + if (!*ppos) { s += snprintf(s, tmpstr + tmpsiz - s, "%-24s %4s %5s %5s %5s %5s %5s %5s %5s %s\n", "nid", "refs", "state", "last", "max", @@ -470,18 +450,20 @@ static int proc_lnet_peers(struct ctl_table *table, int write, } while (hash < LNET_PEER_HASH_SIZE) { - if (p == NULL) + if (!p) p = ptable->pt_hash[hash].next; while (p != &ptable->pt_hash[hash]) { lnet_peer_t *lp = list_entry(p, lnet_peer_t, - lp_hashlist); - if (skip == 0) { + lp_hashlist); + if (!skip) { peer = lp; - /* minor optimization: start from idx+1 + /* + * minor optimization: start from idx+1 * on next iteration if we've just - * drained lp_hashlist */ + * drained lp_hashlist + */ if (lp->lp_hashlist.next == &ptable->pt_hash[hash]) { hoff = 1; @@ -497,7 +479,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, p = lp->lp_hashlist.next; } - if (peer != NULL) + if (peer) break; p = NULL; @@ -505,7 +487,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, hash++; } - if (peer != NULL) { + if (peer) { lnet_nid_t nid = peer->lp_nid; int nrefs = peer->lp_refcount; int lastalive = -1; @@ -553,7 +535,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, cpt++; hash = 0; hoff = 1; - if (peer == NULL && cpt < LNET_CPT_NUMBER) + if (!peer && cpt < LNET_CPT_NUMBER) goto again; } } @@ -571,7 +553,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, LIBCFS_FREE(tmpstr, tmpsiz); - if (rc == 0) + if (!rc) *lenp = len; return rc; @@ -593,7 +575,7 @@ static int __proc_lnet_buffers(void *data, int write, /* (4 %d) * 4 * LNET_CPT_NUMBER */ tmpsiz = 64 * (LNET_NRBPOOLS + 1) * LNET_CPT_NUMBER; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ @@ -603,7 +585,7 @@ static int __proc_lnet_buffers(void *data, int write, "pages", "count", "credits", "min"); LASSERT(tmpstr + tmpsiz - s > 0); - if (the_lnet.ln_rtrpools == NULL) + if (!the_lnet.ln_rtrpools) goto out; /* I'm not a router */ for (idx = 0; idx < LNET_NRBPOOLS; idx++) { @@ -638,8 +620,8 @@ static int __proc_lnet_buffers(void *data, int write, static int proc_lnet_buffers(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - return proc_call_handler(table->data, write, ppos, buffer, lenp, - __proc_lnet_buffers); + return lprocfs_call_handler(table->data, write, ppos, buffer, lenp, + __proc_lnet_buffers); } static int proc_lnet_nis(struct ctl_table *table, int write, @@ -653,16 +635,16 @@ static int proc_lnet_nis(struct ctl_table *table, int write, LASSERT(!write); - if (*lenp == 0) + if (!*lenp) return 0; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ - if (*ppos == 0) { + if (!*ppos) { s += snprintf(s, tmpstr + tmpsiz - s, "%-24s %6s %5s %4s %4s %4s %5s %5s %5s\n", "nid", "status", "alive", "refs", "peer", @@ -680,7 +662,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, while (n != &the_lnet.ln_nis) { lnet_ni_t *a_ni = list_entry(n, lnet_ni_t, ni_list); - if (skip == 0) { + if (!skip) { ni = a_ni; break; } @@ -689,7 +671,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, n = n->next; } - if (ni != NULL) { + if (ni) { struct lnet_tx_queue *tq; char *stat; time64_t now = ktime_get_real_seconds(); @@ -705,15 +687,17 @@ static int proc_lnet_nis(struct ctl_table *table, int write, last_alive = 0; lnet_ni_lock(ni); - LASSERT(ni->ni_status != NULL); + LASSERT(ni->ni_status); stat = (ni->ni_status->ns_status == LNET_NI_STATUS_UP) ? "up" : "down"; lnet_ni_unlock(ni); - /* we actually output credits information for - * TX queue of each partition */ + /* + * we actually output credits information for + * TX queue of each partition + */ cfs_percpt_for_each(tq, i, ni->ni_tx_queues) { - for (j = 0; ni->ni_cpts != NULL && + for (j = 0; ni->ni_cpts && j < ni->ni_ncpts; j++) { if (i == ni->ni_cpts[j]) break; @@ -722,18 +706,19 @@ static int proc_lnet_nis(struct ctl_table *table, int write, if (j == ni->ni_ncpts) continue; - if (i != 0) + if (i) lnet_net_lock(i); s += snprintf(s, tmpstr + tmpsiz - s, - "%-24s %6s %5d %4d %4d %4d %5d %5d %5d\n", - libcfs_nid2str(ni->ni_nid), stat, - last_alive, *ni->ni_refs[i], - ni->ni_peertxcredits, - ni->ni_peerrtrcredits, - tq->tq_credits_max, - tq->tq_credits, tq->tq_credits_min); - if (i != 0) + "%-24s %6s %5d %4d %4d %4d %5d %5d %5d\n", + libcfs_nid2str(ni->ni_nid), stat, + last_alive, *ni->ni_refs[i], + ni->ni_peertxcredits, + ni->ni_peerrtrcredits, + tq->tq_credits_max, + tq->tq_credits, + tq->tq_credits_min); + if (i) lnet_net_unlock(i); } LASSERT(tmpstr + tmpsiz - s > 0); @@ -755,7 +740,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, LIBCFS_FREE(tmpstr, tmpsiz); - if (rc == 0) + if (!rc) *lenp = len; return rc; @@ -795,8 +780,6 @@ static struct lnet_portal_rotors portal_rotors[] = { }, }; -extern int portal_rotor; - static int __proc_lnet_portal_rotor(void *data, int write, loff_t pos, void __user *buffer, int nob) { @@ -807,7 +790,7 @@ static int __proc_lnet_portal_rotor(void *data, int write, int i; LIBCFS_ALLOC(buf, buf_len); - if (buf == NULL) + if (!buf) return -ENOMEM; if (!write) { @@ -831,7 +814,7 @@ static int __proc_lnet_portal_rotor(void *data, int write, rc = 0; } else { rc = cfs_trace_copyout_string(buffer, nob, - buf + pos, "\n"); + buf + pos, "\n"); } goto out; } @@ -844,9 +827,9 @@ static int __proc_lnet_portal_rotor(void *data, int write, rc = -EINVAL; lnet_res_lock(0); - for (i = 0; portal_rotors[i].pr_name != NULL; i++) { - if (strncasecmp(portal_rotors[i].pr_name, tmp, - strlen(portal_rotors[i].pr_name)) == 0) { + for (i = 0; portal_rotors[i].pr_name; i++) { + if (!strncasecmp(portal_rotors[i].pr_name, tmp, + strlen(portal_rotors[i].pr_name))) { portal_rotor = portal_rotors[i].pr_value; rc = 0; break; @@ -862,8 +845,8 @@ static int proc_lnet_portal_rotor(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - return proc_call_handler(table->data, write, ppos, buffer, lenp, - __proc_lnet_portal_rotor); + return lprocfs_call_handler(table->data, write, ppos, buffer, lenp, + __proc_lnet_portal_rotor); } static struct ctl_table lnet_table[] = { |