-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
per_cpu() does not work for external module percpu variables #185
Comments
I've run into this before but haven't gotten around to fixing it. I think that the correct way to fix this is to apply ELF relocations to the Unfortunately, neither approach finds the address of As you pointed out, we can get the "address" of The downside of this fix is that we can no longer use the sysfs-based fast path for the live kernel. The Correctness should of course take priority over performance here, but I was hoping to come up with some way to avoid this performance hit and hence kept this on the backburner. |
Thanks for the detailed explanation, and I share your disappointment. Is there a way to make this work at runtime, only when a module percpu variable is accessed? For instance, when the object finder loads a symbol that is located in the I don't know if that's even feasible since I don't really know the code well. Unfortunately I won't be able to test your module-percpu-hack branch for a while, since I a trip of my own recently, and left my vmcores on my work laptop :) Thankfully the folks impacted on my team have the above |
So I revisited this, and I found that my initial analysis was incorrect -- the extra overhead from disabling the |
According to my test case, I fixed this, but please re-open it if you test it and it doesn't fix this for you. |
Thanks for doing this - I read through the commits and it makes sense but it's unfortunate to lose the /proc/modules fast path. But reading the whole struct module at once is a nice optimization :) I'll verify this fix momentarily on a similar vmcore, but it looks right to me too. |
For external kernel modules, it seems that percpu variables have their indices starting from zero. When they are loaded, the percpu memory is allocated, and the symbol addresses are adjusted based on the allocated percpu area (see
simplify_symbols()
inkernel/module/main.c
). Surprisingly, this patch from 2003 is simple and mostly still revelant enough to show how it works.This means that the
per_cpu()
helper is broken for module percpu variables. For example, seerds_stats
innet/rds/stats.c
, assuming it's built as a module.The
per_cpu()
helper happily uses offset=0 and reads out the wrong value. In reality, the module's percpu allocation is stored in thepercpu
field ofstruct module
, and you need to add the address for the module's percpu variables to that offset. Thus, with the following two helper functions, it's fixed:We can do the following, and I verified the computation compared to crash:
I don't think that's the right approach though, since we shouldn't need to know whether something was built as a module or not. Maybe we need to adjust the symbol lookup routines for modules, so that they fixup the percpu variable addresses at load time, or as they're looked up?
The text was updated successfully, but these errors were encountered: