0

I have a kernel module. It has one IOCTL which allocates pages and then maps in to the kernel using kmap_atomic one page at a time.

When i run exercise this ioctl through a test app, i get the following scheduling BUG:

    [41216.007065] BUG: scheduling while atomic: app/1242/0x00000002
    [41216.007403] Modules linked in: allocator(O) gpu(O) [last unloaded: gpu]
    [41216.007910] CPU: 0 PID: 1242 Comm: app Tainted: G        W  O    4.10.0-rc5-00111-g49e555a-dirty #22
    [41216.008385] Hardware name: linux,dummy-virt (DT)
    [41216.008667] Call trace:
    [41216.008907] [<ffff000008088ba0>] dump_backtrace+0x0/0x23c
    [41216.009242] [<ffff000008088df0>] show_stack+0x14/0x1c
    [41216.009563] [<ffff000008375efc>] dump_stack+0x94/0xb4
    [41216.010318] [<ffff00000816bcb0>] __schedule_bug+0x58/0x6c
    [41216.010723] [<ffff0000088a9204>] __schedule+0x404/0x574
    [41216.011099] [<ffff0000088a93ac>] schedule+0x38/0x9c
    [41216.011454] [<ffff00000808873c>] do_notify_resume+0x90/0xa0
    [41216.011844] [<ffff000008083618>] work_pending+0x8/0x10

Does anyone know what is causing this? In the kernel, this message is printed in kernel/sched/core.c because the following check is true

    if (unlikely(in_atomic_preempt_off())) {
    __schedule_bug(prev);
    preempt_count_set(PREEMPT_DISABLED);
    }

this check is defined in include/linux/preempt.h

    /*
     * Check whether we were atomic before we did preempt_disable():
     * (used by the scheduler)
     */
    #define in_atomic_preempt_off() (preempt_count() != PREEMPT_DISABLE_OFFSET)

If this makes any sense to any person, please share your perspective.

1 Answers1

1

Between kmap_atomic() and kunmap_atomic it is not permitted to sleep.

From Documentation/vm/highmem.txt:

kmap_atomic(). This permits a very short duration mapping of a single page. Since the mapping is restricted to the CPU that issued it, it performs well, but the issuing task is therefore required to stay on that CPU until it has finished, lest some other task displace its mappings.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153