#define MAX_PORTALS 64
+/* these are only used by code with LNET_USE_LIB_FREELIST, but we still
+ * exported them to !LNET_USE_LIB_FREELIST for easy implemetation */
+#define LNET_FL_MAX_MES 2048
+#define LNET_FL_MAX_MDS 2048
+#define LNET_FL_MAX_EQS 512
+#define LNET_FL_MAX_MSGS 2048 /* Outstanding messages */
+
#ifdef LNET_USE_LIB_FREELIST
-#define MAX_MES 2048
-#define MAX_MDS 2048
-#define MAX_MSGS 2048 /* Outstanding messages */
-#define MAX_EQS 512
+int lnet_freelist_init(lnet_freelist_t *fl, int n, int size);
+void lnet_freelist_fini(lnet_freelist_t *fl);
static inline void *
lnet_freelist_alloc (lnet_freelist_t *fl)
static inline lnet_eq_t *
lnet_eq_alloc (void)
{
- /* NEVER called with liblock held */
- lnet_eq_t *eq;
+ /* NEVER called with resource lock held */
+ struct lnet_res_container *rec = &the_lnet.ln_eq_container;
+ lnet_eq_t *eq;
- LNET_LOCK();
- eq = (lnet_eq_t *)lnet_freelist_alloc(&the_lnet.ln_free_eqs);
- LNET_UNLOCK();
+ LNET_LOCK();
+ eq = (lnet_eq_t *)lnet_freelist_alloc(&rec->rec_freelist);
+ LNET_UNLOCK();
- return (eq);
+ return eq;
}
static inline void
lnet_eq_free_locked(lnet_eq_t *eq)
{
/* ALWAYS called with resource lock held */
- lnet_freelist_free(&the_lnet.ln_free_eqs, eq);
+ struct lnet_res_container *rec = &the_lnet.ln_eq_container;
+
+ lnet_freelist_free(&rec->rec_freelist, eq);
}
static inline void
static inline lnet_libmd_t *
lnet_md_alloc (lnet_md_t *umd)
{
- /* NEVER called with liblock held */
- lnet_libmd_t *md;
+ /* NEVER called with resource lock held */
+ struct lnet_res_container *rec = &the_lnet.ln_md_container;
+ lnet_libmd_t *md;
- LNET_LOCK();
- md = (lnet_libmd_t *)lnet_freelist_alloc(&the_lnet.ln_free_mds);
- LNET_UNLOCK();
+ LNET_LOCK();
+ md = (lnet_libmd_t *)lnet_freelist_alloc(&rec->rec_freelist);
+ LNET_UNLOCK();
- if (md != NULL)
- CFS_INIT_LIST_HEAD(&md->md_list);
+ if (md != NULL)
+ CFS_INIT_LIST_HEAD(&md->md_list);
- return (md);
+ return md;
}
static inline void
lnet_md_free_locked(lnet_libmd_t *md)
{
/* ALWAYS called with resource lock held */
- lnet_freelist_free(&the_lnet.ln_free_mds, md);
+ struct lnet_res_container *rec = &the_lnet.ln_md_container;
+
+ lnet_freelist_free(&rec->rec_freelist, md);
}
static inline void
}
static inline lnet_me_t *
-lnet_me_alloc (void)
+lnet_me_alloc(void)
{
- /* NEVER called with liblock held */
- lnet_me_t *me;
+ /* NEVER called with resource lock held */
+ struct lnet_res_container *rec = &the_lnet.ln_me_container;
+ lnet_me_t *me;
- LNET_LOCK();
- me = (lnet_me_t *)lnet_freelist_alloc(&the_lnet.ln_free_mes);
- LNET_UNLOCK();
+ LNET_LOCK();
+ me = (lnet_me_t *)lnet_freelist_alloc(&rec->rec_freelist);
+ LNET_UNLOCK();
- return (me);
+ return me;
}
static inline void
lnet_me_free_locked(lnet_me_t *me)
{
/* ALWAYS called with resource lock held */
- lnet_freelist_free(&the_lnet.ln_free_mes, me);
+ struct lnet_res_container *rec = &the_lnet.ln_me_container;
+
+ lnet_freelist_free(&rec->rec_freelist, me);
}
static inline void
#endif /* LNET_USE_LIB_FREELIST */
-extern lnet_libhandle_t *lnet_lookup_cookie (__u64 cookie, int type);
-extern void lnet_initialise_handle (lnet_libhandle_t *lh, int type);
-extern void lnet_invalidate_handle (lnet_libhandle_t *lh);
+lnet_libhandle_t *lnet_res_lh_lookup(struct lnet_res_container *rec,
+ __u64 cookie);
+void lnet_res_lh_initialize(struct lnet_res_container *rec,
+ lnet_libhandle_t *lh);
+static inline void
+lnet_res_lh_invalidate(lnet_libhandle_t *lh)
+{
+ /* ALWAYS called with resource lock held */
+ cfs_list_del(&lh->lh_hash_chain);
+}
static inline void
lnet_eq2handle (lnet_handle_eq_t *handle, lnet_eq_t *eq)
}
static inline lnet_eq_t *
-lnet_handle2eq (lnet_handle_eq_t *handle)
+lnet_handle2eq(lnet_handle_eq_t *handle)
{
- /* ALWAYS called with liblock held */
- lnet_libhandle_t *lh = lnet_lookup_cookie(handle->cookie,
- LNET_COOKIE_TYPE_EQ);
- if (lh == NULL)
- return (NULL);
+ /* ALWAYS called with resource lock held */
+ lnet_libhandle_t *lh;
- return (lh_entry (lh, lnet_eq_t, eq_lh));
+ lh = lnet_res_lh_lookup(&the_lnet.ln_eq_container, handle->cookie);
+ if (lh == NULL)
+ return NULL;
+
+ return lh_entry(lh, lnet_eq_t, eq_lh);
}
static inline void
}
static inline lnet_libmd_t *
-lnet_handle2md (lnet_handle_md_t *handle)
+lnet_handle2md(lnet_handle_md_t *handle)
{
- /* ALWAYS called with liblock held */
- lnet_libhandle_t *lh = lnet_lookup_cookie(handle->cookie,
- LNET_COOKIE_TYPE_MD);
- if (lh == NULL)
- return (NULL);
+ /* ALWAYS called with resource lock held */
+ lnet_libhandle_t *lh;
+
+ lh = lnet_res_lh_lookup(&the_lnet.ln_md_container, handle->cookie);
+ if (lh == NULL)
+ return NULL;
- return (lh_entry (lh, lnet_libmd_t, md_lh));
+ return lh_entry(lh, lnet_libmd_t, md_lh);
}
static inline lnet_libmd_t *
-lnet_wire_handle2md (lnet_handle_wire_t *wh)
+lnet_wire_handle2md(lnet_handle_wire_t *wh)
{
- /* ALWAYS called with liblock held */
- lnet_libhandle_t *lh;
+ /* ALWAYS called with resource lock held */
+ lnet_libhandle_t *lh;
- if (wh->wh_interface_cookie != the_lnet.ln_interface_cookie)
- return (NULL);
+ if (wh->wh_interface_cookie != the_lnet.ln_interface_cookie)
+ return NULL;
- lh = lnet_lookup_cookie(wh->wh_object_cookie,
- LNET_COOKIE_TYPE_MD);
- if (lh == NULL)
- return (NULL);
+ lh = lnet_res_lh_lookup(&the_lnet.ln_md_container,
+ wh->wh_object_cookie);
+ if (lh == NULL)
+ return NULL;
- return (lh_entry (lh, lnet_libmd_t, md_lh));
+ return lh_entry(lh, lnet_libmd_t, md_lh);
}
static inline void
}
static inline lnet_me_t *
-lnet_handle2me (lnet_handle_me_t *handle)
+lnet_handle2me(lnet_handle_me_t *handle)
{
- /* ALWAYS called with liblock held */
- lnet_libhandle_t *lh = lnet_lookup_cookie(handle->cookie,
- LNET_COOKIE_TYPE_ME);
- if (lh == NULL)
- return (NULL);
+ /* ALWAYS called with resource lock held */
+ lnet_libhandle_t *lh;
+
+ lh = lnet_res_lh_lookup(&the_lnet.ln_me_container, handle->cookie);
+ if (lh == NULL)
+ return NULL;
- return (lh_entry (lh, lnet_me_t, me_lh));
+ return lh_entry(lh, lnet_me_t, me_lh);
}
static inline int
unsigned int ptl_options;
} lnet_portal_t;
+#define LNET_LH_HASH_BITS 12
+#define LNET_LH_HASH_SIZE (1ULL << LNET_LH_HASH_BITS)
+#define LNET_LH_HASH_MASK (LNET_LH_HASH_SIZE - 1)
+
+/* resource container (ME, MD, EQ) */
+struct lnet_res_container {
+ unsigned int rec_type; /* container type */
+ __u64 rec_lh_cookie; /* cookie generator */
+ cfs_list_t rec_active; /* active resource list */
+ cfs_list_t *rec_lh_hash; /* handle hash */
+#ifdef LNET_USE_LIB_FREELIST
+ lnet_freelist_t rec_freelist; /* freelist for resources */
+#endif
+};
+
/* Router Checker states */
#define LNET_RC_STATE_SHUTDOWN 0 /* not started */
#define LNET_RC_STATE_RUNNING 1 /* started up OK */
pthread_mutex_t ln_lnd_mutex;
# endif
#endif
+ /* ME container */
+ struct lnet_res_container ln_me_container;
+ /* MD container */
+ struct lnet_res_container ln_md_container;
+ /* Event Queue container */
+ struct lnet_res_container ln_eq_container;
/* Stuff initialised at LNetNIInit() */
int ln_routing; /* am I a router? */
lnet_rtrbufpool_t ln_rtrpools[LNET_NRBPOOLS]; /* router buffer pools */
- int ln_lh_hash_size; /* size of lib handle hash table */
- cfs_list_t *ln_lh_hash_table; /* all extant lib handles, this interface */
- __u64 ln_next_object_cookie; /* cookie generator */
__u64 ln_interface_cookie; /* uniquely identifies this ni in this epoch */
char *ln_network_tokens; /* space for network names */
lnet_handle_eq_t ln_rc_eqh; /* router checker's event queue */
lnet_handle_md_t ln_rc_mdh;
cfs_list_t ln_zombie_rcd;
-
#ifdef LNET_USE_LIB_FREELIST
- lnet_freelist_t ln_free_mes;
lnet_freelist_t ln_free_msgs;
- lnet_freelist_t ln_free_mds;
- lnet_freelist_t ln_free_eqs;
#endif
cfs_list_t ln_active_msgs;
- cfs_list_t ln_active_mds;
- cfs_list_t ln_active_eqs;
lnet_counters_t ln_counters;
/* ****** */
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));
+ LNET_FL_MAX_MSGS, sizeof(lnet_msg_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)
return cookie;
}
-int
-lnet_setup_handle_hash (void)
+static char *
+lnet_res_type2str(int type)
{
- int i;
+ 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";
+ }
+}
- /* Arbitrary choice of hash table size */
-#ifdef __KERNEL__
- the_lnet.ln_lh_hash_size =
- (2 * 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);
+void
+lnet_res_container_cleanup(struct lnet_res_container *rec)
+{
+ int count = 0;
- for (i = 0; i < the_lnet.ln_lh_hash_size; i++)
- CFS_INIT_LIST_HEAD (&the_lnet.ln_lh_hash_table[i]);
+ if (rec->rec_type == 0) /* not set yet, it's a uninitialized */
+ return;
- the_lnet.ln_next_object_cookie = LNET_COOKIE_TYPES;
+ while (!cfs_list_empty(&rec->rec_active)) {
+ cfs_list_t *e = rec->rec_active.next;
- return (0);
+ 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));
+
+ } else if (rec->rec_type == LNET_COOKIE_TYPE_MD) {
+ lnet_md_free(cfs_list_entry(e, lnet_libmd_t, md_list));
+
+ } else { /* NB: Active MEs should be attached on portals */
+ LBUG();
+ }
+ count++;
+ }
+
+ 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;
+ }
+
+ rec->rec_type = 0; /* mark it as finalized */
}
-void
-lnet_cleanup_handle_hash (void)
+int
+lnet_res_container_setup(struct lnet_res_container *rec,
+ int type, int objnum, int objsz)
{
- if (the_lnet.ln_lh_hash_table == NULL)
- return;
+ int rc = 0;
+ int i;
+
+ LASSERT(rec->rec_type == 0);
- LIBCFS_FREE(the_lnet.ln_lh_hash_table,
- the_lnet.ln_lh_hash_size * sizeof (cfs_list_t));
+ rec->rec_type = type;
+ CFS_INIT_LIST_HEAD(&rec->rec_active);
+
+#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;
}
lnet_libhandle_t *
-lnet_lookup_cookie (__u64 cookie, int type)
+lnet_res_lh_lookup(struct lnet_res_container *rec, __u64 cookie)
{
- /* ALWAYS called with LNET_LOCK held */
- cfs_list_t *list;
- cfs_list_t *el;
- unsigned int hash;
+ /* ALWAYS called with lnet_res_lock held */
+ cfs_list_t *head;
+ lnet_libhandle_t *lh;
+ unsigned int hash;
- if ((cookie & (LNET_COOKIE_TYPES - 1)) != type)
- return (NULL);
+ if ((cookie & (LNET_COOKIE_TYPES - 1)) != rec->rec_type)
+ return NULL;
- hash = ((unsigned int)(cookie >> LNET_COOKIE_TYPE_BITS)) % the_lnet.ln_lh_hash_size;
- list = &the_lnet.ln_lh_hash_table[hash];
+ hash = cookie >> LNET_COOKIE_TYPE_BITS;
+ head = &rec->rec_lh_hash[hash & LNET_LH_HASH_MASK];
- cfs_list_for_each (el, list) {
- lnet_libhandle_t *lh = cfs_list_entry (el, lnet_libhandle_t,
- lh_hash_chain);
+ cfs_list_for_each_entry(lh, head, lh_hash_chain) {
+ if (lh->lh_cookie == cookie)
+ return lh;
+ }
- if (lh->lh_cookie == cookie)
- return (lh);
- }
-
- return (NULL);
+ return NULL;
}
void
-lnet_initialise_handle (lnet_libhandle_t *lh, int type)
+lnet_res_lh_initialize(struct lnet_res_container *rec, lnet_libhandle_t *lh)
{
- /* ALWAYS called with LNET_LOCK held */
- unsigned int hash;
+ /* ALWAYS called with lnet_res_lock held */
+ unsigned int ibits = LNET_COOKIE_TYPE_BITS;
+ unsigned int hash;
- 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;
+ lh->lh_cookie = rec->rec_lh_cookie;
+ rec->rec_lh_cookie += 1 << ibits;
- hash = ((unsigned int)(lh->lh_cookie >> LNET_COOKIE_TYPE_BITS)) % the_lnet.ln_lh_hash_size;
- cfs_list_add (&lh->lh_hash_chain, &the_lnet.ln_lh_hash_table[hash]);
-}
+ hash = (lh->lh_cookie >> ibits) & LNET_LH_HASH_MASK;
-void
-lnet_invalidate_handle (lnet_libhandle_t *lh)
-{
- /* ALWAYS called with LNET_LOCK held */
- cfs_list_del (&lh->lh_hash_chain);
+ cfs_list_add(&lh->lh_hash_chain, &rec->rec_lh_hash[hash]);
}
cfs_list_t *
rc = lnet_descriptor_setup();
if (rc != 0)
- goto failed0;
+ return -ENOMEM;
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);
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();
- if (rc != 0)
- goto failed2;
+ goto failed0;
+
+ rc = lnet_init_finalizers();
+ 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;
+ }
the_lnet.ln_nportals = MAX_PORTALS;
LIBCFS_ALLOC(the_lnet.ln_portals,
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_fini_finalizers();
failed1:
- lnet_cleanup_handle_hash();
+ lnet_destroy_peer_table();
failed0:
- lnet_descriptor_cleanup();
- return rc;
+ lnet_descriptor_cleanup();
+ return rc;
}
int
}
}
- 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);
- }
+ 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);
while (!cfs_list_empty (&the_lnet.ln_active_msgs)) {
lnet_msg_t *msg = cfs_list_entry (the_lnet.ln_active_msgs.next,
lnet_free_rtrpools();
lnet_fini_finalizers();
lnet_destroy_peer_table();
- lnet_cleanup_handle_hash();
lnet_descriptor_cleanup();
return (0);