module: add extra argument for parse_params() callback
authorLuis R. Rodriguez <mcgrof@suse.com>
Mon, 30 Mar 2015 23:20:03 +0000 (16:20 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 May 2015 07:25:24 +0000 (00:25 -0700)
This adds an extra argument onto parse_params() to be used
as a way to make the unused callback a bit more useful and
generic by allowing the caller to pass on a data structure
of its choice. An example use case is to allow us to easily
make module parameters for every module which we will do
next.

@ parse @
identifier name, args, params, num, level_min, level_max;
identifier unknown, param, val, doing;
type s16;
@@
 extern char *parse_args(const char *name,
   char *args,
   const struct kernel_param *params,
   unsigned num,
   s16 level_min,
   s16 level_max,
+  void *arg,
   int (*unknown)(char *param, char *val,
const char *doing
+ , void *arg
));

@ parse_mod @
identifier name, args, params, num, level_min, level_max;
identifier unknown, param, val, doing;
type s16;
@@
 char *parse_args(const char *name,
   char *args,
   const struct kernel_param *params,
   unsigned num,
   s16 level_min,
   s16 level_max,
+  void *arg,
   int (*unknown)(char *param, char *val,
const char *doing
+ , void *arg
))
{
...
}

@ parse_args_found @
expression R, E1, E2, E3, E4, E5, E6;
identifier func;
@@

(
R =
parse_args(E1, E2, E3, E4, E5, E6,
+    NULL,
   func);
|
R =
parse_args(E1, E2, E3, E4, E5, E6,
+    NULL,
   &func);
|
R =
parse_args(E1, E2, E3, E4, E5, E6,
+    NULL,
   NULL);
|
parse_args(E1, E2, E3, E4, E5, E6,
+    NULL,
   func);
|
parse_args(E1, E2, E3, E4, E5, E6,
+    NULL,
   &func);
|
parse_args(E1, E2, E3, E4, E5, E6,
+    NULL,
   NULL);
)

@ parse_args_unused depends on parse_args_found @
identifier parse_args_found.func;
@@

int func(char *param, char *val, const char *unused
+  , void *arg
 )
{
...
}

@ mod_unused depends on parse_args_found @
identifier parse_args_found.func;
expression A1, A2, A3;
@@

- func(A1, A2, A3);
+ func(A1, A2, A3, NULL);

Generated-by: Coccinelle SmPL
Cc: cocci@systeme.lip6.fr
Cc: Tejun Heo <tj@kernel.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Felipe Contreras <felipe.contreras@gmail.com>
Cc: Ewan Milne <emilne@redhat.com>
Cc: Jean Delvare <jdelvare@suse.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: linux-kernel@vger.kernel.org
Reviewed-by: Tejun Heo <tj@kernel.org>
Acked-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/powerpc/mm/hugetlbpage.c
include/linux/moduleparam.h
init/main.c
kernel/module.c
kernel/params.c
lib/dynamic_debug.c

index 0ce968b00b7c665967ca3addc26d0cc04a72f729..d230158c9770e58d03a6603c5678cdec8643c87c 100644 (file)
@@ -336,7 +336,7 @@ int alloc_bootmem_huge_page(struct hstate *hstate)
 unsigned long gpage_npages[MMU_PAGE_COUNT];
 
 static int __init do_gpage_early_setup(char *param, char *val,
-                                      const char *unused)
+                                      const char *unused, void *arg)
 {
        static phys_addr_t size;
        unsigned long npages;
@@ -385,7 +385,7 @@ void __init reserve_hugetlb_gpages(void)
 
        strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE);
        parse_args("hugetlb gpages", cmdline, NULL, 0, 0, 0,
-                       &do_gpage_early_setup);
+                       NULL, &do_gpage_early_setup);
 
        /*
         * Walk gpage list in reverse, allocating larger page sizes first.
index 1c9effa25e2632497384e973a28954f7e33aedbc..13923709d30d0a7b38055f5f9d474f0a86afa930 100644 (file)
@@ -357,8 +357,9 @@ extern char *parse_args(const char *name,
                      unsigned num,
                      s16 level_min,
                      s16 level_max,
+                     void *arg,
                      int (*unknown)(char *param, char *val,
-                             const char *doing));
+                                    const char *doing, void *arg));
 
 /* Called by module remove. */
 #ifdef CONFIG_SYSFS
index 2115055faeac948bd164c9e8d574795f557f02a5..edcb134406469db161956fa68c70b0ee52b4446d 100644 (file)
@@ -235,7 +235,8 @@ static int __init loglevel(char *str)
 early_param("loglevel", loglevel);
 
 /* Change NUL term back to "=", to make "param" the whole string. */
-static int __init repair_env_string(char *param, char *val, const char *unused)
+static int __init repair_env_string(char *param, char *val,
+                                   const char *unused, void *arg)
 {
        if (val) {
                /* param=val or param="val"? */
@@ -252,14 +253,15 @@ static int __init repair_env_string(char *param, char *val, const char *unused)
 }
 
 /* Anything after -- gets handed straight to init. */
-static int __init set_init_arg(char *param, char *val, const char *unused)
+static int __init set_init_arg(char *param, char *val,
+                              const char *unused, void *arg)
 {
        unsigned int i;
 
        if (panic_later)
                return 0;
 
-       repair_env_string(param, val, unused);
+       repair_env_string(param, val, unused, NULL);
 
        for (i = 0; argv_init[i]; i++) {
                if (i == MAX_INIT_ARGS) {
@@ -276,9 +278,10 @@ static int __init set_init_arg(char *param, char *val, const char *unused)
  * Unknown boot options get handed to init, unless they look like
  * unused parameters (modprobe will find them in /proc/cmdline).
  */
-static int __init unknown_bootoption(char *param, char *val, const char *unused)
+static int __init unknown_bootoption(char *param, char *val,
+                                    const char *unused, void *arg)
 {
-       repair_env_string(param, val, unused);
+       repair_env_string(param, val, unused, NULL);
 
        /* Handle obsolete-style parameters */
        if (obsolete_checksetup(param))
@@ -410,7 +413,8 @@ static noinline void __init_refok rest_init(void)
 }
 
 /* Check for early params. */
-static int __init do_early_param(char *param, char *val, const char *unused)
+static int __init do_early_param(char *param, char *val,
+                                const char *unused, void *arg)
 {
        const struct obs_kernel_param *p;
 
@@ -429,7 +433,8 @@ static int __init do_early_param(char *param, char *val, const char *unused)
 
 void __init parse_early_options(char *cmdline)
 {
-       parse_args("early options", cmdline, NULL, 0, 0, 0, do_early_param);
+       parse_args("early options", cmdline, NULL, 0, 0, 0, NULL,
+                  do_early_param);
 }
 
 /* Arch code calls this early on, or if not, just before other parsing. */
@@ -535,10 +540,10 @@ asmlinkage __visible void __init start_kernel(void)
        after_dashes = parse_args("Booting kernel",
                                  static_command_line, __start___param,
                                  __stop___param - __start___param,
-                                 -1, -1, &unknown_bootoption);
+                                 -1, -1, NULL, &unknown_bootoption);
        if (!IS_ERR_OR_NULL(after_dashes))
                parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
-                          set_init_arg);
+                          NULL, set_init_arg);
 
        jump_label_init();
 
@@ -847,7 +852,7 @@ static void __init do_initcall_level(int level)
                   initcall_command_line, __start___param,
                   __stop___param - __start___param,
                   level, level,
-                  &repair_env_string);
+                  NULL, &repair_env_string);
 
        for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
                do_one_initcall(*fn);
index 42a1d2afb2173cd3c7c740098dd72d7a52bdb3f8..24d1f31d02f237f3db445dde9c5b3cc9cfe59687 100644 (file)
@@ -3237,7 +3237,8 @@ out:
        return err;
 }
 
-static int unknown_module_param_cb(char *param, char *val, const char *modname)
+static int unknown_module_param_cb(char *param, char *val, const char *modname,
+                                  void *arg)
 {
        /* Check for magic 'dyndbg' arg */
        int ret = ddebug_dyndbg_module_param_cb(param, val, modname);
@@ -3342,7 +3343,8 @@ static int load_module(struct load_info *info, const char __user *uargs,
 
        /* Module is ready to execute: parsing args may do that. */
        after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
-                                 -32768, 32767, unknown_module_param_cb);
+                                 -32768, 32767, NULL,
+                                 unknown_module_param_cb);
        if (IS_ERR(after_dashes)) {
                err = PTR_ERR(after_dashes);
                goto bug_cleanup;
index a22d6a759b1a9391d5713364097bcfca35f197e7..30288c1e15dd1afe441f7d4dd0cd8f8b288eed28 100644 (file)
@@ -100,8 +100,9 @@ static int parse_one(char *param,
                     unsigned num_params,
                     s16 min_level,
                     s16 max_level,
+                    void *arg,
                     int (*handle_unknown)(char *param, char *val,
-                                    const char *doing))
+                                    const char *doing, void *arg))
 {
        unsigned int i;
        int err;
@@ -128,7 +129,7 @@ static int parse_one(char *param,
 
        if (handle_unknown) {
                pr_debug("doing %s: %s='%s'\n", doing, param, val);
-               return handle_unknown(param, val, doing);
+               return handle_unknown(param, val, doing, arg);
        }
 
        pr_debug("Unknown argument '%s'\n", param);
@@ -194,7 +195,9 @@ char *parse_args(const char *doing,
                 unsigned num,
                 s16 min_level,
                 s16 max_level,
-                int (*unknown)(char *param, char *val, const char *doing))
+                void *arg,
+                int (*unknown)(char *param, char *val,
+                               const char *doing, void *arg))
 {
        char *param, *val;
 
@@ -214,7 +217,7 @@ char *parse_args(const char *doing,
                        return args;
                irq_was_disabled = irqs_disabled();
                ret = parse_one(param, val, doing, params, num,
-                               min_level, max_level, unknown);
+                               min_level, max_level, arg, unknown);
                if (irq_was_disabled && !irqs_disabled())
                        pr_warn("%s: option '%s' enabled irq's!\n",
                                doing, param);
index d8f3d3150603cc0d2abd06e415f0c9a35521e2fa..e491e02eff549fbe8c2e245c3f475b908818938f 100644 (file)
@@ -887,7 +887,7 @@ static int ddebug_dyndbg_param_cb(char *param, char *val,
 
 /* handle both dyndbg and $module.dyndbg params at boot */
 static int ddebug_dyndbg_boot_param_cb(char *param, char *val,
-                               const char *unused)
+                               const char *unused, void *arg)
 {
        vpr_info("%s=\"%s\"\n", param, val);
        return ddebug_dyndbg_param_cb(param, val, NULL, 0);
@@ -1028,7 +1028,7 @@ static int __init dynamic_debug_init(void)
         */
        cmdline = kstrdup(saved_command_line, GFP_KERNEL);
        parse_args("dyndbg params", cmdline, NULL,
-                  0, 0, 0, &ddebug_dyndbg_boot_param_cb);
+                  0, 0, 0, NULL, &ddebug_dyndbg_boot_param_cb);
        kfree(cmdline);
        return 0;