void
lnet_init_locks(void)
{
- cfs_spin_lock_init (&the_lnet.ln_lock);
+ cfs_spin_lock_init(&the_lnet.ln_lock);
+ cfs_spin_lock_init(&the_lnet.ln_eq_wait_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 lnet_init_locks(void)
{
- the_lnet.ln_lock = 0;
- the_lnet.ln_lnd_mutex = 0;
- the_lnet.ln_api_mutex = 0;
+ the_lnet.ln_lock = 0;
+ the_lnet.ln_eq_wait_lock = 0;
+ the_lnet.ln_lnd_mutex = 0;
+ the_lnet.ln_api_mutex = 0;
}
void lnet_fini_locks(void)
{
- LASSERT (the_lnet.ln_api_mutex == 0);
- LASSERT (the_lnet.ln_lnd_mutex == 0);
- LASSERT (the_lnet.ln_lock == 0);
+ LASSERT(the_lnet.ln_api_mutex == 0);
+ LASSERT(the_lnet.ln_lnd_mutex == 0);
+ LASSERT(the_lnet.ln_lock == 0);
+ LASSERT(the_lnet.ln_eq_wait_lock == 0);
}
# else
{
pthread_cond_init(&the_lnet.ln_eq_cond, NULL);
pthread_mutex_init(&the_lnet.ln_lock, NULL);
+ pthread_mutex_init(&the_lnet.ln_eq_wait_lock, NULL);
pthread_mutex_init(&the_lnet.ln_lnd_mutex, NULL);
pthread_mutex_init(&the_lnet.ln_api_mutex, NULL);
}
pthread_mutex_destroy(&the_lnet.ln_api_mutex);
pthread_mutex_destroy(&the_lnet.ln_lnd_mutex);
pthread_mutex_destroy(&the_lnet.ln_lock);
+ pthread_mutex_destroy(&the_lnet.ln_eq_wait_lock);
pthread_cond_destroy(&the_lnet.ln_eq_cond);
}
# endif
#endif
+static int
+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)
+ return 0;
+
+ lnet_fini_locks();
+ return -ENOMEM;
+}
+
+static void
+lnet_destroy_locks(void)
+{
+ if (the_lnet.ln_res_lock != NULL) {
+ cfs_percpt_lock_free(the_lnet.ln_res_lock);
+ the_lnet.ln_res_lock = NULL;
+ }
+
+ lnet_fini_locks();
+}
+
void lnet_assert_wire_constants (void)
{
/* Wire protocol assertions generated by 'wirecheck'
LNET_MUTEX_UNLOCK(&the_lnet.ln_lnd_mutex);
}
+void
+lnet_counters_get(lnet_counters_t *counters)
+{
+ lnet_counters_t *ctr;
+
+ memset(counters, 0, sizeof(*counters));
+
+ LNET_LOCK();
+ ctr = the_lnet.ln_counters;
+ do { /* iterate over counters of all CPTs in upcoming patches */
+ counters->msgs_max += ctr->msgs_max;
+ counters->msgs_alloc += ctr->msgs_alloc;
+ counters->errors += ctr->errors;
+ counters->send_count += ctr->send_count;
+ counters->recv_count += ctr->recv_count;
+ counters->route_count += ctr->route_count;
+ counters->drop_length += ctr->drop_length;
+ counters->send_length += ctr->send_length;
+ counters->recv_length += ctr->recv_length;
+ counters->route_length += ctr->route_length;
+ counters->drop_length += ctr->drop_length;
+ } while (0);
+
+ LNET_UNLOCK();
+}
+EXPORT_SYMBOL(lnet_counters_get);
+
+void
+lnet_counters_reset(void)
+{
+ lnet_counters_t *counters;
+
+ LNET_LOCK();
+ counters = the_lnet.ln_counters;
+ do { /* iterate over counters of all CPTs in upcoming patches */
+ memset(counters, 0, sizeof(lnet_counters_t));
+ } while (0);
+ LNET_UNLOCK();
+}
+EXPORT_SYMBOL(lnet_counters_reset);
+
#ifdef LNET_USE_LIB_FREELIST
int
int
lnet_res_container_setup(struct lnet_res_container *rec,
- int type, int objnum, int objsz)
+ int cpt, int type, int objnum, int objsz)
{
int rc = 0;
int i;
if (rc != 0)
goto out;
#endif
- rec->rec_lh_cookie = type;
+ rec->rec_lh_cookie = (cpt << LNET_COOKIE_TYPE_BITS) | type;
/* Arbitrary choice of hash table size */
- LIBCFS_ALLOC(rec->rec_lh_hash,
- LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0]));
+ 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) {
rc = -ENOMEM;
goto out;
return rc;
}
+static void
+lnet_res_containers_destroy(struct lnet_res_container **recs)
+{
+ struct lnet_res_container *rec;
+ int i;
+
+ cfs_percpt_for_each(rec, i, recs)
+ lnet_res_container_cleanup(rec);
+
+ cfs_percpt_free(recs);
+}
+
+static struct lnet_res_container **
+lnet_res_containers_create(int type, int objnum, int objsz)
+{
+ struct lnet_res_container **recs;
+ struct lnet_res_container *rec;
+ int rc;
+ int i;
+
+ recs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*rec));
+ if (recs == NULL) {
+ CERROR("Failed to allocate %s resource containers\n",
+ lnet_res_type2str(type));
+ return NULL;
+ }
+
+ cfs_percpt_for_each(rec, i, recs) {
+ rc = lnet_res_container_setup(rec, i, type, objnum, objsz);
+ if (rc != 0) {
+ lnet_res_containers_destroy(recs);
+ return NULL;
+ }
+ }
+
+ return recs;
+}
+
lnet_libhandle_t *
lnet_res_lh_lookup(struct lnet_res_container *rec, __u64 cookie)
{
if ((cookie & (LNET_COOKIE_TYPES - 1)) != rec->rec_type)
return NULL;
- hash = cookie >> LNET_COOKIE_TYPE_BITS;
+ hash = cookie >> (LNET_COOKIE_TYPE_BITS + LNET_CPT_BITS);
head = &rec->rec_lh_hash[hash & LNET_LH_HASH_MASK];
cfs_list_for_each_entry(lh, head, lh_hash_chain) {
lnet_res_lh_initialize(struct lnet_res_container *rec, lnet_libhandle_t *lh)
{
/* ALWAYS called with lnet_res_lock held */
- unsigned int ibits = LNET_COOKIE_TYPE_BITS;
+ unsigned int ibits = LNET_COOKIE_TYPE_BITS + LNET_CPT_BITS;
unsigned int hash;
lh->lh_cookie = rec->rec_lh_cookie;
}
#endif
+int lnet_unprepare(void);
+
int
lnet_prepare(lnet_pid_t requested_pid)
{
/* Prepare to bring up the network */
- int rc = 0;
+ struct lnet_res_container **recs;
+ int rc = 0;
LASSERT (the_lnet.ln_refcount == 0);
}
#endif
- memset(&the_lnet.ln_counters, 0,
- sizeof(the_lnet.ln_counters));
-
- 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);
- CFS_INIT_LIST_HEAD (&the_lnet.ln_remote_nets);
- CFS_INIT_LIST_HEAD (&the_lnet.ln_routers);
+ 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);
+ CFS_INIT_LIST_HEAD(&the_lnet.ln_remote_nets);
+ CFS_INIT_LIST_HEAD(&the_lnet.ln_routers);
- the_lnet.ln_interface_cookie = lnet_create_interface_cookie();
+ the_lnet.ln_interface_cookie = lnet_create_interface_cookie();
- lnet_init_rtrpools();
+ LIBCFS_ALLOC(the_lnet.ln_counters, sizeof(lnet_counters_t));
+ if (the_lnet.ln_counters == NULL) {
+ CERROR("Failed to allocate counters for LNet\n");
+ rc = -ENOMEM;
+ goto failed;
+ }
rc = lnet_peer_table_create();
- if (rc != 0)
- goto failed0;
+ if (rc != 0)
+ goto failed;
/* 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;
+ goto failed;
- rc = lnet_res_container_setup(&the_lnet.ln_eq_container,
+ rc = lnet_res_container_setup(&the_lnet.ln_eq_container, 0,
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;
- }
+ if (rc != 0)
+ goto failed;
- /* 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;
- }
+ recs = lnet_res_containers_create(LNET_COOKIE_TYPE_ME, LNET_FL_MAX_MES,
+ sizeof(lnet_me_t));
+ if (recs == NULL)
+ goto failed;
+
+ the_lnet.ln_me_containers = recs;
/* 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;
- }
+ recs = lnet_res_containers_create(LNET_COOKIE_TYPE_MD, LNET_FL_MAX_MDS,
+ sizeof(lnet_libmd_t));
+ if (recs == NULL)
+ goto failed;
+
+ the_lnet.ln_md_containers = recs;
rc = lnet_portals_create();
if (rc != 0) {
CERROR("Failed to create portals for LNet: %d\n", rc);
- goto failed3;
+ goto failed;
}
return 0;
- failed3:
- /* 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_msg_container_cleanup(&the_lnet.ln_msg_container);
- failed1:
- lnet_peer_table_destroy();
- failed0:
+ failed:
+ lnet_unprepare();
return rc;
}
lnet_portals_destroy();
- lnet_res_container_cleanup(&the_lnet.ln_md_container);
- lnet_res_container_cleanup(&the_lnet.ln_me_container);
+ if (the_lnet.ln_md_containers != NULL) {
+ lnet_res_containers_destroy(the_lnet.ln_md_containers);
+ the_lnet.ln_md_containers = NULL;
+ }
+
+ if (the_lnet.ln_me_containers != NULL) {
+ lnet_res_containers_destroy(the_lnet.ln_me_containers);
+ the_lnet.ln_me_containers = NULL;
+ }
+
lnet_res_container_cleanup(&the_lnet.ln_eq_container);
- lnet_free_rtrpools();
lnet_msg_container_cleanup(&the_lnet.ln_msg_container);
lnet_peer_table_destroy();
+ lnet_rtrpools_free();
+
+ if (the_lnet.ln_counters != NULL) {
+ LIBCFS_FREE(the_lnet.ln_counters, sizeof(lnet_counters_t));
+ the_lnet.ln_counters = NULL;
+ }
return 0;
}
return NULL;
}
+unsigned int
+lnet_nid_cpt_hash(lnet_nid_t nid)
+{
+ __u64 key = nid;
+ unsigned int val;
+
+ val = cfs_hash_long(key, LNET_CPT_BITS);
+ /* NB: LNET_CP_NUMBER doesn't have to be PO2 */
+ if (val < LNET_CPT_NUMBER)
+ return val;
+
+ return (unsigned int)((key + val + (val >> 1)) % LNET_CPT_NUMBER);
+}
+
+int
+lnet_cpt_of_nid(lnet_nid_t nid)
+{
+ if (LNET_CPT_NUMBER == 1)
+ return 0; /* the only one */
+
+ return lnet_nid_cpt_hash(nid);
+}
+EXPORT_SYMBOL(lnet_cpt_of_nid);
+
int
lnet_islocalnet (__u32 net)
{
int
LNetInit(void)
{
+ int rc;
+
lnet_assert_wire_constants ();
LASSERT (!the_lnet.ln_init);
memset(&the_lnet, 0, sizeof(the_lnet));
- lnet_init_locks();
+ /* refer to global cfs_cpt_table for now */
+ the_lnet.ln_cpt_table = cfs_cpt_table;
+ the_lnet.ln_cpt_number = cfs_cpt_number(cfs_cpt_table);
+
+ LASSERT(the_lnet.ln_cpt_number > 0);
+ if (the_lnet.ln_cpt_number > LNET_CPT_MAX) {
+ /* 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;
+ }
+
+ while ((1 << the_lnet.ln_cpt_bits) < the_lnet.ln_cpt_number)
+ the_lnet.ln_cpt_bits++;
+
+ rc = lnet_create_locks();
+ if (rc != 0) {
+ CERROR("Can't create LNet global locks: %d\n", rc);
+ return -1;
+ }
+
the_lnet.ln_refcount = 0;
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
void
LNetFini(void)
{
- LASSERT (the_lnet.ln_init);
- LASSERT (the_lnet.ln_refcount == 0);
+ LASSERT(the_lnet.ln_init);
+ LASSERT(the_lnet.ln_refcount == 0);
- while (!cfs_list_empty(&the_lnet.ln_lnds))
- lnet_unregister_lnd(cfs_list_entry(the_lnet.ln_lnds.next,
- lnd_t, lnd_list));
- lnet_fini_locks();
+ while (!cfs_list_empty(&the_lnet.ln_lnds))
+ lnet_unregister_lnd(cfs_list_entry(the_lnet.ln_lnds.next,
+ lnd_t, lnd_list));
+ lnet_destroy_locks();
- the_lnet.ln_init = 0;
+ the_lnet.ln_init = 0;
}
/**
if (rc != 0)
goto failed2;
- rc = lnet_alloc_rtrpools(im_a_router);
+ rc = lnet_rtrpools_alloc(im_a_router);
if (rc != 0)
goto failed2;
/* 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;