LWN.net Logo

Supporting multiple module initialization functions

One longstanding goal in kernel development has been to eliminate the differences between loadable modules and monolithic (linked-in) code. The fewer differences there are, the easier it is to write code which works in either mode - and to maintain that code. In 2.5, this process is almost complete; there is very little code which is unique to either modules or monolithic code.

One remaining difference, however, has to do with initialization and exit code. It is possible to use the module_init() macro to designate an initialization function, and that function will be called properly at module load time or at boot time if the module is built directly into the kernel. (Exit functions for monolithic code are, of course, simply discarded.) One important difference remains, however: monolithic code can have multiple initialization calls, while modules can only have one. Monolithic code initialization calls can even be given priorities (via macros like core_initcall() or late_initcall()) which control when each function is called.

One would think this wouldn't matter a whole lot for loadable modules, since every initialization function would be called at the same time (when the module is loaded) anyway. But this difference forces module and monolithic code to be different. It also prevents the creation of nice, initialization-time macros which ease the process of setting up /proc files or sysfs entries.

With a new patch (since revised) from Rusty Russell, things will change. Rusty notes the real reason why modules can only have a single set of initialization and exit functions: the kernel simply does not know what to do if one of a series of initialization functions fails. In that case, the module load process must fail, and some sort of cleanup must be performed. The problem is knowing what that cleanup is.

The solution is to associate pairs of initialization and exit functions. That is done with a new macro:

    module_init_exit(priority, init_fn, exit_fn);

This call designates a new initialization and exit function pair, and associates a priority with that pair. Each exit function cleans up (only) the work done by its associated initialization function. At module load time, the initialization functions are called in increasing priority order. Should one fail, the exit functions corresponding to the initialization functions that succeeded will be called, in reverse priority order. Thus, a properly-written module should be able to clean up after itself correctly after a failure in any part of the initialization process.

An early version of this patch broke modules using the long-deprecated technique of calling their initialization and exit functions init_module() and cleanup_module(), respectively. That has since been patched up - this stage of the kernel development process is not the time to be making such changes. But the writing is on the wall, and that particular technique is not likely to survive past 2.7.


(Log in to post comments)

Copyright © 2003, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds