Tested-by: Julien Desfossez <[email protected]> On 14-04-16 04:56 PM, Mathieu Desnoyers wrote: > From: Houssem Daoud <[email protected]> > > [ Edited by Mathieu Desnoyers. ] > Signed-off-by: Houssem Daoud <[email protected]> > Signed-off-by: Mathieu Desnoyers <[email protected]> > --- > 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 9aa5b93..119bfa8 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 e4c86d6..efd22d7 100644 > --- a/instrumentation/events/lttng-module/lttng-statedump.h > +++ b/instrumentation/events/lttng-module/lttng-statedump.h > @@ -7,6 +7,7 @@ > #include <linux/tracepoint.h> > #include <linux/nsproxy.h> > #include <linux/pid_namespace.h> > +#include <linux/types.h> > > 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 3e46ca1..e9fe829 100644 > --- a/lttng-statedump-impl.c > +++ b/lttng-statedump-impl.c > @@ -45,6 +45,7 @@ > #include <linux/swap.h> > #include <linux/wait.h> > #include <linux/mutex.h> > +#include <linux/device.h> > > #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 <linux/irq.h> > @@ -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 0000000..5bb390b > --- /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 <[email protected]> > + * > + * 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 <linux/genhd.h> > + > +#ifdef CONFIG_KALLSYMS > + > +#include <linux/kallsyms.h> > +#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 */ >
_______________________________________________ lttng-dev mailing list [email protected] http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
