This huge patch revamps almost everything under dat, and merges the three
layers of external API, dynamic registry and dictinary into a single
one, greatly streamlining all of the code.

Note that I don't have any RDMA hardware to actually takes this, so it
probably needs some testing first.


Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]>

Index: linux-kernel/dat/dr.c
===================================================================
--- linux-kernel/dat/dr.c       (revision 2647)
+++ linux-kernel/dat/dr.c       (working copy)
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- *    copy of which is available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/*
- * Dynamic Registry (DR) functions and data structures
- *
- * $Id$
- */
-
-#include "core.h"
-#include "dictionary.h"
-#include "dr.h"
-
-struct dat_dr_entry {
-       int ref_count;
-       struct dat_provider_info info;
-       DAT_IA_OPEN_FUNC ia_open_func;
-};
-
-static spinlock_t g_dr_lock = SPIN_LOCK_UNLOCKED;
-static struct dat_dictionary g_dr_dictionary = 
-       DAT_DICTIONARY_INIT(g_dr_dictionary);
-
-void dat_dr_fini(void)
-{
-       dat_dictionary_destroy(&g_dr_dictionary);
-}
-
-u32 dat_dr_insert(const struct dat_provider_info *info,
-                 const DAT_IA_OPEN_FUNC ia_open_func)
-{
-       struct dat_dr_entry *data;
-       struct dat_dictionary_entry *dict_entry;
-       unsigned long flags;
-       u32 status;
-
-       data = kmalloc(sizeof *data, GFP_ATOMIC);
-       if (!data) {
-               status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 
-                                  DAT_RESOURCE_MEMORY);
-               goto bail;
-       }
-
-       data->ref_count = 0;
-       data->info = *info;
-       data->ia_open_func = ia_open_func;
-
-       dict_entry = NULL;
-       status = dat_dictionary_entry_create(&dict_entry);
-       if (DAT_SUCCESS != status)
-               goto bail;
-
-       spin_lock_irqsave(&g_dr_lock, flags);
-
-       status = dat_dictionary_insert(&g_dr_dictionary, info, dict_entry,
-                                      data);
-
-       spin_unlock_irqrestore(&g_dr_lock, flags);
-
-bail:
-       if (DAT_SUCCESS != status) {
-               if (NULL != data)
-                       kfree(data);
-
-               if (NULL != dict_entry)
-                       dat_dictionary_entry_destroy(dict_entry);
-       }
-
-       return status;
-}
-
-u32 dat_dr_remove(const struct dat_provider_info *info)
-{
-       struct dat_dr_entry *data;
-       struct dat_dictionary_entry *dict_entry;
-       unsigned long flags;
-       u32 status;
-
-       dict_entry = NULL;
-       spin_lock_irqsave(&g_dr_lock, flags);
-
-       status = dat_dictionary_search(&g_dr_dictionary, info, (void **) &data);
-
-       if (DAT_SUCCESS != status)              
-               goto bail; /* return status from dat_dictionary_search() */
-
-       if (0 != data->ref_count) {
-               status = DAT_ERROR(DAT_PROVIDER_IN_USE, 0);
-               goto bail;
-       }
-
-       status = dat_dictionary_remove(&g_dr_dictionary, info, &dict_entry,
-                                      (void **) &data);
-       if (DAT_SUCCESS != status)
-               goto bail; /* return status from dat_dictionary_remove() */
-        
-       kfree(data);
-
-bail:
-       spin_unlock_irqrestore(&g_dr_lock, flags);
-
-       if (NULL != dict_entry)
-               dat_dictionary_entry_destroy(dict_entry);
-        
-       return status;
-}
-
-u32 dat_dr_provider_open(const struct dat_provider_info *info,
-                               DAT_IA_OPEN_FUNC *p_ia_open_func)
-{
-       struct dat_dr_entry *data;
-       unsigned long flags;
-       u32 status;
-
-       spin_lock_irqsave(&g_dr_lock, flags);
-
-       status = dat_dictionary_search(&g_dr_dictionary, info, (void **) &data);
-
-       spin_unlock_irqrestore(&g_dr_lock, flags);
-
-       if (DAT_SUCCESS == status) {
-               data->ref_count++;
-               *p_ia_open_func = data->ia_open_func;
-       }
-
-       return status;
-}
-
-u32 dat_dr_provider_close(const struct dat_provider_info *info)
-{
-       struct dat_dr_entry *data;
-       unsigned long flags;
-       u32 status;
-
-       spin_lock_irqsave(&g_dr_lock, flags);
-
-       status = dat_dictionary_search(&g_dr_dictionary, info, (void **) &data);
-
-       spin_unlock_irqrestore(&g_dr_lock, flags);
-
-       if (DAT_SUCCESS == status)
-               data->ref_count--;
-
-       return status;
-}
-
-u32 dat_dr_size(int *size)
-{
-       return dat_dictionary_size(&g_dr_dictionary, size);
-}
-
-u32 dat_dr_list(int max_to_return, int *entries_returned,
-               struct dat_provider_info *(dat_provider_list[]))
-{
-       struct dat_dr_entry **array = NULL;
-       int i, array_size;
-       unsigned long flags;
-       u32 status = DAT_SUCCESS;
-
-       /*
-        * The dictionary size may increase between the call to
-        * dat_dictionary_size() and dat_dictionary_enumerate().
-        * Therefore we loop until a successful enumeration is made.
-        */        
-       *entries_returned = 0;
-       for (;;) {
-               status = dat_dictionary_size(&g_dr_dictionary, &array_size);
-               if (DAT_SUCCESS != status)
-                       goto bail;
-
-               if (0 == array_size) {
-                       status = DAT_SUCCESS;
-                       goto bail;
-               }
-
-               array = kmalloc(array_size * sizeof *array, GFP_ATOMIC);
-               if (!array) {
-                       status =
-                           DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
-                                     DAT_RESOURCE_MEMORY);
-                       goto bail;
-               }
-
-               spin_lock_irqsave(&g_dr_lock, flags);
-
-               status = dat_dictionary_enumerate(&g_dr_dictionary, 
-                                                 (void **) array, array_size);
-
-               spin_unlock_irqrestore(&g_dr_lock, flags);
-
-               if (DAT_SUCCESS == status)
-                       break;
-               else {
-                       kfree(array);
-                       array = NULL;
-                       continue;
-               }
-       }
-
-       for (i = 0; (i < max_to_return) && (i < array_size); i++) {
-               if (NULL == dat_provider_list[i]) {
-                       status =
-                           DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
-                       goto bail;
-               }
-
-               *dat_provider_list[i] = array[i]->info;
-       }
-
-       *entries_returned = i;
-        
-bail:
-       if (NULL != array)
-               kfree(array);
-
-       return status;
-}
Index: linux-kernel/dat/dictionary.c
===================================================================
--- linux-kernel/dat/dictionary.c       (revision 2647)
+++ linux-kernel/dat/dictionary.c       (working copy)
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- *    copy of which is available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/*
- * A dictionary data structure implemented with a linked list
- *
- * $Id$
- */
-
-#include "dictionary.h"
-
-static u32 dat_dictionary_key_dup(const struct dat_provider_info *old_key,
-                                 struct dat_provider_info *new_key);
-
-static boolean_t dat_dictionary_key_is_equal(const struct dat_provider_info *a,
-                                            const struct dat_provider_info *b);
-
-void dat_dictionary_destroy(struct dat_dictionary *dictionary)
-{
-       struct list_head *cur_list, *next_list;
-       struct dat_dictionary_entry *cur_entry;
-       
-       BUG_ON(NULL == dictionary);
-       
-       list_for_each_safe(cur_list, next_list, &dictionary->list) {
-               cur_entry = list_entry(cur_list, struct dat_dictionary_entry,
-                                      list);
-               list_del(&cur_entry->list);
-               kfree(cur_entry);
-       }
-}
-
-u32 dat_dictionary_size(const struct dat_dictionary *dictionary, int *size)
-{
-       BUG_ON(NULL == dictionary);
-       BUG_ON(NULL == size);
-
-       *size = dictionary->size;
-
-       return DAT_SUCCESS;
-}
-
-u32 dat_dictionary_entry_create(struct dat_dictionary_entry **p_entry)
-{
-       struct dat_dictionary_entry *entry;
-       u32 status = DAT_SUCCESS;
-
-       BUG_ON(NULL == p_entry);
-
-       entry = kmalloc(sizeof *entry, GFP_ATOMIC);
-       if (!entry) {
-               status =
-                   DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
-               goto bail;
-       }
-
-       *p_entry = entry;
-
-bail:
-       return status;
-}
-
-void dat_dictionary_entry_destroy(const struct dat_dictionary_entry *entry)
-{
-       kfree(entry);
-}
-
-u32 dat_dictionary_insert(struct dat_dictionary *dictionary,
-                         const struct dat_provider_info *key,
-                         struct dat_dictionary_entry *entry, void *data)
-{
-       u32 status;
-
-       BUG_ON(NULL == dictionary);
-       BUG_ON(NULL == entry);
-
-       if (DAT_SUCCESS == dat_dictionary_search(dictionary, key, NULL)) {
-               status = DAT_ERROR(DAT_PROVIDER_ALREADY_REGISTERED, 0);
-               goto bail;
-       }
-
-       status = dat_dictionary_key_dup(key, &entry->key);
-       if (DAT_SUCCESS != status)
-               goto bail;
-
-       entry->data = data;
-
-       /* insert node at end of list to preserve registration order */
-       list_add_tail(&entry->list, &dictionary->list);
-
-       dictionary->size++;
-
-bail:
-       return status;
-}
-
-u32 dat_dictionary_search(struct dat_dictionary *dictionary,
-                         const struct dat_provider_info *key, void **p_data)
-{
-       struct dat_dictionary_entry *cur_entry;
-       u32 status;
-
-       BUG_ON(NULL == dictionary);
-       BUG_ON(NULL == key);
-
-       status = DAT_ERROR(DAT_PROVIDER_NOT_FOUND, DAT_NAME_NOT_REGISTERED);
-
-       list_for_each_entry(cur_entry, &dictionary->list, list) {
-               if (TRUE == dat_dictionary_key_is_equal(&cur_entry->key, key)) {
-                       if (NULL != p_data)
-                               *p_data = cur_entry->data;
-                       
-                       status = DAT_SUCCESS;
-                       goto bail;
-               }
-       }
-
-bail:
-       return status;
-}
-
-u32 dat_dictionary_enumerate(struct dat_dictionary *dictionary, void *array[],
-                            int array_size)
-{
-       struct dat_dictionary_entry *cur_entry;
-       int i;
-       u32 status;
-
-       BUG_ON(NULL == dictionary);
-       BUG_ON(NULL == array);
-
-       status = DAT_SUCCESS;
-
-       if (array_size < dictionary->size) {
-               status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 0);
-               goto bail;
-       }
-       
-       i = 0;
-       list_for_each_entry(cur_entry, &dictionary->list, list)
-               array[i++] = cur_entry->data;
-
-bail:
-       return status;
-}
-
-u32 dat_dictionary_remove(struct dat_dictionary *dictionary,
-                         const struct dat_provider_info *key,
-                         struct dat_dictionary_entry **p_entry, void **p_data)
-{
-       struct list_head *cur_list, *next_list;
-       struct dat_dictionary_entry *cur_entry;
-       u32 status;
-
-       BUG_ON(NULL == dictionary);
-       BUG_ON(NULL == key);
-       BUG_ON(NULL == p_entry);
-
-       status = DAT_ERROR(DAT_PROVIDER_NOT_FOUND, DAT_NAME_NOT_REGISTERED);
-
-       list_for_each_safe(cur_list, next_list, &dictionary->list) {
-               cur_entry = list_entry(cur_list, struct dat_dictionary_entry,
-                                      list);
-               if (TRUE == dat_dictionary_key_is_equal(&cur_entry->key, key)) {
-                       if (NULL != p_data)
-                               *p_data = cur_entry->data;
-                        
-                       list_del(&cur_entry->list);
-                       
-                       *p_entry = cur_entry;
-                       
-                       dictionary->size--;
-
-                       status = DAT_SUCCESS;
-                       goto bail;
-               }
-       }
-       
-bail:
-       return status;
-}
-
-static u32 dat_dictionary_key_dup(const struct dat_provider_info *old_key,
-                                 struct dat_provider_info *new_key)
-{
-       BUG_ON(NULL == old_key);
-       BUG_ON(NULL == new_key);
-
-       strncpy(new_key->ia_name, old_key->ia_name, DAT_NAME_MAX_LENGTH);
-       return DAT_SUCCESS;
-}
-
-static boolean_t dat_dictionary_key_is_equal(const struct dat_provider_info *a,
-                                            const struct dat_provider_info *b)
-{
-        BUG_ON(NULL == a);
-        BUG_ON(NULL == b);
-
-       if ((strlen(a->ia_name) == strlen(b->ia_name)) &&
-           (!strncmp(a->ia_name, b->ia_name, strlen(a->ia_name))))
-               return TRUE;
-       else
-               return FALSE;
-}
Index: linux-kernel/dat/core.c
===================================================================
--- linux-kernel/dat/core.c     (revision 2647)
+++ linux-kernel/dat/core.c     (working copy)
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- *    copy of which is available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/*
- * Core DAT registry functions and data structures
- *
- * $Id$
- */
-
-#include "core.h"
-#include "dr.h"
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("Direct Access Transport (DAT) API");
-MODULE_AUTHOR("James Lentini");
-
-static DAT_DBG_MASK g_dbg_mask = DAT_DBG_TYPE_ERROR;
-module_param_named(dbg_mask, g_dbg_mask, int, 0644);
-MODULE_PARM_DESC(dbg_mask, "Bitmask to enable debug message types.");
-
-void dat_dbg_print(DAT_DBG_TYPE type, const char *fmt, ...)
-{
-       static char buf[1024];
-
-       if (type & g_dbg_mask) {
-               va_list args;
-
-               va_start(args, fmt);
-               vsnprintf(buf, sizeof buf, fmt, args);
-               printk(KERN_ALERT "DAT: %s", buf);
-               va_end(args);
-       }
-}
-
-static int __init dat_init(void)
-{
-       dat_dbg_print(DAT_DBG_TYPE_GENERIC, "registry started\n");
-       return 0;
-}
-
-module_init(dat_init);
-
-static void __exit dat_fini(void)
-{
-       dat_dr_fini();
-       
-       dat_dbg_print(DAT_DBG_TYPE_GENERIC, "registry stopped\n");
-}
-
-module_exit(dat_fini);
Index: linux-kernel/dat/api.c
===================================================================
--- linux-kernel/dat/api.c      (revision 2647)
+++ linux-kernel/dat/api.c      (working copy)
@@ -26,15 +26,53 @@
  * and/or other materials provided with the distribution.
  */
 
-/*
- * DAT functions for consumers
- *
- * $Id: consumer.c 2251 2005-05-04 05:57:41Z jlentini $
- */
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
 
-#include "core.h"
-#include "dr.h"
+#include <dat.h>
 
+
+enum dat_dbg_type {
+       DAT_DBG_TYPE_ERROR        = (1 << 0),
+       DAT_DBG_TYPE_GENERIC      = (1 << 1),
+       DAT_DBG_TYPE_DR           = (1 << 2),
+       DAT_DBG_TYPE_PROVIDER_API = (1 << 3),
+       DAT_DBG_TYPE_CONSUMER_API = (1 << 4),
+       DAT_DBG_TYPE_ALL          = 0x1f
+};
+
+static int dat_dbg_mask = DAT_DBG_TYPE_ERROR;
+module_param_named(dbg_mask, dat_dbg_mask, int, 0644);
+MODULE_PARM_DESC(dbg_mask, "Bitmask to enable debug message types.");
+
+struct dat_dictionary_entry {
+       struct list_head list;
+       struct dat_provider_info info;
+       DAT_IA_OPEN_FUNC ia_open_func;
+       int ref_count;
+};
+
+static LIST_HEAD(dat_provider_list);
+static int dat_provider_list_size;
+static DEFINE_SPINLOCK(dat_provider_list_lock);
+
+static void dat_dbg_print(enum dat_dbg_type type, const char *fmt, ...)
+{
+       static char buf[1024];
+
+       if (type & dat_dbg_mask) {
+               va_list args;
+
+               va_start(args, fmt);
+               vsnprintf(buf, sizeof buf, fmt, args);
+               printk(KERN_ALERT "DAT: %s", buf);
+               va_end(args);
+       }
+}
+
 static u32 dat_strerror_major(u32 value, const char **message)
 {
        switch (DAT_GET_TYPE(value)) {
@@ -350,21 +388,39 @@
        }
 }
 
+static boolean_t dat_dictionary_key_is_equal(const struct dat_provider_info *a,
+                                            const struct dat_provider_info *b)
+{
+       if (strlen(a->ia_name) == strlen(b->ia_name) &&
+           !strncmp(a->ia_name, b->ia_name, strlen(a->ia_name)))
+               return 1;
+       return 0;
+}
+
+static struct dat_dictionary_entry *dat_dictionary_search(
+               struct list_head *list, const struct dat_provider_info *key)
+{
+       struct dat_dictionary_entry *entry;
+
+       list_for_each_entry(entry, list, list)
+               if (dat_dictionary_key_is_equal(&entry->info, key))
+                       return entry;
+
+       return NULL;
+}
+
 u32 dat_ia_open(const char *name, int async_event_qlen,
                struct dat_evd **async_event_handle, struct dat_ia **ia)
 {
-       DAT_IA_OPEN_FUNC ia_open_func;
        struct dat_provider_info info;
-        u32 status;
+       struct dat_dictionary_entry *data;
+       unsigned long flags;
        size_t len;
 
        dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
                       "%s(name:%s, async_qlen:%i, ver:%x.%x, thrd_safe:%x)\n",
                      __func__, name, async_event_qlen);
 
-       if (DAT_IS_BAD_POINTER(name))
-               return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1);
-
        len = strlen(name);
 
        if (DAT_NAME_MAX_LENGTH < len)
@@ -373,62 +429,67 @@
        strncpy(info.ia_name, name, len);
        info.ia_name[len] = '\0';
 
-       status = dat_dr_provider_open(&info, &ia_open_func);
-       if (status != DAT_SUCCESS) {
+       spin_lock_irqsave(&dat_provider_list_lock, flags);
+       data = dat_dictionary_search(&dat_provider_list, &info);
+       spin_unlock_irqrestore(&dat_provider_list_lock, flags);
+
+       if (!data) {
                dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
                               "%s: IA [%s] not found in dynamic registry\n",
                              __func__, name);
 
-               return status;
+               return DAT_ERROR(DAT_PROVIDER_NOT_FOUND,
+                                DAT_NAME_NOT_REGISTERED);
        }
 
-        return ia_open_func(name, async_event_qlen, async_event_handle,        
ia);
+       data->ref_count++;
+        return data->ia_open_func(name, async_event_qlen, async_event_handle,
+                       ia);
 }
-
 EXPORT_SYMBOL(dat_ia_open);
 
-u32 dat_ia_close(struct dat_ia *ia, enum dat_close_flags flags)
+u32 dat_ia_close(struct dat_ia *ia, enum dat_close_flags close_flags)
 {
        struct dat_provider *provider;
-       struct dat_provider_attr provider_attr;
-        u32 status;
+       struct dat_provider_info info;
+       u32 status = DAT_SUCCESS;
        const char *ia_name;
+       struct dat_dictionary_entry *data;
+       unsigned long flags;
+       size_t len;
 
        dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API, 
-                      "%s(ia:%x, flags:%x)\n", __func__, ia, flags);
+                      "%s(ia:%x, flags:%x)\n", __func__, ia, close_flags);
         
        provider = ia->common.provider;
        ia_name = provider->device_name;
 
-       if (DAT_SUCCESS != (status = dat_ia_query(ia, NULL, NULL,
-                                                 &provider_attr)))
+       status = provider->ia_close_func(ia, close_flags);
+       if (status != DAT_SUCCESS) {
                dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
-                             "dat_ia_query for IA %s failed\n", ia_name);
-       else if (DAT_SUCCESS != (status = provider->ia_close_func(ia, flags)))
-               dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
                              "close function for IA %s failed\n", ia_name);
-       else {
-               struct dat_provider_info info;
-               size_t len;
+               return status;
+       }
 
-               len = strlen(ia_name);
+       len = strlen(ia_name);
 
-               BUG_ON(DAT_NAME_MAX_LENGTH < len);
+       BUG_ON(DAT_NAME_MAX_LENGTH < len);
 
-               strncpy(info.ia_name, ia_name, len);
-               info.ia_name[len] = '\0';
+       strncpy(info.ia_name, ia_name, len);
+       info.ia_name[len] = '\0';
 
-               status = dat_dr_provider_close(&info);
-               if (DAT_SUCCESS != status)
-                       dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
-                                     "dynamic registry unable to close "
-                                      "provider for IA %s\n", 
-                                      ia_name);
+       spin_lock_irqsave(&dat_provider_list_lock, flags);
+       data = dat_dictionary_search(&dat_provider_list, &info);
+       if (data) {
+               data->ref_count--;
+       } else {
+               status = DAT_ERROR(DAT_PROVIDER_NOT_FOUND,
+                                  DAT_NAME_NOT_REGISTERED);
        }
+       spin_unlock_irqrestore(&dat_provider_list_lock, flags);
 
        return status;
 }
-
 EXPORT_SYMBOL(dat_ia_close);
 
 u32 dat_strerror(u32 value, const char **major_message,
@@ -454,69 +515,138 @@
 
        return DAT_SUCCESS;
 }
-
 EXPORT_SYMBOL(dat_strerror);
 
 u32 dat_registry_add_provider(const struct dat_provider *provider,
-                             const struct dat_provider_info *provider_info)
+                             const struct dat_provider_info *info)
 {
-       dat_dbg_print(DAT_DBG_TYPE_PROVIDER_API, 
-                      "%s(ia:%s, ver:%x.%x, thrd_safe:%x)\n",
-                      __func__, provider_info->ia_name);
+       struct dat_dictionary_entry *entry;
+       unsigned long flags;
+       u32 status = DAT_SUCCESS;
 
-       if (DAT_IS_BAD_POINTER(provider))
-               return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1);
+       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+       if (!entry) {
+               status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 
+                                  DAT_RESOURCE_MEMORY);
+               goto out;
+       }
 
-       if (DAT_IS_BAD_POINTER(provider_info))
-               return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
+       entry->ref_count = 0;
+       entry->info = *info;
+       entry->ia_open_func = provider->ia_open_func;
 
-       return dat_dr_insert(provider_info, provider->ia_open_func);
+       spin_lock_irqsave(&dat_provider_list_lock, flags);
+       if (dat_dictionary_search(&dat_provider_list, info)) {
+               status = DAT_ERROR(DAT_PROVIDER_ALREADY_REGISTERED, 0);
+               goto out_unlock;
+       }
+
+       strncpy(entry->info.ia_name, info->ia_name, DAT_NAME_MAX_LENGTH);
+
+       /* insert node at end of list to preserve registration order */
+       list_add_tail(&entry->list, &dat_provider_list);
+       dat_provider_list_size++;
+
+ out_unlock:
+       spin_unlock_irqrestore(&dat_provider_list_lock, flags);
+ out:
+       if (status != DAT_SUCCESS)
+               kfree(entry);
+       return status;
 }
+EXPORT_SYMBOL(dat_registry_add_provider);
 
-EXPORT_SYMBOL(dat_registry_remove_provider);
-
 u32 dat_registry_remove_provider(const struct dat_provider *provider,
-                                const struct dat_provider_info *provider_info)
+                                const struct dat_provider_info *info)
 {
-       dat_dbg_print(DAT_DBG_TYPE_PROVIDER_API, "%s(ia:%s)\n", __func__, 
-                     provider_info->ia_name);
+       struct dat_dictionary_entry *cur, *next;
+       unsigned long flags;
+       u32 status = DAT_SUCCESS;
 
-       if (DAT_IS_BAD_POINTER(provider))
-               return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1);
+       spin_lock_irqsave(&dat_provider_list_lock, flags);
+       list_for_each_entry_safe(cur, next, &dat_provider_list, list) {
+               if (dat_dictionary_key_is_equal(&cur->info, info)) {
+                       if (cur->ref_count) {
+                               status = DAT_ERROR(DAT_PROVIDER_IN_USE, 0);
+                               goto out;
+                       }
 
-       return dat_dr_remove(provider_info);
+                       list_del(&cur->list);
+                       dat_provider_list_size--;
+
+                       kfree(cur);
+                       goto out;
+               }
+       }
+
+       status = DAT_ERROR(DAT_PROVIDER_NOT_FOUND, DAT_NAME_NOT_REGISTERED);
+ out:
+       spin_unlock_irqrestore(&dat_provider_list_lock, flags);
+       return status;
 }
+EXPORT_SYMBOL(dat_registry_remove_provider);
 
-EXPORT_SYMBOL(dat_registry_add_provider);
-
 u32 dat_registry_list_providers(int max_to_return, int *entries_returned,
-                               struct dat_provider_info *(dat_provider_list[]))
+                               struct dat_provider_info *provider_list[])
 {
+       struct dat_dictionary_entry *cur;
+       unsigned long flags;
+       int i = 0;
        u32 status = DAT_SUCCESS;
 
-       dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API, 
-                      "%s(max_to_return:%i, entries_rtrn:%p, prvdr_list:%p)\n",
-                      __func__, max_to_return, entries_returned, 
-                      dat_provider_list);
-
-       if ((DAT_IS_BAD_POINTER(entries_returned)))
-               return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
-
-       if (0 != max_to_return && (DAT_IS_BAD_POINTER(dat_provider_list)))
-               return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
-
-       if (0 == max_to_return) {
+       if (!max_to_return) {
                /* the user is allowed to call with max_to_return set to zero.
                 * in which case we simply return (in *entries_returned) the
                 * number of providers currently installed.  We must also
                 * (per spec) return an error
                 */
-               (void)dat_dr_size(entries_returned);
+               *entries_returned = dat_provider_list_size;
                return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1);
-       } else
-               status = dat_dr_list(max_to_return, entries_returned,
-                                     dat_provider_list);
+       }
+
+       *entries_returned = 0;
+
+       spin_lock_irqsave(&dat_provider_list_lock, flags);
+       if (!dat_provider_list_size)
+               goto out_unlock;
+
+       list_for_each_entry(cur, &dat_provider_list, list) {
+               if (i >= max_to_return)
+                       break;
+               if (!provider_list[i]) {
+                       status =
+                           DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
+                       goto out_unlock;
+               }
+               provider_list[i++] = &cur->info;
+       }
+       *entries_returned = i;
+
+ out_unlock:
+       spin_unlock_irqrestore(&dat_provider_list_lock, flags);
        return status;
 }
+EXPORT_SYMBOL(dat_registry_list_providers);
 
-EXPORT_SYMBOL(dat_registry_list_providers);
+static int __init dat_init(void)
+{
+       dat_dbg_print(DAT_DBG_TYPE_GENERIC, "registry started\n");
+       return 0;
+}
+
+static void __exit dat_fini(void)
+{
+       struct dat_dictionary_entry *cur, *next;
+       
+       list_for_each_entry_safe(cur, next, &dat_provider_list, list) {
+               list_del(&cur->list);
+               kfree(cur);
+       }
+}
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("Direct Access Transport (DAT) API");
+MODULE_AUTHOR("James Lentini");
+
+module_init(dat_init);
+module_exit(dat_fini);
Index: linux-kernel/dat/dictionary.h
===================================================================
--- linux-kernel/dat/dictionary.h       (revision 2647)
+++ linux-kernel/dat/dictionary.h       (working copy)
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- *    copy of which is available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/*
- * dictionary data structure
- *
- * $Id$
- */
-
-#ifndef DICTIONARY_H
-#define DICTIONARY_H
-
-#include "core.h"
-
-/*********************************************************************
- *                                                                   *
- * Structures                                                        *
- *                                                                   *
- *********************************************************************/
-
-struct dat_dictionary_entry {
-       struct list_head list;
-       struct dat_provider_info key;
-       void *data;     
-};
-
-struct dat_dictionary {
-       struct list_head list;
-       int size;
-};
-
-/*********************************************************************
- *                                                                   *
- * Macros                                                            *
- *                                                                   *
- *********************************************************************/
-
-#define DAT_DICTIONARY_INIT(name) { LIST_HEAD_INIT((name).list), 0 }
-
-/*********************************************************************
- *                                                                   *
- * Function Prototypes                                               *
- *                                                                   *
- *********************************************************************/
-
-extern void dat_dictionary_destroy(struct dat_dictionary *dictionary);
-
-extern u32 dat_dictionary_size(const struct dat_dictionary *dictionary,
-                              int *size);
-
-extern u32 dat_dictionary_entry_create(struct dat_dictionary_entry **p_entry);
-
-extern void dat_dictionary_entry_destroy(
-       const struct dat_dictionary_entry *entry);
-
-extern u32 dat_dictionary_insert(struct dat_dictionary *dictionary,
-                                const struct dat_provider_info *key,
-                                struct dat_dictionary_entry *entry,
-                                void *data);
-
-extern u32 dat_dictionary_search(struct dat_dictionary *dictionary,
-                                const struct dat_provider_info *key,
-                                void **p_data);
-
-extern u32 dat_dictionary_enumerate(struct dat_dictionary *dictionary,
-                                   void *array[], const int array_size);
-
-extern u32 dat_dictionary_remove(struct dat_dictionary *dictionary,
-                                const struct dat_provider_info *key,
-                                struct dat_dictionary_entry **p_entry,
-                                void **p_data);
-
-#endif /* DICTIONARY_H */
Index: linux-kernel/dat/dr.h
===================================================================
--- linux-kernel/dat/dr.h       (revision 2647)
+++ linux-kernel/dat/dr.h       (working copy)
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- *    copy of which is available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/*
- * Dynamic Registry (DR) functions and data stucture
- *
- * $Id$
- */
-
-#ifndef DR_H
-#define DR_H
-
-#include <dat.h>
-
-extern void dat_dr_fini(void);
-
-extern u32 dat_dr_insert(const struct dat_provider_info *info,
-                        const DAT_IA_OPEN_FUNC ia_open_func);
-
-extern u32 dat_dr_remove(const struct dat_provider_info *info);
-
-extern u32 dat_dr_provider_open(const struct dat_provider_info *info,
-                               DAT_IA_OPEN_FUNC *p_ia_open_func);
-
-extern u32 dat_dr_provider_close(const struct dat_provider_info *info);
-
-extern u32 dat_dr_size(int *size);
-
-extern u32 dat_dr_list(int max_to_return, int *entries_returned,
-                      struct dat_provider_info *(dat_provider_list[]));
-
-#endif /* DR_H */
Index: linux-kernel/dat/Makefile
===================================================================
--- linux-kernel/dat/Makefile   (revision 2647)
+++ linux-kernel/dat/Makefile   (working copy)
@@ -5,8 +5,4 @@
 
 obj-$(CONFIG_DAT) += dat.o
 
-dat-y := \
-    api.o              \
-    core.o             \
-    dictionary.o       \
-    dr.o
+dat-y += api.o
Index: linux-kernel/dat/core.h
===================================================================
--- linux-kernel/dat/core.h     (revision 2647)
+++ linux-kernel/dat/core.h     (working copy)
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- *    copy of which is available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/*
- * core DAT registry functions and data structures
- *
- * $Id$
- */
-
-#ifndef CORE_H
-#define CORE_H
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-
-#include <dat.h>
-
-#define DAT_IS_BAD_POINTER(p) ( NULL == (p) )
-
-typedef enum {
-       DAT_DBG_TYPE_ERROR        = (1 << 0),
-       DAT_DBG_TYPE_GENERIC      = (1 << 1),
-       DAT_DBG_TYPE_DR           = (1 << 2),
-       DAT_DBG_TYPE_PROVIDER_API = (1 << 3),
-       DAT_DBG_TYPE_CONSUMER_API = (1 << 4),
-       DAT_DBG_TYPE_ALL          = 0x1f
-} DAT_DBG_TYPE;
-
-typedef int DAT_DBG_MASK;
-
-extern void dat_dbg_print(DAT_DBG_TYPE type, const char *fmt, ...);
-
-#endif /* CORE_H */
_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to