[openib-general] Re: [PATCH] cleanup dat provider registration
James Lentini
jlentini at netapp.com
Wed Jun 22 14:13:03 PDT 2005
This is an excellent simplification. Committed in revision 2682 with a
few minor modifications:
- kept printouts in dat_registry_add_provider,
dat_registry_remove_provider, and dat_registry_list_providers
- updated printout in dat_ia_close (this wasn't something you
changed)
- removed parens around sizeof
- removed space in front of labels
The last two are for consistency with the coding style we've been
using. If we've deviated from what is acceptable, let us know.
Given this simplification, I can think of a few more changes:
- rename api.c to registry.c
- remove all "dictionary" references: rename dat_dictionary_search to
dat_provider_list_search, rename struct dat_dictionary_entry to
struct dat_provider_list_entry, rename
dat_dictionary_key_is_equal() to dat_provider_info_is_equal()
Anyone have opinions for or against?
On Fri, 17 Jun 2005, Christoph Hellwig wrote:
hch> This huge patch revamps almost everything under dat, and merges the three
hch> layers of external API, dynamic registry and dictinary into a single
hch> one, greatly streamlining all of the code.
hch>
hch> Note that I don't have any RDMA hardware to actually takes this, so it
hch> probably needs some testing first.
hch>
hch>
hch> Signed-off-by: Christoph Hellwig <hch at lst.de>
hch>
hch> Index: linux-kernel/dat/dr.c
hch> ===================================================================
hch> --- linux-kernel/dat/dr.c (revision 2647)
hch> +++ linux-kernel/dat/dr.c (working copy)
hch> @@ -1,242 +0,0 @@
hch> -/*
hch> - * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
hch> - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
hch> - *
hch> - * This Software is licensed under one of the following licenses:
hch> - *
hch> - * 1) under the terms of the "Common Public License 1.0" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/cpl.php.
hch> - *
hch> - * 2) under the terms of the "The BSD License" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/bsd-license.php.
hch> - *
hch> - * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
hch> - * copy of which is available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/gpl-license.php.
hch> - *
hch> - * Licensee has the right to choose one of the above licenses.
hch> - *
hch> - * Redistributions of source code must retain the above copyright
hch> - * notice and one of the license notices.
hch> - *
hch> - * Redistributions in binary form must reproduce both the above copyright
hch> - * notice, one of the license notices in the documentation
hch> - * and/or other materials provided with the distribution.
hch> - */
hch> -
hch> -/*
hch> - * Dynamic Registry (DR) functions and data structures
hch> - *
hch> - * $Id$
hch> - */
hch> -
hch> -#include "core.h"
hch> -#include "dictionary.h"
hch> -#include "dr.h"
hch> -
hch> -struct dat_dr_entry {
hch> - int ref_count;
hch> - struct dat_provider_info info;
hch> - DAT_IA_OPEN_FUNC ia_open_func;
hch> -};
hch> -
hch> -static spinlock_t g_dr_lock = SPIN_LOCK_UNLOCKED;
hch> -static struct dat_dictionary g_dr_dictionary =
hch> - DAT_DICTIONARY_INIT(g_dr_dictionary);
hch> -
hch> -void dat_dr_fini(void)
hch> -{
hch> - dat_dictionary_destroy(&g_dr_dictionary);
hch> -}
hch> -
hch> -u32 dat_dr_insert(const struct dat_provider_info *info,
hch> - const DAT_IA_OPEN_FUNC ia_open_func)
hch> -{
hch> - struct dat_dr_entry *data;
hch> - struct dat_dictionary_entry *dict_entry;
hch> - unsigned long flags;
hch> - u32 status;
hch> -
hch> - data = kmalloc(sizeof *data, GFP_ATOMIC);
hch> - if (!data) {
hch> - status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
hch> - DAT_RESOURCE_MEMORY);
hch> - goto bail;
hch> - }
hch> -
hch> - data->ref_count = 0;
hch> - data->info = *info;
hch> - data->ia_open_func = ia_open_func;
hch> -
hch> - dict_entry = NULL;
hch> - status = dat_dictionary_entry_create(&dict_entry);
hch> - if (DAT_SUCCESS != status)
hch> - goto bail;
hch> -
hch> - spin_lock_irqsave(&g_dr_lock, flags);
hch> -
hch> - status = dat_dictionary_insert(&g_dr_dictionary, info, dict_entry,
hch> - data);
hch> -
hch> - spin_unlock_irqrestore(&g_dr_lock, flags);
hch> -
hch> -bail:
hch> - if (DAT_SUCCESS != status) {
hch> - if (NULL != data)
hch> - kfree(data);
hch> -
hch> - if (NULL != dict_entry)
hch> - dat_dictionary_entry_destroy(dict_entry);
hch> - }
hch> -
hch> - return status;
hch> -}
hch> -
hch> -u32 dat_dr_remove(const struct dat_provider_info *info)
hch> -{
hch> - struct dat_dr_entry *data;
hch> - struct dat_dictionary_entry *dict_entry;
hch> - unsigned long flags;
hch> - u32 status;
hch> -
hch> - dict_entry = NULL;
hch> - spin_lock_irqsave(&g_dr_lock, flags);
hch> -
hch> - status = dat_dictionary_search(&g_dr_dictionary, info, (void **) &data);
hch> -
hch> - if (DAT_SUCCESS != status)
hch> - goto bail; /* return status from dat_dictionary_search() */
hch> -
hch> - if (0 != data->ref_count) {
hch> - status = DAT_ERROR(DAT_PROVIDER_IN_USE, 0);
hch> - goto bail;
hch> - }
hch> -
hch> - status = dat_dictionary_remove(&g_dr_dictionary, info, &dict_entry,
hch> - (void **) &data);
hch> - if (DAT_SUCCESS != status)
hch> - goto bail; /* return status from dat_dictionary_remove() */
hch> -
hch> - kfree(data);
hch> -
hch> -bail:
hch> - spin_unlock_irqrestore(&g_dr_lock, flags);
hch> -
hch> - if (NULL != dict_entry)
hch> - dat_dictionary_entry_destroy(dict_entry);
hch> -
hch> - return status;
hch> -}
hch> -
hch> -u32 dat_dr_provider_open(const struct dat_provider_info *info,
hch> - DAT_IA_OPEN_FUNC *p_ia_open_func)
hch> -{
hch> - struct dat_dr_entry *data;
hch> - unsigned long flags;
hch> - u32 status;
hch> -
hch> - spin_lock_irqsave(&g_dr_lock, flags);
hch> -
hch> - status = dat_dictionary_search(&g_dr_dictionary, info, (void **) &data);
hch> -
hch> - spin_unlock_irqrestore(&g_dr_lock, flags);
hch> -
hch> - if (DAT_SUCCESS == status) {
hch> - data->ref_count++;
hch> - *p_ia_open_func = data->ia_open_func;
hch> - }
hch> -
hch> - return status;
hch> -}
hch> -
hch> -u32 dat_dr_provider_close(const struct dat_provider_info *info)
hch> -{
hch> - struct dat_dr_entry *data;
hch> - unsigned long flags;
hch> - u32 status;
hch> -
hch> - spin_lock_irqsave(&g_dr_lock, flags);
hch> -
hch> - status = dat_dictionary_search(&g_dr_dictionary, info, (void **) &data);
hch> -
hch> - spin_unlock_irqrestore(&g_dr_lock, flags);
hch> -
hch> - if (DAT_SUCCESS == status)
hch> - data->ref_count--;
hch> -
hch> - return status;
hch> -}
hch> -
hch> -u32 dat_dr_size(int *size)
hch> -{
hch> - return dat_dictionary_size(&g_dr_dictionary, size);
hch> -}
hch> -
hch> -u32 dat_dr_list(int max_to_return, int *entries_returned,
hch> - struct dat_provider_info *(dat_provider_list[]))
hch> -{
hch> - struct dat_dr_entry **array = NULL;
hch> - int i, array_size;
hch> - unsigned long flags;
hch> - u32 status = DAT_SUCCESS;
hch> -
hch> - /*
hch> - * The dictionary size may increase between the call to
hch> - * dat_dictionary_size() and dat_dictionary_enumerate().
hch> - * Therefore we loop until a successful enumeration is made.
hch> - */
hch> - *entries_returned = 0;
hch> - for (;;) {
hch> - status = dat_dictionary_size(&g_dr_dictionary, &array_size);
hch> - if (DAT_SUCCESS != status)
hch> - goto bail;
hch> -
hch> - if (0 == array_size) {
hch> - status = DAT_SUCCESS;
hch> - goto bail;
hch> - }
hch> -
hch> - array = kmalloc(array_size * sizeof *array, GFP_ATOMIC);
hch> - if (!array) {
hch> - status =
hch> - DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
hch> - DAT_RESOURCE_MEMORY);
hch> - goto bail;
hch> - }
hch> -
hch> - spin_lock_irqsave(&g_dr_lock, flags);
hch> -
hch> - status = dat_dictionary_enumerate(&g_dr_dictionary,
hch> - (void **) array, array_size);
hch> -
hch> - spin_unlock_irqrestore(&g_dr_lock, flags);
hch> -
hch> - if (DAT_SUCCESS == status)
hch> - break;
hch> - else {
hch> - kfree(array);
hch> - array = NULL;
hch> - continue;
hch> - }
hch> - }
hch> -
hch> - for (i = 0; (i < max_to_return) && (i < array_size); i++) {
hch> - if (NULL == dat_provider_list[i]) {
hch> - status =
hch> - DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
hch> - goto bail;
hch> - }
hch> -
hch> - *dat_provider_list[i] = array[i]->info;
hch> - }
hch> -
hch> - *entries_returned = i;
hch> -
hch> -bail:
hch> - if (NULL != array)
hch> - kfree(array);
hch> -
hch> - return status;
hch> -}
hch> Index: linux-kernel/dat/dictionary.c
hch> ===================================================================
hch> --- linux-kernel/dat/dictionary.c (revision 2647)
hch> +++ linux-kernel/dat/dictionary.c (working copy)
hch> @@ -1,229 +0,0 @@
hch> -/*
hch> - * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
hch> - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
hch> - *
hch> - * This Software is licensed under one of the following licenses:
hch> - *
hch> - * 1) under the terms of the "Common Public License 1.0" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/cpl.php.
hch> - *
hch> - * 2) under the terms of the "The BSD License" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/bsd-license.php.
hch> - *
hch> - * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
hch> - * copy of which is available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/gpl-license.php.
hch> - *
hch> - * Licensee has the right to choose one of the above licenses.
hch> - *
hch> - * Redistributions of source code must retain the above copyright
hch> - * notice and one of the license notices.
hch> - *
hch> - * Redistributions in binary form must reproduce both the above copyright
hch> - * notice, one of the license notices in the documentation
hch> - * and/or other materials provided with the distribution.
hch> - */
hch> -
hch> -/*
hch> - * A dictionary data structure implemented with a linked list
hch> - *
hch> - * $Id$
hch> - */
hch> -
hch> -#include "dictionary.h"
hch> -
hch> -static u32 dat_dictionary_key_dup(const struct dat_provider_info *old_key,
hch> - struct dat_provider_info *new_key);
hch> -
hch> -static boolean_t dat_dictionary_key_is_equal(const struct dat_provider_info *a,
hch> - const struct dat_provider_info *b);
hch> -
hch> -void dat_dictionary_destroy(struct dat_dictionary *dictionary)
hch> -{
hch> - struct list_head *cur_list, *next_list;
hch> - struct dat_dictionary_entry *cur_entry;
hch> -
hch> - BUG_ON(NULL == dictionary);
hch> -
hch> - list_for_each_safe(cur_list, next_list, &dictionary->list) {
hch> - cur_entry = list_entry(cur_list, struct dat_dictionary_entry,
hch> - list);
hch> - list_del(&cur_entry->list);
hch> - kfree(cur_entry);
hch> - }
hch> -}
hch> -
hch> -u32 dat_dictionary_size(const struct dat_dictionary *dictionary, int *size)
hch> -{
hch> - BUG_ON(NULL == dictionary);
hch> - BUG_ON(NULL == size);
hch> -
hch> - *size = dictionary->size;
hch> -
hch> - return DAT_SUCCESS;
hch> -}
hch> -
hch> -u32 dat_dictionary_entry_create(struct dat_dictionary_entry **p_entry)
hch> -{
hch> - struct dat_dictionary_entry *entry;
hch> - u32 status = DAT_SUCCESS;
hch> -
hch> - BUG_ON(NULL == p_entry);
hch> -
hch> - entry = kmalloc(sizeof *entry, GFP_ATOMIC);
hch> - if (!entry) {
hch> - status =
hch> - DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
hch> - goto bail;
hch> - }
hch> -
hch> - *p_entry = entry;
hch> -
hch> -bail:
hch> - return status;
hch> -}
hch> -
hch> -void dat_dictionary_entry_destroy(const struct dat_dictionary_entry *entry)
hch> -{
hch> - kfree(entry);
hch> -}
hch> -
hch> -u32 dat_dictionary_insert(struct dat_dictionary *dictionary,
hch> - const struct dat_provider_info *key,
hch> - struct dat_dictionary_entry *entry, void *data)
hch> -{
hch> - u32 status;
hch> -
hch> - BUG_ON(NULL == dictionary);
hch> - BUG_ON(NULL == entry);
hch> -
hch> - if (DAT_SUCCESS == dat_dictionary_search(dictionary, key, NULL)) {
hch> - status = DAT_ERROR(DAT_PROVIDER_ALREADY_REGISTERED, 0);
hch> - goto bail;
hch> - }
hch> -
hch> - status = dat_dictionary_key_dup(key, &entry->key);
hch> - if (DAT_SUCCESS != status)
hch> - goto bail;
hch> -
hch> - entry->data = data;
hch> -
hch> - /* insert node at end of list to preserve registration order */
hch> - list_add_tail(&entry->list, &dictionary->list);
hch> -
hch> - dictionary->size++;
hch> -
hch> -bail:
hch> - return status;
hch> -}
hch> -
hch> -u32 dat_dictionary_search(struct dat_dictionary *dictionary,
hch> - const struct dat_provider_info *key, void **p_data)
hch> -{
hch> - struct dat_dictionary_entry *cur_entry;
hch> - u32 status;
hch> -
hch> - BUG_ON(NULL == dictionary);
hch> - BUG_ON(NULL == key);
hch> -
hch> - status = DAT_ERROR(DAT_PROVIDER_NOT_FOUND, DAT_NAME_NOT_REGISTERED);
hch> -
hch> - list_for_each_entry(cur_entry, &dictionary->list, list) {
hch> - if (TRUE == dat_dictionary_key_is_equal(&cur_entry->key, key)) {
hch> - if (NULL != p_data)
hch> - *p_data = cur_entry->data;
hch> -
hch> - status = DAT_SUCCESS;
hch> - goto bail;
hch> - }
hch> - }
hch> -
hch> -bail:
hch> - return status;
hch> -}
hch> -
hch> -u32 dat_dictionary_enumerate(struct dat_dictionary *dictionary, void *array[],
hch> - int array_size)
hch> -{
hch> - struct dat_dictionary_entry *cur_entry;
hch> - int i;
hch> - u32 status;
hch> -
hch> - BUG_ON(NULL == dictionary);
hch> - BUG_ON(NULL == array);
hch> -
hch> - status = DAT_SUCCESS;
hch> -
hch> - if (array_size < dictionary->size) {
hch> - status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, 0);
hch> - goto bail;
hch> - }
hch> -
hch> - i = 0;
hch> - list_for_each_entry(cur_entry, &dictionary->list, list)
hch> - array[i++] = cur_entry->data;
hch> -
hch> -bail:
hch> - return status;
hch> -}
hch> -
hch> -u32 dat_dictionary_remove(struct dat_dictionary *dictionary,
hch> - const struct dat_provider_info *key,
hch> - struct dat_dictionary_entry **p_entry, void **p_data)
hch> -{
hch> - struct list_head *cur_list, *next_list;
hch> - struct dat_dictionary_entry *cur_entry;
hch> - u32 status;
hch> -
hch> - BUG_ON(NULL == dictionary);
hch> - BUG_ON(NULL == key);
hch> - BUG_ON(NULL == p_entry);
hch> -
hch> - status = DAT_ERROR(DAT_PROVIDER_NOT_FOUND, DAT_NAME_NOT_REGISTERED);
hch> -
hch> - list_for_each_safe(cur_list, next_list, &dictionary->list) {
hch> - cur_entry = list_entry(cur_list, struct dat_dictionary_entry,
hch> - list);
hch> - if (TRUE == dat_dictionary_key_is_equal(&cur_entry->key, key)) {
hch> - if (NULL != p_data)
hch> - *p_data = cur_entry->data;
hch> -
hch> - list_del(&cur_entry->list);
hch> -
hch> - *p_entry = cur_entry;
hch> -
hch> - dictionary->size--;
hch> -
hch> - status = DAT_SUCCESS;
hch> - goto bail;
hch> - }
hch> - }
hch> -
hch> -bail:
hch> - return status;
hch> -}
hch> -
hch> -static u32 dat_dictionary_key_dup(const struct dat_provider_info *old_key,
hch> - struct dat_provider_info *new_key)
hch> -{
hch> - BUG_ON(NULL == old_key);
hch> - BUG_ON(NULL == new_key);
hch> -
hch> - strncpy(new_key->ia_name, old_key->ia_name, DAT_NAME_MAX_LENGTH);
hch> - return DAT_SUCCESS;
hch> -}
hch> -
hch> -static boolean_t dat_dictionary_key_is_equal(const struct dat_provider_info *a,
hch> - const struct dat_provider_info *b)
hch> -{
hch> - BUG_ON(NULL == a);
hch> - BUG_ON(NULL == b);
hch> -
hch> - if ((strlen(a->ia_name) == strlen(b->ia_name)) &&
hch> - (!strncmp(a->ia_name, b->ia_name, strlen(a->ia_name))))
hch> - return TRUE;
hch> - else
hch> - return FALSE;
hch> -}
hch> Index: linux-kernel/dat/core.c
hch> ===================================================================
hch> --- linux-kernel/dat/core.c (revision 2647)
hch> +++ linux-kernel/dat/core.c (working copy)
hch> @@ -1,75 +0,0 @@
hch> -/*
hch> - * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
hch> - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
hch> - *
hch> - * This Software is licensed under one of the following licenses:
hch> - *
hch> - * 1) under the terms of the "Common Public License 1.0" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/cpl.php.
hch> - *
hch> - * 2) under the terms of the "The BSD License" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/bsd-license.php.
hch> - *
hch> - * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
hch> - * copy of which is available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/gpl-license.php.
hch> - *
hch> - * Licensee has the right to choose one of the above licenses.
hch> - *
hch> - * Redistributions of source code must retain the above copyright
hch> - * notice and one of the license notices.
hch> - *
hch> - * Redistributions in binary form must reproduce both the above copyright
hch> - * notice, one of the license notices in the documentation
hch> - * and/or other materials provided with the distribution.
hch> - */
hch> -
hch> -/*
hch> - * Core DAT registry functions and data structures
hch> - *
hch> - * $Id$
hch> - */
hch> -
hch> -#include "core.h"
hch> -#include "dr.h"
hch> -
hch> -MODULE_LICENSE("Dual BSD/GPL");
hch> -MODULE_DESCRIPTION("Direct Access Transport (DAT) API");
hch> -MODULE_AUTHOR("James Lentini");
hch> -
hch> -static DAT_DBG_MASK g_dbg_mask = DAT_DBG_TYPE_ERROR;
hch> -module_param_named(dbg_mask, g_dbg_mask, int, 0644);
hch> -MODULE_PARM_DESC(dbg_mask, "Bitmask to enable debug message types.");
hch> -
hch> -void dat_dbg_print(DAT_DBG_TYPE type, const char *fmt, ...)
hch> -{
hch> - static char buf[1024];
hch> -
hch> - if (type & g_dbg_mask) {
hch> - va_list args;
hch> -
hch> - va_start(args, fmt);
hch> - vsnprintf(buf, sizeof buf, fmt, args);
hch> - printk(KERN_ALERT "DAT: %s", buf);
hch> - va_end(args);
hch> - }
hch> -}
hch> -
hch> -static int __init dat_init(void)
hch> -{
hch> - dat_dbg_print(DAT_DBG_TYPE_GENERIC, "registry started\n");
hch> - return 0;
hch> -}
hch> -
hch> -module_init(dat_init);
hch> -
hch> -static void __exit dat_fini(void)
hch> -{
hch> - dat_dr_fini();
hch> -
hch> - dat_dbg_print(DAT_DBG_TYPE_GENERIC, "registry stopped\n");
hch> -}
hch> -
hch> -module_exit(dat_fini);
hch> Index: linux-kernel/dat/api.c
hch> ===================================================================
hch> --- linux-kernel/dat/api.c (revision 2647)
hch> +++ linux-kernel/dat/api.c (working copy)
hch> @@ -26,15 +26,53 @@
hch> * and/or other materials provided with the distribution.
hch> */
hch>
hch> -/*
hch> - * DAT functions for consumers
hch> - *
hch> - * $Id: consumer.c 2251 2005-05-04 05:57:41Z jlentini $
hch> - */
hch> +#include <linux/kernel.h>
hch> +#include <linux/list.h>
hch> +#include <linux/module.h>
hch> +#include <linux/slab.h>
hch> +#include <linux/spinlock.h>
hch>
hch> -#include "core.h"
hch> -#include "dr.h"
hch> +#include <dat.h>
hch>
hch> +
hch> +enum dat_dbg_type {
hch> + DAT_DBG_TYPE_ERROR = (1 << 0),
hch> + DAT_DBG_TYPE_GENERIC = (1 << 1),
hch> + DAT_DBG_TYPE_DR = (1 << 2),
hch> + DAT_DBG_TYPE_PROVIDER_API = (1 << 3),
hch> + DAT_DBG_TYPE_CONSUMER_API = (1 << 4),
hch> + DAT_DBG_TYPE_ALL = 0x1f
hch> +};
hch> +
hch> +static int dat_dbg_mask = DAT_DBG_TYPE_ERROR;
hch> +module_param_named(dbg_mask, dat_dbg_mask, int, 0644);
hch> +MODULE_PARM_DESC(dbg_mask, "Bitmask to enable debug message types.");
hch> +
hch> +struct dat_dictionary_entry {
hch> + struct list_head list;
hch> + struct dat_provider_info info;
hch> + DAT_IA_OPEN_FUNC ia_open_func;
hch> + int ref_count;
hch> +};
hch> +
hch> +static LIST_HEAD(dat_provider_list);
hch> +static int dat_provider_list_size;
hch> +static DEFINE_SPINLOCK(dat_provider_list_lock);
hch> +
hch> +static void dat_dbg_print(enum dat_dbg_type type, const char *fmt, ...)
hch> +{
hch> + static char buf[1024];
hch> +
hch> + if (type & dat_dbg_mask) {
hch> + va_list args;
hch> +
hch> + va_start(args, fmt);
hch> + vsnprintf(buf, sizeof buf, fmt, args);
hch> + printk(KERN_ALERT "DAT: %s", buf);
hch> + va_end(args);
hch> + }
hch> +}
hch> +
hch> static u32 dat_strerror_major(u32 value, const char **message)
hch> {
hch> switch (DAT_GET_TYPE(value)) {
hch> @@ -350,21 +388,39 @@
hch> }
hch> }
hch>
hch> +static boolean_t dat_dictionary_key_is_equal(const struct dat_provider_info *a,
hch> + const struct dat_provider_info *b)
hch> +{
hch> + if (strlen(a->ia_name) == strlen(b->ia_name) &&
hch> + !strncmp(a->ia_name, b->ia_name, strlen(a->ia_name)))
hch> + return 1;
hch> + return 0;
hch> +}
hch> +
hch> +static struct dat_dictionary_entry *dat_dictionary_search(
hch> + struct list_head *list, const struct dat_provider_info *key)
hch> +{
hch> + struct dat_dictionary_entry *entry;
hch> +
hch> + list_for_each_entry(entry, list, list)
hch> + if (dat_dictionary_key_is_equal(&entry->info, key))
hch> + return entry;
hch> +
hch> + return NULL;
hch> +}
hch> +
hch> u32 dat_ia_open(const char *name, int async_event_qlen,
hch> struct dat_evd **async_event_handle, struct dat_ia **ia)
hch> {
hch> - DAT_IA_OPEN_FUNC ia_open_func;
hch> struct dat_provider_info info;
hch> - u32 status;
hch> + struct dat_dictionary_entry *data;
hch> + unsigned long flags;
hch> size_t len;
hch>
hch> dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
hch> "%s(name:%s, async_qlen:%i, ver:%x.%x, thrd_safe:%x)\n",
hch> __func__, name, async_event_qlen);
hch>
hch> - if (DAT_IS_BAD_POINTER(name))
hch> - return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1);
hch> -
hch> len = strlen(name);
hch>
hch> if (DAT_NAME_MAX_LENGTH < len)
hch> @@ -373,62 +429,67 @@
hch> strncpy(info.ia_name, name, len);
hch> info.ia_name[len] = '\0';
hch>
hch> - status = dat_dr_provider_open(&info, &ia_open_func);
hch> - if (status != DAT_SUCCESS) {
hch> + spin_lock_irqsave(&dat_provider_list_lock, flags);
hch> + data = dat_dictionary_search(&dat_provider_list, &info);
hch> + spin_unlock_irqrestore(&dat_provider_list_lock, flags);
hch> +
hch> + if (!data) {
hch> dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
hch> "%s: IA [%s] not found in dynamic registry\n",
hch> __func__, name);
hch>
hch> - return status;
hch> + return DAT_ERROR(DAT_PROVIDER_NOT_FOUND,
hch> + DAT_NAME_NOT_REGISTERED);
hch> }
hch>
hch> - return ia_open_func(name, async_event_qlen, async_event_handle, ia);
hch> + data->ref_count++;
hch> + return data->ia_open_func(name, async_event_qlen, async_event_handle,
hch> + ia);
hch> }
hch> -
hch> EXPORT_SYMBOL(dat_ia_open);
hch>
hch> -u32 dat_ia_close(struct dat_ia *ia, enum dat_close_flags flags)
hch> +u32 dat_ia_close(struct dat_ia *ia, enum dat_close_flags close_flags)
hch> {
hch> struct dat_provider *provider;
hch> - struct dat_provider_attr provider_attr;
hch> - u32 status;
hch> + struct dat_provider_info info;
hch> + u32 status = DAT_SUCCESS;
hch> const char *ia_name;
hch> + struct dat_dictionary_entry *data;
hch> + unsigned long flags;
hch> + size_t len;
hch>
hch> dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
hch> - "%s(ia:%x, flags:%x)\n", __func__, ia, flags);
hch> + "%s(ia:%x, flags:%x)\n", __func__, ia, close_flags);
hch>
hch> provider = ia->common.provider;
hch> ia_name = provider->device_name;
hch>
hch> - if (DAT_SUCCESS != (status = dat_ia_query(ia, NULL, NULL,
hch> - &provider_attr)))
hch> + status = provider->ia_close_func(ia, close_flags);
hch> + if (status != DAT_SUCCESS) {
hch> dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
hch> - "dat_ia_query for IA %s failed\n", ia_name);
hch> - else if (DAT_SUCCESS != (status = provider->ia_close_func(ia, flags)))
hch> - dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
hch> "close function for IA %s failed\n", ia_name);
hch> - else {
hch> - struct dat_provider_info info;
hch> - size_t len;
hch> + return status;
hch> + }
hch>
hch> - len = strlen(ia_name);
hch> + len = strlen(ia_name);
hch>
hch> - BUG_ON(DAT_NAME_MAX_LENGTH < len);
hch> + BUG_ON(DAT_NAME_MAX_LENGTH < len);
hch>
hch> - strncpy(info.ia_name, ia_name, len);
hch> - info.ia_name[len] = '\0';
hch> + strncpy(info.ia_name, ia_name, len);
hch> + info.ia_name[len] = '\0';
hch>
hch> - status = dat_dr_provider_close(&info);
hch> - if (DAT_SUCCESS != status)
hch> - dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
hch> - "dynamic registry unable to close "
hch> - "provider for IA %s\n",
hch> - ia_name);
hch> + spin_lock_irqsave(&dat_provider_list_lock, flags);
hch> + data = dat_dictionary_search(&dat_provider_list, &info);
hch> + if (data) {
hch> + data->ref_count--;
hch> + } else {
hch> + status = DAT_ERROR(DAT_PROVIDER_NOT_FOUND,
hch> + DAT_NAME_NOT_REGISTERED);
hch> }
hch> + spin_unlock_irqrestore(&dat_provider_list_lock, flags);
hch>
hch> return status;
hch> }
hch> -
hch> EXPORT_SYMBOL(dat_ia_close);
hch>
hch> u32 dat_strerror(u32 value, const char **major_message,
hch> @@ -454,69 +515,138 @@
hch>
hch> return DAT_SUCCESS;
hch> }
hch> -
hch> EXPORT_SYMBOL(dat_strerror);
hch>
hch> u32 dat_registry_add_provider(const struct dat_provider *provider,
hch> - const struct dat_provider_info *provider_info)
hch> + const struct dat_provider_info *info)
hch> {
hch> - dat_dbg_print(DAT_DBG_TYPE_PROVIDER_API,
hch> - "%s(ia:%s, ver:%x.%x, thrd_safe:%x)\n",
hch> - __func__, provider_info->ia_name);
hch> + struct dat_dictionary_entry *entry;
hch> + unsigned long flags;
hch> + u32 status = DAT_SUCCESS;
hch>
hch> - if (DAT_IS_BAD_POINTER(provider))
hch> - return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1);
hch> + entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
hch> + if (!entry) {
hch> + status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
hch> + DAT_RESOURCE_MEMORY);
hch> + goto out;
hch> + }
hch>
hch> - if (DAT_IS_BAD_POINTER(provider_info))
hch> - return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
hch> + entry->ref_count = 0;
hch> + entry->info = *info;
hch> + entry->ia_open_func = provider->ia_open_func;
hch>
hch> - return dat_dr_insert(provider_info, provider->ia_open_func);
hch> + spin_lock_irqsave(&dat_provider_list_lock, flags);
hch> + if (dat_dictionary_search(&dat_provider_list, info)) {
hch> + status = DAT_ERROR(DAT_PROVIDER_ALREADY_REGISTERED, 0);
hch> + goto out_unlock;
hch> + }
hch> +
hch> + strncpy(entry->info.ia_name, info->ia_name, DAT_NAME_MAX_LENGTH);
hch> +
hch> + /* insert node at end of list to preserve registration order */
hch> + list_add_tail(&entry->list, &dat_provider_list);
hch> + dat_provider_list_size++;
hch> +
hch> + out_unlock:
hch> + spin_unlock_irqrestore(&dat_provider_list_lock, flags);
hch> + out:
hch> + if (status != DAT_SUCCESS)
hch> + kfree(entry);
hch> + return status;
hch> }
hch> +EXPORT_SYMBOL(dat_registry_add_provider);
hch>
hch> -EXPORT_SYMBOL(dat_registry_remove_provider);
hch> -
hch> u32 dat_registry_remove_provider(const struct dat_provider *provider,
hch> - const struct dat_provider_info *provider_info)
hch> + const struct dat_provider_info *info)
hch> {
hch> - dat_dbg_print(DAT_DBG_TYPE_PROVIDER_API, "%s(ia:%s)\n", __func__,
hch> - provider_info->ia_name);
hch> + struct dat_dictionary_entry *cur, *next;
hch> + unsigned long flags;
hch> + u32 status = DAT_SUCCESS;
hch>
hch> - if (DAT_IS_BAD_POINTER(provider))
hch> - return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1);
hch> + spin_lock_irqsave(&dat_provider_list_lock, flags);
hch> + list_for_each_entry_safe(cur, next, &dat_provider_list, list) {
hch> + if (dat_dictionary_key_is_equal(&cur->info, info)) {
hch> + if (cur->ref_count) {
hch> + status = DAT_ERROR(DAT_PROVIDER_IN_USE, 0);
hch> + goto out;
hch> + }
hch>
hch> - return dat_dr_remove(provider_info);
hch> + list_del(&cur->list);
hch> + dat_provider_list_size--;
hch> +
hch> + kfree(cur);
hch> + goto out;
hch> + }
hch> + }
hch> +
hch> + status = DAT_ERROR(DAT_PROVIDER_NOT_FOUND, DAT_NAME_NOT_REGISTERED);
hch> + out:
hch> + spin_unlock_irqrestore(&dat_provider_list_lock, flags);
hch> + return status;
hch> }
hch> +EXPORT_SYMBOL(dat_registry_remove_provider);
hch>
hch> -EXPORT_SYMBOL(dat_registry_add_provider);
hch> -
hch> u32 dat_registry_list_providers(int max_to_return, int *entries_returned,
hch> - struct dat_provider_info *(dat_provider_list[]))
hch> + struct dat_provider_info *provider_list[])
hch> {
hch> + struct dat_dictionary_entry *cur;
hch> + unsigned long flags;
hch> + int i = 0;
hch> u32 status = DAT_SUCCESS;
hch>
hch> - dat_dbg_print(DAT_DBG_TYPE_CONSUMER_API,
hch> - "%s(max_to_return:%i, entries_rtrn:%p, prvdr_list:%p)\n",
hch> - __func__, max_to_return, entries_returned,
hch> - dat_provider_list);
hch> -
hch> - if ((DAT_IS_BAD_POINTER(entries_returned)))
hch> - return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
hch> -
hch> - if (0 != max_to_return && (DAT_IS_BAD_POINTER(dat_provider_list)))
hch> - return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
hch> -
hch> - if (0 == max_to_return) {
hch> + if (!max_to_return) {
hch> /* the user is allowed to call with max_to_return set to zero.
hch> * in which case we simply return (in *entries_returned) the
hch> * number of providers currently installed. We must also
hch> * (per spec) return an error
hch> */
hch> - (void)dat_dr_size(entries_returned);
hch> + *entries_returned = dat_provider_list_size;
hch> return DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1);
hch> - } else
hch> - status = dat_dr_list(max_to_return, entries_returned,
hch> - dat_provider_list);
hch> + }
hch> +
hch> + *entries_returned = 0;
hch> +
hch> + spin_lock_irqsave(&dat_provider_list_lock, flags);
hch> + if (!dat_provider_list_size)
hch> + goto out_unlock;
hch> +
hch> + list_for_each_entry(cur, &dat_provider_list, list) {
hch> + if (i >= max_to_return)
hch> + break;
hch> + if (!provider_list[i]) {
hch> + status =
hch> + DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
hch> + goto out_unlock;
hch> + }
hch> + provider_list[i++] = &cur->info;
hch> + }
hch> + *entries_returned = i;
hch> +
hch> + out_unlock:
hch> + spin_unlock_irqrestore(&dat_provider_list_lock, flags);
hch> return status;
hch> }
hch> +EXPORT_SYMBOL(dat_registry_list_providers);
hch>
hch> -EXPORT_SYMBOL(dat_registry_list_providers);
hch> +static int __init dat_init(void)
hch> +{
hch> + dat_dbg_print(DAT_DBG_TYPE_GENERIC, "registry started\n");
hch> + return 0;
hch> +}
hch> +
hch> +static void __exit dat_fini(void)
hch> +{
hch> + struct dat_dictionary_entry *cur, *next;
hch> +
hch> + list_for_each_entry_safe(cur, next, &dat_provider_list, list) {
hch> + list_del(&cur->list);
hch> + kfree(cur);
hch> + }
hch> +}
hch> +
hch> +MODULE_LICENSE("Dual BSD/GPL");
hch> +MODULE_DESCRIPTION("Direct Access Transport (DAT) API");
hch> +MODULE_AUTHOR("James Lentini");
hch> +
hch> +module_init(dat_init);
hch> +module_exit(dat_fini);
hch> Index: linux-kernel/dat/dictionary.h
hch> ===================================================================
hch> --- linux-kernel/dat/dictionary.h (revision 2647)
hch> +++ linux-kernel/dat/dictionary.h (working copy)
hch> @@ -1,98 +0,0 @@
hch> -/*
hch> - * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
hch> - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
hch> - *
hch> - * This Software is licensed under one of the following licenses:
hch> - *
hch> - * 1) under the terms of the "Common Public License 1.0" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/cpl.php.
hch> - *
hch> - * 2) under the terms of the "The BSD License" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/bsd-license.php.
hch> - *
hch> - * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
hch> - * copy of which is available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/gpl-license.php.
hch> - *
hch> - * Licensee has the right to choose one of the above licenses.
hch> - *
hch> - * Redistributions of source code must retain the above copyright
hch> - * notice and one of the license notices.
hch> - *
hch> - * Redistributions in binary form must reproduce both the above copyright
hch> - * notice, one of the license notices in the documentation
hch> - * and/or other materials provided with the distribution.
hch> - */
hch> -
hch> -/*
hch> - * dictionary data structure
hch> - *
hch> - * $Id$
hch> - */
hch> -
hch> -#ifndef DICTIONARY_H
hch> -#define DICTIONARY_H
hch> -
hch> -#include "core.h"
hch> -
hch> -/*********************************************************************
hch> - * *
hch> - * Structures *
hch> - * *
hch> - *********************************************************************/
hch> -
hch> -struct dat_dictionary_entry {
hch> - struct list_head list;
hch> - struct dat_provider_info key;
hch> - void *data;
hch> -};
hch> -
hch> -struct dat_dictionary {
hch> - struct list_head list;
hch> - int size;
hch> -};
hch> -
hch> -/*********************************************************************
hch> - * *
hch> - * Macros *
hch> - * *
hch> - *********************************************************************/
hch> -
hch> -#define DAT_DICTIONARY_INIT(name) { LIST_HEAD_INIT((name).list), 0 }
hch> -
hch> -/*********************************************************************
hch> - * *
hch> - * Function Prototypes *
hch> - * *
hch> - *********************************************************************/
hch> -
hch> -extern void dat_dictionary_destroy(struct dat_dictionary *dictionary);
hch> -
hch> -extern u32 dat_dictionary_size(const struct dat_dictionary *dictionary,
hch> - int *size);
hch> -
hch> -extern u32 dat_dictionary_entry_create(struct dat_dictionary_entry **p_entry);
hch> -
hch> -extern void dat_dictionary_entry_destroy(
hch> - const struct dat_dictionary_entry *entry);
hch> -
hch> -extern u32 dat_dictionary_insert(struct dat_dictionary *dictionary,
hch> - const struct dat_provider_info *key,
hch> - struct dat_dictionary_entry *entry,
hch> - void *data);
hch> -
hch> -extern u32 dat_dictionary_search(struct dat_dictionary *dictionary,
hch> - const struct dat_provider_info *key,
hch> - void **p_data);
hch> -
hch> -extern u32 dat_dictionary_enumerate(struct dat_dictionary *dictionary,
hch> - void *array[], const int array_size);
hch> -
hch> -extern u32 dat_dictionary_remove(struct dat_dictionary *dictionary,
hch> - const struct dat_provider_info *key,
hch> - struct dat_dictionary_entry **p_entry,
hch> - void **p_data);
hch> -
hch> -#endif /* DICTIONARY_H */
hch> Index: linux-kernel/dat/dr.h
hch> ===================================================================
hch> --- linux-kernel/dat/dr.h (revision 2647)
hch> +++ linux-kernel/dat/dr.h (working copy)
hch> @@ -1,57 +0,0 @@
hch> -/*
hch> - * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
hch> - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
hch> - *
hch> - * This Software is licensed under one of the following licenses:
hch> - *
hch> - * 1) under the terms of the "Common Public License 1.0" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/cpl.php.
hch> - *
hch> - * 2) under the terms of the "The BSD License" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/bsd-license.php.
hch> - *
hch> - * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
hch> - * copy of which is available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/gpl-license.php.
hch> - *
hch> - * Licensee has the right to choose one of the above licenses.
hch> - *
hch> - * Redistributions of source code must retain the above copyright
hch> - * notice and one of the license notices.
hch> - *
hch> - * Redistributions in binary form must reproduce both the above copyright
hch> - * notice, one of the license notices in the documentation
hch> - * and/or other materials provided with the distribution.
hch> - */
hch> -
hch> -/*
hch> - * Dynamic Registry (DR) functions and data stucture
hch> - *
hch> - * $Id$
hch> - */
hch> -
hch> -#ifndef DR_H
hch> -#define DR_H
hch> -
hch> -#include <dat.h>
hch> -
hch> -extern void dat_dr_fini(void);
hch> -
hch> -extern u32 dat_dr_insert(const struct dat_provider_info *info,
hch> - const DAT_IA_OPEN_FUNC ia_open_func);
hch> -
hch> -extern u32 dat_dr_remove(const struct dat_provider_info *info);
hch> -
hch> -extern u32 dat_dr_provider_open(const struct dat_provider_info *info,
hch> - DAT_IA_OPEN_FUNC *p_ia_open_func);
hch> -
hch> -extern u32 dat_dr_provider_close(const struct dat_provider_info *info);
hch> -
hch> -extern u32 dat_dr_size(int *size);
hch> -
hch> -extern u32 dat_dr_list(int max_to_return, int *entries_returned,
hch> - struct dat_provider_info *(dat_provider_list[]));
hch> -
hch> -#endif /* DR_H */
hch> Index: linux-kernel/dat/Makefile
hch> ===================================================================
hch> --- linux-kernel/dat/Makefile (revision 2647)
hch> +++ linux-kernel/dat/Makefile (working copy)
hch> @@ -5,8 +5,4 @@
hch>
hch> obj-$(CONFIG_DAT) += dat.o
hch>
hch> -dat-y := \
hch> - api.o \
hch> - core.o \
hch> - dictionary.o \
hch> - dr.o
hch> +dat-y += api.o
hch> Index: linux-kernel/dat/core.h
hch> ===================================================================
hch> --- linux-kernel/dat/core.h (revision 2647)
hch> +++ linux-kernel/dat/core.h (working copy)
hch> @@ -1,61 +0,0 @@
hch> -/*
hch> - * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
hch> - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
hch> - *
hch> - * This Software is licensed under one of the following licenses:
hch> - *
hch> - * 1) under the terms of the "Common Public License 1.0" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/cpl.php.
hch> - *
hch> - * 2) under the terms of the "The BSD License" a copy of which is
hch> - * available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/bsd-license.php.
hch> - *
hch> - * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
hch> - * copy of which is available from the Open Source Initiative, see
hch> - * http://www.opensource.org/licenses/gpl-license.php.
hch> - *
hch> - * Licensee has the right to choose one of the above licenses.
hch> - *
hch> - * Redistributions of source code must retain the above copyright
hch> - * notice and one of the license notices.
hch> - *
hch> - * Redistributions in binary form must reproduce both the above copyright
hch> - * notice, one of the license notices in the documentation
hch> - * and/or other materials provided with the distribution.
hch> - */
hch> -
hch> -/*
hch> - * core DAT registry functions and data structures
hch> - *
hch> - * $Id$
hch> - */
hch> -
hch> -#ifndef CORE_H
hch> -#define CORE_H
hch> -
hch> -#include <linux/kernel.h>
hch> -#include <linux/list.h>
hch> -#include <linux/module.h>
hch> -#include <linux/slab.h>
hch> -#include <linux/spinlock.h>
hch> -
hch> -#include <dat.h>
hch> -
hch> -#define DAT_IS_BAD_POINTER(p) ( NULL == (p) )
hch> -
hch> -typedef enum {
hch> - DAT_DBG_TYPE_ERROR = (1 << 0),
hch> - DAT_DBG_TYPE_GENERIC = (1 << 1),
hch> - DAT_DBG_TYPE_DR = (1 << 2),
hch> - DAT_DBG_TYPE_PROVIDER_API = (1 << 3),
hch> - DAT_DBG_TYPE_CONSUMER_API = (1 << 4),
hch> - DAT_DBG_TYPE_ALL = 0x1f
hch> -} DAT_DBG_TYPE;
hch> -
hch> -typedef int DAT_DBG_MASK;
hch> -
hch> -extern void dat_dbg_print(DAT_DBG_TYPE type, const char *fmt, ...);
hch> -
hch> -#endif /* CORE_H */
hch>
More information about the general
mailing list