Blame view

kernel/params.c 22.1 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
22
23
  #include <linux/kernel.h>
  #include <linux/string.h>
  #include <linux/errno.h>
  #include <linux/module.h>
  #include <linux/device.h>
  #include <linux/err.h>
4e57b6817   Tim Schmielau   [PATCH] fix missi...
24
  #include <linux/slab.h>
26d052bfc   Peter Oberparleiter   param: allow whit...
25
  #include <linux/ctype.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26

907b29eb4   Rusty Russell   param: locking fo...
27
28
  /* Protects all parameters, and incidentally kmalloced_param list. */
  static DEFINE_MUTEX(param_lock);
a1054322a   Rusty Russell   param: use free h...
29
30
31
32
33
  /* 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...
34
35
36
37
38
39
40
41
42
  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...
43
  	list_add(&p->list, &kmalloced_params);
a1054322a   Rusty Russell   param: use free h...
44
45
46
47
48
49
50
  	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...
51
52
53
54
55
56
57
  	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...
58
  }
b1e4d20cb   Michal Schmidt   params: make dash...
59
  static char dash2underscore(char c)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
  {
  	if (c == '-')
  		return '_';
  	return c;
  }
b1e4d20cb   Michal Schmidt   params: make dash...
65
  bool parameqn(const char *a, const char *b, size_t n)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  {
b1e4d20cb   Michal Schmidt   params: make dash...
67
68
69
70
71
72
73
74
75
76
77
78
  	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
79
80
81
82
  }
  
  static int parse_one(char *param,
  		     char *val,
9fb48c744   Jim Cromie   params: add 3rd a...
83
  		     const char *doing,
914dcaa84   Rusty Russell   param: make param...
84
  		     const struct kernel_param *params,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  		     unsigned num_params,
026cee008   Pawel Moll   params: <level>_i...
86
87
  		     s16 min_level,
  		     s16 max_level,
9fb48c744   Jim Cromie   params: add 3rd a...
88
89
  		     int (*handle_unknown)(char *param, char *val,
  				     const char *doing))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  {
  	unsigned int i;
907b29eb4   Rusty Russell   param: locking fo...
92
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
  
  	/* Find parameter */
  	for (i = 0; i < num_params; i++) {
  		if (parameq(param, params[i].name)) {
026cee008   Pawel Moll   params: <level>_i...
97
98
99
  			if (params[i].level < min_level
  			    || params[i].level > max_level)
  				return 0;
25985edce   Lucas De Marchi   Fix common misspe...
100
  			/* No one handled NULL, so do it here. */
ab013c5f6   Steven Rostedt   module: Add flag ...
101
102
  			if (!val &&
  			    !(params[i].ops->flags & KERNEL_PARAM_FL_NOARG))
2e9fb9953   Rusty Russell   params: don't han...
103
  				return -EINVAL;
9fb48c744   Jim Cromie   params: add 3rd a...
104
105
106
  			pr_debug("handling %s with %p
  ", param,
  				params[i].ops->set);
907b29eb4   Rusty Russell   param: locking fo...
107
108
109
110
  			mutex_lock(&param_lock);
  			err = params[i].ops->set(val, &params[i]);
  			mutex_unlock(&param_lock);
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
  		}
  	}
  
  	if (handle_unknown) {
9fb48c744   Jim Cromie   params: add 3rd a...
115
116
117
  		pr_debug("doing %s: %s='%s'
  ", doing, param, val);
  		return handle_unknown(param, val, doing);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  	}
9fb48c744   Jim Cromie   params: add 3rd a...
119
120
  	pr_debug("Unknown argument '%s'
  ", param);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
126
127
128
129
130
  	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
131
132
133
134
135
136
137
  	if (*args == '"') {
  		args++;
  		in_quote = 1;
  		quoted = 1;
  	}
  
  	for (i = 0; args[i]; i++) {
26d052bfc   Peter Oberparleiter   param: allow whit...
138
  		if (isspace(args[i]) && !in_quote)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  			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...
170
171
  
  	/* Chew up trailing spaces. */
e7d2860b6   AndrĂ© Goddard Rosa   tree-wide: conver...
172
  	return skip_spaces(next);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
  }
  
  /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
9fb48c744   Jim Cromie   params: add 3rd a...
176
  int parse_args(const char *doing,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  	       char *args,
914dcaa84   Rusty Russell   param: make param...
178
  	       const struct kernel_param *params,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  	       unsigned num,
026cee008   Pawel Moll   params: <level>_i...
180
181
  	       s16 min_level,
  	       s16 max_level,
9fb48c744   Jim Cromie   params: add 3rd a...
182
  	       int (*unknown)(char *param, char *val, const char *doing))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
  {
  	char *param, *val;
f36462f07   Rusty Russell   [PATCH] Ignore tr...
185
  	/* Chew leading spaces */
e7d2860b6   AndrĂ© Goddard Rosa   tree-wide: conver...
186
  	args = skip_spaces(args);
f36462f07   Rusty Russell   [PATCH] Ignore tr...
187

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

6072ddc85   Jingoo Han   kernel: replace s...
253
  STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", unsigned long, kstrtoul);
3a126f85e   Jean Delvare   kernel/params: fi...
254
  STANDARD_PARAM_DEF(short, short, "%hi", long, kstrtol);
6072ddc85   Jingoo Han   kernel: replace s...
255
  STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, kstrtoul);
3a126f85e   Jean Delvare   kernel/params: fi...
256
  STANDARD_PARAM_DEF(int, int, "%i", long, kstrtol);
6072ddc85   Jingoo Han   kernel: replace s...
257
  STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, kstrtoul);
3a126f85e   Jean Delvare   kernel/params: fi...
258
  STANDARD_PARAM_DEF(long, long, "%li", long, kstrtol);
6072ddc85   Jingoo Han   kernel: replace s...
259
  STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, kstrtoul);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260

9bbb9e5a3   Rusty Russell   param: use ops in...
261
  int param_set_charp(const char *val, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	if (strlen(val) > 1024) {
b5f3abf95   Jim Cromie   params: replace p...
264
265
  		pr_err("%s: string parameter too long
  ", kp->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  		return -ENOSPC;
  	}
a1054322a   Rusty Russell   param: use free h...
268
269
270
  	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 ...
271
272
  	 * don't need to; this mangled commandline is preserved. */
  	if (slab_is_available()) {
a1054322a   Rusty Russell   param: use free h...
273
  		*(char **)kp->arg = kmalloc_parameter(strlen(val)+1);
d553ad864   Rusty Russell   param: fix NULL c...
274
  		if (!*(char **)kp->arg)
e180a6b77   Rusty Russell   param: fix charp ...
275
  			return -ENOMEM;
a1054322a   Rusty Russell   param: use free h...
276
  		strcpy(*(char **)kp->arg, val);
e180a6b77   Rusty Russell   param: fix charp ...
277
278
  	} else
  		*(const char **)kp->arg = val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  	return 0;
  }
a14fe249a   Rusty Russell   param: move the E...
281
  EXPORT_SYMBOL(param_set_charp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282

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

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

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

9bbb9e5a3   Rusty Russell   param: use ops in...
317
  struct kernel_param_ops param_ops_bool = {
ab013c5f6   Steven Rostedt   module: Add flag ...
318
  	.flags = KERNEL_PARAM_FL_NOARG,
9bbb9e5a3   Rusty Russell   param: use ops in...
319
320
321
322
  	.set = param_set_bool,
  	.get = param_get_bool,
  };
  EXPORT_SYMBOL(param_ops_bool);
fddd52012   Rusty Russell   module_param: all...
323
  /* This one must be bool. */
9bbb9e5a3   Rusty Russell   param: use ops in...
324
  int param_set_invbool(const char *val, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  {
fddd52012   Rusty Russell   module_param: all...
326
327
  	int ret;
  	bool boolval;
22e48eaf5   Jan Beulich   constify string/a...
328
  	struct kernel_param dummy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329

22e48eaf5   Jan Beulich   constify string/a...
330
  	dummy.arg = &boolval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
332
  	ret = param_set_bool(val, &dummy);
  	if (ret == 0)
9a71af2c3   Rusty Russell   module_param: inv...
333
  		*(bool *)kp->arg = !boolval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
  	return ret;
  }
a14fe249a   Rusty Russell   param: move the E...
336
  EXPORT_SYMBOL(param_set_invbool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337

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

9bbb9e5a3   Rusty Russell   param: use ops in...
344
345
346
347
348
  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...
349
350
351
352
353
354
355
356
357
  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...
358
359
360
361
362
363
364
365
366
  
  	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 = {
ab013c5f6   Steven Rostedt   module: Add flag ...
367
  	.flags = KERNEL_PARAM_FL_NOARG,
69116f279   Rusty Russell   module_param: avo...
368
369
370
371
  	.set = param_set_bint,
  	.get = param_get_int,
  };
  EXPORT_SYMBOL(param_ops_bint);
9730b5b06   Bert Wesarg   kernel/params.c: ...
372
  /* We break the rule and mangle the string. */
9871728b7   Adrian Bunk   [PATCH] kernel/pa...
373
374
375
376
  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...
377
  		       int (*set)(const char *, const struct kernel_param *kp),
026cee008   Pawel Moll   params: <level>_i...
378
  		       s16 level,
eb38a996e   Richard Knutsson   kernel/params.c: ...
379
  		       unsigned int *num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
381
382
383
384
385
386
387
  {
  	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...
388
  	kp.level = level;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389

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

9bbb9e5a3   Rusty Russell   param: use ops in...
482
  int param_get_string(char *buffer, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
  {
22e48eaf5   Jan Beulich   constify string/a...
484
  	const struct kparam_string *kps = kp->str;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
  	return strlcpy(buffer, kps->string, kps->maxlen);
  }
a14fe249a   Rusty Russell   param: move the E...
487
  EXPORT_SYMBOL(param_get_string);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488

9bbb9e5a3   Rusty Russell   param: use ops in...
489
490
491
492
493
  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
494
  /* sysfs output in /sys/modules/XYZ/parameters/ */
350f82586   Edward Z. Yang   Remove redundant ...
495
496
  #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
497
498
  
  extern struct kernel_param __start___param[], __stop___param[];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
501
  struct param_attribute
  {
  	struct module_attribute mattr;
9bbb9e5a3   Rusty Russell   param: use ops in...
502
  	const struct kernel_param *param;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
506
  };
  
  struct module_param_attrs
  {
9b473de87   Rusty Russell   param: Fix duplic...
507
  	unsigned int num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
  	struct attribute_group grp;
  	struct param_attribute attrs[0];
  };
ef665c1a0   Randy Dunlap   sysfs: fix build ...
511
  #ifdef CONFIG_SYSFS
350f82586   Edward Z. Yang   Remove redundant ...
512
  #define to_param_attr(n) container_of(n, struct param_attribute, mattr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
  
  static ssize_t param_attr_show(struct module_attribute *mattr,
4befb026c   Kay Sievers   module: change at...
515
  			       struct module_kobject *mk, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
  {
  	int count;
  	struct param_attribute *attribute = to_param_attr(mattr);
9bbb9e5a3   Rusty Russell   param: use ops in...
519
  	if (!attribute->param->ops->get)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  		return -EPERM;
907b29eb4   Rusty Russell   param: locking fo...
521
  	mutex_lock(&param_lock);
9bbb9e5a3   Rusty Russell   param: use ops in...
522
  	count = attribute->param->ops->get(buf, attribute->param);
907b29eb4   Rusty Russell   param: locking fo...
523
  	mutex_unlock(&param_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
526
527
528
529
530
531
532
533
  	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...
534
  				struct module_kobject *km,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
  				const char *buf, size_t len)
  {
   	int err;
  	struct param_attribute *attribute = to_param_attr(mattr);
9bbb9e5a3   Rusty Russell   param: use ops in...
539
  	if (!attribute->param->ops->set)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
  		return -EPERM;
907b29eb4   Rusty Russell   param: locking fo...
541
  	mutex_lock(&param_lock);
9bbb9e5a3   Rusty Russell   param: use ops in...
542
  	err = attribute->param->ops->set(buf, attribute->param);
907b29eb4   Rusty Russell   param: locking fo...
543
  	mutex_unlock(&param_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
546
547
  	if (!err)
  		return len;
  	return err;
  }
ef665c1a0   Randy Dunlap   sysfs: fix build ...
548
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
551
552
553
554
  
  #ifdef CONFIG_MODULES
  #define __modinit
  #else
  #define __modinit __init
  #endif
ef665c1a0   Randy Dunlap   sysfs: fix build ...
555
  #ifdef CONFIG_SYSFS
907b29eb4   Rusty Russell   param: locking fo...
556
557
558
559
560
561
562
563
564
565
566
  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
567
  /*
9b473de87   Rusty Russell   param: Fix duplic...
568
569
570
571
   * 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
572
   *
9b473de87   Rusty Russell   param: Fix duplic...
573
574
575
   * 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
576
   */
9b473de87   Rusty Russell   param: Fix duplic...
577
  static __modinit int add_sysfs_param(struct module_kobject *mk,
9bbb9e5a3   Rusty Russell   param: use ops in...
578
  				     const struct kernel_param *kp,
9b473de87   Rusty Russell   param: Fix duplic...
579
  				     const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  {
9b473de87   Rusty Russell   param: Fix duplic...
581
582
583
584
585
586
587
588
589
590
591
592
593
  	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
594
  	}
9b473de87   Rusty Russell   param: Fix duplic...
595
596
597
598
599
  	/* 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...
600
  		kfree(attrs);
9b473de87   Rusty Russell   param: Fix duplic...
601
602
603
  		err = -ENOMEM;
  		goto fail;
  	}
63662139e   David Woodhouse   params: Fix poten...
604
605
606
  	/* 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...
607
608
609
610
611
  	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
612

9b473de87   Rusty Russell   param: Fix duplic...
613
614
615
616
617
618
619
620
  	/* 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_...
621
  	sysfs_attr_init(&new->attrs[num].mattr.attr);
9b473de87   Rusty Russell   param: Fix duplic...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
  	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
636

9b473de87   Rusty Russell   param: Fix duplic...
637
638
639
640
641
642
  fail_free_new:
  	kfree(new);
  fail:
  	mk->mp = NULL;
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643

d2441183d   Linus Torvalds   Fix compile warni...
644
  #ifdef CONFIG_MODULES
9b473de87   Rusty Russell   param: Fix duplic...
645
646
647
648
649
  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
650
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
653
654
655
656
  /*
   * 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...
657
658
   * Adds sysfs entries for module parameters under
   * /sys/module/[mod->name]/parameters/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
   */
  int module_param_sysfs_setup(struct module *mod,
9bbb9e5a3   Rusty Russell   param: use ops in...
661
  			     const struct kernel_param *kparam,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
  			     unsigned int num_params)
  {
9b473de87   Rusty Russell   param: Fix duplic...
664
665
666
667
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);
  		if (err)
  			return err;
  		params = true;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675

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

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

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

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

9b473de87   Rusty Russell   param: Fix duplic...
786
  	for (kp = __start___param; kp < __stop___param; kp++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  		char *dot;
9b473de87   Rusty Russell   param: Fix duplic...
788
789
  		if (kp->perm == 0)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
833
834
835
836
837
838
839
840
841
842
843
  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...
844
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
  	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...
863
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864

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

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

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

e94965ed5   Dmitry Torokhov   module: show vers...
910
  	version_sysfs_builtin();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
913
914
  	param_sysfs_builtin();
  
  	return 0;
  }
d10be6d1b   Mark Huang   [PATCH] module_su...
915
  subsys_initcall(param_sysfs_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916

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