jprobes for 'enqueue_entity' and 'dequeue_entity' causes kernel hang on spinlock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I have to log when a process gets in/out of the runqueue. For the same
I took the jprobes example code from Documentation/kprobes.txt and
modified it to probe enqueue_entity() and dequeue_entity() . When I
insmod my module the kernel hangs. On running with a remote gdb I
could figure out that it is spinning on a spinlock.

I have used printks in my module code.  It is interesting to note that
wake_up_klogd() is being called twice in this chain and I think it is
causing the trouble, as it is spinning on a lock which it has already
locked earlier.  Is my analysis right ?  Am I doing anything wrong
here ?


#0  0xc04180fa in __ticket_spin_lock (lock=0xc0740ea4) at
include/asm/spinlock.h:75
#1  0xc0639667 in _spin_lock_irqsave (lock=0x1e1d) at
include/asm/paravirt.h:1401
#2  0xc041dfc3 in __wake_up (q=0xc0740ea4, mode=7709, nr_exclusive=1,
key=0x0) at kernel/sched.c:4585
#3  0xc0429eb5 in wake_up_klogd () at kernel/printk.c:988
#4  0xc042a03d in release_console_sem () at kernel/printk.c:1036
#5  0xc042a49e in vprintk (fmt=0xe0a370d0 "<6>probe[enqueue_entity]:
[pid:%u]\n", args=0xde98edd4 "\215\006") at kernel/printk.c:771
#6  0xc063762d in printk (fmt=0xe0a370d0 "<6>probe[enqueue_entity]:
[pid:%u]\n") at kernel/printk.c:604
#7  0xe0a37041 in ?? ()
#8  0xc042041a in enqueue_task_fair (rq=0xc140a580, p=<value optimized
out>, wakeup=1) at kernel/sched_fair.c:928
#9  0xc041c540 in enqueue_task (rq=0xc140a580, p=0xdecb8000, wakeup=1)
at kernel/sched.c:1644
#10 0xc041c67d in activate_task (rq=0xc140a580, p=0x1e1d, wakeup=1) at
kernel/sched.c:1715
#11 0xc0424133 in try_to_wake_up (p=0xdecb8000, state=1, sync=0) at
kernel/sched.c:2281
#12 0xc04241bc in default_wake_function (curr=<value optimized out>,
mode=7709, sync=1, key=0x0) at kernel/sched.c:4546
#13 0xc043a1ea in autoremove_wake_function (wait=0xc0740ea4,
mode=7709, sync=1, key=0x0) at kernel/wait.c:132
#14 0xc041cb30 in __wake_up_common (q=<value optimized out>, mode=1,
nr_exclusive=1, sync=0, key=0x0) at kernel/sched.c:4567
#15 0xc041dfd6 in __wake_up (q=0xc0740ea4, mode=1, nr_exclusive=1,
key=0x0) at kernel/sched.c:4586
#16 0xc0429eb5 in wake_up_klogd () at kernel/printk.c:988
#17 0xc042a03d in release_console_sem () at kernel/printk.c:1036
#18 0xc042a49e in vprintk (fmt=0xe0a3712d "<6>Planted jprobe at %p,
handler addr %p\n", args=0xde98ef3c "�\001B�%p����\230�%\021@�")
    at kernel/printk.c:771
#19 0xc063762d in printk (fmt=0xe0a3712d "<6>Planted jprobe at %p,
handler addr %p\n") at kernel/printk.c:604
#20 0xe089802f in ?? ()
#21 0xc0401125 in do_one_initcall (fn=0xe0898000) at init/main.c:715
#22 0xc0449167 in sys_init_module (umod=0x9e2c018, len=94352,
uargs=0x9e2c008 "") at kernel/module.c:2291
#23 <signal handler called>
#24 0xb7f66424 in ?? ()
#25 0x00a595d6 in ?? ()
#26 0x08048631 in ?? ()


My code:
-----------
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/sched.h>

/* An entity is a task if it doesn't "own" a runqueue */
#define entity_is_task(se)	(!se->my_q)

static inline struct task_struct *task_of(struct sched_entity *se)
{
	return container_of(se, struct task_struct, se);
}

static void j_enqueue_entity(struct cfs_rq *cfs_rq, struct
sched_entity *se, int wakeup)
{
	if (entity_is_task(se)) {
			struct task_struct *tsk = task_of(se);
			printk(KERN_INFO "probe[enqueue_entity]: [pid:%u]\n", tsk->pid);
	}
	/* Always end with a call to jprobe_return(). */
	jprobe_return();
}

static struct jprobe enqueue_entity_jprobe = {
	.entry			= j_enqueue_entity,
	.kp = {
		.symbol_name	= "enqueue_entity",
	},
};

static void j_dequeue_entity(struct cfs_rq *cfs_rq, struct
sched_entity *se, int sleep)
{
	if (entity_is_task(se)) {
			struct task_struct *tsk = task_of(se);
			printk(KERN_INFO "probe[dequeue_entity]: [pid:%u]\n", tsk->pid);
	}
	/* Always end with a call to jprobe_return(). */
	jprobe_return();
}

static struct jprobe dequeue_entity_jprobe = {
	.entry			= j_dequeue_entity,
	.kp = {
		.symbol_name	= "dequeue_entity",
	},
};

static int __init jprobe_init(void)
{
	int ret;

	ret = register_jprobe(&enqueue_entity_jprobe);
	if (ret < 0) {
		printk(KERN_INFO "register_jprobe [enqueue_entity] failed, returned
%d\n", ret);
		return -1;
	}
	printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
	       enqueue_entity_jprobe.kp.addr, enqueue_entity_jprobe.entry);

	ret = register_jprobe(&dequeue_entity_jprobe);
	if (ret < 0) {
		printk(KERN_INFO "register_jprobe [dequeue_entity] failed, returned
%d\n", ret);
		return -1;
	}
	printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
	       dequeue_entity_jprobe.kp.addr, dequeue_entity_jprobe.entry);
	return 0;
}

static void __exit jprobe_exit(void)
{
	unregister_jprobe(&enqueue_entity_jprobe);
	unregister_jprobe(&dequeue_entity_jprobe);
	printk(KERN_INFO "jprobe unregistered\n");
}

module_init(jprobe_init)
module_exit(jprobe_exit)
MODULE_LICENSE("GPL");





-- 
Regards,
Sukanto Ghosh

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux