Blame view

kernel/params.c 22.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /* Helpers for initial module or kernel cmdline parsing
     Copyright (C) 2001 Rusty Russell.
  
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.
  
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
  
      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
  #include <linux/kernel.h>
  #include <linux/string.h>
  #include <linux/errno.h>
  #include <linux/module.h>
63a12d9d0   Geert Uytterhoeven   kernel/param: con...
22
  #include <linux/moduleparam.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
  #include <linux/device.h>
  #include <linux/err.h>
4e57b6817   Tim Schmielau   [PATCH] fix missi...
25
  #include <linux/slab.h>
26d052bfc   Peter Oberparleiter   param: allow whit...
26
  #include <linux/ctype.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

907b29eb4   Rusty Russell   param: locking fo...
28
29
  /* Protects all parameters, and incidentally kmalloced_param list. */
  static DEFINE_MUTEX(param_lock);
a1054322a   Rusty Russell   param: use free h...
30
31
32
33
34
  /* This just allows us to keep track of which parameters are kmalloced. */
  struct kmalloced_param {
  	struct list_head list;
  	char val[];
  };
a1054322a   Rusty Russell   param: use free h...
35
36
37
38
39
40
41
42
43
  static LIST_HEAD(kmalloced_params);
  
  static void *kmalloc_parameter(unsigned int size)
  {
  	struct kmalloced_param *p;
  
  	p = kmalloc(sizeof(*p) + size, GFP_KERNEL);
  	if (!p)
  		return NULL;
a1054322a   Rusty Russell   param: use free h...
44
  	list_add(&p->list, &kmalloced_params);
a1054322a   Rusty Russell   param: use free h...
45
46
47
48
49
50
51
  	return p->val;
  }
  
  /* Does nothing if parameter wasn't kmalloced above. */
  static void maybe_kfree_parameter(void *param)
  {
  	struct kmalloced_param *p;
a1054322a   Rusty Russell   param: use free h...
52
53
54
55
56
57
58
  	list_for_each_entry(p, &kmalloced_params, list) {
  		if (p->val == param) {
  			list_del(&p->list);
  			kfree(p);
  			break;
  		}
  	}
a1054322a   Rusty Russell   param: use free h...
59
  }
b1e4d20cb   Michal Schmidt   params: make dash...
60
  static char dash2underscore(char c)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
65
  {
  	if (c == '-')
  		return '_';
  	return c;
  }
b1e4d20cb   Michal Schmidt   params: make dash...
66
  bool parameqn(const char *a, const char *b, size_t n)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  {
b1e4d20cb   Michal Schmidt   params: make dash...
68
69
70
71
72
73
74
75
76
77
78
79
  	size_t i;
  
  	for (i = 0; i < n; i++) {
  		if (dash2underscore(a[i]) != dash2underscore(b[i]))
  			return false;
  	}
  	return true;
  }
  
  bool parameq(const char *a, const char *b)
  {
  	return parameqn(a, b, strlen(a)+1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  }
7a486d378   Rusty Russell   param: check for ...
81
82
83
84
85
86
87
88
89
  static void param_check_unsafe(const struct kernel_param *kp)
  {
  	if (kp->flags & KERNEL_PARAM_FL_UNSAFE) {
  		pr_warn("Setting dangerous option %s - tainting kernel
  ",
  			kp->name);
  		add_taint(TAINT_USER, LOCKDEP_STILL_OK);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  static int parse_one(char *param,
  		     char *val,
9fb48c744   Jim Cromie   params: add 3rd a...
92
  		     const char *doing,
914dcaa84   Rusty Russell   param: make param...
93
  		     const struct kernel_param *params,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  		     unsigned num_params,
026cee008   Pawel Moll   params: <level>_i...
95
96
  		     s16 min_level,
  		     s16 max_level,
9fb48c744   Jim Cromie   params: add 3rd a...
97
98
  		     int (*handle_unknown)(char *param, char *val,
  				     const char *doing))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
  {
  	unsigned int i;
907b29eb4   Rusty Russell   param: locking fo...
101
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
105
  
  	/* Find parameter */
  	for (i = 0; i < num_params; i++) {
  		if (parameq(param, params[i].name)) {
026cee008   Pawel Moll   params: <level>_i...
106
107
108
  			if (params[i].level < min_level
  			    || params[i].level > max_level)
  				return 0;
25985edce   Lucas De Marchi   Fix common misspe...
109
  			/* No one handled NULL, so do it here. */
ab013c5f6   Steven Rostedt   module: Add flag ...
110
  			if (!val &&
6a4c26431   Jani Nikula   module: rename KE...
111
  			    !(params[i].ops->flags & KERNEL_PARAM_OPS_FL_NOARG))
2e9fb9953   Rusty Russell   params: don't han...
112
  				return -EINVAL;
9fb48c744   Jim Cromie   params: add 3rd a...
113
114
115
  			pr_debug("handling %s with %p
  ", param,
  				params[i].ops->set);
907b29eb4   Rusty Russell   param: locking fo...
116
  			mutex_lock(&param_lock);
7a486d378   Rusty Russell   param: check for ...
117
  			param_check_unsafe(&params[i]);
907b29eb4   Rusty Russell   param: locking fo...
118
119
120
  			err = params[i].ops->set(val, &params[i]);
  			mutex_unlock(&param_lock);
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
  		}
  	}
  
  	if (handle_unknown) {
9fb48c744   Jim Cromie   params: add 3rd a...
125
126
127
  		pr_debug("doing %s: %s='%s'
  ", doing, param, val);
  		return handle_unknown(param, val, doing);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  	}
9fb48c744   Jim Cromie   params: add 3rd a...
129
130
  	pr_debug("Unknown argument '%s'
  ", param);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
134
135
136
137
138
139
140
  	return -ENOENT;
  }
  
  /* You can use " around spaces, but can't escape ". */
  /* Hyphens and underscores equivalent in parameter names. */
  static char *next_arg(char *args, char **param, char **val)
  {
  	unsigned int i, equals = 0;
  	int in_quote = 0, quoted = 0;
  	char *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
145
146
147
  	if (*args == '"') {
  		args++;
  		in_quote = 1;
  		quoted = 1;
  	}
  
  	for (i = 0; args[i]; i++) {
26d052bfc   Peter Oberparleiter   param: allow whit...
148
  		if (isspace(args[i]) && !in_quote)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  			break;
  		if (equals == 0) {
  			if (args[i] == '=')
  				equals = i;
  		}
  		if (args[i] == '"')
  			in_quote = !in_quote;
  	}
  
  	*param = args;
  	if (!equals)
  		*val = NULL;
  	else {
  		args[equals] = '\0';
  		*val = args + equals + 1;
  
  		/* Don't include quotes in value. */
  		if (**val == '"') {
  			(*val)++;
  			if (args[i-1] == '"')
  				args[i-1] = '\0';
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  	}
b9cc4489c   Rusty Russell   params: handle qu...
172
173
  	if (quoted && args[i-1] == '"')
  		args[i-1] = '\0';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
179
  
  	if (args[i]) {
  		args[i] = '\0';
  		next = args + i + 1;
  	} else
  		next = args + i;
f36462f07   Rusty Russell   [PATCH] Ignore tr...
180
181
  
  	/* Chew up trailing spaces. */
e7d2860b6   AndrĂ© Goddard Rosa   tree-wide: conver...
182
  	return skip_spaces(next);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
  }
  
  /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
51e158c12   Rusty Russell   param: hand argum...
186
187
188
189
190
191
192
  char *parse_args(const char *doing,
  		 char *args,
  		 const struct kernel_param *params,
  		 unsigned num,
  		 s16 min_level,
  		 s16 max_level,
  		 int (*unknown)(char *param, char *val, const char *doing))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
  {
  	char *param, *val;
f36462f07   Rusty Russell   [PATCH] Ignore tr...
195
  	/* Chew leading spaces */
e7d2860b6   AndrĂ© Goddard Rosa   tree-wide: conver...
196
  	args = skip_spaces(args);
f36462f07   Rusty Russell   [PATCH] Ignore tr...
197

1ef9eaf2b   Jim Cromie   params.c: fix Sma...
198
  	if (*args)
9fb48c744   Jim Cromie   params: add 3rd a...
199
200
  		pr_debug("doing %s, parsing ARGS: '%s'
  ", doing, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
  	while (*args) {
  		int ret;
a416aba63   Ard van Breemen   [PATCH] kernelpar...
203
  		int irq_was_disabled;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
  
  		args = next_arg(args, &param, &val);
51e158c12   Rusty Russell   param: hand argum...
206
207
208
  		/* Stop at -- */
  		if (!val && strcmp(param, "--") == 0)
  			return args;
a416aba63   Ard van Breemen   [PATCH] kernelpar...
209
  		irq_was_disabled = irqs_disabled();
9fb48c744   Jim Cromie   params: add 3rd a...
210
  		ret = parse_one(param, val, doing, params, num,
026cee008   Pawel Moll   params: <level>_i...
211
  				min_level, max_level, unknown);
b5f3abf95   Jim Cromie   params: replace p...
212
213
214
215
  		if (irq_was_disabled && !irqs_disabled())
  			pr_warn("%s: option '%s' enabled irq's!
  ",
  				doing, param);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
  		switch (ret) {
  		case -ENOENT:
b5f3abf95   Jim Cromie   params: replace p...
218
219
  			pr_err("%s: Unknown parameter `%s'
  ", doing, param);
51e158c12   Rusty Russell   param: hand argum...
220
  			return ERR_PTR(ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  		case -ENOSPC:
b5f3abf95   Jim Cromie   params: replace p...
222
223
  			pr_err("%s: `%s' too large for parameter `%s'
  ",
9fb48c744   Jim Cromie   params: add 3rd a...
224
  			       doing, val ?: "", param);
51e158c12   Rusty Russell   param: hand argum...
225
  			return ERR_PTR(ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
228
  		case 0:
  			break;
  		default:
b5f3abf95   Jim Cromie   params: replace p...
229
230
  			pr_err("%s: `%s' invalid for parameter `%s'
  ",
9fb48c744   Jim Cromie   params: add 3rd a...
231
  			       doing, val ?: "", param);
51e158c12   Rusty Russell   param: hand argum...
232
  			return ERR_PTR(ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
236
  		}
  	}
  
  	/* All parsed OK. */
51e158c12   Rusty Russell   param: hand argum...
237
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
  }
  
  /* Lazy bastard, eh? */
88a88b320   Felipe Contreras   params: improve s...
241
  #define STANDARD_PARAM_DEF(name, type, format, strtolfn)      		\
9bbb9e5a3   Rusty Russell   param: use ops in...
242
  	int param_set_##name(const char *val, const struct kernel_param *kp) \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  	{								\
88a88b320   Felipe Contreras   params: improve s...
244
  		return strtolfn(val, 0, (type *)kp->arg);		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  	}								\
9bbb9e5a3   Rusty Russell   param: use ops in...
246
  	int param_get_##name(char *buffer, const struct kernel_param *kp) \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  	{								\
f4940ab7c   Chen Gang   kernel/params.c: ...
248
249
  		return scnprintf(buffer, PAGE_SIZE, format,		\
  				*((type *)kp->arg));			\
a14fe249a   Rusty Russell   param: move the E...
250
  	}								\
9bbb9e5a3   Rusty Russell   param: use ops in...
251
252
253
254
  	struct kernel_param_ops param_ops_##name = {			\
  		.set = param_set_##name,				\
  		.get = param_get_##name,				\
  	};								\
a14fe249a   Rusty Russell   param: move the E...
255
  	EXPORT_SYMBOL(param_set_##name);				\
9bbb9e5a3   Rusty Russell   param: use ops in...
256
257
  	EXPORT_SYMBOL(param_get_##name);				\
  	EXPORT_SYMBOL(param_ops_##name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258

88a88b320   Felipe Contreras   params: improve s...
259
260
261
262
263
264
265
  STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8);
  STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16);
  STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16);
  STANDARD_PARAM_DEF(int, int, "%i", kstrtoint);
  STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint);
  STANDARD_PARAM_DEF(long, long, "%li", kstrtol);
  STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul);
b4210b810   Hannes Reinecke   Add module param ...
266
  STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267

9bbb9e5a3   Rusty Russell   param: use ops in...
268
  int param_set_charp(const char *val, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  	if (strlen(val) > 1024) {
b5f3abf95   Jim Cromie   params: replace p...
271
272
  		pr_err("%s: string parameter too long
  ", kp->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
  		return -ENOSPC;
  	}
a1054322a   Rusty Russell   param: use free h...
275
276
277
  	maybe_kfree_parameter(*(char **)kp->arg);
  
  	/* This is a hack.  We can't kmalloc in early boot, and we
e180a6b77   Rusty Russell   param: fix charp ...
278
279
  	 * don't need to; this mangled commandline is preserved. */
  	if (slab_is_available()) {
a1054322a   Rusty Russell   param: use free h...
280
  		*(char **)kp->arg = kmalloc_parameter(strlen(val)+1);
d553ad864   Rusty Russell   param: fix NULL c...
281
  		if (!*(char **)kp->arg)
e180a6b77   Rusty Russell   param: fix charp ...
282
  			return -ENOMEM;
a1054322a   Rusty Russell   param: use free h...
283
  		strcpy(*(char **)kp->arg, val);
e180a6b77   Rusty Russell   param: fix charp ...
284
285
  	} else
  		*(const char **)kp->arg = val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
  	return 0;
  }
a14fe249a   Rusty Russell   param: move the E...
288
  EXPORT_SYMBOL(param_set_charp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289

9bbb9e5a3   Rusty Russell   param: use ops in...
290
  int param_get_charp(char *buffer, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
  {
f4940ab7c   Chen Gang   kernel/params.c: ...
292
  	return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  }
a14fe249a   Rusty Russell   param: move the E...
294
  EXPORT_SYMBOL(param_get_charp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295

a1054322a   Rusty Russell   param: use free h...
296
297
298
299
  static void param_free_charp(void *arg)
  {
  	maybe_kfree_parameter(*((char **)arg));
  }
9bbb9e5a3   Rusty Russell   param: use ops in...
300
301
302
  struct kernel_param_ops param_ops_charp = {
  	.set = param_set_charp,
  	.get = param_get_charp,
a1054322a   Rusty Russell   param: use free h...
303
  	.free = param_free_charp,
9bbb9e5a3   Rusty Russell   param: use ops in...
304
305
  };
  EXPORT_SYMBOL(param_ops_charp);
fddd52012   Rusty Russell   module_param: all...
306
  /* Actually could be a bool or an int, for historical reasons. */
9bbb9e5a3   Rusty Russell   param: use ops in...
307
  int param_set_bool(const char *val, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
310
311
312
  {
  	/* No equals means "set"... */
  	if (!val) val = "1";
  
  	/* One of =[yYnN01] */
8b8252813   Rusty Russell   module_param: rem...
313
  	return strtobool(val, kp->arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
  }
a14fe249a   Rusty Russell   param: move the E...
315
  EXPORT_SYMBOL(param_set_bool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316

9bbb9e5a3   Rusty Russell   param: use ops in...
317
  int param_get_bool(char *buffer, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
  {
  	/* Y and N chosen as being relatively non-coder friendly */
8b8252813   Rusty Russell   module_param: rem...
320
  	return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  }
a14fe249a   Rusty Russell   param: move the E...
322
  EXPORT_SYMBOL(param_get_bool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323

9bbb9e5a3   Rusty Russell   param: use ops in...
324
  struct kernel_param_ops param_ops_bool = {
6a4c26431   Jani Nikula   module: rename KE...
325
  	.flags = KERNEL_PARAM_OPS_FL_NOARG,
9bbb9e5a3   Rusty Russell   param: use ops in...
326
327
328
329
  	.set = param_set_bool,
  	.get = param_get_bool,
  };
  EXPORT_SYMBOL(param_ops_bool);
fddd52012   Rusty Russell   module_param: all...
330
  /* This one must be bool. */
9bbb9e5a3   Rusty Russell   param: use ops in...
331
  int param_set_invbool(const char *val, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
  {
fddd52012   Rusty Russell   module_param: all...
333
334
  	int ret;
  	bool boolval;
22e48eaf5   Jan Beulich   constify string/a...
335
  	struct kernel_param dummy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336

22e48eaf5   Jan Beulich   constify string/a...
337
  	dummy.arg = &boolval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
339
  	ret = param_set_bool(val, &dummy);
  	if (ret == 0)
9a71af2c3   Rusty Russell   module_param: inv...
340
  		*(bool *)kp->arg = !boolval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  	return ret;
  }
a14fe249a   Rusty Russell   param: move the E...
343
  EXPORT_SYMBOL(param_set_invbool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344

9bbb9e5a3   Rusty Russell   param: use ops in...
345
  int param_get_invbool(char *buffer, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  {
9a71af2c3   Rusty Russell   module_param: inv...
347
  	return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  }
a14fe249a   Rusty Russell   param: move the E...
349
  EXPORT_SYMBOL(param_get_invbool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350

9bbb9e5a3   Rusty Russell   param: use ops in...
351
352
353
354
355
  struct kernel_param_ops param_ops_invbool = {
  	.set = param_set_invbool,
  	.get = param_get_invbool,
  };
  EXPORT_SYMBOL(param_ops_invbool);
69116f279   Rusty Russell   module_param: avo...
356
357
358
359
360
361
362
363
364
  int param_set_bint(const char *val, const struct kernel_param *kp)
  {
  	struct kernel_param boolkp;
  	bool v;
  	int ret;
  
  	/* Match bool exactly, by re-using it. */
  	boolkp = *kp;
  	boolkp.arg = &v;
69116f279   Rusty Russell   module_param: avo...
365
366
367
368
369
370
371
372
373
  
  	ret = param_set_bool(val, &boolkp);
  	if (ret == 0)
  		*(int *)kp->arg = v;
  	return ret;
  }
  EXPORT_SYMBOL(param_set_bint);
  
  struct kernel_param_ops param_ops_bint = {
6a4c26431   Jani Nikula   module: rename KE...
374
  	.flags = KERNEL_PARAM_OPS_FL_NOARG,
69116f279   Rusty Russell   module_param: avo...
375
376
377
378
  	.set = param_set_bint,
  	.get = param_get_int,
  };
  EXPORT_SYMBOL(param_ops_bint);
9730b5b06   Bert Wesarg   kernel/params.c: ...
379
  /* We break the rule and mangle the string. */
9871728b7   Adrian Bunk   [PATCH] kernel/pa...
380
381
382
383
  static int param_array(const char *name,
  		       const char *val,
  		       unsigned int min, unsigned int max,
  		       void *elem, int elemsize,
9bbb9e5a3   Rusty Russell   param: use ops in...
384
  		       int (*set)(const char *, const struct kernel_param *kp),
026cee008   Pawel Moll   params: <level>_i...
385
  		       s16 level,
eb38a996e   Richard Knutsson   kernel/params.c: ...
386
  		       unsigned int *num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
390
391
392
393
394
  {
  	int ret;
  	struct kernel_param kp;
  	char save;
  
  	/* Get the name right for errors. */
  	kp.name = name;
  	kp.arg = elem;
026cee008   Pawel Moll   params: <level>_i...
395
  	kp.level = level;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
400
401
402
  	*num = 0;
  	/* We expect a comma-separated list of values. */
  	do {
  		int len;
  
  		if (*num == max) {
b5f3abf95   Jim Cromie   params: replace p...
403
404
  			pr_err("%s: can only take %i arguments
  ", name, max);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
408
409
410
411
  			return -EINVAL;
  		}
  		len = strcspn(val, ",");
  
  		/* nul-terminate and parse */
  		save = val[len];
  		((char *)val)[len] = '\0';
907b29eb4   Rusty Russell   param: locking fo...
412
  		BUG_ON(!mutex_is_locked(&param_lock));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
417
418
419
420
421
422
  		ret = set(val, &kp);
  
  		if (ret != 0)
  			return ret;
  		kp.arg += elemsize;
  		val += len+1;
  		(*num)++;
  	} while (save == ',');
  
  	if (*num < min) {
b5f3abf95   Jim Cromie   params: replace p...
423
424
  		pr_err("%s: needs at least %i arguments
  ", name, min);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
427
428
  		return -EINVAL;
  	}
  	return 0;
  }
9bbb9e5a3   Rusty Russell   param: use ops in...
429
  static int param_array_set(const char *val, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
  {
22e48eaf5   Jan Beulich   constify string/a...
431
  	const struct kparam_array *arr = kp->arr;
31143a120   Bert Wesarg   [PATCH] kernel/pa...
432
  	unsigned int temp_num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
  
  	return param_array(kp->name, val, 1, arr->max, arr->elem,
026cee008   Pawel Moll   params: <level>_i...
435
  			   arr->elemsize, arr->ops->set, kp->level,
3c7d76e37   Rusty Russell   param: fix settin...
436
  			   arr->num ?: &temp_num);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  }
9bbb9e5a3   Rusty Russell   param: use ops in...
438
  static int param_array_get(char *buffer, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
  {
  	int i, off, ret;
22e48eaf5   Jan Beulich   constify string/a...
441
  	const struct kparam_array *arr = kp->arr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
443
444
445
446
447
448
  	struct kernel_param p;
  
  	p = *kp;
  	for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
  		if (i)
  			buffer[off++] = ',';
  		p.arg = arr->elem + arr->elemsize * i;
907b29eb4   Rusty Russell   param: locking fo...
449
  		BUG_ON(!mutex_is_locked(&param_lock));
9bbb9e5a3   Rusty Russell   param: use ops in...
450
  		ret = arr->ops->get(buffer + off, &p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
455
456
457
  		if (ret < 0)
  			return ret;
  		off += ret;
  	}
  	buffer[off] = '\0';
  	return off;
  }
e6df34a44   Rusty Russell   param: add a free...
458
459
460
461
462
463
464
465
466
  static void param_array_free(void *arg)
  {
  	unsigned int i;
  	const struct kparam_array *arr = arg;
  
  	if (arr->ops->free)
  		for (i = 0; i < (arr->num ? *arr->num : arr->max); i++)
  			arr->ops->free(arr->elem + arr->elemsize * i);
  }
9bbb9e5a3   Rusty Russell   param: use ops in...
467
468
469
  struct kernel_param_ops param_array_ops = {
  	.set = param_array_set,
  	.get = param_array_get,
e6df34a44   Rusty Russell   param: add a free...
470
  	.free = param_array_free,
9bbb9e5a3   Rusty Russell   param: use ops in...
471
472
473
474
  };
  EXPORT_SYMBOL(param_array_ops);
  
  int param_set_copystring(const char *val, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
  {
22e48eaf5   Jan Beulich   constify string/a...
476
  	const struct kparam_string *kps = kp->str;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
  
  	if (strlen(val)+1 > kps->maxlen) {
b5f3abf95   Jim Cromie   params: replace p...
479
480
  		pr_err("%s: string doesn't fit in %u chars.
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
  		       kp->name, kps->maxlen-1);
  		return -ENOSPC;
  	}
  	strcpy(kps->string, val);
  	return 0;
  }
a14fe249a   Rusty Russell   param: move the E...
487
  EXPORT_SYMBOL(param_set_copystring);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488

9bbb9e5a3   Rusty Russell   param: use ops in...
489
  int param_get_string(char *buffer, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  {
22e48eaf5   Jan Beulich   constify string/a...
491
  	const struct kparam_string *kps = kp->str;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
  	return strlcpy(buffer, kps->string, kps->maxlen);
  }
a14fe249a   Rusty Russell   param: move the E...
494
  EXPORT_SYMBOL(param_get_string);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495

9bbb9e5a3   Rusty Russell   param: use ops in...
496
497
498
499
500
  struct kernel_param_ops param_ops_string = {
  	.set = param_set_copystring,
  	.get = param_get_string,
  };
  EXPORT_SYMBOL(param_ops_string);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  /* sysfs output in /sys/modules/XYZ/parameters/ */
350f82586   Edward Z. Yang   Remove redundant ...
502
503
  #define to_module_attr(n) container_of(n, struct module_attribute, attr)
  #define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
506
507
  struct param_attribute
  {
  	struct module_attribute mattr;
9bbb9e5a3   Rusty Russell   param: use ops in...
508
  	const struct kernel_param *param;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
511
512
  };
  
  struct module_param_attrs
  {
9b473de87   Rusty Russell   param: Fix duplic...
513
  	unsigned int num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
516
  	struct attribute_group grp;
  	struct param_attribute attrs[0];
  };
ef665c1a0   Randy Dunlap   sysfs: fix build ...
517
  #ifdef CONFIG_SYSFS
350f82586   Edward Z. Yang   Remove redundant ...
518
  #define to_param_attr(n) container_of(n, struct param_attribute, mattr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
  
  static ssize_t param_attr_show(struct module_attribute *mattr,
4befb026c   Kay Sievers   module: change at...
521
  			       struct module_kobject *mk, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
523
524
  {
  	int count;
  	struct param_attribute *attribute = to_param_attr(mattr);
9bbb9e5a3   Rusty Russell   param: use ops in...
525
  	if (!attribute->param->ops->get)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
  		return -EPERM;
907b29eb4   Rusty Russell   param: locking fo...
527
  	mutex_lock(&param_lock);
9bbb9e5a3   Rusty Russell   param: use ops in...
528
  	count = attribute->param->ops->get(buf, attribute->param);
907b29eb4   Rusty Russell   param: locking fo...
529
  	mutex_unlock(&param_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
532
533
534
535
536
537
538
539
  	if (count > 0) {
  		strcat(buf, "
  ");
  		++count;
  	}
  	return count;
  }
  
  /* sysfs always hands a nul-terminated string in buf.  We rely on that. */
  static ssize_t param_attr_store(struct module_attribute *mattr,
4befb026c   Kay Sievers   module: change at...
540
  				struct module_kobject *km,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
  				const char *buf, size_t len)
  {
   	int err;
  	struct param_attribute *attribute = to_param_attr(mattr);
9bbb9e5a3   Rusty Russell   param: use ops in...
545
  	if (!attribute->param->ops->set)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
  		return -EPERM;
907b29eb4   Rusty Russell   param: locking fo...
547
  	mutex_lock(&param_lock);
7a486d378   Rusty Russell   param: check for ...
548
  	param_check_unsafe(attribute->param);
9bbb9e5a3   Rusty Russell   param: use ops in...
549
  	err = attribute->param->ops->set(buf, attribute->param);
907b29eb4   Rusty Russell   param: locking fo...
550
  	mutex_unlock(&param_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
554
  	if (!err)
  		return len;
  	return err;
  }
ef665c1a0   Randy Dunlap   sysfs: fix build ...
555
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
557
558
559
560
561
  
  #ifdef CONFIG_MODULES
  #define __modinit
  #else
  #define __modinit __init
  #endif
ef665c1a0   Randy Dunlap   sysfs: fix build ...
562
  #ifdef CONFIG_SYSFS
907b29eb4   Rusty Russell   param: locking fo...
563
564
565
566
567
568
569
570
571
572
573
  void __kernel_param_lock(void)
  {
  	mutex_lock(&param_lock);
  }
  EXPORT_SYMBOL(__kernel_param_lock);
  
  void __kernel_param_unlock(void)
  {
  	mutex_unlock(&param_lock);
  }
  EXPORT_SYMBOL(__kernel_param_unlock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  /*
9b473de87   Rusty Russell   param: Fix duplic...
575
576
577
578
   * add_sysfs_param - add a parameter to sysfs
   * @mk: struct module_kobject
   * @kparam: the actual parameter definition to add to sysfs
   * @name: name of parameter
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
   *
9b473de87   Rusty Russell   param: Fix duplic...
580
581
582
   * Create a kobject if for a (per-module) parameter if mp NULL, and
   * create file in sysfs.  Returns an error on out of memory.  Always cleans up
   * if there's an error.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
   */
9b473de87   Rusty Russell   param: Fix duplic...
584
  static __modinit int add_sysfs_param(struct module_kobject *mk,
9bbb9e5a3   Rusty Russell   param: use ops in...
585
  				     const struct kernel_param *kp,
9b473de87   Rusty Russell   param: Fix duplic...
586
  				     const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
  {
18eb74fa9   Rusty Russell   params: cleanup s...
588
589
590
  	struct module_param_attrs *new_mp;
  	struct attribute **new_attrs;
  	unsigned int i;
9b473de87   Rusty Russell   param: Fix duplic...
591
592
593
594
595
  
  	/* We don't bother calling this with invisible parameters. */
  	BUG_ON(!kp->perm);
  
  	if (!mk->mp) {
18eb74fa9   Rusty Russell   params: cleanup s...
596
597
598
599
600
601
602
603
604
605
606
  		/* First allocation. */
  		mk->mp = kzalloc(sizeof(*mk->mp), GFP_KERNEL);
  		if (!mk->mp)
  			return -ENOMEM;
  		mk->mp->grp.name = "parameters";
  		/* NULL-terminated attribute array. */
  		mk->mp->grp.attrs = kzalloc(sizeof(mk->mp->grp.attrs[0]),
  					    GFP_KERNEL);
  		/* Caller will cleanup via free_module_param_attrs */
  		if (!mk->mp->grp.attrs)
  			return -ENOMEM;
9b473de87   Rusty Russell   param: Fix duplic...
607
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608

18eb74fa9   Rusty Russell   params: cleanup s...
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  	/* Enlarge allocations. */
  	new_mp = krealloc(mk->mp,
  			  sizeof(*mk->mp) +
  			  sizeof(mk->mp->attrs[0]) * (mk->mp->num + 1),
  			  GFP_KERNEL);
  	if (!new_mp)
  		return -ENOMEM;
  	mk->mp = new_mp;
  
  	/* Extra pointer for NULL terminator */
  	new_attrs = krealloc(mk->mp->grp.attrs,
  			     sizeof(mk->mp->grp.attrs[0]) * (mk->mp->num + 2),
  			     GFP_KERNEL);
  	if (!new_attrs)
  		return -ENOMEM;
  	mk->mp->grp.attrs = new_attrs;
9b473de87   Rusty Russell   param: Fix duplic...
625
626
  
  	/* Tack new one on the end. */
c772be523   Rusty Russell   param: fix uninit...
627
  	memset(&mk->mp->attrs[mk->mp->num], 0, sizeof(mk->mp->attrs[0]));
18eb74fa9   Rusty Russell   params: cleanup s...
628
629
630
  	sysfs_attr_init(&mk->mp->attrs[mk->mp->num].mattr.attr);
  	mk->mp->attrs[mk->mp->num].param = kp;
  	mk->mp->attrs[mk->mp->num].mattr.show = param_attr_show;
b0a65b0cc   Kees Cook   param: do not set...
631
632
633
  	/* Do not allow runtime DAC changes to make param writable. */
  	if ((kp->perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
  		mk->mp->attrs[mk->mp->num].mattr.store = param_attr_store;
574732c73   Rusty Russell   param: initialize...
634
635
  	else
  		mk->mp->attrs[mk->mp->num].mattr.store = NULL;
18eb74fa9   Rusty Russell   params: cleanup s...
636
637
638
  	mk->mp->attrs[mk->mp->num].mattr.attr.name = (char *)name;
  	mk->mp->attrs[mk->mp->num].mattr.attr.mode = kp->perm;
  	mk->mp->num++;
9b473de87   Rusty Russell   param: Fix duplic...
639
640
  
  	/* Fix up all the pointers, since krealloc can move us */
18eb74fa9   Rusty Russell   params: cleanup s...
641
642
643
  	for (i = 0; i < mk->mp->num; i++)
  		mk->mp->grp.attrs[i] = &mk->mp->attrs[i].mattr.attr;
  	mk->mp->grp.attrs[mk->mp->num] = NULL;
9b473de87   Rusty Russell   param: Fix duplic...
644
  	return 0;
9b473de87   Rusty Russell   param: Fix duplic...
645
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646

d2441183d   Linus Torvalds   Fix compile warni...
647
  #ifdef CONFIG_MODULES
9b473de87   Rusty Russell   param: Fix duplic...
648
649
  static void free_module_param_attrs(struct module_kobject *mk)
  {
18eb74fa9   Rusty Russell   params: cleanup s...
650
651
  	if (mk->mp)
  		kfree(mk->mp->grp.attrs);
9b473de87   Rusty Russell   param: Fix duplic...
652
653
  	kfree(mk->mp);
  	mk->mp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
657
658
659
660
  /*
   * module_param_sysfs_setup - setup sysfs support for one module
   * @mod: module
   * @kparam: module parameters (array)
   * @num_params: number of module parameters
   *
9b473de87   Rusty Russell   param: Fix duplic...
661
662
   * Adds sysfs entries for module parameters under
   * /sys/module/[mod->name]/parameters/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
664
   */
  int module_param_sysfs_setup(struct module *mod,
9bbb9e5a3   Rusty Russell   param: use ops in...
665
  			     const struct kernel_param *kparam,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
  			     unsigned int num_params)
  {
9b473de87   Rusty Russell   param: Fix duplic...
668
669
670
671
672
673
674
  	int i, err;
  	bool params = false;
  
  	for (i = 0; i < num_params; i++) {
  		if (kparam[i].perm == 0)
  			continue;
  		err = add_sysfs_param(&mod->mkobj, &kparam[i], kparam[i].name);
18eb74fa9   Rusty Russell   params: cleanup s...
675
676
  		if (err) {
  			free_module_param_attrs(&mod->mkobj);
9b473de87   Rusty Russell   param: Fix duplic...
677
  			return err;
18eb74fa9   Rusty Russell   params: cleanup s...
678
  		}
9b473de87   Rusty Russell   param: Fix duplic...
679
680
  		params = true;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681

9b473de87   Rusty Russell   param: Fix duplic...
682
683
  	if (!params)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684

9b473de87   Rusty Russell   param: Fix duplic...
685
686
687
688
689
  	/* Create the param group. */
  	err = sysfs_create_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
  	if (err)
  		free_module_param_attrs(&mod->mkobj);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
692
693
694
695
696
697
698
699
700
  }
  
  /*
   * module_param_sysfs_remove - remove sysfs support for one module
   * @mod: module
   *
   * Remove sysfs entries for module parameters and the corresponding
   * kobject.
   */
  void module_param_sysfs_remove(struct module *mod)
  {
9b473de87   Rusty Russell   param: Fix duplic...
701
702
  	if (mod->mkobj.mp) {
  		sysfs_remove_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
  		/* We are positive that no one is using any param
  		 * attrs at this point.  Deallocate immediately. */
9b473de87   Rusty Russell   param: Fix duplic...
705
  		free_module_param_attrs(&mod->mkobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
708
  	}
  }
  #endif
e180a6b77   Rusty Russell   param: fix charp ...
709
710
  void destroy_params(const struct kernel_param *params, unsigned num)
  {
e6df34a44   Rusty Russell   param: add a free...
711
712
713
714
715
  	unsigned int i;
  
  	for (i = 0; i < num; i++)
  		if (params[i].ops->free)
  			params[i].ops->free(params[i].arg);
e180a6b77   Rusty Russell   param: fix charp ...
716
  }
e94965ed5   Dmitry Torokhov   module: show vers...
717
  static struct module_kobject * __init locate_module_kobject(const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
719
  {
  	struct module_kobject *mk;
9b473de87   Rusty Russell   param: Fix duplic...
720
721
  	struct kobject *kobj;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722

9b473de87   Rusty Russell   param: Fix duplic...
723
724
  	kobj = kset_find_obj(module_kset, name);
  	if (kobj) {
9b473de87   Rusty Russell   param: Fix duplic...
725
  		mk = to_module_kobject(kobj);
9b473de87   Rusty Russell   param: Fix duplic...
726
727
728
729
730
731
732
733
  	} else {
  		mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
  		BUG_ON(!mk);
  
  		mk->mod = THIS_MODULE;
  		mk->kobj.kset = module_kset;
  		err = kobject_init_and_add(&mk->kobj, &module_ktype, NULL,
  					   "%s", name);
88bfa3247   Kay Sievers   module: add /sys/...
734
735
736
737
  #ifdef CONFIG_MODULES
  		if (!err)
  			err = sysfs_create_file(&mk->kobj, &module_uevent.attr);
  #endif
9b473de87   Rusty Russell   param: Fix duplic...
738
739
  		if (err) {
  			kobject_put(&mk->kobj);
b5f3abf95   Jim Cromie   params: replace p...
740
741
  			pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.
  ",
e94965ed5   Dmitry Torokhov   module: show vers...
742
  				name, err);
e94965ed5   Dmitry Torokhov   module: show vers...
743
  			return NULL;
9b473de87   Rusty Russell   param: Fix duplic...
744
  		}
e94965ed5   Dmitry Torokhov   module: show vers...
745
746
  
  		/* So that we hold reference in both cases. */
9b473de87   Rusty Russell   param: Fix duplic...
747
  		kobject_get(&mk->kobj);
74c5b597e   Greg Kroah-Hartman   modules: better e...
748
  	}
9b473de87   Rusty Russell   param: Fix duplic...
749

e94965ed5   Dmitry Torokhov   module: show vers...
750
751
752
753
  	return mk;
  }
  
  static void __init kernel_add_sysfs_param(const char *name,
63a12d9d0   Geert Uytterhoeven   kernel/param: con...
754
  					  const struct kernel_param *kparam,
e94965ed5   Dmitry Torokhov   module: show vers...
755
756
757
758
759
760
761
762
763
764
765
766
  					  unsigned int name_skip)
  {
  	struct module_kobject *mk;
  	int err;
  
  	mk = locate_module_kobject(name);
  	if (!mk)
  		return;
  
  	/* We need to remove old parameters before adding more. */
  	if (mk->mp)
  		sysfs_remove_group(&mk->kobj, &mk->mp->grp);
9b473de87   Rusty Russell   param: Fix duplic...
767
768
769
770
771
  	/* These should not fail at boot. */
  	err = add_sysfs_param(mk, kparam, kparam->name + name_skip);
  	BUG_ON(err);
  	err = sysfs_create_group(&mk->kobj, &mk->mp->grp);
  	BUG_ON(err);
f30c53a87   Kay Sievers   MODULES: add the ...
772
  	kobject_uevent(&mk->kobj, KOBJ_ADD);
9b473de87   Rusty Russell   param: Fix duplic...
773
  	kobject_put(&mk->kobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
776
  }
  
  /*
b634d130e   Jean Delvare   There is no /sys/...
777
   * param_sysfs_builtin - add sysfs parameters for built-in modules
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
779
780
781
782
783
   *
   * Add module_parameters to sysfs for "modules" built into the kernel.
   *
   * The "module" name (KBUILD_MODNAME) is stored before a dot, the
   * "parameter" name is stored behind a dot in kernel_param->name. So,
   * extract the "module" name for all built-in kernel_param-eters,
9b473de87   Rusty Russell   param: Fix duplic...
784
   * and for all who have the same, call kernel_add_sysfs_param.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
787
   */
  static void __init param_sysfs_builtin(void)
  {
63a12d9d0   Geert Uytterhoeven   kernel/param: con...
788
  	const struct kernel_param *kp;
9b473de87   Rusty Russell   param: Fix duplic...
789
790
  	unsigned int name_len;
  	char modname[MODULE_NAME_LEN];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791

9b473de87   Rusty Russell   param: Fix duplic...
792
  	for (kp = __start___param; kp < __stop___param; kp++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
  		char *dot;
9b473de87   Rusty Russell   param: Fix duplic...
794
795
  		if (kp->perm == 0)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796

730b69d22   Rusty Russell   module: check ker...
797
  		dot = strchr(kp->name, '.');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
  		if (!dot) {
67e67ceaa   Rusty Russell   core_param() for ...
799
800
801
802
803
804
  			/* This happens for core_param() */
  			strcpy(modname, "kernel");
  			name_len = 0;
  		} else {
  			name_len = dot - kp->name + 1;
  			strlcpy(modname, kp->name, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
  		}
67e67ceaa   Rusty Russell   core_param() for ...
806
  		kernel_add_sysfs_param(modname, kp, name_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  }
e94965ed5   Dmitry Torokhov   module: show vers...
809
  ssize_t __modver_version_show(struct module_attribute *mattr,
4befb026c   Kay Sievers   module: change at...
810
  			      struct module_kobject *mk, char *buf)
e94965ed5   Dmitry Torokhov   module: show vers...
811
812
813
  {
  	struct module_version_attribute *vattr =
  		container_of(mattr, struct module_version_attribute, mattr);
f4940ab7c   Chen Gang   kernel/params.c: ...
814
815
  	return scnprintf(buf, PAGE_SIZE, "%s
  ", vattr->version);
e94965ed5   Dmitry Torokhov   module: show vers...
816
  }
b4bc84280   Dmitry Torokhov   module: deal with...
817
818
  extern const struct module_version_attribute *__start___modver[];
  extern const struct module_version_attribute *__stop___modver[];
e94965ed5   Dmitry Torokhov   module: show vers...
819
820
821
  
  static void __init version_sysfs_builtin(void)
  {
b4bc84280   Dmitry Torokhov   module: deal with...
822
  	const struct module_version_attribute **p;
e94965ed5   Dmitry Torokhov   module: show vers...
823
824
  	struct module_kobject *mk;
  	int err;
b4bc84280   Dmitry Torokhov   module: deal with...
825
826
  	for (p = __start___modver; p < __stop___modver; p++) {
  		const struct module_version_attribute *vattr = *p;
e94965ed5   Dmitry Torokhov   module: show vers...
827
828
829
830
831
832
833
834
  		mk = locate_module_kobject(vattr->module_name);
  		if (mk) {
  			err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
  			kobject_uevent(&mk->kobj, KOBJ_ADD);
  			kobject_put(&mk->kobj);
  		}
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
  
  /* module-related sysfs stuff */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
842
843
844
845
846
847
848
849
  static ssize_t module_attr_show(struct kobject *kobj,
  				struct attribute *attr,
  				char *buf)
  {
  	struct module_attribute *attribute;
  	struct module_kobject *mk;
  	int ret;
  
  	attribute = to_module_attr(attr);
  	mk = to_module_kobject(kobj);
  
  	if (!attribute->show)
70f2817a4   Dmitry Torokhov   [PATCH] sysfs: (r...
850
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851

4befb026c   Kay Sievers   module: change at...
852
  	ret = attribute->show(attribute, mk, buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
  	return ret;
  }
  
  static ssize_t module_attr_store(struct kobject *kobj,
  				struct attribute *attr,
  				const char *buf, size_t len)
  {
  	struct module_attribute *attribute;
  	struct module_kobject *mk;
  	int ret;
  
  	attribute = to_module_attr(attr);
  	mk = to_module_kobject(kobj);
  
  	if (!attribute->store)
70f2817a4   Dmitry Torokhov   [PATCH] sysfs: (r...
869
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870

4befb026c   Kay Sievers   module: change at...
871
  	ret = attribute->store(attribute, mk, buf, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
874
  	return ret;
  }
52cf25d0a   Emese Revfy   Driver core: Cons...
875
  static const struct sysfs_ops module_sysfs_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876
877
878
  	.show = module_attr_show,
  	.store = module_attr_store,
  };
270a6c4ca   Kay Sievers   /sys/modules/*/ho...
879
880
881
882
883
884
885
886
  static int uevent_filter(struct kset *kset, struct kobject *kobj)
  {
  	struct kobj_type *ktype = get_ktype(kobj);
  
  	if (ktype == &module_ktype)
  		return 1;
  	return 0;
  }
9cd43611c   Emese Revfy   kobject: Constify...
887
  static const struct kset_uevent_ops module_uevent_ops = {
270a6c4ca   Kay Sievers   /sys/modules/*/ho...
888
889
  	.filter = uevent_filter,
  };
7405c1e15   Greg Kroah-Hartman   kset: convert /sy...
890
  struct kset *module_kset;
823bccfc4   Greg Kroah-Hartman   remove "struct su...
891
  int module_sysfs_initialized;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892

942e44312   Li Zhong   module: Fix mod->...
893
894
895
896
897
  static void module_kobj_release(struct kobject *kobj)
  {
  	struct module_kobject *mk = to_module_kobject(kobj);
  	complete(mk->kobj_completion);
  }
7405c1e15   Greg Kroah-Hartman   kset: convert /sy...
898
  struct kobj_type module_ktype = {
942e44312   Li Zhong   module: Fix mod->...
899
  	.release   =	module_kobj_release,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
901
  	.sysfs_ops =	&module_sysfs_ops,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
903
904
905
906
  /*
   * param_sysfs_init - wrapper for built-in params support
   */
  static int __init param_sysfs_init(void)
  {
7405c1e15   Greg Kroah-Hartman   kset: convert /sy...
907
908
909
910
911
912
  	module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
  	if (!module_kset) {
  		printk(KERN_WARNING "%s (%d): error creating kset
  ",
  			__FILE__, __LINE__);
  		return -ENOMEM;
d8c7649e9   Randy Dunlap   [PATCH] kernel/pa...
913
  	}
823bccfc4   Greg Kroah-Hartman   remove "struct su...
914
  	module_sysfs_initialized = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915

e94965ed5   Dmitry Torokhov   module: show vers...
916
  	version_sysfs_builtin();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
919
920
  	param_sysfs_builtin();
  
  	return 0;
  }
d10be6d1b   Mark Huang   [PATCH] module_su...
921
  subsys_initcall(param_sysfs_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922

7405c1e15   Greg Kroah-Hartman   kset: convert /sy...
923
  #endif /* CONFIG_SYSFS */