Some modules claim to have a need to maintain persistent data in the
kernel even when the module is unloaded and reloaded. I can see four
approaches to fixing this problem, there may be others. Note: this
only applies to kernel data, it says nothing about maintaining external
data across reboots.
Comments please.
Options.
(1) Forbid persistent data. "Sorry, the kernel does not support module
data that retains its value across unload/reload".
(2) For every module that needs persistent data and is configured in,
compile some module specific variables into the static kernel and
export them.
(3) Designate persistent variables in the module source, modutils
handles these variable differently when unloading and reloading a
module.
(4) Add a kernel service where a module can register arbitrary data and
find it again during reload.
(5) Any other ideas?
Pros and cons.
(1) Forbid persistent data.
Pro: No change, this is the current position. If this is the
required policy, it must be documented as a restriction on
modules.
Con: Some developers believe that they need persistent kernel data.
(2) Add kernel static variables.
Pro: Easy to code. Just add a small object that only contains the
persistent data for a module. When the module is configured,
compile and the link the persistent data into the kernel.
ifeq ($(CONFIG_FOO),y)
O_OBJS := FOO.o
else
ifeq ($(CONFIG_FOO),m)
OX_OBJS += FOO_persistent.o
M_OBJS += FOO.o
endif
endif
Con: The persistent data is compiled into the static kernel when
the module is configured, even if the module is never loaded.
The persistent variables now have to be exported, even though
only one module uses them.
Source that used to be in a single file is now split.
Changes to Makefiles as well as source.
(3) Designate persistent variables in the module source with modutils
support. Example
static __persistent struct foo *foo_p;
if (!foo_p)
initialize(&foo_p);
Pro: A cleaner solution than splitting the source.
The code source looks the same with or without -DMODULES.
It is similar to the existing methods such as __init code.
No Makefile changes.
Minimal source changes, add one string to each persistent
variable definition.
Persistent data is only allocated when a module is used at
least once instead of always compiled into the kernel.
No unnecessary exports.
Con: Changes to modutils and the module related syscalls with the
backward compatibility problems that introduces (my problem).
ksymoops has to understand __persistent data (my problem).
Some extra overhead in the kernel to maintain the list of
persistent data, each set of persistent data has a header
which defines where the persistent data is, how big it is and
which module it belongs to.
Users have to upgrade to the latest modutils and ksymoops.
(4) Kernel service to register arbitrary data by name.
This idea was pinched from MVS which has exactly the same problem.
The kernel provides a service which takes an arbitrary name and an
associated token and stores that data. The module or any other
module can ask "give me the token for this name" or "update the
token for this name". The name is limited to 16 bytes, an
arbitrary length. The token is fixed at 4*(min(sizeof(void *),
sizeof(long))) bytes which gives enough room for a couple of
pointers and lengths.
The module can store whatever it likes in the token. Small amounts
of data can be stored in the token itself. For larger amounts of
persistent data, the module must kmalloc the larger data and store
its address and length in the token.
Example code to use name tokens.
/* name_token_create() returns 0 if the name does not already exist
* or it exists and the token is zeroes. It returns -EEXIST if the
* token exists and is non-zero. The name_token_xxx routines can
* be called from anywhere, they do not rely on any external locks.
* They could be restricted to non-IRQ contexts, I see no reason
* for an IRQ to call name_token_xxx().
*/
/* Can race with other copies of the code that creates the same
* name, loop until we get a defined result.
*/
while (1) {
memset(&token, 0, sizeof(token));
if ((i = name_token_create(&name, &token)) == 0) {
/* New token, first time in */
old_token = token;
alloc_my_persistent_data();
token.p = my_persistent_data_p;
token.l = sizeof(*my_persistent_data_p);
if (name_token_update(&name, &token, &old_token) == 0)
break; /* Token created and set */
else
dealloc_my_persistent_data(); /* Race, other code updated the token */
}
else if (i != -EEXISTS) {
printk(KERN_ERROR "name_token_create failed %d\n", i);
return(-EBUSY);
}
break; /* token exists and is non-zero */
}
/* token now contains the persistent data for this module */
Pro: No changes to Makefiles, modutils, ksymoops.
Persistent data is only allocated when a module is used at
least once instead of always compiled into the kernel.
No unnecessary exports.
Con: Every module that needs persistent data has to be modified to
call name_token_xxx() and kmalloc its persistent data.
ksymoops can not find kmalloc data so it will not be able to
decode persistent data created using this technique.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sat Jan 15 2000 - 21:00:19 EST