cregit-Linux how code gets into the kernel

Release 4.18 kernel/params.c

Directory: kernel
/* 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
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/ctype.h>

#ifdef CONFIG_SYSFS
/* Protects all built-in parameters, modules use their own param_lock */
static DEFINE_MUTEX(param_lock);

/* Use the module's mutex, or if built-in use the built-in mutex */
#ifdef CONFIG_MODULES

#define KPARAM_MUTEX(mod)	((mod) ? &(mod)->param_lock : &param_lock)
#else

#define KPARAM_MUTEX(mod)	(&param_lock)
#endif


static inline void check_kparam_locked(struct module *mod) { BUG_ON(!mutex_is_locked(KPARAM_MUTEX(mod))); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell2187.50%150.00%
Dan Streetman312.50%150.00%
Total24100.00%2100.00%

#else
static inline void check_kparam_locked(struct module *mod) { }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell11100.00%1100.00%
Total11100.00%1100.00%

#endif /* !CONFIG_SYSFS */ /* This just allows us to keep track of which parameters are kmalloced. */ struct kmalloced_param { struct list_head list; char val[]; }; static LIST_HEAD(kmalloced_params); static DEFINE_SPINLOCK(kmalloced_params_lock);
static void *kmalloc_parameter(unsigned int size) { struct kmalloced_param *p; p = kmalloc(sizeof(*p) + size, GFP_KERNEL); if (!p) return NULL; spin_lock(&kmalloced_params_lock); list_add(&p->list, &kmalloced_params); spin_unlock(&kmalloced_params_lock); return p->val; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell5582.09%150.00%
Dan Streetman1217.91%150.00%
Total67100.00%2100.00%

/* Does nothing if parameter wasn't kmalloced above. */
static void maybe_kfree_parameter(void *param) { struct kmalloced_param *p; spin_lock(&kmalloced_params_lock); list_for_each_entry(p, &kmalloced_params, list) { if (p->val == param) { list_del(&p->list); kfree(p); break; } } spin_unlock(&kmalloced_params_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell4980.33%150.00%
Dan Streetman1219.67%150.00%
Total61100.00%2100.00%


static char dash2underscore(char c) { if (c == '-') return '_'; return c; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton2095.24%150.00%
Eric Sesterhenn / Snakebyte14.76%150.00%
Total21100.00%2100.00%


bool parameqn(const char *a, const char *b, size_t n) { size_t i; for (i = 0; i < n; i++) { if (dash2underscore(a[i]) != dash2underscore(b[i])) return false; } return true; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton3253.33%150.00%
Michal Schmidt2846.67%150.00%
Total60100.00%2100.00%


bool parameq(const char *a, const char *b) { return parameqn(a, b, strlen(a)+1); }

Contributors

PersonTokensPropCommitsCommitProp
Michal Schmidt2893.33%150.00%
Andrew Morton26.67%150.00%
Total30100.00%2100.00%


static void param_check_unsafe(const struct kernel_param *kp) { if (kp->flags & KERNEL_PARAM_FL_UNSAFE) { pr_notice("Setting dangerous option %s - tainting kernel\n", kp->name); add_taint(TAINT_USER, LOCKDEP_STILL_OK); } }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell3797.37%150.00%
Chris Wilson12.63%150.00%
Total38100.00%2100.00%


static int parse_one(char *param, char *val, const char *doing, const struct kernel_param *params, unsigned num_params, s16 min_level, s16 max_level, void *arg, int (*handle_unknown)(char *param, char *val, const char *doing, void *arg)) { unsigned int i; int err; /* Find parameter */ for (i = 0; i < num_params; i++) { if (parameq(param, params[i].name)) { if (params[i].level < min_level || params[i].level > max_level) return 0; /* No one handled NULL, so do it here. */ if (!val && !(params[i].ops->flags & KERNEL_PARAM_OPS_FL_NOARG)) return -EINVAL; pr_debug("handling %s with %p\n", param, params[i].ops->set); kernel_param_lock(params[i].mod); param_check_unsafe(&params[i]); err = params[i].ops->set(val, &params[i]); kernel_param_unlock(params[i].mod); return err; } } if (handle_unknown) { pr_debug("doing %s: %s='%s'\n", doing, param, val); return handle_unknown(param, val, doing, arg); } pr_debug("Unknown argument '%s'\n", param); return -ENOENT; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell17066.41%640.00%
Pawel Moll2911.33%16.67%
Jim Cromie259.77%213.33%
Dan Streetman145.47%16.67%
Luis R. Rodriguez103.91%16.67%
Steven Rostedt51.95%16.67%
Jani Nikula10.39%16.67%
Lucas De Marchi10.39%16.67%
Andrew Morton10.39%16.67%
Total256100.00%15100.00%

/* Args looks like "foo=bar,bar2 baz=fuz wiz". */
char *parse_args(const char *doing, char *args, const struct kernel_param *params, unsigned num, s16 min_level, s16 max_level, void *arg, int (*unknown)(char *param, char *val, const char *doing, void *arg)) { char *param, *val, *err = NULL; /* Chew leading spaces */ args = skip_spaces(args); if (*args) pr_debug("doing %s, parsing ARGS: '%s'\n", doing, args); while (*args) { int ret; int irq_was_disabled; args = next_arg(args, &param, &val); /* Stop at -- */ if (!val && strcmp(param, "--") == 0) return err ?: args; irq_was_disabled = irqs_disabled(); ret = parse_one(param, val, doing, params, num, min_level, max_level, arg, unknown); if (irq_was_disabled && !irqs_disabled()) pr_warn("%s: option '%s' enabled irq's!\n", doing, param); switch (ret) { case 0: continue; case -ENOENT: pr_err("%s: Unknown parameter `%s'\n", doing, param); break; case -ENOSPC: pr_err("%s: `%s' too large for parameter `%s'\n", doing, val ?: "", param); break; default: pr_err("%s: `%s' invalid for parameter `%s'\n", doing, val ?: "", param); break; } err = ERR_PTR(ret); } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell15962.85%436.36%
Jim Cromie3212.65%218.18%
Ard van Breemen218.30%19.09%
Oleg Nesterov197.51%19.09%
Luis R. Rodriguez103.95%19.09%
Pawel Moll103.95%19.09%
Peter Oberparleiter20.79%19.09%
Total253100.00%11100.00%

/* Lazy bastard, eh? */ #define STANDARD_PARAM_DEF(name, type, format, strtolfn) \ int param_set_##name(const char *val, const struct kernel_param *kp) \ { \ return strtolfn(val, 0, (type *)kp->arg); \ } \ int param_get_##name(char *buffer, const struct kernel_param *kp) \ { \ return scnprintf(buffer, PAGE_SIZE, format "\n", \ *((type *)kp->arg)); \ } \ const struct kernel_param_ops param_ops_##name = { \ .set = param_set_##name, \ .get = param_get_##name, \ }; \ EXPORT_SYMBOL(param_set_##name); \ EXPORT_SYMBOL(param_get_##name); \ EXPORT_SYMBOL(param_ops_##name) STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8); STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16); STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16); STANDARD_PARAM_DEF(int, int, "%i", kstrtoint); STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint); STANDARD_PARAM_DEF(long, long, "%li", kstrtol); STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul); STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull);
int param_set_charp(const char *val, const struct kernel_param *kp) { if (strlen(val) > 1024) { pr_err("%s: string parameter too long\n", kp->name); return -ENOSPC; } maybe_kfree_parameter(*(char **)kp->arg); /* This is a hack. We can't kmalloc in early boot, and we * don't need to; this mangled commandline is preserved. */ if (slab_is_available()) { *(char **)kp->arg = kmalloc_parameter(strlen(val)+1); if (!*(char **)kp->arg) return -ENOMEM; strcpy(*(char **)kp->arg, val); } else *(const char **)kp->arg = val; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell12999.23%583.33%
Jim Cromie10.77%116.67%
Total130100.00%6100.00%

EXPORT_SYMBOL(param_set_charp);
int param_get_charp(char *buffer, const struct kernel_param *kp) { return scnprintf(buffer, PAGE_SIZE, "%s\n", *((char **)kp->arg)); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell3389.19%250.00%
Chen Gang S38.11%125.00%
Jean Delvare12.70%125.00%
Total37100.00%4100.00%

EXPORT_SYMBOL(param_get_charp);
void param_free_charp(void *arg) { maybe_kfree_parameter(*((char **)arg)); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell22100.00%1100.00%
Total22100.00%1100.00%

EXPORT_SYMBOL(param_free_charp); const struct kernel_param_ops param_ops_charp = { .set = param_set_charp, .get = param_get_charp, .free = param_free_charp, }; EXPORT_SYMBOL(param_ops_charp); /* Actually could be a bool or an int, for historical reasons. */
int param_set_bool(const char *val, const struct kernel_param *kp) { /* No equals means "set"... */ if (!val) val = "1"; /* One of =[yYnN01] */ return strtobool(val, kp->arg); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell3389.19%375.00%
Jonathan Cameron410.81%125.00%
Total37100.00%4100.00%

EXPORT_SYMBOL(param_set_bool);
int param_get_bool(char *buffer, const struct kernel_param *kp) { /* Y and N chosen as being relatively non-coder friendly */ return sprintf(buffer, "%c\n", *(bool *)kp->arg ? 'Y' : 'N'); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell3697.30%480.00%
Jean Delvare12.70%120.00%
Total37100.00%5100.00%

EXPORT_SYMBOL(param_get_bool); const struct kernel_param_ops param_ops_bool = { .flags = KERNEL_PARAM_OPS_FL_NOARG, .set = param_set_bool, .get = param_get_bool, }; EXPORT_SYMBOL(param_ops_bool);
int param_set_bool_enable_only(const char *val, const struct kernel_param *kp) { int err = 0; bool new_value; bool orig_value = *(bool *)kp->arg; struct kernel_param dummy_kp = *kp; dummy_kp.arg = &new_value; err = param_set_bool(val, &dummy_kp); if (err) return err; /* Don't let them unset it once it's set! */ if (!new_value && orig_value) return -EROFS; if (new_value) err = param_set_bool(val, kp); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Luis R. Rodriguez95100.00%1100.00%
Total95100.00%1100.00%

EXPORT_SYMBOL_GPL(param_set_bool_enable_only); const struct kernel_param_ops param_ops_bool_enable_only = { .flags = KERNEL_PARAM_OPS_FL_NOARG, .set = param_set_bool_enable_only, .get = param_get_bool, }; EXPORT_SYMBOL_GPL(param_ops_bool_enable_only); /* This one must be bool. */
int param_set_invbool(const char *val, const struct kernel_param *kp) { int ret; bool boolval; struct kernel_param dummy; dummy.arg = &boolval; ret = param_set_bool(val, &dummy); if (ret == 0) *(bool *)kp->arg = !boolval; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell6195.31%480.00%
Jan Beulich34.69%120.00%
Total64100.00%5100.00%

EXPORT_SYMBOL(param_set_invbool);
int param_get_invbool(char *buffer, const struct kernel_param *kp) { return sprintf(buffer, "%c\n", (*(bool *)kp->arg) ? 'N' : 'Y'); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell2565.79%360.00%
Jan Beulich1231.58%120.00%
Jean Delvare12.63%120.00%
Total38100.00%5100.00%

EXPORT_SYMBOL(param_get_invbool); const struct kernel_param_ops param_ops_invbool = { .set = param_set_invbool, .get = param_get_invbool, }; EXPORT_SYMBOL(param_ops_invbool);
int param_set_bint(const char *val, const struct kernel_param *kp) { /* Match bool exactly, by re-using it. */ struct kernel_param boolkp = *kp; bool v; int ret; boolkp.arg = &v; ret = param_set_bool(val, &boolkp); if (ret == 0) *(int *)kp->arg = v; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell6394.03%150.00%
Dan Streetman45.97%150.00%
Total67100.00%2100.00%

EXPORT_SYMBOL(param_set_bint); const struct kernel_param_ops param_ops_bint = { .flags = KERNEL_PARAM_OPS_FL_NOARG, .set = param_set_bint, .get = param_get_int, }; EXPORT_SYMBOL(param_ops_bint); /* We break the rule and mangle the string. */
static int param_array(struct module *mod, const char *name, const char *val, unsigned int min, unsigned int max, void *elem, int elemsize, int (*set)(const char *, const struct kernel_param *kp), s16 level, unsigned int *num) { int ret; struct kernel_param kp; char save; /* Get the name right for errors. */ kp.name = name; kp.arg = elem; kp.level = level; *num = 0; /* We expect a comma-separated list of values. */ do { int len; if (*num == max) { pr_err("%s: can only take %i arguments\n", name, max); return -EINVAL; } len = strcspn(val, ","); /* nul-terminate and parse */ save = val[len]; ((char *)val)[len] = '\0'; check_kparam_locked(mod); ret = set(val, &kp); if (ret != 0) return ret; kp.arg += elemsize; val += len+1; (*num)++; } while (save == ','); if (*num < min) { pr_err("%s: needs at least %i arguments\n", name, min); return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell19685.96%650.00%
Andrew Morton187.89%18.33%
Dan Streetman62.63%18.33%
Pawel Moll41.75%18.33%
Jim Cromie20.88%18.33%
Richard Knutsson10.44%18.33%
Adrian Bunk10.44%18.33%
Total228100.00%12100.00%


static int param_array_set(const char *val, const struct kernel_param *kp) { const struct kparam_array *arr = kp->arr; unsigned int temp_num; return param_array(kp->mod, kp->name, val, 1, arr->max, arr->elem, arr->elemsize, arr->ops->set, kp->level, arr->num ?: &temp_num); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell4254.55%444.44%
Andrew Morton2329.87%111.11%
Bert Wesarg56.49%111.11%
Dan Streetman45.19%111.11%
Jan Beulich22.60%111.11%
Pawel Moll11.30%111.11%
Total77100.00%9100.00%


static int param_array_get(char *buffer, const struct kernel_param *kp) { int i, off, ret; const struct kparam_array *arr = kp->arr; struct kernel_param p = *kp; for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) { /* Replace \n with comma */ if (i) buffer[off - 1] = ','; p.arg = arr->elem + arr->elemsize * i; check_kparam_locked(p.mod); ret = arr->ops->get(buffer + off, &p); if (ret < 0) return ret; off += ret; } buffer[off] = '\0'; return off; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton7954.86%110.00%
Rusty Russell5538.19%550.00%
Dan Streetman53.47%220.00%
Jean Delvare32.08%110.00%
Jan Beulich21.39%110.00%
Total144100.00%10100.00%


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); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell73100.00%1100.00%
Total73100.00%1100.00%

const struct kernel_param_ops param_array_ops = { .set = param_array_set, .get = param_array_get, .free = param_array_free, }; EXPORT_SYMBOL(param_array_ops);
int param_set_copystring(const char *val, const struct kernel_param *kp) { const struct kparam_string *kps = kp->str; if (strlen(val)+1 > kps->maxlen) { pr_err("%s: string doesn't fit in %u chars.\n", kp->name, kps->maxlen-1); return -ENOSPC; } strcpy(kps->string, val); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell6995.83%250.00%
Jan Beulich22.78%125.00%
Jim Cromie11.39%125.00%
Total72100.00%4100.00%

EXPORT_SYMBOL(param_set_copystring);
int param_get_string(char *buffer, const struct kernel_param *kp) { const struct kparam_string *kps = kp->str; return scnprintf(buffer, PAGE_SIZE, "%s\n", kps->string); }

Contributors

PersonTokensPropCommitsCommitProp
Arnd Bergmann3179.49%125.00%
Jean Delvare512.82%125.00%
Jan Beulich25.13%125.00%
Rusty Russell12.56%125.00%
Total39100.00%4100.00%

EXPORT_SYMBOL(param_get_string); const struct kernel_param_ops param_ops_string = { .set = param_set_copystring, .get = param_get_string, }; EXPORT_SYMBOL(param_ops_string); /* sysfs output in /sys/modules/XYZ/parameters/ */ #define to_module_attr(n) container_of(n, struct module_attribute, attr) #define to_module_kobject(n) container_of(n, struct module_kobject, kobj) struct param_attribute { struct module_attribute mattr; const struct kernel_param *param; }; struct module_param_attrs { unsigned int num; struct attribute_group grp; struct param_attribute attrs[0]; }; #ifdef CONFIG_SYSFS #define to_param_attr(n) container_of(n, struct param_attribute, mattr)
static ssize_t param_attr_show(struct module_attribute *mattr, struct module_kobject *mk, char *buf) { int count; struct param_attribute *attribute = to_param_attr(mattr); if (!attribute->param->ops->get) return -EPERM; kernel_param_lock(mk->mod); count = attribute->param->ops->get(buf, attribute->param); kernel_param_unlock(mk->mod); return count; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell6984.15%350.00%
Dan Streetman89.76%116.67%
Tejun Heo33.66%116.67%
Kay Sievers22.44%116.67%
Total82100.00%6100.00%

/* sysfs always hands a nul-terminated string in buf. We rely on that. */
static ssize_t param_attr_store(struct module_attribute *mattr, struct module_kobject *mk, const char *buf, size_t len) { int err; struct param_attribute *attribute = to_param_attr(mattr); if (!attribute->param->ops->set) return -EPERM; kernel_param_lock(mk->mod); param_check_unsafe(attribute->param); err = attribute->param->ops->set(buf, attribute->param); kernel_param_unlock(mk->mod); if (!err) return len; return err; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell8887.13%457.14%
Dan Streetman98.91%114.29%
Tejun Heo32.97%114.29%
Kay Sievers10.99%114.29%
Total101100.00%7100.00%

#endif #ifdef CONFIG_MODULES #define __modinit #else #define __modinit __init #endif #ifdef CONFIG_SYSFS
void kernel_param_lock(struct module *mod) { mutex_lock(KPARAM_MUTEX(mod)); }

Contributors

PersonTokensPropCommitsCommitProp
Dan Streetman950.00%150.00%
Rusty Russell950.00%150.00%
Total18100.00%2100.00%


void kernel_param_unlock(struct module *mod) { mutex_unlock(KPARAM_MUTEX(mod)); }

Contributors

PersonTokensPropCommitsCommitProp
Dan Streetman950.00%150.00%
Rusty Russell950.00%150.00%
Total18100.00%2100.00%

EXPORT_SYMBOL(kernel_param_lock); EXPORT_SYMBOL(kernel_param_unlock); /* * add_sysfs_param - add a parameter to sysfs * @mk: struct module_kobject * @kp: the actual parameter definition to add to sysfs * @name: name of parameter * * 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. */
static __modinit int add_sysfs_param(struct module_kobject *mk, const struct kernel_param *kp, const char *name) { struct module_param_attrs *new_mp; struct attribute **new_attrs; unsigned int i; /* We don't bother calling this with invisible parameters. */ BUG_ON(!kp->perm); if (!mk->mp) { /* First allocation. */ mk->mp = kzalloc(sizeof(*mk->mp), GFP_KERNEL); if (!mk->mp) return -ENOMEM; mk->mp->grp.name = "parameters"; /* NULL-terminated attribute array. */ mk->mp->grp.attrs = kzalloc(sizeof(mk->mp->grp.attrs[0]), GFP_KERNEL); /* Caller will cleanup via free_module_param_attrs */ if (!mk->mp->grp.attrs) return -ENOMEM; } /* Enlarge allocations. */ new_mp = krealloc(mk->mp, sizeof(*mk->mp) + sizeof(mk->mp->attrs[0]) * (mk->mp->num + 1), GFP_KERNEL); if (!new_mp) return -ENOMEM; mk->mp = new_mp; /* Extra pointer for NULL terminator */ new_attrs = krealloc(mk->mp->grp.attrs, sizeof(mk->mp->grp.attrs[0]) * (mk->mp->num + 2), GFP_KERNEL); if (!new_attrs) return -ENOMEM; mk->mp->grp.attrs = new_attrs; /* Tack new one on the end. */ memset(&mk->mp->attrs[mk->mp->num], 0, sizeof(mk->mp->attrs[0])); sysfs_attr_init(&mk->mp->attrs[mk->mp->num].mattr.attr); mk->mp->attrs[mk->mp->num].param = kp; mk->mp->attrs[mk->mp->num].mattr.show = param_attr_show; /* Do not allow runtime DAC changes to make param writable. */ if ((kp->perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) mk->mp->attrs[mk->mp->num].mattr.store = param_attr_store; else mk->mp->attrs[mk->mp->num].mattr.store = NULL; mk->mp->attrs[mk->mp->num].mattr.attr.name = (char *)name; mk->mp->attrs[mk->mp->num].mattr.attr.mode = kp->perm; mk->mp->num++; /* Fix up all the pointers, since krealloc can move us */ for (i = 0; i < mk->mp->num; i++) mk->mp->grp.attrs[i] = &mk->mp->attrs[i].mattr.attr; mk->mp->grp.attrs[mk->mp->num] = NULL; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell42080.77%666.67%
Tejun Heo6712.88%111.11%
Kees Cook193.65%111.11%
Eric W. Biedermann142.69%111.11%
Total520100.00%9100.00%

#ifdef CONFIG_MODULES
static void free_module_param_attrs(struct module_kobject *mk) { if (mk->mp) kfree(mk->mp->grp.attrs); kfree(mk->mp); mk->mp = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell3892.68%375.00%
Tejun Heo37.32%125.00%
Total41100.00%4100.00%

/* * module_param_sysfs_setup - setup sysfs support for one module * @mod: module * @kparam: module parameters (array) * @num_params: number of module parameters * * Adds sysfs entries for module parameters under * /sys/module/[mod->name]/parameters/ */
int module_param_sysfs_setup(struct module *mod, const struct kernel_param *kparam, unsigned int num_params) { 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) { free_module_param_attrs(&mod->mkobj); return err; } params = true; } if (!params) return 0; /* 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; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell14498.63%466.67%
Tejun Heo21.37%233.33%
Total146100.00%6100.00%

/* * 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) { if (mod->mkobj.mp) { sysfs_remove_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp); /* We are positive that no one is using any param * attrs at this point. Deallocate immediately. */ free_module_param_attrs(&mod->mkobj); } }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell3164.58%266.67%
Tejun Heo1735.42%133.33%
Total48100.00%3100.00%

#endif
void destroy_params(const struct kernel_param *params, unsigned num) { unsigned int i; for (i = 0; i < num; i++) if (params[i].ops->free) params[i].ops->free(params[i].arg); }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell59100.00%2100.00%
Total59100.00%2100.00%


static struct module_kobject * __init locate_module_kobject(const char *name) { struct module_kobject *mk; struct kobject *kobj; int err; kobj = kset_find_obj(module_kset, name); if (kobj) { mk = to_module_kobject(kobj); } 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); #ifdef CONFIG_MODULES if (!err) err = sysfs_create_file(&mk->kobj, &module_uevent.attr); #endif if (err) { kobject_put(&mk->kobj); pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n", name, err); return NULL; } /* So that we hold reference in both cases. */ kobject_get(&mk->kobj); } return mk; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell9255.09%216.67%
Kay Sievers2816.77%216.67%
Greg Kroah-Hartman2514.97%433.33%
Dmitry Torokhov127.19%18.33%
Randy Dunlap52.99%18.33%
Pekka J Enberg31.80%18.33%
Jim Cromie21.20%18.33%
Total167100.00%12100.00%


static void __init kernel_add_sysfs_param(const char *name, const 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); /* 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); kobject_uevent(&mk->kobj, KOBJ_ADD); kobject_put(&mk->kobj); }

Contributors

PersonTokensPropCommitsCommitProp
Dmitry Torokhov6350.00%116.67%
Rusty Russell5039.68%233.33%
Kay Sievers75.56%116.67%
Tejun Heo53.97%116.67%
Geert Uytterhoeven10.79%116.67%
Total126100.00%6100.00%

/* * param_sysfs_builtin - add sysfs 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, * and for all who have the same, call kernel_add_sysfs_param. */
static void __init param_sysfs_builtin(void) { const struct kernel_param *kp; unsigned int name_len; char modname[MODULE_NAME_LEN]; for (kp = __start___param; kp < __stop___param; kp++) { char *dot; if (kp->perm == 0) continue; dot = strchr(kp->name, '.'); if (!dot) { /* This happens for core_param() */ strcpy(modname, "kernel"); name_len = 0; } else { name_len = dot - kp->name + 1; strlcpy(modname, kp->name, name_len); } kernel_add_sysfs_param(modname, kp, name_len); } }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell11498.28%466.67%
Cheng Renquan10.86%116.67%
Geert Uytterhoeven10.86%116.67%
Total116100.00%6100.00%


ssize_t __modver_version_show(struct module_attribute *mattr, struct module_kobject *mk, char *buf) { struct module_version_attribute *vattr = container_of(mattr, struct module_version_attribute, mattr); return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version); }

Contributors

PersonTokensPropCommitsCommitProp
Dmitry Torokhov4389.58%133.33%
Chen Gang S36.25%133.33%
Kay Sievers24.17%133.33%
Total48100.00%3100.00%

extern const struct module_version_attribute *__start___modver[]; extern const struct module_version_attribute *__stop___modver[];
static void __init version_sysfs_builtin(void) { const struct module_version_attribute **p; struct module_kobject *mk; int err; for (p = __start___modver; p < __stop___modver; p++) { const struct module_version_attribute *vattr = *p; mk = locate_module_kobject(vattr->module_name); if (mk) { err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr); WARN_ON_ONCE(err); kobject_uevent(&mk->kobj, KOBJ_ADD); kobject_put(&mk->kobj); } } }

Contributors

PersonTokensPropCommitsCommitProp
Dmitry Torokhov9895.15%266.67%
Rusty Russell54.85%133.33%
Total103100.00%3100.00%

/* module-related sysfs stuff */
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) return -EIO; ret = attribute->show(attribute, mk, buf); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell7195.95%133.33%
Tejun Heo22.70%133.33%
Dmitry Torokhov11.35%133.33%
Total74100.00%3100.00%


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) return -EIO; ret = attribute->store(attribute, mk, buf, len); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Greg Kroah-Hartman7998.75%150.00%
Dmitry Torokhov11.25%150.00%
Total80100.00%2100.00%

static const struct sysfs_ops module_sysfs_ops = { .show = module_attr_show, .store = module_attr_store, };
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; }

Contributors

PersonTokensPropCommitsCommitProp
Kay Sievers39100.00%1100.00%
Total39100.00%1100.00%

static const struct kset_uevent_ops module_uevent_ops = { .filter = uevent_filter, }; struct kset *module_kset; int module_sysfs_initialized;
static void module_kobj_release(struct kobject *kobj) { struct module_kobject *mk = to_module_kobject(kobj); complete(mk->kobj_completion); }

Contributors

PersonTokensPropCommitsCommitProp
Li Zhong28100.00%1100.00%
Total28100.00%1100.00%

struct kobj_type module_ktype = { .release = module_kobj_release, .sysfs_ops = &module_sysfs_ops, }; /* * param_sysfs_init - wrapper for built-in params support */
static int __init param_sysfs_init(void) { module_kset = kset_create_and_add("module", &module_uevent_ops, NULL); if (!module_kset) { printk(KERN_WARNING "%s (%d): error creating kset\n", __FILE__, __LINE__); return -ENOMEM; } module_sysfs_initialized = 1; version_sysfs_builtin(); param_sysfs_builtin(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell1934.55%120.00%
Randy Dunlap1730.91%120.00%
Greg Kroah-Hartman1629.09%240.00%
Dmitry Torokhov35.45%120.00%
Total55100.00%5100.00%

subsys_initcall(param_sysfs_init); #endif /* CONFIG_SYSFS */

Overall Contributors

PersonTokensPropCommitsCommitProp
Rusty Russell297766.69%2929.29%
Dmitry Torokhov2375.31%33.03%
Andrew Morton1753.92%22.02%
Luis R. Rodriguez1533.43%44.04%
Greg Kroah-Hartman1393.11%77.07%
Dan Streetman1192.67%33.03%
Tejun Heo1082.42%33.03%
Kay Sievers912.04%44.04%
Jim Cromie631.41%33.03%
Michal Schmidt561.25%11.01%
Pawel Moll440.99%11.01%
Li Zhong330.74%11.01%
Randy Dunlap320.72%22.02%
Arnd Bergmann310.69%11.01%
Jan Beulich230.52%11.01%
Ard van Breemen210.47%11.01%
Oleg Nesterov190.43%11.01%
Kees Cook190.43%11.01%
Jean Delvare150.34%44.04%
Stephen Rothwell140.31%11.01%
Eric W. Biedermann140.31%11.01%
Steven Rostedt130.29%11.01%
Hannes Reinecke110.25%11.01%
Chen Gang S60.13%11.01%
Bert Wesarg60.13%22.02%
Peter Oberparleiter50.11%11.01%
Geert Uytterhoeven50.11%11.01%
Felipe Contreras50.11%11.01%
Jonathan Cameron40.09%11.01%
Linus Torvalds30.07%11.01%
Pekka J Enberg30.07%11.01%
Edward Z. Yang30.07%11.01%
Jani Nikula30.07%11.01%
Tim Schmielau30.07%11.01%
Emese Revfy20.04%22.02%
Christoph Jaeger10.02%11.01%
Eric Sesterhenn / Snakebyte10.02%11.01%
Adrian Bunk10.02%11.01%
Lucas De Marchi10.02%11.01%
Cheng Renquan10.02%11.01%
Richard Knutsson10.02%11.01%
Chris Wilson10.02%11.01%
Mark Huang10.02%11.01%
Jingoo Han10.02%11.01%
Total4464100.00%99100.00%
Directory: kernel
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.