Blame view

kernel/params.c 21.9 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. */
10f296cbf   Dave Young   module: make modu...
101
102
  			if (!val && params[i].ops->set != param_set_bool
  			    && params[i].ops->set != param_set_bint)
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
242
  	{								\
  		return sprintf(buffer, format, *((type *)kp->arg));	\
a14fe249a   Rusty Russell   param: move the E...
243
  	}								\
9bbb9e5a3   Rusty Russell   param: use ops in...
244
245
246
247
  	struct kernel_param_ops param_ops_##name = {			\
  		.set = param_set_##name,				\
  		.get = param_get_##name,				\
  	};								\
a14fe249a   Rusty Russell   param: move the E...
248
  	EXPORT_SYMBOL(param_set_##name);				\
9bbb9e5a3   Rusty Russell   param: use ops in...
249
250
  	EXPORT_SYMBOL(param_get_##name);				\
  	EXPORT_SYMBOL(param_ops_##name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251

06b2a76d2   Yi Yang   Add new string fu...
252
253
254
255
256
257
258
  STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul);
  STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol);
  STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, strict_strtoul);
  STANDARD_PARAM_DEF(int, int, "%i", long, strict_strtol);
  STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, strict_strtoul);
  STANDARD_PARAM_DEF(long, long, "%li", long, strict_strtol);
  STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

7405c1e15   Greg Kroah-Hartman   kset: convert /sy...
885
  struct kobj_type module_ktype = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
887
  	.sysfs_ops =	&module_sysfs_ops,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
889
890
891
892
  /*
   * param_sysfs_init - wrapper for built-in params support
   */
  static int __init param_sysfs_init(void)
  {
7405c1e15   Greg Kroah-Hartman   kset: convert /sy...
893
894
895
896
897
898
  	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...
899
  	}
823bccfc4   Greg Kroah-Hartman   remove "struct su...
900
  	module_sysfs_initialized = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901

e94965ed5   Dmitry Torokhov   module: show vers...
902
  	version_sysfs_builtin();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
905
906
  	param_sysfs_builtin();
  
  	return 0;
  }
d10be6d1b   Mark Huang   [PATCH] module_su...
907
  subsys_initcall(param_sysfs_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908

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