The original issue,
https://lore.kernel.org/netdev/[email protected]/
The debugging so far seems point to that the compilers get confused by the
module sections. During module_param(), it stores “__param_rx_frag_size"
as a “struct kernel_param” into the __param section. Later, load_module()
obtains all “kernel_param” from the __param section and compare against the
user-input module parameters from the command-line. If there is a match, it
calls params[i].ops->set(¶ms[I]) to replace the value. If compilers can’t
see that params[i].ops->set(¶ms[I]) could potentially change the value
of rx_frag_size, it will wrongly optimize it as a constant.
For example (it is not
compilable yet as I have not able to extract variable from the __param section
like find_module_sections()),
#include <stdio.h>
#include <string.h>
#define __module_param_call(name, ops, arg) \
static struct kernel_param __param_##name \
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void
*)))) = { \
#name, ops, { arg } }
struct kernel_param {
const char *name;
const struct kernel_param_ops *ops;
union {
int *arg;
};
};
struct kernel_param_ops {
int (*set)(const struct kernel_param *kp);
};
#define STANDARD_PARAM_DEF(name) \
int param_set_##name(const struct kernel_param *kp) \
{ \
*kp->arg = 2; \
} \
const struct kernel_param_ops param_ops_##name = { \
.set = param_set_##name, \
};
STANDARD_PARAM_DEF(ushort);
static int rx = 1;
__module_param_call(rx_frag_siz, ¶m_ops_ushort, &rx_frag_size);
int main(int argc, char *argv[])
{
const struct kernel_param *params = <<< Get all kernel_param from the
__param section >>>;
int i;
if (__builtin_constant_p(rx_frag_size))
printf("rx_frag_size is a const.\n");
for (i = 0; i < num_param; i++) {
if (!strcmp(params[I].name, argv[1])) {
params[i].ops->set(¶ms[i]);
break;
}
}
printf("rx_frag_size = %d\n", rx_frag_size);
return 0;
}