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
  */
72a59aaad   Paul Gortmaker   kernel: params.c ...
18
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
24
  #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...
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
81
82
83
  }
  
  static int parse_one(char *param,
  		     char *val,
914dcaa84   Rusty Russell   param: make param...
84
  		     const struct kernel_param *params,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
88
  		     unsigned num_params,
  		     int (*handle_unknown)(char *param, char *val))
  {
  	unsigned int i;
907b29eb4   Rusty Russell   param: locking fo...
89
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
  
  	/* Find parameter */
  	for (i = 0; i < num_params; i++) {
  		if (parameq(param, params[i].name)) {
25985edce   Lucas De Marchi   Fix common misspe...
94
  			/* No one handled NULL, so do it here. */
9bbb9e5a3   Rusty Russell   param: use ops in...
95
  			if (!val && params[i].ops->set != param_set_bool)
2e9fb9953   Rusty Russell   params: don't han...
96
  				return -EINVAL;
8487bfd95   Jim Cromie   kernel/params: re...
97
98
  			pr_debug("They are equal!  Calling %p
  ",
9bbb9e5a3   Rusty Russell   param: use ops in...
99
  			       params[i].ops->set);
907b29eb4   Rusty Russell   param: locking fo...
100
101
102
103
  			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
104
105
106
107
  		}
  	}
  
  	if (handle_unknown) {
8487bfd95   Jim Cromie   kernel/params: re...
108
109
  		pr_debug("Unknown argument: calling %p
  ", handle_unknown);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
  		return handle_unknown(param, val);
  	}
8487bfd95   Jim Cromie   kernel/params: re...
112
113
  	pr_debug("Unknown argument `%s'
  ", param);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
117
118
119
120
121
122
123
  	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
124
125
126
127
128
129
130
  	if (*args == '"') {
  		args++;
  		in_quote = 1;
  		quoted = 1;
  	}
  
  	for (i = 0; args[i]; i++) {
26d052bfc   Peter Oberparleiter   param: allow whit...
131
  		if (isspace(args[i]) && !in_quote)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  			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...
163
164
  
  	/* Chew up trailing spaces. */
e7d2860b6   AndrĂ© Goddard Rosa   tree-wide: conver...
165
  	return skip_spaces(next);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
169
170
  }
  
  /* Args looks like "foo=bar,bar2 baz=fuz wiz". */
  int parse_args(const char *name,
  	       char *args,
914dcaa84   Rusty Russell   param: make param...
171
  	       const struct kernel_param *params,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
175
  	       unsigned num,
  	       int (*unknown)(char *param, char *val))
  {
  	char *param, *val;
8487bfd95   Jim Cromie   kernel/params: re...
176
177
  	pr_debug("Parsing ARGS: %s
  ", args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178

f36462f07   Rusty Russell   [PATCH] Ignore tr...
179
  	/* Chew leading spaces */
e7d2860b6   AndrĂ© Goddard Rosa   tree-wide: conver...
180
  	args = skip_spaces(args);
f36462f07   Rusty Russell   [PATCH] Ignore tr...
181

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
  	while (*args) {
  		int ret;
a416aba63   Ard van Breemen   [PATCH] kernelpar...
184
  		int irq_was_disabled;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
  
  		args = next_arg(args, &param, &val);
a416aba63   Ard van Breemen   [PATCH] kernelpar...
187
  		irq_was_disabled = irqs_disabled();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  		ret = parse_one(param, val, params, num, unknown);
a416aba63   Ard van Breemen   [PATCH] kernelpar...
189
190
191
192
193
  		if (irq_was_disabled && !irqs_disabled()) {
  			printk(KERN_WARNING "parse_args(): option '%s' enabled "
  					"irq's!
  ", param);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  		switch (ret) {
  		case -ENOENT:
  			printk(KERN_ERR "%s: Unknown parameter `%s'
  ",
  			       name, param);
  			return ret;
  		case -ENOSPC:
  			printk(KERN_ERR
  			       "%s: `%s' too large for parameter `%s'
  ",
  			       name, val ?: "", param);
  			return ret;
  		case 0:
  			break;
  		default:
  			printk(KERN_ERR
  			       "%s: `%s' invalid for parameter `%s'
  ",
  			       name, val ?: "", param);
  			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...
223
  	int param_set_##name(const char *val, const struct kernel_param *kp) \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  	{								\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  		tmptype l;						\
06b2a76d2   Yi Yang   Add new string fu...
226
  		int ret;						\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
  									\
06b2a76d2   Yi Yang   Add new string fu...
228
  		ret = strtolfn(val, 0, &l);				\
81c741365   Satoru Moriya   param: fix return...
229
230
  		if (ret < 0 || ((type)l != l))				\
  			return ret < 0 ? ret : -EINVAL;			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
  		*((type *)kp->arg) = l;					\
  		return 0;						\
  	}								\
9bbb9e5a3   Rusty Russell   param: use ops in...
234
  	int param_get_##name(char *buffer, const struct kernel_param *kp) \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
  	{								\
  		return sprintf(buffer, format, *((type *)kp->arg));	\
a14fe249a   Rusty Russell   param: move the E...
237
  	}								\
9bbb9e5a3   Rusty Russell   param: use ops in...
238
239
240
241
  	struct kernel_param_ops param_ops_##name = {			\
  		.set = param_set_##name,				\
  		.get = param_get_##name,				\
  	};								\
a14fe249a   Rusty Russell   param: move the E...
242
  	EXPORT_SYMBOL(param_set_##name);				\
9bbb9e5a3   Rusty Russell   param: use ops in...
243
244
  	EXPORT_SYMBOL(param_get_##name);				\
  	EXPORT_SYMBOL(param_ops_##name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245

06b2a76d2   Yi Yang   Add new string fu...
246
247
248
249
250
251
252
  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
253

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

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

a1054322a   Rusty Russell   param: use free h...
283
284
285
286
  static void param_free_charp(void *arg)
  {
  	maybe_kfree_parameter(*((char **)arg));
  }
9bbb9e5a3   Rusty Russell   param: use ops in...
287
288
289
  struct kernel_param_ops param_ops_charp = {
  	.set = param_set_charp,
  	.get = param_get_charp,
a1054322a   Rusty Russell   param: use free h...
290
  	.free = param_free_charp,
9bbb9e5a3   Rusty Russell   param: use ops in...
291
292
  };
  EXPORT_SYMBOL(param_ops_charp);
fddd52012   Rusty Russell   module_param: all...
293
  /* Actually could be a bool or an int, for historical reasons. */
9bbb9e5a3   Rusty Russell   param: use ops in...
294
  int param_set_bool(const char *val, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  {
fddd52012   Rusty Russell   module_param: all...
296
  	bool v;
f721a465c   Jonathan Cameron   params.c: Use new...
297
  	int ret;
fddd52012   Rusty Russell   module_param: all...
298

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
  	/* No equals means "set"... */
  	if (!val) val = "1";
  
  	/* One of =[yYnN01] */
f721a465c   Jonathan Cameron   params.c: Use new...
303
304
305
  	ret = strtobool(val, &v);
  	if (ret)
  		return ret;
fddd52012   Rusty Russell   module_param: all...
306
307
308
309
310
311
  
  	if (kp->flags & KPARAM_ISBOOL)
  		*(bool *)kp->arg = v;
  	else
  		*(int *)kp->arg = v;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  }
a14fe249a   Rusty Russell   param: move the E...
313
  EXPORT_SYMBOL(param_set_bool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314

9bbb9e5a3   Rusty Russell   param: use ops in...
315
  int param_get_bool(char *buffer, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  {
fddd52012   Rusty Russell   module_param: all...
317
318
319
320
321
  	bool val;
  	if (kp->flags & KPARAM_ISBOOL)
  		val = *(bool *)kp->arg;
  	else
  		val = *(int *)kp->arg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  	/* Y and N chosen as being relatively non-coder friendly */
fddd52012   Rusty Russell   module_param: all...
323
  	return sprintf(buffer, "%c", val ? 'Y' : 'N');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
  }
a14fe249a   Rusty Russell   param: move the E...
325
  EXPORT_SYMBOL(param_get_bool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326

9bbb9e5a3   Rusty Russell   param: use ops in...
327
328
329
330
331
  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...
332
  /* This one must be bool. */
9bbb9e5a3   Rusty Russell   param: use ops in...
333
  int param_set_invbool(const char *val, const struct kernel_param *kp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
  {
fddd52012   Rusty Russell   module_param: all...
335
336
  	int ret;
  	bool boolval;
22e48eaf5   Jan Beulich   constify string/a...
337
  	struct kernel_param dummy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338

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

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

9bbb9e5a3   Rusty Russell   param: use ops in...
354
355
356
357
358
  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...
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
  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;
  	boolkp.flags |= KPARAM_ISBOOL;
  
  	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: ...
382
  /* We break the rule and mangle the string. */
9871728b7   Adrian Bunk   [PATCH] kernel/pa...
383
384
385
386
  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...
387
  		       int (*set)(const char *, const struct kernel_param *kp),
3c7d76e37   Rusty Russell   param: fix settin...
388
  		       u16 flags,
eb38a996e   Richard Knutsson   kernel/params.c: ...
389
  		       unsigned int *num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
392
393
394
395
396
397
  {
  	int ret;
  	struct kernel_param kp;
  	char save;
  
  	/* Get the name right for errors. */
  	kp.name = name;
  	kp.arg = elem;
3c7d76e37   Rusty Russell   param: fix settin...
398
  	kp.flags = flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399

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

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

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

9b473de87   Rusty Russell   param: Fix duplic...
622
623
624
625
626
627
628
629
  	/* 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_...
630
  	sysfs_attr_init(&new->attrs[num].mattr.attr);
9b473de87   Rusty Russell   param: Fix duplic...
631
632
633
634
635
636
637
638
639
640
641
642
643
644
  	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
645

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

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

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

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

9b473de87   Rusty Russell   param: Fix duplic...
726
727
  	kobj = kset_find_obj(module_kset, name);
  	if (kobj) {
9b473de87   Rusty Russell   param: Fix duplic...
728
  		mk = to_module_kobject(kobj);
9b473de87   Rusty Russell   param: Fix duplic...
729
730
731
732
733
734
735
736
  	} 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/...
737
738
739
740
  #ifdef CONFIG_MODULES
  		if (!err)
  			err = sysfs_create_file(&mk->kobj, &module_uevent.attr);
  #endif
9b473de87   Rusty Russell   param: Fix duplic...
741
742
  		if (err) {
  			kobject_put(&mk->kobj);
e94965ed5   Dmitry Torokhov   module: show vers...
743
744
745
746
747
748
749
750
  			printk(KERN_ERR
  				"Module '%s' failed add to sysfs, error number %d
  ",
  				name, err);
  			printk(KERN_ERR
  				"The system will be unstable now.
  ");
  			return NULL;
9b473de87   Rusty Russell   param: Fix duplic...
751
  		}
e94965ed5   Dmitry Torokhov   module: show vers...
752
753
  
  		/* So that we hold reference in both cases. */
9b473de87   Rusty Russell   param: Fix duplic...
754
  		kobject_get(&mk->kobj);
74c5b597e   Greg Kroah-Hartman   modules: better e...
755
  	}
9b473de87   Rusty Russell   param: Fix duplic...
756

e94965ed5   Dmitry Torokhov   module: show vers...
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
  	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...
774
775
776
777
778
  	/* 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 ...
779
  	kobject_uevent(&mk->kobj, KOBJ_ADD);
9b473de87   Rusty Russell   param: Fix duplic...
780
  	kobject_put(&mk->kobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
783
784
785
786
787
788
789
790
  }
  
  /*
   * param_sysfs_builtin - add contents in /sys/parameters for built-in modules
   *
   * 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...
791
   * and for all who have the same, call kernel_add_sysfs_param.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
794
   */
  static void __init param_sysfs_builtin(void)
  {
9b473de87   Rusty Russell   param: Fix duplic...
795
796
797
  	struct kernel_param *kp;
  	unsigned int name_len;
  	char modname[MODULE_NAME_LEN];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798

9b473de87   Rusty Russell   param: Fix duplic...
799
  	for (kp = __start___param; kp < __stop___param; kp++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  		char *dot;
9b473de87   Rusty Russell   param: Fix duplic...
801
802
  		if (kp->perm == 0)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
  	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...
877
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878

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

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

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

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

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