RHEL4/kernel/intermodule.c
<<
>>
Prefs
   1/* Deprecated, do not use.  Moved from module.c to here. --RR */
   2
   3/* Written by Keith Owens <kaos@ocs.com.au> Oct 2000 */
   4#include <linux/module.h>
   5#include <linux/kmod.h>
   6#include <linux/spinlock.h>
   7#include <linux/list.h>
   8#include <linux/slab.h>
   9
  10/* inter_module functions are always available, even when the kernel is
  11 * compiled without modules.  Consumers of inter_module_xxx routines
  12 * will always work, even when both are built into the kernel, this
  13 * approach removes lots of #ifdefs in mainline code.
  14 */
  15
  16static struct list_head ime_list = LIST_HEAD_INIT(ime_list);
  17static spinlock_t ime_lock = SPIN_LOCK_UNLOCKED;
  18static int kmalloc_failed;
  19
  20struct inter_module_entry {
  21        struct list_head list;
  22        const char *im_name;
  23        struct module *owner;
  24        const void *userdata;
  25};
  26
  27/**
  28 * inter_module_register - register a new set of inter module data.
  29 * @im_name: an arbitrary string to identify the data, must be unique
  30 * @owner: module that is registering the data, always use THIS_MODULE
  31 * @userdata: pointer to arbitrary userdata to be registered
  32 *
  33 * Description: Check that the im_name has not already been registered,
  34 * complain if it has.  For new data, add it to the inter_module_entry
  35 * list.
  36 */
  37void inter_module_register(const char *im_name, struct module *owner, const void *userdata)
  38{
  39        struct list_head *tmp;
  40        struct inter_module_entry *ime, *ime_new;
  41
  42        if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {
  43                /* Overloaded kernel, not fatal */
  44                printk(KERN_ERR
  45                        "Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
  46                        im_name);
  47                kmalloc_failed = 1;
  48                return;
  49        }
  50        memset(ime_new, 0, sizeof(*ime_new));
  51        ime_new->im_name = im_name;
  52        ime_new->owner = owner;
  53        ime_new->userdata = userdata;
  54
  55        spin_lock(&ime_lock);
  56        list_for_each(tmp, &ime_list) {
  57                ime = list_entry(tmp, struct inter_module_entry, list);
  58                if (strcmp(ime->im_name, im_name) == 0) {
  59                        spin_unlock(&ime_lock);
  60                        kfree(ime_new);
  61                        /* Program logic error, fatal */
  62                        printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name);
  63                        BUG();
  64                }
  65        }
  66        list_add(&(ime_new->list), &ime_list);
  67        spin_unlock(&ime_lock);
  68}
  69
  70/**
  71 * inter_module_unregister - unregister a set of inter module data.
  72 * @im_name: an arbitrary string to identify the data, must be unique
  73 *
  74 * Description: Check that the im_name has been registered, complain if
  75 * it has not.  For existing data, remove it from the
  76 * inter_module_entry list.
  77 */
  78void inter_module_unregister(const char *im_name)
  79{
  80        struct list_head *tmp;
  81        struct inter_module_entry *ime;
  82
  83        spin_lock(&ime_lock);
  84        list_for_each(tmp, &ime_list) {
  85                ime = list_entry(tmp, struct inter_module_entry, list);
  86                if (strcmp(ime->im_name, im_name) == 0) {
  87                        list_del(&(ime->list));
  88                        spin_unlock(&ime_lock);
  89                        kfree(ime);
  90                        return;
  91                }
  92        }
  93        spin_unlock(&ime_lock);
  94        if (kmalloc_failed) {
  95                printk(KERN_ERR
  96                        "inter_module_unregister: no entry for '%s', "
  97                        "probably caused by previous kmalloc failure\n",
  98                        im_name);
  99                return;
 100        }
 101        else {
 102                /* Program logic error, fatal */
 103                printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name);
 104                BUG();
 105        }
 106}
 107
 108/**
 109 * inter_module_get - return arbitrary userdata from another module.
 110 * @im_name: an arbitrary string to identify the data, must be unique
 111 *
 112 * Description: If the im_name has not been registered, return NULL.
 113 * Try to increment the use count on the owning module, if that fails
 114 * then return NULL.  Otherwise return the userdata.
 115 */
 116const void *inter_module_get(const char *im_name)
 117{
 118        struct list_head *tmp;
 119        struct inter_module_entry *ime;
 120        const void *result = NULL;
 121
 122        spin_lock(&ime_lock);
 123        list_for_each(tmp, &ime_list) {
 124                ime = list_entry(tmp, struct inter_module_entry, list);
 125                if (strcmp(ime->im_name, im_name) == 0) {
 126                        if (try_module_get(ime->owner))
 127                                result = ime->userdata;
 128                        break;
 129                }
 130        }
 131        spin_unlock(&ime_lock);
 132        return(result);
 133}
 134
 135/**
 136 * inter_module_get_request - im get with automatic request_module.
 137 * @im_name: an arbitrary string to identify the data, must be unique
 138 * @modname: module that is expected to register im_name
 139 *
 140 * Description: If inter_module_get fails, do request_module then retry.
 141 */
 142const void *inter_module_get_request(const char *im_name, const char *modname)
 143{
 144        const void *result = inter_module_get(im_name);
 145        if (!result) {
 146                request_module("%s", modname);
 147                result = inter_module_get(im_name);
 148        }
 149        return(result);
 150}
 151
 152/**
 153 * inter_module_put - release use of data from another module.
 154 * @im_name: an arbitrary string to identify the data, must be unique
 155 *
 156 * Description: If the im_name has not been registered, complain,
 157 * otherwise decrement the use count on the owning module.
 158 */
 159void inter_module_put(const char *im_name)
 160{
 161        struct list_head *tmp;
 162        struct inter_module_entry *ime;
 163
 164        spin_lock(&ime_lock);
 165        list_for_each(tmp, &ime_list) {
 166                ime = list_entry(tmp, struct inter_module_entry, list);
 167                if (strcmp(ime->im_name, im_name) == 0) {
 168                        if (ime->owner)
 169                                module_put(ime->owner);
 170                        spin_unlock(&ime_lock);
 171                        return;
 172                }
 173        }
 174        spin_unlock(&ime_lock);
 175        printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name);
 176        BUG();
 177}
 178
 179EXPORT_SYMBOL(inter_module_register);
 180EXPORT_SYMBOL(inter_module_unregister);
 181EXPORT_SYMBOL(inter_module_get);
 182EXPORT_SYMBOL(inter_module_get_request);
 183EXPORT_SYMBOL(inter_module_put);
 184