From f0dbdefbdbc26a000ed546180b22144c5b48857d Mon Sep 17 00:00:00 2001 From: Houssem Daoud Date: Tue, 15 Apr 2014 12:06:50 -0400 Subject: [PATCH] Statedump event for block devices Signed-off-by: Houssem Daoud [ Edited by Mathieu Desnoyers. ] Tested-by: Julien Desfossez Signed-off-by: Mathieu Desnoyers --- README | 2 + .../events/lttng-module/lttng-statedump.h | 16 +++ lttng-statedump-impl.c | 46 +++++++ wrapper/genhd.h | 113 ++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 wrapper/genhd.h diff --git a/README b/README index 9aa5b939..119bfa89 100644 --- a/README +++ b/README @@ -83,6 +83,8 @@ CONFIG_KPROBES: CONFIG_KRETPROBES: Dynamic function entry/return probe. lttng enable-event -k --function ... +CONFIG_KALLSYMS_ALL: + State dump of mapping between block device number and name. * Note about Perf PMU counters support diff --git a/instrumentation/events/lttng-module/lttng-statedump.h b/instrumentation/events/lttng-module/lttng-statedump.h index e4c86d65..efd22d77 100644 --- a/instrumentation/events/lttng-module/lttng-statedump.h +++ b/instrumentation/events/lttng-module/lttng-statedump.h @@ -7,6 +7,7 @@ #include #include #include +#include TRACE_EVENT(lttng_statedump_start, TP_PROTO(struct lttng_session *session), @@ -141,6 +142,21 @@ TRACE_EVENT(lttng_statedump_network_interface, TP_printk("") ) +TRACE_EVENT(lttng_statedump_block_device, + TP_PROTO(struct lttng_session *session, + dev_t dev, const char *diskname), + TP_ARGS(session, dev, diskname), + TP_STRUCT__entry( + __field(dev_t, dev) + __string(diskname, diskname) + ), + TP_fast_assign( + tp_assign(dev, dev) + tp_strcpy(diskname, diskname) + ), + TP_printk("") +) + /* Called with desc->lock held */ TRACE_EVENT(lttng_statedump_interrupt, TP_PROTO(struct lttng_session *session, diff --git a/lttng-statedump-impl.c b/lttng-statedump-impl.c index 3e46ca16..e9fe829f 100644 --- a/lttng-statedump-impl.c +++ b/lttng-statedump-impl.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "lttng-events.h" #include "lttng-tracer.h" @@ -54,6 +55,7 @@ #include "wrapper/nsproxy.h" #include "wrapper/irq.h" #include "wrapper/tracepoint.h" +#include "wrapper/genhd.h" #ifdef CONFIG_LTTNG_HAS_LIST_IRQ #include @@ -65,6 +67,7 @@ #define TRACE_INCLUDE_FILE lttng-statedump #include "instrumentation/events/lttng-module/lttng-statedump.h" +DEFINE_TRACE(lttng_statedump_block_device); DEFINE_TRACE(lttng_statedump_end); DEFINE_TRACE(lttng_statedump_interrupt); DEFINE_TRACE(lttng_statedump_file_descriptor); @@ -115,7 +118,49 @@ enum lttng_process_status { LTTNG_DEAD = 7, }; +static +int lttng_enumerate_block_devices(struct lttng_session *session) +{ + struct class *ptr_block_class; + struct device_type *ptr_disk_type; + struct class_dev_iter iter; + struct device *dev; + + ptr_block_class = wrapper_get_block_class(); + if (!ptr_block_class) + return -ENOSYS; + ptr_disk_type = wrapper_get_disk_type(); + if (!ptr_disk_type) { + return -ENOSYS; + } + class_dev_iter_init(&iter, ptr_block_class, NULL, ptr_disk_type); + while ((dev = class_dev_iter_next(&iter))) { + struct disk_part_iter piter; + struct gendisk *disk = dev_to_disk(dev); + struct hd_struct *part; + + disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0); + while ((part = disk_part_iter_next(&piter))) { + char name_buf[BDEVNAME_SIZE]; + char *p; + + p = wrapper_disk_name(disk, part->partno, name_buf); + if (!p) { + disk_part_iter_exit(&piter); + class_dev_iter_exit(&iter); + return -ENOSYS; + } + trace_lttng_statedump_block_device(session, + part_devt(part), name_buf); + } + disk_part_iter_exit(&piter); + } + class_dev_iter_exit(&iter); + return 0; +} + #ifdef CONFIG_INET + static void lttng_enumerate_device(struct lttng_session *session, struct net_device *dev) @@ -397,6 +442,7 @@ int do_lttng_statedump(struct lttng_session *session) /* FIXME lttng_enumerate_vm_maps(session); */ lttng_list_interrupts(session); lttng_enumerate_network_ip_interface(session); + lttng_enumerate_block_devices(session); /* TODO lttng_dump_idt_table(session); */ /* TODO lttng_dump_softirq_vec(session); */ diff --git a/wrapper/genhd.h b/wrapper/genhd.h new file mode 100644 index 00000000..5bb390b6 --- /dev/null +++ b/wrapper/genhd.h @@ -0,0 +1,113 @@ +#ifndef _LTTNG_WRAPPER_GENHD_H +#define _LTTNG_WRAPPER_GENHD_H + +/* + * wrapper/genhd.h + * + * wrapper around block layer functions and data structures. Using + * KALLSYMS to get its address when available, else we need to have a + * kernel that exports this function to GPL modules. + * + * Copyright (C) 2011-2014 Mathieu Desnoyers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; only + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#ifdef CONFIG_KALLSYMS + +#include +#include "kallsyms.h" + +static inline +char *wrapper_disk_name(struct gendisk *hd, int partno, char *buf) +{ + char *(*disk_name_sym)(struct gendisk *hd, int partno, char *buf); + + disk_name_sym = (void *) kallsyms_lookup_funcptr("disk_name"); + if (disk_name_sym) { + return disk_name_sym(hd, partno, buf); + } else { + printk(KERN_WARNING "LTTng: disk_name symbol lookup failed.\n"); + return NULL; + } +} + +#else + +static inline +char *wrapper_disk_name(struct gendisk *hd, int partno, char *buf) +{ + return disk_name(hd, partno, buf); +} + +#endif + +#ifdef CONFIG_KALLSYMS_ALL + +static inline +struct class *wrapper_get_block_class(void) +{ + struct class *ptr_block_class; + + ptr_block_class = (struct class *) kallsyms_lookup_dataptr("block_class"); + if (!ptr_block_class) { + printk(KERN_WARNING "LTTng: block_class symbol lookup failed.\n"); + return NULL; + } + return ptr_block_class; +} + +static inline +struct device_type *wrapper_get_disk_type(void) +{ + struct device_type *ptr_disk_type; + + ptr_disk_type = (struct device_type *) kallsyms_lookup_dataptr("disk_type"); + if (!ptr_disk_type) { + printk(KERN_WARNING "LTTng: disk_type symbol lookup failed.\n"); + return NULL; + } + return ptr_disk_type; +} + +#else + +static inline +struct class *wrapper_get_block_class(void) +{ + /* + * Symbol block_class is not exported. + * TODO: return &block_class; + */ + /* Feature currently unavailable without KALLSYMS_ALL */ + return NULL; +} + +static inline +struct device_type *wrapper_get_disk_type(void) +{ + /* + * Symbol disk_type is not exported. + * TODO: return &disk_type; + */ + /* Feature currently unavailable without KALLSYMS_ALL */ + return NULL; +} + +#endif + +#endif /* _LTTNG_WRAPPER_GENHD_H */ -- 2.34.1