Blame view

kernel/params.c 22.3 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
171
172
173
174
175
176
177
178
179
  			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';
  		}
  		if (quoted && args[i-1] == '"')
  			args[i-1] = '\0';
  	}
  
  	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
  {
9b473de87   Rusty Russell   param: Fix duplic...
588
589
590
591
592
593
594
595
596
597
598
599
600
  	struct module_param_attrs *new;
  	struct attribute **attrs;
  	int err, num;
  
  	/* We don't bother calling this with invisible parameters. */
  	BUG_ON(!kp->perm);
  
  	if (!mk->mp) {
  		num = 0;
  		attrs = NULL;
  	} else {
  		num = mk->mp->num;
  		attrs = mk->mp->grp.attrs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
  	}
9b473de87   Rusty Russell   param: Fix duplic...
602
603
604
605
606
  	/* Enlarge. */
  	new = krealloc(mk->mp,
  		       sizeof(*mk->mp) + sizeof(mk->mp->attrs[0]) * (num+1),
  		       GFP_KERNEL);
  	if (!new) {
63662139e   David Woodhouse   params: Fix poten...
607
  		kfree(attrs);
9b473de87   Rusty Russell   param: Fix duplic...
608
609
610
  		err = -ENOMEM;
  		goto fail;
  	}
63662139e   David Woodhouse   params: Fix poten...
611
612
613
  	/* Despite looking like the typical realloc() bug, this is safe.
  	 * We *want* the old 'attrs' to be freed either way, and we'll store
  	 * the new one in the success case. */
9b473de87   Rusty Russell   param: Fix duplic...
614
615
616
617
618
  	attrs = krealloc(attrs, sizeof(new->grp.attrs[0])*(num+2), GFP_KERNEL);
  	if (!attrs) {
  		err = -ENOMEM;
  		goto fail_free_new;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619

9b473de87   Rusty Russell   param: Fix duplic...
620
621
622
623
624
625
626
627
  	/* Sysfs wants everything zeroed. */
  	memset(new, 0, sizeof(*new));
  	memset(&new->attrs[num], 0, sizeof(new->attrs[num]));
  	memset(&attrs[num], 0, sizeof(attrs[num]));
  	new->grp.name = "parameters";
  	new->grp.attrs = attrs;
  
  	/* Tack new one on the end. */
a07e4156a   Eric W. Biederman   sysfs: Use sysfs_...
628
  	sysfs_attr_init(&new->attrs[num].mattr.attr);
9b473de87   Rusty Russell   param: Fix duplic...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
  	new->attrs[num].param = kp;
  	new->attrs[num].mattr.show = param_attr_show;
  	new->attrs[num].mattr.store = param_attr_store;
  	new->attrs[num].mattr.attr.name = (char *)name;
  	new->attrs[num].mattr.attr.mode = kp->perm;
  	new->num = num+1;
  
  	/* Fix up all the pointers, since krealloc can move us */
  	for (num = 0; num < new->num; num++)
  		new->grp.attrs[num] = &new->attrs[num].mattr.attr;
  	new->grp.attrs[num] = NULL;
  
  	mk->mp = new;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643

9b473de87   Rusty Russell   param: Fix duplic...
644
645
646
647
648
649
  fail_free_new:
  	kfree(new);
  fail:
  	mk->mp = NULL;
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650

d2441183d   Linus Torvalds   Fix compile warni...
651
  #ifdef CONFIG_MODULES
9b473de87   Rusty Russell   param: Fix duplic...
652
653
654
655
656
  static void free_module_param_attrs(struct module_kobject *mk)
  {
  	kfree(mk->mp->grp.attrs);
  	kfree(mk->mp);
  	mk->mp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
661
662
663
  /*
   * 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...
664
665
   * Adds sysfs entries for module parameters under
   * /sys/module/[mod->name]/parameters/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
   */
  int module_param_sysfs_setup(struct module *mod,
9bbb9e5a3   Rusty Russell   param: use ops in...
668
  			     const struct kernel_param *kparam,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
  			     unsigned int num_params)
  {
9b473de87   Rusty Russell   param: Fix duplic...
671
672
673
674
675
676
677
678
679
680
681
  	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);
  		if (err)
  			return err;
  		params = true;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682

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

9b473de87   Rusty Russell   param: Fix duplic...
686
687
688
689
690
  	/* 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
691
692
693
694
695
696
697
698
699
700
701
  }
  
  /*
   * 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...
702
703
  	if (mod->mkobj.mp) {
  		sysfs_remove_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
  		/* We are positive that no one is using any param
  		 * attrs at this point.  Deallocate immediately. */
9b473de87   Rusty Russell   param: Fix duplic...
706
  		free_module_param_attrs(&mod->mkobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
708
709
  	}
  }
  #endif
e180a6b77   Rusty Russell   param: fix charp ...
710
711
  void destroy_params(const struct kernel_param *params, unsigned num)
  {
e6df34a44   Rusty Russell   param: add a free...
712
713
714
715
716
  	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 ...
717
  }
e94965ed5   Dmitry Torokhov   module: show vers...
718
  static struct module_kobject * __init locate_module_kobject(const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
  {
  	struct module_kobject *mk;
9b473de87   Rusty Russell   param: Fix duplic...
721
722
  	struct kobject *kobj;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723

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

e94965ed5   Dmitry Torokhov   module: show vers...
751
752
753
754
  	return mk;
  }
  
  static void __init kernel_add_sysfs_param(const char *name,
63a12d9d0   Geert Uytterhoeven   kernel/param: con...
755
  					  const struct kernel_param *kparam,
e94965ed5   Dmitry Torokhov   module: show vers...
756
757
758
759
760
761
762
763
764
765
766
767
  					  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...
768
769
770
771
772
  	/* 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 ...
773
  	kobject_uevent(&mk->kobj, KOBJ_ADD);
9b473de87   Rusty Russell   param: Fix duplic...
774
  	kobject_put(&mk->kobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
776
777
  }
  
  /*
b634d130e   Jean Delvare   There is no /sys/...
778
   * param_sysfs_builtin - add sysfs parameters for built-in modules
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
781
782
783
784
   *
   * 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...
785
   * and for all who have the same, call kernel_add_sysfs_param.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
787
788
   */
  static void __init param_sysfs_builtin(void)
  {
63a12d9d0   Geert Uytterhoeven   kernel/param: con...
789
  	const struct kernel_param *kp;
9b473de87   Rusty Russell   param: Fix duplic...
790
791
  	unsigned int name_len;
  	char modname[MODULE_NAME_LEN];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
840
841
842
843
844
845
846
847
848
849
850
  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...
851
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
  	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...
870
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
875
  	return ret;
  }
52cf25d0a   Emese Revfy   Driver core: Cons...
876
  static const struct sysfs_ops module_sysfs_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
878
879
  	.show = module_attr_show,
  	.store = module_attr_store,
  };
270a6c4ca   Kay Sievers   /sys/modules/*/ho...
880
881
882
883
884
885
886
887
  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...
888
  static const struct kset_uevent_ops module_uevent_ops = {
270a6c4ca   Kay Sievers   /sys/modules/*/ho...
889
890
  	.filter = uevent_filter,
  };
7405c1e15   Greg Kroah-Hartman   kset: convert /sy...
891
  struct kset *module_kset;
823bccfc4   Greg Kroah-Hartman   remove "struct su...
892
  int module_sysfs_initialized;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893

942e44312   Li Zhong   module: Fix mod->...
894
895
896
897
898
  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...
899
  struct kobj_type module_ktype = {
942e44312   Li Zhong   module: Fix mod->...
900
  	.release   =	module_kobj_release,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
902
  	.sysfs_ops =	&module_sysfs_ops,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
905
906
907
  /*
   * param_sysfs_init - wrapper for built-in params support
   */
  static int __init param_sysfs_init(void)
  {
7405c1e15   Greg Kroah-Hartman   kset: convert /sy...
908
909
910
911
912
913
  	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...
914
  	}
823bccfc4   Greg Kroah-Hartman   remove "struct su...
915
  	module_sysfs_initialized = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916

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

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