Bug 8127

Summary: kernel.bbclass logic precludes building out-of-tree modules depending on in-tree modules
Product: [Yocto Project Subprojects] Kernel Reporter: Robert ABEL <abel>
Component: kernel-toolingAssignee: Bruce Ashfield <bruce.ashfield>
Status: VERIFIED FIXED QA Contact: Daniel Istrate <daniel.alexandrux.istrate>
Severity: normal    
Priority: Medium+ CC: abel, awais_belal, bogdanx.a.voiculescu, mhalstead, poky.bs.watcher, poky.watcher, s.mueller-klieser, yp.kernel.watcher, yp.watcher
Version: 2.0.1   
Target Milestone: 2.0.1   
Hardware: All   
OS: Multiple   
Whiteboard:
OS type for building Yocto: --- Type of Regression: ---
Verified: Documentation change: Don't know

Description Robert ABEL 2015-08-07 15:56:29 UTC
This is related to this mailing list thread: http://comments.gmane.org/gmane.linux.embedded.yocto.general/24484

Scenario:

We have an out-of-tree driver module that is built using its own recipe. This module uses functions that are provided by another module, in our case videodev.

We get the following output per function in log.do_compile:
> WARNING: "v4l2_i2c_subdev_init" [/path/to/module.ko] undefined!

Upon modprobe'ing the module, we get the following error once per function:
> Unknown symbol v4l2_i2c_subdev_init (err -22)

Bruce Ashfield originally concluded this was a race condition in kernel.bbclass. While that might have been the case for modules built in-tree, it's not true for modules built out-of-tree.

In kernel.bbclass:
>addtask shared_workdir after do_compile before do_compile_kernelmodules

kernel.bbclass's do_shared_workdir copies Module.symvers from ${B} to ${STAGING_KERNEL_BUILDDIR} before do_compile_kernelmodules is run.
Thus, any symbols exported by in-tree kernel modules are simply included in ${STAGING_KERNEL_BUILDDIR}/Module.symvers.

This would require collecting and merging all Module.symvers fragments up the dependency chain for such a module recipe.

do_compile_kernelmodules runs in ${B} anyway, hence in-tree modules linked against in-tree modules compile fine.

It's not really clear to me what the purpose of running do_shared_workdir before do_compile_kernelmodules is. It doesn't seem like do_compile_kernelmodules needs work-shared at all.

My preliminary testing showed no ill effects for me when changing the offending line to
>addtask shared_workdir after do_compile after do_compile_kernelmodules before do_install

This solution obviously still precludes linking out-of-tree modules against other out-of-tree modules. But I'm not sure that this would even have been possible in pre-fido times.
Comment 1 Richard Purdie 2015-08-09 23:24:19 UTC
(In reply to comment #0)
> It's not really clear to me what the purpose of running do_shared_workdir
> before do_compile_kernelmodules is. It doesn't seem like
> do_compile_kernelmodules needs work-shared at all.

Its more that do_shared_workdir shouldn't really need compile_kernelmodules, except that you've just proved that in fact it does.

do_shared_workdir can be thought of as a "make the kernel source code available" task buts its turning into a "make all the generated objects available" too :(.

> My preliminary testing showed no ill effects for me when changing the
> offending line to
> >addtask shared_workdir after do_compile after do_compile_kernelmodules before do_install
> 
> This solution obviously still precludes linking out-of-tree modules against
> other out-of-tree modules. But I'm not sure that this would even have been
> possible in pre-fido times.

The bigger issue here is that we tried changing things so that we don't have large tarballs of the kernel source in sstate. This means the kernel always extracts from source rather than being populated from sstate.

With your change, the downside is that if you try building a new kernel module in a clean tmpdir, the code will now not only recompile the kernel but all the kernel modules too. There are some simpler workloads (e.g. building perf) where we don't really want this compile overhead, let alone the module compile overhead, just to have kernel source available.

Clearly something needs more thought here although I'm struggling to think exactly how we can fix this in a way which doesn’t kill performance for everyone.
Comment 2 Bruce Ashfield 2015-08-11 04:23:24 UTC
(In reply to comment #1)
> (In reply to comment #0)
> > It's not really clear to me what the purpose of running do_shared_workdir
> > before do_compile_kernelmodules is. It doesn't seem like
> > do_compile_kernelmodules needs work-shared at all.
> 
> Its more that do_shared_workdir shouldn't really need compile_kernelmodules,
> except that you've just proved that in fact it does.
> 
> do_shared_workdir can be thought of as a "make the kernel source code
> available" task buts its turning into a "make all the generated objects
> available" too :(.
> 
> > My preliminary testing showed no ill effects for me when changing the
> > offending line to
> > >addtask shared_workdir after do_compile after do_compile_kernelmodules before do_install
> > 
> > This solution obviously still precludes linking out-of-tree modules against
> > other out-of-tree modules. But I'm not sure that this would even have been
> > possible in pre-fido times.
> 
> The bigger issue here is that we tried changing things so that we don't have
> large tarballs of the kernel source in sstate. This means the kernel always
> extracts from source rather than being populated from sstate.
> 
> With your change, the downside is that if you try building a new kernel
> module in a clean tmpdir, the code will now not only recompile the kernel
> but all the kernel modules too. There are some simpler workloads (e.g.
> building perf) where we don't really want this compile overhead, let alone
> the module compile overhead, just to have kernel source available.
> 

That was my first thought as well. We really didn't want to wait through
a kernel + modules build to have the shared workdir available.


> Clearly something needs more thought here although I'm struggling to think
> exactly how we can fix this in a way which doesn’t kill performance for
> everyone.

I know we considered (and proposed a patch, but due to locking/race
concerns it didn't merge) simply adding a second copy of the symbols
after the modules built. That is what we've been doing internally, and
nothing has blown up yet.

In a scenario like that, an external module could depend on 
do_compile_kernelmodules, take the overhead and then get the updated copy.

But as we said before, we need to make sure that nothing is actively
accessing the existing symbols (tar, etc) or we'll start getting all
sorts of failures.

Is there a lock file we can use to make sure that a task can get 
exclusive access to the shared dir ?
Comment 3 Bruce Ashfield 2015-08-21 13:54:28 UTC
Finally getting to this after clearing my backlog. Moving
the state to "in design".
Comment 4 Awais 2015-12-02 11:06:56 UTC
Hi,
Is there an update on this?
Comment 5 Bruce Ashfield 2015-12-02 13:18:44 UTC
(In reply to comment #4)
> Hi,
> Is there an update on this?

A patch was proposed in November on the mailing list (not
by me) to mitigate the issue while development proceeds with
this larger feature.
Comment 6 Awais 2015-12-02 13:56:35 UTC
I do not know which kernel this is being tested on. But on one of the BSPs I am looking at I use the 3.14 kernel which exhibited the same sort of behavior and using a patch from the mainline kernel fixed the issue for me.
http://www.spinics.net/lists/linux-kbuild/msg09204.html
Comment 7 Bruce Ashfield 2015-12-02 16:24:54 UTC
(In reply to comment #6)
> I do not know which kernel this is being tested on. But on one of the BSPs I
> am looking at I use the 3.14 kernel which exhibited the same sort of
> behavior and using a patch from the mainline kernel fixed the issue for me.
> http://www.spinics.net/lists/linux-kbuild/msg09204.html

In our case, the fix is build system related (and with the placement
of the symbols file after kernel modules have been built), versus
a problem specific to the kernel, or the kernel build.
Comment 8 Bruce Ashfield 2016-01-08 16:10:25 UTC
Marking this case as resolved, since this was merged.

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

commit a9cc27e6916e5affe8b0cc431c3e89abd7681643
Author: Jens Rehsack <rehsack@gmail.com>
Date:   Thu Nov 12 17:13:15 2015 +0100

    kernel: fix race condition between compile_kernelmodules and shared_workdir
    
    Fixes https://bugzilla.yoctoproject.org/show_bug.cgi?id=8127 which causes
    [ 1225.089323] 8189es: Unknown symbol cfg80211_scan_done (err -22)
    [ 1225.095916] 8189es: no symbol version for cfg80211_remain_on_channel_expired
    when loading external compiled 8189es module.
    
    (From OE-Core rev: afcea61e8eb39234d336c706fdfd4680dea7c060)
    
    Signed-off-by: Jens Rehsack <sno@netbsd.org>
    Signed-off-by: Ross Burton <ross.burton@intel.com>
    Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>

:100644 100644 5e8b6cf34318... b75a4621807a... M        meta/classes/kernel.bbclass

---------

This introduces a longer build time for things like perf, but was the accepted short term solution.

If we want to fix the build time issues for perf, we can re-work the dependency in another bugzilla.
Comment 9 Daniel Istrate 2016-01-22 13:23:59 UTC
Marking this as verified since no one complained after the fix was merged.