3 * Lunix Trace Toolkit Kernel State Dump
6 * Jean-Hugues Deschenes <jean-hugues.deschenes@polymtl.ca>
9 * Eric Clement: add listing of network IP interface
12 #include <linux/config.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/ltt-core.h>
16 #include <linux/netlink.h>
17 #include <linux/inet.h>
19 #include <linux/kthread.h>
20 #include <linux/proc_fs.h>
21 #include <linux/file.h>
22 #include <linux/interrupt.h>
23 #include <linux/irq.h>
24 #include <linux/cpu.h>
25 #include <linux/ltt/ltt-facility-statedump.h>
27 #define NB_PROC_CHUNK 20
29 #include <linux/netdevice.h>
30 #include <linux/inetdevice.h>
33 extern int ltt_enumerate_modules(void);
35 static inline int ltt_enumerate_network_ip_interface(void)
37 struct net_device
*list
;
38 struct in_device
*in_dev
= NULL
;
39 struct in_ifaddr
*ifa
= NULL
;
41 read_lock(&dev_base_lock
);
42 for(list
=dev_base
; list
!= NULL
; list
=list
->next
) {
44 if(list
->flags
& IFF_UP
) {
45 in_dev
= in_dev_get(list
);
48 for (ifa
= in_dev
->ifa_list
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
49 trace_statedump_enumerate_network_ip_interface(list
->name
,
56 trace_statedump_enumerate_network_ip_interface(list
->name
,
61 read_unlock(&dev_base_lock
);
66 static inline int ltt_enumerate_file_descriptors(void)
68 struct task_struct
* t
= &init_task
;
71 char *tmp
= (char*)__get_free_page(GFP_KERNEL
), *path
;
74 /* Enumerate active file descriptors */
77 read_lock(&tasklist_lock
);
78 if(t
!= &init_task
) atomic_dec(&t
->usage
);
80 atomic_inc(&t
->usage
);
81 read_unlock(&tasklist_lock
);
85 spin_lock(&t
->files
->file_lock
);
86 fdt
= files_fdtable(t
->files
);
87 for (i
=0; i
< fdt
->max_fds
; i
++) {
88 filp
= fcheck_files(t
->files
, i
);
91 path
= d_path(filp
->f_dentry
, filp
->f_vfsmnt
, tmp
, PAGE_SIZE
);
93 /* Make sure we give at least some info */
95 trace_statedump_enumerate_file_descriptors(filp
->f_dentry
->d_name
.name
, t
->pid
, i
);
97 trace_statedump_enumerate_file_descriptors(path
, t
->pid
, i
);
99 spin_unlock(&t
->files
->file_lock
);
103 } while( t
!= &init_task
);
105 free_page((unsigned long)tmp
);
110 static inline int ltt_enumerate_vm_maps(void)
112 struct mm_struct
*mm
;
113 struct task_struct
* t
= &init_task
;
114 struct vm_area_struct
* map
;
115 unsigned long ino
= 0;
118 read_lock(&tasklist_lock
);
119 if(t
!= &init_task
) atomic_dec(&t
->usage
);
121 atomic_inc(&t
->usage
);
122 read_unlock(&tasklist_lock
);
124 /* get_task_mm does a task_lock... */
134 down_read(&mm
->mmap_sem
);
138 ino
= map
->vm_file
->f_dentry
->d_inode
->i_ino
;
143 trace_statedump_enumerate_vm_maps(t
->pid
, (void *)map
->vm_start
, (void *)map
->vm_end
, map
->vm_flags
, map
->vm_pgoff
<< PAGE_SHIFT
, ino
);
147 up_read(&mm
->mmap_sem
);
153 } while( t
!= &init_task
);
158 #if defined( CONFIG_ARM )
159 /* defined in arch/arm/kernel/irq.c because of dependency on statically-defined lock & irq_desc */
160 int ltt_enumerate_interrupts(void);
162 static inline int ltt_enumerate_interrupts(void)
165 unsigned long flags
= 0;
169 for(i
= 0; i
< NR_IRQS
; i
++)
171 struct irqaction
* action
;
173 spin_lock_irqsave(&irq_desc
[i
].lock
, flags
);
176 for (action
=irq_desc
[i
].action
; action
; action
= action
->next
)
177 trace_statedump_enumerate_interrupts(
178 irq_desc
[i
].handler
->typename
,
182 spin_unlock_irqrestore(&irq_desc
[i
].lock
, flags
);
189 static inline int ltt_enumerate_process_states(void)
191 struct task_struct
* t
= &init_task
;
192 struct task_struct
* p
= t
;
193 enum lttng_process_status status
;
194 enum lttng_thread_type type
;
195 enum lttng_execution_mode mode
;
196 enum lttng_execution_submode submode
;
199 mode
= LTTNG_MODE_UNKNOWN
;
200 submode
= LTTNG_UNKNOWN
;
202 read_lock(&tasklist_lock
);
203 if(t
!= &init_task
) {
204 atomic_dec(&t
->usage
);
208 t
= p
= next_task(t
);
210 atomic_inc(&t
->usage
);
211 read_unlock(&tasklist_lock
);
215 if(t
->exit_state
== EXIT_ZOMBIE
)
216 status
= LTTNG_ZOMBIE
;
217 else if(t
->exit_state
== EXIT_DEAD
)
219 else if(t
->state
== TASK_RUNNING
)
221 /* Is this a forked child that has not run yet? */
222 if( list_empty(&t
->run_list
) )
224 status
= LTTNG_WAIT_FORK
;
228 /* All tasks are considered as wait_cpu; the viewer will sort out if the task was relly running at this time. */
229 status
= LTTNG_WAIT_CPU
;
232 else if(t
->state
& (TASK_INTERRUPTIBLE
| TASK_UNINTERRUPTIBLE
))
234 /* Task is waiting for something to complete */
238 status
= LTTNG_UNNAMED
;
240 submode
= LTTNG_NONE
;
243 /* Verification of t->mm is to filter out kernel threads;
244 Viewer will further filter out if a user-space thread was in syscall mode or not */
246 type
= LTTNG_USER_THREAD
;
248 type
= LTTNG_KERNEL_THREAD
;
250 trace_statedump_enumerate_process_state(t
->pid
, t
->parent
->pid
, t
->comm
,
251 type
, mode
, submode
, status
);
255 } while( t
!= &init_task
);
260 void ltt_statedump_work_func(void *sem
)
262 /* Our job is just to release the semaphore so
263 that we are sure that each CPU has been in syscall
264 mode before the end of ltt_statedump_thread */
265 up((struct semaphore
*)sem
);
268 static struct work_struct cpu_work
[NR_CPUS
];
270 int ltt_statedump_thread(void *data
)
272 struct semaphore work_sema4
;
275 printk("ltt_statedump_thread\n");
277 ltt_enumerate_process_states();
279 ltt_enumerate_file_descriptors();
281 ltt_enumerate_modules();
283 ltt_enumerate_vm_maps();
285 ltt_enumerate_interrupts();
287 ltt_enumerate_network_ip_interface();
289 /* Fire off a work queue on each CPU. Their sole purpose in life
290 * is to guarantee that each CPU has been in a state where is was in syscall
291 * mode (i.e. not in a trap, an IRQ or a soft IRQ) */
292 sema_init(&work_sema4
, 1 - num_online_cpus());
295 for_each_online_cpu(cpu
)
297 INIT_WORK(&cpu_work
[cpu
], ltt_statedump_work_func
, &work_sema4
);
299 schedule_delayed_work_on(cpu
,&cpu_work
[cpu
],0);
301 unlock_cpu_hotplug();
303 /* Wait for all work queues to have completed */
306 /* Our work is done */
307 printk("trace_statedump_statedump_end\n");
308 trace_statedump_statedump_end();
315 int ltt_statedump_start(struct ltt_trace_struct
*trace
)
317 printk("ltt_statedump_start\n");
319 kthread_run( ltt_statedump_thread
,
327 /* Dynamic facility. */
329 static int __init
statedump_init(void)
332 printk(KERN_INFO
"LTT : ltt-facility-statedump init\n");
334 ret
= ltt_module_register(LTT_FUNCTION_STATEDUMP
,
335 ltt_statedump_start
,THIS_MODULE
);
340 static void __exit
statedump_exit(void)
342 ltt_module_unregister(LTT_FUNCTION_STATEDUMP
);
345 module_init(statedump_init
)
346 module_exit(statedump_exit
)
349 MODULE_LICENSE("GPL");
350 MODULE_AUTHOR("Jean-Hugues Deschenes");
351 MODULE_DESCRIPTION("Linux Trace Toolkit Statedump");