X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lnet%2Flnet%2Fapi-ni.c;h=f2b4b2bf3b310a7f65b0fc8e10d1b2c34a5d3a81;hp=2f681d772615aadc3bdbcf67b3f3393ab9523c8d;hb=2118a8b92cec2df85d1bdbe2e58b389d83fe06b2;hpb=c72335a45d56d1ad61a65c228a8aff0cf010b1dc diff --git a/lnet/lnet/api-ni.c b/lnet/lnet/api-ni.c index 2f681d7..f2b4b2b 100644 --- a/lnet/lnet/api-ni.c +++ b/lnet/lnet/api-ni.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -28,6 +26,8 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2011, Whamcloud, Inc. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -91,10 +91,10 @@ lnet_get_networks(void) void lnet_init_locks(void) { - cfs_spin_lock_init (&the_lnet.ln_lock); - cfs_waitq_init (&the_lnet.ln_waitq); - cfs_init_mutex(&the_lnet.ln_lnd_mutex); - cfs_init_mutex(&the_lnet.ln_api_mutex); + cfs_spin_lock_init (&the_lnet.ln_lock); + cfs_waitq_init(&the_lnet.ln_eq_waitq); + cfs_mutex_init(&the_lnet.ln_lnd_mutex); + cfs_mutex_init(&the_lnet.ln_api_mutex); } void @@ -137,8 +137,8 @@ lnet_get_networks (void) return (rc == 0) ? networks : NULL; } #else - ip2nets = NULL; - rc = 0; + SET_BUT_UNUSED(ip2nets); + SET_BUT_UNUSED(rc); #endif if (networks != NULL) return networks; @@ -189,18 +189,18 @@ void lnet_fini_locks(void) void lnet_init_locks(void) { - pthread_cond_init(&the_lnet.ln_cond, NULL); - pthread_mutex_init(&the_lnet.ln_lock, NULL); - pthread_mutex_init(&the_lnet.ln_lnd_mutex, NULL); - pthread_mutex_init(&the_lnet.ln_api_mutex, NULL); + pthread_cond_init(&the_lnet.ln_eq_cond, NULL); + pthread_mutex_init(&the_lnet.ln_lock, NULL); + pthread_mutex_init(&the_lnet.ln_lnd_mutex, NULL); + pthread_mutex_init(&the_lnet.ln_api_mutex, NULL); } void lnet_fini_locks(void) { - pthread_mutex_destroy(&the_lnet.ln_api_mutex); - pthread_mutex_destroy(&the_lnet.ln_lnd_mutex); - pthread_mutex_destroy(&the_lnet.ln_lock); - pthread_cond_destroy(&the_lnet.ln_cond); + pthread_mutex_destroy(&the_lnet.ln_api_mutex); + pthread_mutex_destroy(&the_lnet.ln_lnd_mutex); + pthread_mutex_destroy(&the_lnet.ln_lock); + pthread_cond_destroy(&the_lnet.ln_eq_cond); } # endif @@ -319,7 +319,7 @@ lnet_find_lnd_by_type (int type) void lnet_register_lnd (lnd_t *lnd) { - LNET_MUTEX_DOWN(&the_lnet.ln_lnd_mutex); + LNET_MUTEX_LOCK(&the_lnet.ln_lnd_mutex); LASSERT (the_lnet.ln_init); LASSERT (libcfs_isknown_lnd(lnd->lnd_type)); @@ -330,13 +330,13 @@ lnet_register_lnd (lnd_t *lnd) CDEBUG(D_NET, "%s LND registered\n", libcfs_lnd2str(lnd->lnd_type)); - LNET_MUTEX_UP(&the_lnet.ln_lnd_mutex); + LNET_MUTEX_UNLOCK(&the_lnet.ln_lnd_mutex); } void lnet_unregister_lnd (lnd_t *lnd) { - LNET_MUTEX_DOWN(&the_lnet.ln_lnd_mutex); + LNET_MUTEX_LOCK(&the_lnet.ln_lnd_mutex); LASSERT (the_lnet.ln_init); LASSERT (lnet_find_lnd_by_type(lnd->lnd_type) == lnd); @@ -345,23 +345,10 @@ lnet_unregister_lnd (lnd_t *lnd) cfs_list_del (&lnd->lnd_list); CDEBUG(D_NET, "%s LND unregistered\n", libcfs_lnd2str(lnd->lnd_type)); - LNET_MUTEX_UP(&the_lnet.ln_lnd_mutex); -} - -#ifndef LNET_USE_LIB_FREELIST - -int -lnet_descriptor_setup (void) -{ - return 0; -} - -void -lnet_descriptor_cleanup (void) -{ + LNET_MUTEX_UNLOCK(&the_lnet.ln_lnd_mutex); } -#else +#ifdef LNET_USE_LIB_FREELIST int lnet_freelist_init (lnet_freelist_t *fl, int n, int size) @@ -410,48 +397,7 @@ lnet_freelist_fini (lnet_freelist_t *fl) memset (fl, 0, sizeof (*fl)); } -int -lnet_descriptor_setup (void) -{ - /* NB on failure caller must still call lnet_descriptor_cleanup */ - /* ****** */ - int rc; - - memset (&the_lnet.ln_free_mes, 0, sizeof (the_lnet.ln_free_mes)); - memset (&the_lnet.ln_free_msgs, 0, sizeof (the_lnet.ln_free_msgs)); - memset (&the_lnet.ln_free_mds, 0, sizeof (the_lnet.ln_free_mds)); - memset (&the_lnet.ln_free_eqs, 0, sizeof (the_lnet.ln_free_eqs)); - - rc = lnet_freelist_init(&the_lnet.ln_free_mes, - MAX_MES, sizeof (lnet_me_t)); - if (rc != 0) - return (rc); - - rc = lnet_freelist_init(&the_lnet.ln_free_msgs, - MAX_MSGS, sizeof (lnet_msg_t)); - if (rc != 0) - return (rc); - - rc = lnet_freelist_init(&the_lnet.ln_free_mds, - MAX_MDS, sizeof (lnet_libmd_t)); - if (rc != 0) - return (rc); - - rc = lnet_freelist_init(&the_lnet.ln_free_eqs, - MAX_EQS, sizeof (lnet_eq_t)); - return (rc); -} - -void -lnet_descriptor_cleanup (void) -{ - lnet_freelist_fini (&the_lnet.ln_free_mes); - lnet_freelist_fini (&the_lnet.ln_free_msgs); - lnet_freelist_fini (&the_lnet.ln_free_mds); - lnet_freelist_fini (&the_lnet.ln_free_eqs); -} - -#endif +#endif /* LNET_USE_LIB_FREELIST */ __u64 lnet_create_interface_cookie (void) @@ -474,133 +420,146 @@ lnet_create_interface_cookie (void) return cookie; } -int -lnet_setup_handle_hash (void) +static char * +lnet_res_type2str(int type) { - int i; - - /* Arbitrary choice of hash table size */ -#ifdef __KERNEL__ - the_lnet.ln_lh_hash_size = - CFS_PAGE_SIZE / sizeof (cfs_list_t); -#else - the_lnet.ln_lh_hash_size = (MAX_MES + MAX_MDS + MAX_EQS)/4; -#endif - LIBCFS_ALLOC(the_lnet.ln_lh_hash_table, - the_lnet.ln_lh_hash_size * sizeof (cfs_list_t)); - if (the_lnet.ln_lh_hash_table == NULL) - return (-ENOMEM); - - for (i = 0; i < the_lnet.ln_lh_hash_size; i++) - CFS_INIT_LIST_HEAD (&the_lnet.ln_lh_hash_table[i]); - - the_lnet.ln_next_object_cookie = LNET_COOKIE_TYPES; - - return (0); + switch (type) { + default: + LBUG(); + case LNET_COOKIE_TYPE_MD: + return "MD"; + case LNET_COOKIE_TYPE_ME: + return "ME"; + case LNET_COOKIE_TYPE_EQ: + return "EQ"; + } } void -lnet_cleanup_handle_hash (void) +lnet_res_container_cleanup(struct lnet_res_container *rec) { - if (the_lnet.ln_lh_hash_table == NULL) - return; + int count = 0; - LIBCFS_FREE(the_lnet.ln_lh_hash_table, - the_lnet.ln_lh_hash_size * sizeof (cfs_list_t)); -} + if (rec->rec_type == 0) /* not set yet, it's a uninitialized */ + return; -lnet_libhandle_t * -lnet_lookup_cookie (__u64 cookie, int type) -{ - /* ALWAYS called with LNET_LOCK held */ - cfs_list_t *list; - cfs_list_t *el; - unsigned int hash; + while (!cfs_list_empty(&rec->rec_active)) { + cfs_list_t *e = rec->rec_active.next; - if ((cookie & (LNET_COOKIE_TYPES - 1)) != type) - return (NULL); + cfs_list_del_init(e); + if (rec->rec_type == LNET_COOKIE_TYPE_EQ) { + lnet_eq_free(cfs_list_entry(e, lnet_eq_t, eq_list)); - hash = ((unsigned int)cookie) % the_lnet.ln_lh_hash_size; - list = &the_lnet.ln_lh_hash_table[hash]; + } else if (rec->rec_type == LNET_COOKIE_TYPE_MD) { + lnet_md_free(cfs_list_entry(e, lnet_libmd_t, md_list)); - cfs_list_for_each (el, list) { - lnet_libhandle_t *lh = cfs_list_entry (el, lnet_libhandle_t, - lh_hash_chain); + } else { /* NB: Active MEs should be attached on portals */ + LBUG(); + } + count++; + } - if (lh->lh_cookie == cookie) - return (lh); - } + if (count > 0) { + /* 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 */ + CERROR("%d active elements on exit of %s container\n", + count, lnet_res_type2str(rec->rec_type)); + } + +#ifdef LNET_USE_LIB_FREELIST + lnet_freelist_fini(&rec->rec_freelist); +#endif + if (rec->rec_lh_hash != NULL) { + LIBCFS_FREE(rec->rec_lh_hash, + LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0])); + rec->rec_lh_hash = NULL; + } - return (NULL); + rec->rec_type = 0; /* mark it as finalized */ } -void -lnet_initialise_handle (lnet_libhandle_t *lh, int type) +int +lnet_res_container_setup(struct lnet_res_container *rec, + int type, int objnum, int objsz) { - /* ALWAYS called with LNET_LOCK held */ - unsigned int hash; + int rc = 0; + int i; - LASSERT (type >= 0 && type < LNET_COOKIE_TYPES); - lh->lh_cookie = the_lnet.ln_next_object_cookie | type; - the_lnet.ln_next_object_cookie += LNET_COOKIE_TYPES; + LASSERT(rec->rec_type == 0); - hash = ((unsigned int)lh->lh_cookie) % the_lnet.ln_lh_hash_size; - cfs_list_add (&lh->lh_hash_chain, &the_lnet.ln_lh_hash_table[hash]); -} + rec->rec_type = type; + CFS_INIT_LIST_HEAD(&rec->rec_active); -void -lnet_invalidate_handle (lnet_libhandle_t *lh) -{ - /* ALWAYS called with LNET_LOCK held */ - cfs_list_del (&lh->lh_hash_chain); +#ifdef LNET_USE_LIB_FREELIST + memset(&rec->rec_freelist, 0, sizeof(rec->rec_freelist)); + rc = lnet_freelist_init(&rec->rec_freelist, objnum, objsz); + if (rc != 0) + goto out; +#endif + rec->rec_lh_cookie = type; + + /* Arbitrary choice of hash table size */ + LIBCFS_ALLOC(rec->rec_lh_hash, + LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0])); + if (rec->rec_lh_hash == NULL) { + rc = -ENOMEM; + goto out; + } + + for (i = 0; i < LNET_LH_HASH_SIZE; i++) + CFS_INIT_LIST_HEAD(&rec->rec_lh_hash[i]); + + return 0; + +out: + CERROR("Failed to setup %s resource container\n", + lnet_res_type2str(type)); + lnet_res_container_cleanup(rec); + return rc; } -int -lnet_init_finalizers(void) +lnet_libhandle_t * +lnet_res_lh_lookup(struct lnet_res_container *rec, __u64 cookie) { -#ifdef __KERNEL__ - int i; + /* ALWAYS called with lnet_res_lock held */ + cfs_list_t *head; + lnet_libhandle_t *lh; + unsigned int hash; - the_lnet.ln_nfinalizers = (int) cfs_num_online_cpus(); + if ((cookie & (LNET_COOKIE_TYPES - 1)) != rec->rec_type) + return NULL; - LIBCFS_ALLOC(the_lnet.ln_finalizers, - the_lnet.ln_nfinalizers * - sizeof(*the_lnet.ln_finalizers)); - if (the_lnet.ln_finalizers == NULL) { - CERROR("Can't allocate ln_finalizers\n"); - return -ENOMEM; - } + hash = cookie >> LNET_COOKIE_TYPE_BITS; + head = &rec->rec_lh_hash[hash & LNET_LH_HASH_MASK]; - for (i = 0; i < the_lnet.ln_nfinalizers; i++) - the_lnet.ln_finalizers[i] = NULL; -#else - the_lnet.ln_finalizing = 0; -#endif + cfs_list_for_each_entry(lh, head, lh_hash_chain) { + if (lh->lh_cookie == cookie) + return lh; + } - CFS_INIT_LIST_HEAD(&the_lnet.ln_finalizeq); - return 0; + return NULL; } void -lnet_fini_finalizers(void) +lnet_res_lh_initialize(struct lnet_res_container *rec, lnet_libhandle_t *lh) { -#ifdef __KERNEL__ - int i; + /* ALWAYS called with lnet_res_lock held */ + unsigned int ibits = LNET_COOKIE_TYPE_BITS; + unsigned int hash; - for (i = 0; i < the_lnet.ln_nfinalizers; i++) - LASSERT (the_lnet.ln_finalizers[i] == NULL); + lh->lh_cookie = rec->rec_lh_cookie; + rec->rec_lh_cookie += 1 << ibits; - LIBCFS_FREE(the_lnet.ln_finalizers, - the_lnet.ln_nfinalizers * - sizeof(*the_lnet.ln_finalizers)); -#else - LASSERT (!the_lnet.ln_finalizing); -#endif - LASSERT (cfs_list_empty(&the_lnet.ln_finalizeq)); + hash = (lh->lh_cookie >> ibits) & LNET_LH_HASH_MASK; + + cfs_list_add(&lh->lh_hash_chain, &rec->rec_lh_hash[hash]); } #ifndef __KERNEL__ -/* Temporary workaround to allow uOSS and test programs force server +/** + * Reserved API - do not use. + * Temporary workaround to allow uOSS and test programs force server * mode in userspace. See comments near ln_server_mode_flag in * lnet/lib-types.h */ @@ -615,7 +574,6 @@ lnet_prepare(lnet_pid_t requested_pid) { /* Prepare to bring up the network */ int rc = 0; - int i; LASSERT (the_lnet.ln_refcount == 0); @@ -639,16 +597,9 @@ lnet_prepare(lnet_pid_t requested_pid) } #endif - rc = lnet_descriptor_setup(); - if (rc != 0) - goto failed0; - memset(&the_lnet.ln_counters, 0, sizeof(the_lnet.ln_counters)); - CFS_INIT_LIST_HEAD (&the_lnet.ln_active_msgs); - CFS_INIT_LIST_HEAD (&the_lnet.ln_active_mds); - CFS_INIT_LIST_HEAD (&the_lnet.ln_active_eqs); CFS_INIT_LIST_HEAD (&the_lnet.ln_test_peers); CFS_INIT_LIST_HEAD (&the_lnet.ln_nis); CFS_INIT_LIST_HEAD (&the_lnet.ln_zombie_nis); @@ -659,51 +610,66 @@ lnet_prepare(lnet_pid_t requested_pid) lnet_init_rtrpools(); - rc = lnet_setup_handle_hash (); - if (rc != 0) - goto failed0; - - rc = lnet_create_peer_table(); - if (rc != 0) - goto failed1; - - rc = lnet_init_finalizers(); + rc = lnet_peer_table_create(); if (rc != 0) - goto failed2; - - the_lnet.ln_nportals = MAX_PORTALS; - LIBCFS_ALLOC(the_lnet.ln_portals, - the_lnet.ln_nportals * - sizeof(*the_lnet.ln_portals)); - if (the_lnet.ln_portals == NULL) { - rc = -ENOMEM; - goto failed3; - } - - for (i = 0; i < the_lnet.ln_nportals; i++) { - CFS_INIT_LIST_HEAD(&(the_lnet.ln_portals[i].ptl_ml)); - CFS_INIT_LIST_HEAD(&(the_lnet.ln_portals[i].ptl_msgq)); - the_lnet.ln_portals[i].ptl_options = 0; - } - - return 0; + goto failed0; + + /* NB: we will have instance of message container per CPT soon */ + rc = lnet_msg_container_setup(&the_lnet.ln_msg_container); + if (rc != 0) + goto failed1; + + rc = lnet_res_container_setup(&the_lnet.ln_eq_container, + LNET_COOKIE_TYPE_EQ, LNET_FL_MAX_EQS, + sizeof(lnet_eq_t)); + if (rc != 0) { + CERROR("Failed to create EQ container for LNet: %d\n", rc); + goto failed2; + } + + /* NB: we will have instance of ME container per CPT soon */ + rc = lnet_res_container_setup(&the_lnet.ln_me_container, + LNET_COOKIE_TYPE_ME, LNET_FL_MAX_MES, + sizeof(lnet_me_t)); + if (rc != 0) { + CERROR("Failed to create ME container for LNet: %d\n", rc); + goto failed3; + } + + /* NB: we will have instance of MD container per CPT soon */ + rc = lnet_res_container_setup(&the_lnet.ln_md_container, + LNET_COOKIE_TYPE_MD, LNET_FL_MAX_MDS, + sizeof(lnet_libmd_t)); + if (rc != 0) { + CERROR("Failed to create MD container for LNet: %d\n", rc); + goto failed3; + } + + rc = lnet_portals_create(); + if (rc != 0) { + CERROR("Failed to create portals for LNet: %d\n", rc); + goto failed3; + } + + return 0; failed3: - lnet_fini_finalizers(); + /* NB: lnet_res_container_cleanup is safe to call for + * uninitialized container */ + lnet_res_container_cleanup(&the_lnet.ln_md_container); + lnet_res_container_cleanup(&the_lnet.ln_me_container); + lnet_res_container_cleanup(&the_lnet.ln_eq_container); failed2: - lnet_destroy_peer_table(); + lnet_msg_container_cleanup(&the_lnet.ln_msg_container); failed1: - lnet_cleanup_handle_hash(); + lnet_peer_table_destroy(); failed0: - lnet_descriptor_cleanup(); - return rc; + return rc; } int lnet_unprepare (void) { - int idx; - /* 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 @@ -717,58 +683,17 @@ lnet_unprepare (void) LASSERT (cfs_list_empty(&the_lnet.ln_zombie_nis)); LASSERT (the_lnet.ln_nzombie_nis == 0); - for (idx = 0; idx < the_lnet.ln_nportals; idx++) { - LASSERT (cfs_list_empty(&the_lnet.ln_portals[idx].ptl_msgq)); - - while (!cfs_list_empty (&the_lnet.ln_portals[idx].ptl_ml)) { - lnet_me_t *me = cfs_list_entry (the_lnet.ln_portals[idx].ptl_ml.next, - lnet_me_t, me_list); - - CERROR ("Active me %p on exit\n", me); - cfs_list_del (&me->me_list); - lnet_me_free (me); - } - } - - while (!cfs_list_empty (&the_lnet.ln_active_mds)) { - lnet_libmd_t *md = cfs_list_entry (the_lnet.ln_active_mds.next, - lnet_libmd_t, md_list); - - CERROR ("Active md %p on exit\n", md); - cfs_list_del_init (&md->md_list); - lnet_md_free (md); - } - - while (!cfs_list_empty (&the_lnet.ln_active_eqs)) { - lnet_eq_t *eq = cfs_list_entry (the_lnet.ln_active_eqs.next, - lnet_eq_t, eq_list); - - CERROR ("Active eq %p on exit\n", eq); - cfs_list_del (&eq->eq_list); - lnet_eq_free (eq); - } - - while (!cfs_list_empty (&the_lnet.ln_active_msgs)) { - lnet_msg_t *msg = cfs_list_entry (the_lnet.ln_active_msgs.next, - lnet_msg_t, msg_activelist); - - CERROR ("Active msg %p on exit\n", msg); - LASSERT (msg->msg_onactivelist); - msg->msg_onactivelist = 0; - cfs_list_del (&msg->msg_activelist); - lnet_msg_free (msg); - } + lnet_portals_destroy(); - LIBCFS_FREE(the_lnet.ln_portals, - the_lnet.ln_nportals * sizeof(*the_lnet.ln_portals)); + lnet_res_container_cleanup(&the_lnet.ln_md_container); + lnet_res_container_cleanup(&the_lnet.ln_me_container); + lnet_res_container_cleanup(&the_lnet.ln_eq_container); lnet_free_rtrpools(); - lnet_fini_finalizers(); - lnet_destroy_peer_table(); - lnet_cleanup_handle_hash(); - lnet_descriptor_cleanup(); + lnet_msg_container_cleanup(&the_lnet.ln_msg_container); + lnet_peer_table_destroy(); - return (0); + return 0; } lnet_ni_t * @@ -884,14 +809,14 @@ lnet_shutdown_lndnis (void) cfs_list_del (&ni->ni_list); the_lnet.ln_nzombie_nis++; - lnet_ni_decref_locked(ni); /* drop apini's ref */ + lnet_ni_decref_locked(ni); /* drop ln_nis' ref */ } /* Drop the cached eqwait NI. */ - if (the_lnet.ln_eqwaitni != NULL) { - lnet_ni_decref_locked(the_lnet.ln_eqwaitni); - the_lnet.ln_eqwaitni = NULL; - } + if (the_lnet.ln_eq_waitni != NULL) { + lnet_ni_decref_locked(the_lnet.ln_eq_waitni); + the_lnet.ln_eq_waitni = NULL; + } /* Drop the cached loopback NI. */ if (the_lnet.ln_loni != NULL) { @@ -908,10 +833,10 @@ lnet_shutdown_lndnis (void) /* Clear the peer table and wait for all peers to go (they hold refs on * their NIs) */ - lnet_clear_peer_table(); + lnet_peer_table_cleanup(); LNET_LOCK(); - /* Now wait for the NI's I just nuked to show up on apini_zombie_nis + /* 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 (the_lnet.ln_nzombie_nis != 0) { @@ -987,19 +912,28 @@ lnet_startup_lndnis (void) LASSERT (libcfs_isknown_lnd(lnd_type)); - LNET_MUTEX_DOWN(&the_lnet.ln_lnd_mutex); + if (lnd_type == CIBLND || + lnd_type == OPENIBLND || + lnd_type == IIBLND || + lnd_type == VIBLND) { + CERROR("LND %s obsoleted\n", + libcfs_lnd2str(lnd_type)); + goto failed; + } + + LNET_MUTEX_LOCK(&the_lnet.ln_lnd_mutex); lnd = lnet_find_lnd_by_type(lnd_type); #ifdef __KERNEL__ if (lnd == NULL) { - LNET_MUTEX_UP(&the_lnet.ln_lnd_mutex); + LNET_MUTEX_UNLOCK(&the_lnet.ln_lnd_mutex); rc = cfs_request_module("%s", libcfs_lnd2modname(lnd_type)); - LNET_MUTEX_DOWN(&the_lnet.ln_lnd_mutex); + LNET_MUTEX_LOCK(&the_lnet.ln_lnd_mutex); lnd = lnet_find_lnd_by_type(lnd_type); if (lnd == NULL) { - LNET_MUTEX_UP(&the_lnet.ln_lnd_mutex); + LNET_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); @@ -1013,7 +947,7 @@ lnet_startup_lndnis (void) } #else if (lnd == NULL) { - LNET_MUTEX_UP(&the_lnet.ln_lnd_mutex); + LNET_MUTEX_UNLOCK(&the_lnet.ln_lnd_mutex); CERROR("LND %s not supported\n", libcfs_lnd2str(lnd_type)); goto failed; @@ -1030,7 +964,7 @@ lnet_startup_lndnis (void) rc = (lnd->lnd_startup)(ni); - LNET_MUTEX_UP(&the_lnet.ln_lnd_mutex); + LNET_MUTEX_UNLOCK(&the_lnet.ln_lnd_mutex); if (rc != 0) { LCONSOLE_ERROR_MSG(0x105, "Error %d starting up LNI %s" @@ -1059,10 +993,10 @@ lnet_startup_lndnis (void) #ifndef __KERNEL__ if (lnd->lnd_wait != NULL) { - if (the_lnet.ln_eqwaitni == NULL) { - lnet_ni_addref(ni); - the_lnet.ln_eqwaitni = ni; - } + if (the_lnet.ln_eq_waitni == NULL) { + lnet_ni_addref(ni); + the_lnet.ln_eq_waitni = ni; + } } else { # ifndef HAVE_LIBPTHREAD LCONSOLE_ERROR_MSG(0x106, "LND %s not supported in a " @@ -1091,8 +1025,8 @@ lnet_startup_lndnis (void) nicount++; } - if (the_lnet.ln_eqwaitni != NULL && nicount > 1) { - lnd_type = the_lnet.ln_eqwaitni->ni_lnd->lnd_type; + 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)); @@ -1113,6 +1047,16 @@ lnet_startup_lndnis (void) return -ENETDOWN; } +/** + * 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 LNetFini() + * after a call to LNetInit(), if and only if the latter returned 0. It must + * be called exactly once. + * + * \return 0 on success, and -ve on failures. + */ int LNetInit(void) { @@ -1126,7 +1070,8 @@ LNetInit(void) the_lnet.ln_init = 1; LNetInvalidateHandle(&the_lnet.ln_rc_eqh); CFS_INIT_LIST_HEAD(&the_lnet.ln_lnds); - CFS_INIT_LIST_HEAD(&the_lnet.ln_zombie_rcd); + CFS_INIT_LIST_HEAD(&the_lnet.ln_rcd_zombie); + CFS_INIT_LIST_HEAD(&the_lnet.ln_rcd_deathrow); #ifdef __KERNEL__ /* All LNDs apart from the LOLND are in separate modules. They @@ -1146,6 +1091,15 @@ LNetInit(void) return 0; } +/** + * Finalize LNet library. + * + * Only userspace program needs to call this function. It can be called + * at most once. + * + * \pre LNetInit() called with success. + * \pre All LNet users called LNetNIFini() for matching LNetNIInit() calls. + */ void LNetFini(void) { @@ -1160,13 +1114,29 @@ LNetFini(void) 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 LNetInit(). + * 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 + * ignored. + * + * The PID used by LNet may be different from the one requested. + * See LNetGetId(). + * + * \param requested_pid PID requested by the caller. + * + * \return >= 0 on success, and < 0 error code on failures. + */ int LNetNIInit(lnet_pid_t requested_pid) { int im_a_router = 0; int rc; - LNET_MUTEX_DOWN(&the_lnet.ln_api_mutex); + LNET_MUTEX_LOCK(&the_lnet.ln_api_mutex); LASSERT (the_lnet.ln_init); CDEBUG(D_OTHER, "refs %d\n", the_lnet.ln_refcount); @@ -1212,7 +1182,7 @@ LNetNIInit(lnet_pid_t requested_pid) /* 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 */ + * lnet_router_checker -> lnet_update_ni_status_locked */ rc = lnet_ping_target_init(); if (rc != 0) goto failed3; @@ -1237,14 +1207,23 @@ LNetNIInit(lnet_pid_t requested_pid) failed0: LASSERT (rc < 0); out: - LNET_MUTEX_UP(&the_lnet.ln_api_mutex); + LNET_MUTEX_UNLOCK(&the_lnet.ln_api_mutex); return rc; } +/** + * Stop LNet interfaces, routing, and forwarding. + * + * Users must call this function once for each successful call to LNetNIInit(). + * Once the LNetNIFini() operation has been started, the results of pending + * API operations are undefined. + * + * \return always 0 for current implementation. + */ int LNetNIFini() { - LNET_MUTEX_DOWN(&the_lnet.ln_api_mutex); + LNET_MUTEX_LOCK(&the_lnet.ln_api_mutex); LASSERT (the_lnet.ln_init); LASSERT (the_lnet.ln_refcount > 0); @@ -1267,10 +1246,23 @@ LNetNIFini() lnet_unprepare(); } - LNET_MUTEX_UP(&the_lnet.ln_api_mutex); + LNET_MUTEX_UNLOCK(&the_lnet.ln_api_mutex); return 0; } +/** + * 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. + * + * 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. + * + * \return Always return 0 when called by users directly (i.e., not via ioctl). + */ int LNetCtl(unsigned int cmd, void *arg) { @@ -1377,6 +1369,17 @@ LNetCtl(unsigned int cmd, void *arg) /* not reached */ } +/** + * 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(). + * + * \param index Index of the interface to look up. + * \param id On successful return, this location will hold the + * lnet_process_id_t ID of the interface. + * + * \retval 0 If an interface exists at \a index. + * \retval -ENOENT If no interface has been found. + */ int LNetGetId(unsigned int index, lnet_process_id_t *id) { @@ -1406,6 +1409,10 @@ LNetGetId(unsigned int index, lnet_process_id_t *id) return rc; } +/** + * Print a string representation of handle \a h into buffer \a str of + * \a len bytes. + */ void LNetSnprintHandle(char *str, int len, lnet_handle_any_t h) {