Exported symbols and the internal API
This article brought to you by LWN subscribersSubscribers to LWN.net made this article — and everything that surrounds it — possible. If you appreciate our content, please buy a subscription and make the next set of articles possible.
Loadable kernel modules do not automatically have access to all symbols (functions and variables) defined in the kernel. In fact, access is limited to those symbols which have been explicitly exported for modular use. The idea behind this whitelist-like policy is that it helps the kernel developers to keep the module interface under control, limiting the ability of modules to dig into parts of the kernel where they are not welcome. The practice turns out to be a little more messy: current kernels have over 16,000 EXPORT_SYMBOL() declarations sprinkled around the source.
Unsurprisingly, there are developers who would like to reduce the number of exported symbols. It is often the case that, once a symbol can be shown to have no users among in-tree modules, it will be removed altogether. But there is not universal agreement on just how this process should be handled; as a result, we see occasional debates on how stable the modular API should actually be and what provisions should be made for out-of-tree code.
Adrian Bunk recently posted a patch to unexport sys_open() and sys_read(). These symbols (which implement the open() and read() system calls) have been on the hit-list for a long time. It is easy to make catastrophic mistakes when using them from kernel space, and there is almost no situation where opening and reading files from within the kernel is considered to be the right thing to do. But removing the exports has always proved hard, until now - there have always been stubborn in-tree users which have kept the export around.
The final holdout in 2.6.23 is the wavefront sound driver which uses sys_open() and sys_read() to obtain firmware to load into the device. The kernel has had a proper API for dealing with firmware loads for years, so no driver should be trying to read firmware directly from files itself. The current ALSA development tree contains a patch for the wavefront driver which makes it use the firmware API; once that patch is merged, there will be no more in-tree users of those symbols. Adrian, forever on the lookout for things to remove from the kernel, noticed this fact and promptly sent in a patch.
Andrew Morton's response went like this:
Andrew would like to have the symbols marked with EXPORT_UNUSED_SYMBOL() for one development cycle so that maintainers of out-of-tree code can get the resulting warning message and fix their code in response. It quickly became clear that he is in a minority among the developers on this issue. Adrian was particularly upset, complaining that other developers are allowed to make no-warning changes which break almost every module in existence while his patch, which affects very few modules, must go through a special process. He says:
Christoph Hellwig also responded strongly, leading to this amusing (but not for the easily offended) exchange. Calmer voices made a few arguments against the warning period:
- These symbols have been on the chopping block for a long time, and
most out-of-tree module authors should have figured that out by now.
It is worth noting, though, that the feature removal schedule in the
kernel documentation says nothing about sys_open() and
sys_read().
- In this sort of situation warnings are almost entirely ineffective. Users
tend not to see them at all, and they do not report them in any case.
According to Alan Cox: "
Short of using their sound card to scream 'Next release you are screwed' they won't notice (and if you the sound card trick they'll think they got rooted....)
" - Keeping unused symbols around bloats the kernel and increases the load on developers who must remember to remove them in a future release.
Andrew does not appear willing to budge on the issue, though. He does not want to unnecessarily upset users who use out-of-tree modules:
Many of these people are non-programmers. So when they download a new kernel and find that the module which they use doesn't work because of something which we've done, they get pissed off, and we lose a tester. This has happened many times.
To avoid this problem, he wants exported symbols targeted for removal to marked with EXPORT_UNUSED_SYMBOL() (or EXPORT_UNUSED_SYMBOL_GPL()) for one development cycle. The exports should be marked with a comment noting when the export should be removed altogether. Each release cycle would include a quick grep to find the symbols which are now due to be removed for real. He concludes:
Elsewhere he has noted that, if a warning is sufficiently widespread,
somebody, somewhere, will act on it. One gets the sense that he has not
convinced a whole lot of developers that this position is right. But
Andrew is in a position to enforce it and most of the others seem to think
that, in the end, it's easier to just go along with what he wants in this
case. The end result is the same, it just takes a little longer.
Index entries for this article | |
---|---|
Kernel | Development model/Loadable modules |
Kernel | Modules/Exported symbols |
Posted Sep 13, 2007 11:23 UTC (Thu)
by jengelh (guest, #33263)
[Link]
s/
Posted Sep 13, 2007 15:28 UTC (Thu)
by dwheeler (guest, #1216)
[Link] (1 responses)
Posted Sep 23, 2007 6:54 UTC (Sun)
by kzm (guest, #47358)
[Link]
-k
Posted Sep 14, 2007 1:41 UTC (Fri)
by vomlehn (guest, #45588)
[Link]
Posted Sep 19, 2007 17:12 UTC (Wed)
by sfink (guest, #6405)
[Link]
Exported symbols and the internal API
EXPORT_MODULE
/EXPORT_SYMBOL
/g;
I _like_ the idea of giving warning before removing something, so I hope that Morton stands firm on this. I don't see the harm in it, and frankly, having a clear way to get rid of things is likely to help get things ON the chopping block that need to be there.Exported symbols and the internal API
..and if the counter argument is that people will just ignore it, make the warning require action by the user. "Warning: module foo uses deprecated functionality, and will break with the next kernel. Press Enter to continue." That'll get you bug reports.Exported symbols and the internal API
I, too, support the idea of giving warning. When people ignore the warning and then complain, you can say, "I told you this was going to happen X months ago". They're still ticked off, but normal people will shut up and learn to pay more attention to those warnings next time. The result, in the long run, is that fewer people are ticked off when they shouldn't be. In my book, that's a good thing.Exported symbols and the internal API
I'd vote for the single-deprecation release approach, too, but for a slightly different reason: if symbols were marked for removal, and a grep listed out all such symbols and got posted somewhere along with the release notes, then when I'm trying to compile a module with version n+8, I have some hope of doing a Google search on the missing symbol and discovering that it was removed in version n+1. I very often encounter problems of this sort, but I can't tell if the symbol is missing because symbol versioning is screwed up again, or because the distribution kernel is too different from the stock kernel, or the module is just borked.Exported symbols and the internal API