This is a clearly a execution context problem. To use appropriate locking in kernel code, one needs to be aware in which execution context (hard_irq
| bottom_half
| process_context
) the code gets called.
mutex_lock
| mutex_unlock
are solely for guarding process_context code.
according to http://www.gossamer-threads.com/lists/iptables/devel/56853
discussion, your function hook_func
can be called in sot_irq
or process_context
.
So, you need to use locking mechanism suitable for guarding between these two context.
I suggest you go through kernel-locking guide (https://www.kernel.org/pub/linux/kernel/people/rusty/kernel-locking/). The guide also explains the peculiarities involved when system is SMP (very common) and preemption is on.
for quick test you can use spin_lock_irqsave
lock in your hook_func
. spin_lock_irqsave
is always safe, it disables interrupts on current cpu and spinlock will guarantee atomic operation on SMP system.
Now, word about the crash:
mutex_lock
| mutex_unlock
can only be used in process_context code. When your hook_func
gets called from soft_irq
, mutex_lock
causes current process to sleep and in turn invokes scheduler. Sleeping in kernel code is not allowed in atomic context (here it is soft_irq
).