aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/params.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/kernel/params.c b/kernel/params.c
index 458a09b886c4..ef60db14fae0 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -31,6 +31,45 @@
31#define DEBUGP(fmt, a...) 31#define DEBUGP(fmt, a...)
32#endif 32#endif
33 33
34/* This just allows us to keep track of which parameters are kmalloced. */
35struct kmalloced_param {
36 struct list_head list;
37 char val[];
38};
39static DEFINE_MUTEX(param_lock);
40static LIST_HEAD(kmalloced_params);
41
42static void *kmalloc_parameter(unsigned int size)
43{
44 struct kmalloced_param *p;
45
46 p = kmalloc(sizeof(*p) + size, GFP_KERNEL);
47 if (!p)
48 return NULL;
49
50 mutex_lock(&param_lock);
51 list_add(&p->list, &kmalloced_params);
52 mutex_unlock(&param_lock);
53
54 return p->val;
55}
56
57/* Does nothing if parameter wasn't kmalloced above. */
58static void maybe_kfree_parameter(void *param)
59{
60 struct kmalloced_param *p;
61
62 mutex_lock(&param_lock);
63 list_for_each_entry(p, &kmalloced_params, list) {
64 if (p->val == param) {
65 list_del(&p->list);
66 kfree(p);
67 break;
68 }
69 }
70 mutex_unlock(&param_lock);
71}
72
34static inline char dash2underscore(char c) 73static inline char dash2underscore(char c)
35{ 74{
36 if (c == '-') 75 if (c == '-')
@@ -219,12 +258,15 @@ int param_set_charp(const char *val, const struct kernel_param *kp)
219 return -ENOSPC; 258 return -ENOSPC;
220 } 259 }
221 260
222 /* This is a hack. We can't need to strdup in early boot, and we 261 maybe_kfree_parameter(*(char **)kp->arg);
262
263 /* This is a hack. We can't kmalloc in early boot, and we
223 * don't need to; this mangled commandline is preserved. */ 264 * don't need to; this mangled commandline is preserved. */
224 if (slab_is_available()) { 265 if (slab_is_available()) {
225 *(char **)kp->arg = kstrdup(val, GFP_KERNEL); 266 *(char **)kp->arg = kmalloc_parameter(strlen(val)+1);
226 if (!*(char **)kp->arg) 267 if (!*(char **)kp->arg)
227 return -ENOMEM; 268 return -ENOMEM;
269 strcpy(*(char **)kp->arg, val);
228 } else 270 } else
229 *(const char **)kp->arg = val; 271 *(const char **)kp->arg = val;
230 272
@@ -238,9 +280,15 @@ int param_get_charp(char *buffer, const struct kernel_param *kp)
238} 280}
239EXPORT_SYMBOL(param_get_charp); 281EXPORT_SYMBOL(param_get_charp);
240 282
283static void param_free_charp(void *arg)
284{
285 maybe_kfree_parameter(*((char **)arg));
286}
287
241struct kernel_param_ops param_ops_charp = { 288struct kernel_param_ops param_ops_charp = {
242 .set = param_set_charp, 289 .set = param_set_charp,
243 .get = param_get_charp, 290 .get = param_get_charp,
291 .free = param_free_charp,
244}; 292};
245EXPORT_SYMBOL(param_ops_charp); 293EXPORT_SYMBOL(param_ops_charp);
246 294