Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull module updates from Rusty Russell: "Main excitement here is Peter Zijlstra's lockless rbtree optimization to speed module address lookup. He found some abusers of the module lock doing that too. A little bit of parameter work here too; including Dan Streetman's breaking up the big param mutex so writing a parameter can load another module (yeah, really). Unfortunately that broke the usual suspects, !CONFIG_MODULES and !CONFIG_SYSFS, so those fixes were appended too" * tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: (26 commits) modules: only use mod->param_lock if CONFIG_MODULES param: fix module param locks when !CONFIG_SYSFS. rcu: merge fix for Convert ACCESS_ONCE() to READ_ONCE() and WRITE_ONCE() module: add per-module param_lock module: make perm const params: suppress unused variable error, warn once just in case code changes. modules: clarify CONFIG_MODULE_COMPRESS help, suggest 'N'. kernel/module.c: avoid ifdefs for sig_enforce declaration kernel/workqueue.c: remove ifdefs over wq_power_efficient kernel/params.c: export param_ops_bool_enable_only kernel/params.c: generalize bool_enable_only kernel/module.c: use generic module param operaters for sig_enforce kernel/params: constify struct kernel_param_ops uses sysfs: tightened sysfs permission checks module: Rework module_addr_{min,max} module: Use __module_address() for module_address_lookup() module: Make the mod_tree stuff conditional on PERF_EVENTS || TRACING module: Optimize __module_address() using a latched RB-tree rbtree: Implement generic latch_tree seqlock: Introduce raw_read_seqcount_latch() ...
This commit is contained in:
@@ -67,8 +67,9 @@ enum {
|
||||
|
||||
struct kernel_param {
|
||||
const char *name;
|
||||
struct module *mod;
|
||||
const struct kernel_param_ops *ops;
|
||||
u16 perm;
|
||||
const u16 perm;
|
||||
s8 level;
|
||||
u8 flags;
|
||||
union {
|
||||
@@ -108,7 +109,7 @@ struct kparam_array
|
||||
*
|
||||
* @perm is 0 if the the variable is not to appear in sysfs, or 0444
|
||||
* for world-readable, 0644 for root-writable, etc. Note that if it
|
||||
* is writable, you may need to use kparam_block_sysfs_write() around
|
||||
* is writable, you may need to use kernel_param_lock() around
|
||||
* accesses (esp. charp, which can be kfreed when it changes).
|
||||
*
|
||||
* The @type is simply pasted to refer to a param_ops_##type and a
|
||||
@@ -216,16 +217,16 @@ struct kparam_array
|
||||
parameters. */
|
||||
#define __module_param_call(prefix, name, ops, arg, perm, level, flags) \
|
||||
/* Default value instead of permissions? */ \
|
||||
static const char __param_str_##name[] = prefix #name; \
|
||||
static const char __param_str_##name[] = prefix #name; \
|
||||
static struct kernel_param __moduleparam_const __param_##name \
|
||||
__used \
|
||||
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
|
||||
= { __param_str_##name, ops, VERIFY_OCTAL_PERMISSIONS(perm), \
|
||||
level, flags, { arg } }
|
||||
= { __param_str_##name, THIS_MODULE, ops, \
|
||||
VERIFY_OCTAL_PERMISSIONS(perm), level, flags, { arg } }
|
||||
|
||||
/* Obsolete - use module_param_cb() */
|
||||
#define module_param_call(name, set, get, arg, perm) \
|
||||
static struct kernel_param_ops __param_ops_##name = \
|
||||
static const struct kernel_param_ops __param_ops_##name = \
|
||||
{ .flags = 0, (void *)set, (void *)get }; \
|
||||
__module_param_call(MODULE_PARAM_PREFIX, \
|
||||
name, &__param_ops_##name, arg, \
|
||||
@@ -238,58 +239,14 @@ __check_old_set_param(int (*oldset)(const char *, struct kernel_param *))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* kparam_block_sysfs_write - make sure a parameter isn't written via sysfs.
|
||||
* @name: the name of the parameter
|
||||
*
|
||||
* There's no point blocking write on a paramter that isn't writable via sysfs!
|
||||
*/
|
||||
#define kparam_block_sysfs_write(name) \
|
||||
do { \
|
||||
BUG_ON(!(__param_##name.perm & 0222)); \
|
||||
__kernel_param_lock(); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* kparam_unblock_sysfs_write - allows sysfs to write to a parameter again.
|
||||
* @name: the name of the parameter
|
||||
*/
|
||||
#define kparam_unblock_sysfs_write(name) \
|
||||
do { \
|
||||
BUG_ON(!(__param_##name.perm & 0222)); \
|
||||
__kernel_param_unlock(); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* kparam_block_sysfs_read - make sure a parameter isn't read via sysfs.
|
||||
* @name: the name of the parameter
|
||||
*
|
||||
* This also blocks sysfs writes.
|
||||
*/
|
||||
#define kparam_block_sysfs_read(name) \
|
||||
do { \
|
||||
BUG_ON(!(__param_##name.perm & 0444)); \
|
||||
__kernel_param_lock(); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* kparam_unblock_sysfs_read - allows sysfs to read a parameter again.
|
||||
* @name: the name of the parameter
|
||||
*/
|
||||
#define kparam_unblock_sysfs_read(name) \
|
||||
do { \
|
||||
BUG_ON(!(__param_##name.perm & 0444)); \
|
||||
__kernel_param_unlock(); \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
extern void __kernel_param_lock(void);
|
||||
extern void __kernel_param_unlock(void);
|
||||
extern void kernel_param_lock(struct module *mod);
|
||||
extern void kernel_param_unlock(struct module *mod);
|
||||
#else
|
||||
static inline void __kernel_param_lock(void)
|
||||
static inline void kernel_param_lock(struct module *mod)
|
||||
{
|
||||
}
|
||||
static inline void __kernel_param_unlock(void)
|
||||
static inline void kernel_param_unlock(struct module *mod)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -386,64 +343,70 @@ static inline void destroy_params(const struct kernel_param *params,
|
||||
#define __param_check(name, p, type) \
|
||||
static inline type __always_unused *__check_##name(void) { return(p); }
|
||||
|
||||
extern struct kernel_param_ops param_ops_byte;
|
||||
extern const 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_check_byte(name, p) __param_check(name, p, unsigned char)
|
||||
|
||||
extern struct kernel_param_ops param_ops_short;
|
||||
extern const 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_check_short(name, p) __param_check(name, p, short)
|
||||
|
||||
extern struct kernel_param_ops param_ops_ushort;
|
||||
extern const 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_check_ushort(name, p) __param_check(name, p, unsigned short)
|
||||
|
||||
extern struct kernel_param_ops param_ops_int;
|
||||
extern const 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_check_int(name, p) __param_check(name, p, int)
|
||||
|
||||
extern struct kernel_param_ops param_ops_uint;
|
||||
extern const 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_check_uint(name, p) __param_check(name, p, unsigned int)
|
||||
|
||||
extern struct kernel_param_ops param_ops_long;
|
||||
extern const 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_check_long(name, p) __param_check(name, p, long)
|
||||
|
||||
extern struct kernel_param_ops param_ops_ulong;
|
||||
extern const 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_check_ulong(name, p) __param_check(name, p, unsigned long)
|
||||
|
||||
extern struct kernel_param_ops param_ops_ullong;
|
||||
extern const struct kernel_param_ops param_ops_ullong;
|
||||
extern int param_set_ullong(const char *val, const struct kernel_param *kp);
|
||||
extern int param_get_ullong(char *buffer, const struct kernel_param *kp);
|
||||
#define param_check_ullong(name, p) __param_check(name, p, unsigned long long)
|
||||
|
||||
extern struct kernel_param_ops param_ops_charp;
|
||||
extern const 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_check_charp(name, p) __param_check(name, p, char *)
|
||||
|
||||
/* We used to allow int as well as bool. We're taking that away! */
|
||||
extern struct kernel_param_ops param_ops_bool;
|
||||
extern const 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_check_bool(name, p) __param_check(name, p, bool)
|
||||
|
||||
extern struct kernel_param_ops param_ops_invbool;
|
||||
extern const struct kernel_param_ops param_ops_bool_enable_only;
|
||||
extern int param_set_bool_enable_only(const char *val,
|
||||
const struct kernel_param *kp);
|
||||
/* getter is the same as for the regular bool */
|
||||
#define param_check_bool_enable_only param_check_bool
|
||||
|
||||
extern const 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_check_invbool(name, p) __param_check(name, p, bool)
|
||||
|
||||
/* An int, which can only be set like a bool (though it shows as an int). */
|
||||
extern struct kernel_param_ops param_ops_bint;
|
||||
extern const struct kernel_param_ops param_ops_bint;
|
||||
extern int param_set_bint(const char *val, const struct kernel_param *kp);
|
||||
#define param_get_bint param_get_int
|
||||
#define param_check_bint param_check_int
|
||||
@@ -487,9 +450,9 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp);
|
||||
perm, -1, 0); \
|
||||
__MODULE_PARM_TYPE(name, "array of " #type)
|
||||
|
||||
extern struct kernel_param_ops param_array_ops;
|
||||
extern const struct kernel_param_ops param_array_ops;
|
||||
|
||||
extern struct kernel_param_ops param_ops_string;
|
||||
extern const 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);
|
||||
|
||||
|
Reference in New Issue
Block a user