Re: [PATCH 2/8] param: use ops in struct kernel_param, rather than get and set fns directly

From: Takashi Iwai
Date: Mon Nov 16 2009 - 10:50:24 EST


At Fri, 30 Oct 2009 21:43:39 +1030,
Rusty Russell wrote:
>
> On Fri, 30 Oct 2009 08:48:12 pm Takashi Iwai wrote:
> > At Fri, 23 Oct 2009 00:51:28 +1030,
> > Rusty Russell wrote:
> > >
> > > This is more kernel-ish, saves some space, and also allows us to
> > > expand the ops without breaking all the callers who are happy for the
> > > new members to be NULL.
> > >
> > > The few places which defined their own param types are changed to the
> > > new scheme.
> > >
> > > Since we're touching them anyway, we change get and set to take a
> > > const struct kernel_param (which they were, and will be again).
> > >
> > > To reduce churn, module_param_call creates the ops struct so the callers
> > > don't have to change (and casts the functions to reduce warnings).
> > > The modern version which takes an ops struct is called module_param_cb.
> >
> > This is nice, as it also reduces the size of struct kernel_param, so
> > each parameter uses less footprint (who cares, though?) :)
> >
> > But, just wondering whether we still need to export get/set
> > functions. They can be called from ops now, so if any, it can be
> > defined even as an inlinefunction or a macro.
>
> My thought too, so I tried that, but many are still used like so:
>
> module_param_call(foo, set_foo, param_get_uint, NULL, 0644);
>
> They can all be replaced in time with something like:
> static int param_get_foo(char *buffer, const struct kernel_param *kp)
> {
> return param_ops_uint.get(buffer, kp);
> }
>
> But it'll take a transition period.

[Removed Cc's since it's no sub-device specific issue]

Regarding the removal of exports:

I found that static inline functions can be used also as pointers.
So, expanding them in moduleparam.h seems working actually as is.

A test patch is below. I just did a short build-test, though.


thanks,

Takashi

===
From: Takashi Iwai <tiwai@xxxxxxx>
Subject: param: use static inline functions for param_{get|set}_*()

Instead of exporting each param_{get|set}_*() function, expand it as
a static inline function to call the ops.{get|set}. Since static inline
functions can be used as function pointers, the currently existing codes
work as they are.

Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>

---
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 893549c..00baae9 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -283,50 +283,53 @@ static inline void destroy_params(const struct kernel_param *params,
#define __param_check(name, p, type) \
static inline type *__check_##name(void) { return(p); }

+/* Define param_get_xxx() and param_set_xxx() for compatibility.
+ * They are defined as inline functions so that they can be used also
+ * as function pointers.
+ */
+#define DEFINE_PARAM_GET_SET(name) \
+ static inline int param_set_##name(const char *val, \
+ const struct kernel_param *kp) \
+ { return param_ops_##name.set(val, kp); } \
+ static inline int param_get_##name(char *buffer, \
+ const struct kernel_param *kp) \
+ { return param_ops_##name.get(buffer, kp); }
+
extern struct kernel_param_ops param_ops_byte;
-extern int param_set_byte(const char *val, const struct kernel_param *kp);
-extern int param_get_byte(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(byte);
#define param_check_byte(name, p) __param_check(name, p, unsigned char)

extern struct kernel_param_ops param_ops_short;
-extern int param_set_short(const char *val, const struct kernel_param *kp);
-extern int param_get_short(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(short);
#define param_check_short(name, p) __param_check(name, p, short)

extern struct kernel_param_ops param_ops_ushort;
-extern int param_set_ushort(const char *val, const struct kernel_param *kp);
-extern int param_get_ushort(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(ushort);
#define param_check_ushort(name, p) __param_check(name, p, unsigned short)

extern struct kernel_param_ops param_ops_int;
-extern int param_set_int(const char *val, const struct kernel_param *kp);
-extern int param_get_int(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(int);
#define param_check_int(name, p) __param_check(name, p, int)

extern struct kernel_param_ops param_ops_uint;
-extern int param_set_uint(const char *val, const struct kernel_param *kp);
-extern int param_get_uint(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(uint);
#define param_check_uint(name, p) __param_check(name, p, unsigned int)

extern struct kernel_param_ops param_ops_long;
-extern int param_set_long(const char *val, const struct kernel_param *kp);
-extern int param_get_long(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(long);
#define param_check_long(name, p) __param_check(name, p, long)

extern struct kernel_param_ops param_ops_ulong;
-extern int param_set_ulong(const char *val, const struct kernel_param *kp);
-extern int param_get_ulong(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(ulong);
#define param_check_ulong(name, p) __param_check(name, p, unsigned long)

extern struct kernel_param_ops param_ops_charp;
-extern int param_set_charp(const char *val, const struct kernel_param *kp);
-extern int param_get_charp(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(charp);
#define param_check_charp(name, p) __param_check(name, p, char *)

/* For historical reasons "bool" parameters can be (unsigned) "int". */
extern struct kernel_param_ops param_ops_bool;
-extern int param_set_bool(const char *val, const struct kernel_param *kp);
-extern int param_get_bool(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(bool);
#define param_check_bool(name, p) \
static inline void __check_##name(void) \
{ \
@@ -336,8 +339,7 @@ extern int param_get_bool(char *buffer, const struct kernel_param *kp);
}

extern struct kernel_param_ops param_ops_invbool;
-extern int param_set_invbool(const char *val, const struct kernel_param *kp);
-extern int param_get_invbool(char *buffer, const struct kernel_param *kp);
+DEFINE_PARAM_GET_SET(invbool);
#define param_check_invbool(name, p) __param_check(name, p, bool)

/**
@@ -380,8 +382,15 @@ extern int param_get_invbool(char *buffer, const struct kernel_param *kp);
extern struct kernel_param_ops param_array_ops;

extern struct kernel_param_ops param_ops_string;
-extern int param_set_copystring(const char *val, const struct kernel_param *);
-extern int param_get_string(char *buffer, const struct kernel_param *kp);
+static inline int param_set_copystring(const char *val,
+ const struct kernel_param *kp)
+{
+ return param_ops_string.set(val, kp);
+}
+static inline int param_get_string(char *buffer, const struct kernel_param *kp)
+{
+ return param_ops_string.get(buffer, kp);
+}

/* for exporting parameters in /sys/parameters */

diff --git a/kernel/params.c b/kernel/params.c
index 9ed6fcd..12513f1 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -219,7 +219,7 @@ int parse_args(const char *name,

/* Lazy bastard, eh? */
#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
- int param_set_##name(const char *val, const struct kernel_param *kp) \
+ static int _param_set_##name(const char *val, const struct kernel_param *kp) \
{ \
tmptype l; \
int ret; \
@@ -231,16 +231,14 @@ int parse_args(const char *name,
*((type *)kp->arg) = l; \
return 0; \
} \
- int param_get_##name(char *buffer, const struct kernel_param *kp) \
+ static int _param_get_##name(char *buffer, const struct kernel_param *kp) \
{ \
return sprintf(buffer, format, *((type *)kp->arg)); \
} \
struct kernel_param_ops param_ops_##name = { \
- .set = param_set_##name, \
- .get = param_get_##name, \
+ .set = _param_set_##name, \
+ .get = _param_get_##name, \
}; \
- EXPORT_SYMBOL(param_set_##name); \
- EXPORT_SYMBOL(param_get_##name); \
EXPORT_SYMBOL(param_ops_##name)


@@ -252,7 +250,7 @@ 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);

-int param_set_charp(const char *val, const struct kernel_param *kp)
+static int _param_set_charp(const char *val, const struct kernel_param *kp)
{
if (!val) {
printk(KERN_ERR "%s: string parameter expected\n",
@@ -280,13 +278,11 @@ int param_set_charp(const char *val, const struct kernel_param *kp)

return 0;
}
-EXPORT_SYMBOL(param_set_charp);

-int param_get_charp(char *buffer, const struct kernel_param *kp)
+static int _param_get_charp(char *buffer, const struct kernel_param *kp)
{
return sprintf(buffer, "%s", *((char **)kp->arg));
}
-EXPORT_SYMBOL(param_get_charp);

static void param_free_charp(void *arg)
{
@@ -294,14 +290,14 @@ static void param_free_charp(void *arg)
}

struct kernel_param_ops param_ops_charp = {
- .set = param_set_charp,
- .get = param_get_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)
+static int _param_set_bool(const char *val, const struct kernel_param *kp)
{
bool v;

@@ -326,9 +322,8 @@ int param_set_bool(const char *val, const struct kernel_param *kp)
*(int *)kp->arg = v;
return 0;
}
-EXPORT_SYMBOL(param_set_bool);

-int param_get_bool(char *buffer, const struct kernel_param *kp)
+static int _param_get_bool(char *buffer, const struct kernel_param *kp)
{
bool val;
if (kp->flags & KPARAM_ISBOOL)
@@ -339,16 +334,15 @@ 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", val ? 'Y' : 'N');
}
-EXPORT_SYMBOL(param_get_bool);

struct kernel_param_ops param_ops_bool = {
- .set = param_set_bool,
- .get = param_get_bool,
+ .set = _param_set_bool,
+ .get = _param_get_bool,
};
EXPORT_SYMBOL(param_ops_bool);

/* This one must be bool. */
-int param_set_invbool(const char *val, const struct kernel_param *kp)
+static int _param_set_invbool(const char *val, const struct kernel_param *kp)
{
int ret;
bool boolval;
@@ -356,22 +350,20 @@ int param_set_invbool(const char *val, const struct kernel_param *kp)

dummy.arg = &boolval;
dummy.flags = KPARAM_ISBOOL;
- ret = param_set_bool(val, &dummy);
+ ret = _param_set_bool(val, &dummy);
if (ret == 0)
*(bool *)kp->arg = !boolval;
return ret;
}
-EXPORT_SYMBOL(param_set_invbool);

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

struct kernel_param_ops param_ops_invbool = {
- .set = param_set_invbool,
- .get = param_get_invbool,
+ .set = _param_set_invbool,
+ .get = _param_get_invbool,
};
EXPORT_SYMBOL(param_ops_invbool);

@@ -480,7 +472,7 @@ struct kernel_param_ops param_array_ops = {
};
EXPORT_SYMBOL(param_array_ops);

-int param_set_copystring(const char *val, const struct kernel_param *kp)
+static int _param_set_string(const char *val, const struct kernel_param *kp)
{
const struct kparam_string *kps = kp->str;

@@ -496,18 +488,16 @@ int param_set_copystring(const char *val, const struct kernel_param *kp)
strcpy(kps->string, val);
return 0;
}
-EXPORT_SYMBOL(param_set_copystring);

-int param_get_string(char *buffer, const struct kernel_param *kp)
+static int _param_get_string(char *buffer, const struct kernel_param *kp)
{
const struct kparam_string *kps = kp->str;
return strlcpy(buffer, kps->string, kps->maxlen);
}
-EXPORT_SYMBOL(param_get_string);

struct kernel_param_ops param_ops_string = {
- .set = param_set_copystring,
- .get = param_get_string,
+ .set = _param_set_string,
+ .get = _param_get_string,
};
EXPORT_SYMBOL(param_ops_string);

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/