]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - kernel/intermodule.c
Linux-2.6.12-rc2
[mirror_ubuntu-artful-kernel.git] / kernel / intermodule.c
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
16 static struct list_head ime_list = LIST_HEAD_INIT(ime_list);
17 static DEFINE_SPINLOCK(ime_lock);
18 static int kmalloc_failed;
19
20 struct 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 */
37 void 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 */
78 void 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 */
116 static const 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 */
142 const 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 */
159 void 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
179 EXPORT_SYMBOL(inter_module_register);
180 EXPORT_SYMBOL(inter_module_unregister);
181 EXPORT_SYMBOL(inter_module_get_request);
182 EXPORT_SYMBOL(inter_module_put);