Re: Module versioning (was: Re: OFFTOPIC: binary modules, bad idea!)

Jacques Gelinas (jack@solucorp.qc.ca)
Sat, 20 Dec 1997 12:36:25 -0500 (EST)


On Sat, 20 Dec 1997, Dominik Kubla wrote:

>
> Theodore T'so wrote:
> [...]
> : However, storing the information in a separate ELF section doesn't
> : solve this, unless you actually have GCC generate the hash code.
> : (If you store the hash code in slab.ver, you'd still have the same
> : problem.) In fact, if you have GCC generate the hash code, it'd
> : solve this problem whether the hash code is stored as part of the
> : symbol name, or in a separate ELF section.
> [...]
>
> Hmm, for ELF-based systems, one could try to use ELF symbol versioning
> instead of a hash-code and since that is already part of the current
> binutils it should not be a problem. The question however is if that
> is sufficient for our purposes? Could someone with more understanding
> how module versioning works comment on this?

The major problem with module versionning is not that much related to the
technology (ELF trickery or preprocessor solution with .ver file). The
problem is that genksyms does not know where to stop. This is a kernel
header issue. Let me explain with an example.

---- In the kernel, you have this ---------

foo.h:

struct foo{
int count;
int total;
};

foo.c:

void foo_add (struct foo *p, int val)
{
p->count++;
p->total += val;
}

void foo_reset (struct foo *p)
{
p->count = p->total = 0;
}

---- Then you have one module --------------

mod.c:

void modfoo (struct foo *p)
{
.
.
if (something){
foo_reset (p);
}
.
.
foo_add (p,1);
.
.
}

---------------------------------------------

For mod.c, the exact structure (definition) of struct foo is not
important. It is some sort of "handle". So one can add a third field to
struct foo and recompile the kernel, BUT NOT the module and this will
work.

The linux kernel really works like this. Mostly, you have some code which
maintain a struct and the rest of the kernel use that as an opaque type

genksyms try to compute the proper versionning CRC for function foo_add
and foo_reset. It simply walk the source and compute a CRC based on the
exact definition of struct foo. Any change to struct foo will create a new
CRC for foo_add() and foo_reset()

Now, if one change foo.h like this

foo.h:

#ifndef COMPILING_MODULES

struct foo{
int count;
int total;
};

#endif

This will hide the exact definition of struct foo to genksyms. As such the
CRC won't include it and the functions foo_add() and foo_reset() won't
have a new versionning signature. If one can compile the module with
COMPILING_MODULES defined, this means that the module is really independant
from the exact definition of struct foo, so all this is safe.

Once you have reorganised the kernel header to hide the exact definition
of many kernel internal types and have successfully compile all modules
with this, you are getting

-module with longer life (ie, module compile for kernel x.y.z
work for kernel x.y.z+w)

-The ability to fiddle with makefile dependancies in
a smarter ways, avoiding complete recompile everytime you
touch a header.

This strategy is not that difficult to implement. Many struct in the
kernel are manipulated with inline functions. Although they are
logically "opaque" for modules, this is not really the case for the
compiler. This means that although, at the source code level, one
module never declare or access a struct directly, it nevertheless
do that because of the inline functions. There are two solutions to
this problem.

-drop the inline function when compiling module. In many
case, this won't create any slowdown. We could end up
with a new kernel CONFIG parameter such as
CONFIG_MODULE_LONG_LIVE. A kernel header would look like

#ifdef CONFIG_MODULE_LONG_LIVE
void foo_add();
void foo_reset();
#else
inline void foo_add()
{
.
.
}
inline void foo_reset()
{
.
.
}
#endif

-Make the whole strategy with finer grain, which would yield
some module with more dependancies than others. Currently
insmod has no problem loading module compiled without versionning
into a versionning kernel. So we can end up with some module
compile with versionning and other without. Some will be long
live, some won't.

Until such an issue is addressed, the .ver vs ELF versionning is
mooth.

--------------------------------------------------------
Jacques Gelinas (jacques@solucorp.qc.ca)
Linuxconf: The ultimate administration system for Linux.
see http://www.solucorp.qc.ca/linuxconf
new developments: remote GUI admin, multiple machines admin