I have been eyeballing the code in current sched-devel/latest and there's
something I think I found.
This is the beginning of my enter_uniprocessor() which is called from
enable_mmiotrace() seen in the backtrace.
static void enter_uniprocessor(void)
{
int cpu;
int err;
get_online_cpus();
downed_cpus = cpu_online_map;
cpu_clear(first_cpu(cpu_online_map), downed_cpus);
if (num_online_cpus() > 1)
pr_notice(NAME "Disabling non-boot CPUs...\n");
put_online_cpus();
for_each_cpu_mask(cpu, downed_cpus) {
err = cpu_down(cpu);
The function get_online_cpus() calls might_sleep(), so at that
point everything is fine.
Following the backtrace, we come to alternatives_smp_switch(),
which does
spin_lock(&smp_alt);
and then continues eventually into this function:
void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
{
unsigned long flags;
char *vaddr;
int nr_pages = 2;
BUG_ON(len > sizeof(long));
BUG_ON((((long)addr + len - 1) & ~(sizeof(long) - 1))
- ((long)addr & ~(sizeof(long) - 1)));
if (kernel_text_address((unsigned long)addr)) {
struct page *pages[2] = { virt_to_page(addr),
virt_to_page(addr + PAGE_SIZE) };
if (!pages[1])
nr_pages = 1;
vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
After which we find ourselves in
struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end)
{
return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL);
and in __get_vm_area_node() there is
area = kmalloc_node(sizeof(*area), gfp_mask & GFP_RECLAIM_MASK, node);
where gfp_mask is now GFP_KERNEL. As far as I can tell, using SLAB,
kmalloc_node() here is actually kmalloc(). Anyway, looks like we end up
in __kmalloc with such flags that it may sleep.
I have followed the code so that the path up to kmalloc_node() is
possible, unless there are some "should never happen" conditions
along the way, which I just cannot know of.
Is this the bug?
Thanks.
--
Pekka Paalanen
http://www.iki.fi/pq/
--