Whamcloud - gitweb
removed some empty files (authors, news, readme)
[fs/lustre-release.git] / lnet / lnet / api-ni.c
index 02082c6..91a307a 100644 (file)
@@ -1,11 +1,7 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * api/api-ni.c
- * Network Interface code
- *
  *  Copyright (c) 2001-2003 Cluster File Systems, Inc.
- *  Copyright (c) 2001-2002 Sandia National Laboratories
  *
  *   This file is part of Lustre, http://www.sf.net/projects/lustre/
  *
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define DEBUG_SUBSYSTEM S_PORTALS
 #include <portals/api-support.h>
 
+int ptl_init;
+
 /* Put some magic in the NI handle so uninitialised/zeroed handles are easy
  * to spot */
 #define NI_HANDLE_MAGIC  0xebc0de00
 #define NI_HANDLE_MASK   0x000000ff
-#define MAX_NIS          8         
-static nal_t *ptl_interfaces[MAX_NIS];
-int ptl_num_interfaces = 0;
+
+static struct nal_t *ptl_nal_table[NAL_MAX_NR + 1];
+
+#ifdef __KERNEL__
+struct semaphore ptl_mutex;
+
+static void ptl_mutex_enter (void) 
+{
+        mutex_down (&ptl_mutex);
+}
+
+static void ptl_mutex_exit (void)
+{
+        mutex_up (&ptl_mutex);
+}
+#else
+static void ptl_mutex_enter (void)
+{
+}
+
+static void ptl_mutex_exit (void) 
+{
+}
+#endif
 
 nal_t *ptl_hndl2nal(ptl_handle_any_t *handle)
 {
@@ -42,156 +62,200 @@ nal_t *ptl_hndl2nal(ptl_handle_any_t *handle)
          * invalidated out from under her (or worse, swapped for a
          * completely different interface!) */
 
+        LASSERT (ptl_init);
+
         if (((idx ^ NI_HANDLE_MAGIC) & ~NI_HANDLE_MASK) != 0)
                 return NULL;
 
         idx &= NI_HANDLE_MASK;
-        if (idx < MAX_NIS)
-                return ptl_interfaces[idx];
+        
+        if (idx > NAL_MAX_NR ||
+            ptl_nal_table[idx] == NULL ||
+            ptl_nal_table[idx]->nal_refct == 0)
+                return NULL;
 
-        return NULL;
+        return ptl_nal_table[idx];
 }
 
-int ptl_ni_init(void)
+int ptl_register_nal (ptl_interface_t interface, nal_t *nal)
 {
-        int i;
-
-        LASSERT (MAX_NIS <= (NI_HANDLE_MASK + 1));
+        int    rc;
         
-        for (i = 0; i < MAX_NIS; i++)
-                ptl_interfaces[i] = NULL;
+        ptl_mutex_enter();
+        
+        if (interface < 0 || interface > NAL_MAX_NR)
+                rc = PTL_IFACE_INVALID;
+        else if (ptl_nal_table[interface] != NULL)
+                rc = PTL_IFACE_DUP;
+        else {
+                rc = PTL_OK;
+                ptl_nal_table[interface] = nal;
+                LASSERT(nal->nal_refct == 0);
+        }
 
-        return PTL_OK;
+        ptl_mutex_exit();
+        return (rc);
 }
 
-void ptl_ni_fini(void)
+void ptl_unregister_nal (ptl_interface_t interface)
 {
-        int i;
-
-        for (i = 0; i < MAX_NIS; i++) {
-                nal_t *nal = ptl_interfaces[i];
-                if (!nal)
-                        continue;
+        LASSERT(interface >= 0 && interface <= NAL_MAX_NR);
+        LASSERT(ptl_nal_table[interface] != NULL);
+        LASSERT(ptl_nal_table[interface]->nal_refct == 0);
+        
+        ptl_mutex_enter();
+        
+        ptl_nal_table[interface] = NULL;
 
-                if (nal->shutdown)
-                        nal->shutdown(nal, i);
-        }
+        ptl_mutex_exit();
 }
 
-#ifdef __KERNEL__
-DECLARE_MUTEX(ptl_ni_init_mutex);
-
-static void ptl_ni_init_mutex_enter (void) 
+int PtlInit(int *max_interfaces)
 {
-        down (&ptl_ni_init_mutex);
-}
+        LASSERT(!strcmp(ptl_err_str[PTL_MAX_ERRNO], "PTL_MAX_ERRNO"));
 
-static void ptl_ni_init_mutex_exit (void)
-{
-        up (&ptl_ni_init_mutex);
-}
+        /* If this assertion fails, we need more bits in NI_HANDLE_MASK and
+         * to shift NI_HANDLE_MAGIC left appropriately */
+        LASSERT (NAL_MAX_NR < (NI_HANDLE_MASK + 1));
+        
+        if (max_interfaces != NULL)
+                *max_interfaces = NAL_MAX_NR + 1;
+
+        ptl_mutex_enter();
+
+        if (!ptl_init) {
+                /* NULL pointers, clear flags */
+                memset(ptl_nal_table, 0, sizeof(ptl_nal_table));
+#ifndef __KERNEL__
+                /* Kernel NALs register themselves when their module loads,
+                 * and unregister themselves when their module is unloaded.
+                 * Userspace NALs, are plugged in explicitly here... */
+                {
+                        extern nal_t procapi_nal;
+
+                        /* XXX pretend it's socknal to keep liblustre happy... */
+                        ptl_nal_table[SOCKNAL] = &procapi_nal;
+                        LASSERT (procapi_nal.nal_refct == 0);
+                }
+#endif
+                ptl_init = 1;
+        }
 
-#else
-static void ptl_ni_init_mutex_enter (void)
-{
+        ptl_mutex_exit();
+        
+        return PTL_OK;
 }
 
-static void ptl_ni_init_mutex_exit (void) 
+void PtlFini(void)
 {
-}
+        nal_t  *nal;
+        int     i;
+
+        ptl_mutex_enter();
+
+        if (ptl_init) {
+                for (i = 0; i <= NAL_MAX_NR; i++) {
+
+                        nal = ptl_nal_table[i];
+                        if (nal == NULL)
+                                continue;
+                        
+                        if (nal->nal_refct != 0) {
+                                CWARN("NAL %x has outstanding refcount %d\n",
+                                      i, nal->nal_refct);
+                                nal->nal_ni_fini(nal);
+                        }
+                        
+                        ptl_nal_table[i] = NULL;
+                }
 
-#endif
+                ptl_init = 0;
+        }
+        
+        ptl_mutex_exit();
+}
 
-int PtlNIInit(ptl_interface_t interface, ptl_pt_index_t ptl_size,
-              ptl_ac_index_t acl_size, ptl_pid_t requested_pid,
-              ptl_handle_ni_t * handle)
+int PtlNIInit(ptl_interface_t interface, ptl_pid_t requested_pid,
+              ptl_ni_limits_t *desired_limits, ptl_ni_limits_t *actual_limits,
+              ptl_handle_ni_t *handle)
 {
         nal_t *nal;
-        int i;
+        int    i;
+        int    rc;
 
         if (!ptl_init)
                 return PTL_NO_INIT;
 
-        ptl_ni_init_mutex_enter ();
-
-        nal = interface(ptl_num_interfaces, ptl_size, acl_size, requested_pid);
+        ptl_mutex_enter ();
 
-        if (!nal) {
-                ptl_ni_init_mutex_exit ();
-                return PTL_NAL_FAILED;
+        if (interface == PTL_IFACE_DEFAULT) {
+                for (i = 0; i <= NAL_MAX_NR; i++)
+                        if (ptl_nal_table[i] != NULL) {
+                                interface = i;
+                                break;
+                        }
+                /* NB if no interfaces are registered, 'interface' will
+                 * fail the valid test below */
         }
-
-        for (i = 0; i < ptl_num_interfaces; i++) {
-                if (ptl_interfaces[i] == nal) {
-                        nal->refct++;
-                        handle->nal_idx = (NI_HANDLE_MAGIC & ~NI_HANDLE_MASK) | i;
-                        CDEBUG(D_OTHER, "Returning existing NAL (%d)\n", i);
-                        ptl_ni_init_mutex_exit ();
-                        return PTL_OK;
-                }
+        
+        if (interface < 0 || 
+            interface > NAL_MAX_NR ||
+            ptl_nal_table[interface] == NULL) {
+                GOTO(out, rc = PTL_IFACE_INVALID);
         }
-        nal->refct = 1;
 
-        if (ptl_num_interfaces >= MAX_NIS) {
-                if (nal->shutdown)
-                        nal->shutdown (nal, ptl_num_interfaces);
-                ptl_ni_init_mutex_exit ();
-                return PTL_NO_SPACE;
-        }
+        nal = ptl_nal_table[interface];
+        nal->nal_handle.nal_idx = (NI_HANDLE_MAGIC & ~NI_HANDLE_MASK) | interface;
+        nal->nal_handle.cookie = 0;
+        
+        CDEBUG(D_OTHER, "Starting up NAL (%x) refs %d\n", interface, nal->nal_refct);
+        rc = nal->nal_ni_init(nal, requested_pid, desired_limits, actual_limits);
 
-        handle->nal_idx = (NI_HANDLE_MAGIC & ~NI_HANDLE_MASK) | ptl_num_interfaces;
-        ptl_interfaces[ptl_num_interfaces++] = nal;
+        if (rc != PTL_OK) {
+                CERROR("Error %d starting up NAL %x, refs %d\n", rc,
+                       interface, nal->nal_refct);
+                GOTO(out, rc);
+        }
+        
+        if (nal->nal_refct != 0) {
+                /* Caller gets to know if this was the first ref or not */
+                rc = PTL_IFACE_DUP;
+        }
+        
+        nal->nal_refct++;
+        *handle = nal->nal_handle;
 
-        ptl_eq_ni_init(nal);
-        ptl_me_ni_init(nal);
+ out:
+        ptl_mutex_exit ();
 
-        ptl_ni_init_mutex_exit ();
-        return PTL_OK;
+        return rc;
 }
 
-
 int PtlNIFini(ptl_handle_ni_t ni)
 {
         nal_t *nal;
-        int idx;
-        int rc;
+        int    idx;
 
         if (!ptl_init)
                 return PTL_NO_INIT;
 
-        ptl_ni_init_mutex_enter ();
+        ptl_mutex_enter ();
 
         nal = ptl_hndl2nal (&ni);
         if (nal == NULL) {
-                ptl_ni_init_mutex_exit ();
+                ptl_mutex_exit ();
                 return PTL_HANDLE_INVALID;
         }
 
         idx = ni.nal_idx & NI_HANDLE_MASK;
 
-        nal->refct--;
-        if (nal->refct > 0) {
-                ptl_ni_init_mutex_exit ();
-                return PTL_OK;
-        }
-
-        ptl_me_ni_fini(nal);
-        ptl_eq_ni_fini(nal);
-
-        rc = PTL_OK;
-        if (nal->shutdown)
-                rc = nal->shutdown(nal, idx);
+        LASSERT(nal->nal_refct > 0);
 
-        ptl_interfaces[idx] = NULL;
-        ptl_num_interfaces--;
+        nal->nal_refct--;
 
-        ptl_ni_init_mutex_exit ();
-        return rc;
-}
-
-int PtlNIHandle(ptl_handle_any_t handle_in, ptl_handle_ni_t * ni_out)
-{
-        *ni_out = handle_in;
+        /* nal_refct == 0 tells nal->shutdown to really shut down */
+        nal->nal_ni_fini(nal);
 
+        ptl_mutex_exit ();
         return PTL_OK;
 }