at v2.6.15-rc3 5.2 kB view raw
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 DEFINE_SPINLOCK(ime_lock); 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 = kzalloc(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 ime_new->im_name = im_name; 51 ime_new->owner = owner; 52 ime_new->userdata = userdata; 53 54 spin_lock(&ime_lock); 55 list_for_each(tmp, &ime_list) { 56 ime = list_entry(tmp, struct inter_module_entry, list); 57 if (strcmp(ime->im_name, im_name) == 0) { 58 spin_unlock(&ime_lock); 59 kfree(ime_new); 60 /* Program logic error, fatal */ 61 printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name); 62 BUG(); 63 } 64 } 65 list_add(&(ime_new->list), &ime_list); 66 spin_unlock(&ime_lock); 67} 68 69/** 70 * inter_module_unregister - unregister a set of inter module data. 71 * @im_name: an arbitrary string to identify the data, must be unique 72 * 73 * Description: Check that the im_name has been registered, complain if 74 * it has not. For existing data, remove it from the 75 * inter_module_entry list. 76 */ 77void inter_module_unregister(const char *im_name) 78{ 79 struct list_head *tmp; 80 struct inter_module_entry *ime; 81 82 spin_lock(&ime_lock); 83 list_for_each(tmp, &ime_list) { 84 ime = list_entry(tmp, struct inter_module_entry, list); 85 if (strcmp(ime->im_name, im_name) == 0) { 86 list_del(&(ime->list)); 87 spin_unlock(&ime_lock); 88 kfree(ime); 89 return; 90 } 91 } 92 spin_unlock(&ime_lock); 93 if (kmalloc_failed) { 94 printk(KERN_ERR 95 "inter_module_unregister: no entry for '%s', " 96 "probably caused by previous kmalloc failure\n", 97 im_name); 98 return; 99 } 100 else { 101 /* Program logic error, fatal */ 102 printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name); 103 BUG(); 104 } 105} 106 107/** 108 * inter_module_get - return arbitrary userdata from another module. 109 * @im_name: an arbitrary string to identify the data, must be unique 110 * 111 * Description: If the im_name has not been registered, return NULL. 112 * Try to increment the use count on the owning module, if that fails 113 * then return NULL. Otherwise return the userdata. 114 */ 115static const void *inter_module_get(const char *im_name) 116{ 117 struct list_head *tmp; 118 struct inter_module_entry *ime; 119 const void *result = NULL; 120 121 spin_lock(&ime_lock); 122 list_for_each(tmp, &ime_list) { 123 ime = list_entry(tmp, struct inter_module_entry, list); 124 if (strcmp(ime->im_name, im_name) == 0) { 125 if (try_module_get(ime->owner)) 126 result = ime->userdata; 127 break; 128 } 129 } 130 spin_unlock(&ime_lock); 131 return(result); 132} 133 134/** 135 * inter_module_get_request - im get with automatic request_module. 136 * @im_name: an arbitrary string to identify the data, must be unique 137 * @modname: module that is expected to register im_name 138 * 139 * Description: If inter_module_get fails, do request_module then retry. 140 */ 141const void *inter_module_get_request(const char *im_name, const char *modname) 142{ 143 const void *result = inter_module_get(im_name); 144 if (!result) { 145 request_module("%s", modname); 146 result = inter_module_get(im_name); 147 } 148 return(result); 149} 150 151/** 152 * inter_module_put - release use of data from another module. 153 * @im_name: an arbitrary string to identify the data, must be unique 154 * 155 * Description: If the im_name has not been registered, complain, 156 * otherwise decrement the use count on the owning module. 157 */ 158void inter_module_put(const char *im_name) 159{ 160 struct list_head *tmp; 161 struct inter_module_entry *ime; 162 163 spin_lock(&ime_lock); 164 list_for_each(tmp, &ime_list) { 165 ime = list_entry(tmp, struct inter_module_entry, list); 166 if (strcmp(ime->im_name, im_name) == 0) { 167 if (ime->owner) 168 module_put(ime->owner); 169 spin_unlock(&ime_lock); 170 return; 171 } 172 } 173 spin_unlock(&ime_lock); 174 printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name); 175 BUG(); 176} 177 178EXPORT_SYMBOL(inter_module_register); 179EXPORT_SYMBOL(inter_module_unregister); 180EXPORT_SYMBOL(inter_module_get_request); 181EXPORT_SYMBOL(inter_module_put);