2001-04-05 06:51:08

by Dawson Engler

[permalink] [raw]
Subject: [CHECKER] __init functions called by non-__init

as per a suggestion from Jonathan ([email protected]) I wrote a simple
checker to warn when non-__init functions call __init functions or use
__initdata. Before sending the entire list of "bugs" I want to make
sure they actually are errors rather than bugs in how I understand the
kernel. So, as I understand it, there seem to be two error cases:

1. The best case: an init function calls a non-init, which in
turn calls an init:

void __init probe() { a(); }
void a() { b(); }
void __init b() { ... }

in this case, is the missing __init on 'a' only a performance
bug in that a's code won't be freed up?

2. The worst case: some random post-initialization routine
calls an __init routine which can cause the kernel to go into
hyperspace if the __init routine's code has been deleted.

Are these error cases correct? Are there other interesting, related
__init problems to look for? The doc's I read were a little coy about
specifics.

There were about 43 errors flagged. Most seem to be case 1. An example:

/u2/engler/mc/oses/linux/2.4.1/drivers/scsi/g_NCR5380.c:240:generic_NCR53C400A_setup: ERROR:INIT: non-init fn 'generic_NCR53C400A_setup' calling init fn 'internal_setup'
/u2/engler/mc/oses/linux/2.4.1/drivers/scsi/g_NCR5380.c:253:generic_DTC3181E_setup: ERROR:INIT: non-init fn 'generic_DTC3181E_setup' calling init fn 'internal_setup'


where if you look in the code, the flagged routine generic_NCR53C400A_setup
does indeed not have __init:
void generic_NCR53C400A_setup (char *str, int *ints) {
internal_setup (BOARD_NCR53C400A, str, ints);
}

but a nearby, almost identiical routine does:

void __init generic_NCR53C400_setup (char *str, int *ints){
internal_setup (BOARD_NCR53C400, str, ints);
}

This just seems to be a case where someone forgot to type the __init
in, thereby causing a (small) storage leak.

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

On the other hand, if I understood the rules right, this next one looks like
a more exciting error, since an __exit routine is calling an __init routine:

/u2/engler/mc/oses/linux/2.4.1/drivers/sound/aedsp16.c:1356:cleanup_aedsp16: ERROR:INIT: non-init fn 'cleanup_aedsp16' calling init fn 'uninit_aedsp16'

void __init uninit_aedsp16(void)
{
if (ae_config.mss_base != -1)
uninit_aedsp16_mss();
else
uninit_aedsp16_sb();
if (ae_config.mpu_base != -1)
uninit_aedsp16_mpu();
}


static void __exit cleanup_aedsp16(void) {
uninit_aedsp16();
}
-----------------------------------------------------------------

Any clarifications, etc would be appreciated.

Thanks,
Dawson


2001-04-06 19:29:51

by Rusty Russell

[permalink] [raw]
Subject: Re: [CHECKER] __init functions called by non-__init

In message <[email protected]> you write:
> where if you look in the code, the flagged routine generic_NCR53C400A_setup
> does indeed not have __init:
> void generic_NCR53C400A_setup (char *str, int *ints) {
> internal_setup (BOARD_NCR53C400A, str, ints);
> }

As long as, of course, making that function an __init would not make
it a class 2 error.

> void __init uninit_aedsp16(void)
>
> static void __exit cleanup_aedsp16(void) {
> uninit_aedsp16();
> }

Ick. Currently, this will work, since if it's not a module, __exit
function never get included or called. If it is a module, __init does
nothing.

It's incredibly poor taste, though, and if we ever implement __init
dropping for modules (Keith?), it'll break horribly of course. Thus
it's a bug to call __init functions from __exit functions, but not a
very exciting one.

Rusty.
--
Premature optmztion is rt of all evl. --DK

2001-04-06 19:33:52

by David Miller

[permalink] [raw]
Subject: Re: [CHECKER] __init functions called by non-__init


Rusty Russell writes:
> It's incredibly poor taste, though, and if we ever implement __init
> dropping for modules (Keith?),

Jakub Jelinek implemented this about 2 years ago, right before
we hit 2.2.x, Linus thought it was too late at the time so
we dropped that work from our trees.

It was really good at finding __init bugs though...

Later,
David S. Miller
[email protected]

2001-04-09 20:32:23

by Pavel Machek

[permalink] [raw]
Subject: Re: [CHECKER] __init functions called by non-__init

Hi!

> 1. The best case: an init function calls a non-init, which in
> turn calls an init:
>
> void __init probe() { a(); }
> void a() { b(); }
> void __init b() { ... }

> in this case, is the missing __init on 'a' only a performance
> bug in that a's code won't be freed up?

...not neccesarily an error. If a() is being used to do stuff needed at
runtime, and only calls b() at initialzation.

> On the other hand, if I understood the rules right, this next one looks like
> a more exciting error, since an __exit routine is calling an __init routine:

Actually, it is right for subtle reasons:

__exit is only used in module case. And in module case __init functions are
not freed.
Pavel
--
Philips Velo 1: 1"x4"x8", 300gram, 60, 12MB, 40bogomips, linux, mutt,
details at http://atrey.karlin.mff.cuni.cz/~pavel/velo/index.html.