X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttng-statedump-impl.c;h=fef97812f2b87f2eb89e74783981ddc45441b1f2;hb=refs%2Fheads%2Fstable-2.11;hp=1c09e51a8ce6a454b4bb8c86b3e079789cc9cfcd;hpb=887bcdac230a9081d5088bde59725edab93b8fb7;p=lttng-modules.git diff --git a/lttng-statedump-impl.c b/lttng-statedump-impl.c index 1c09e51a..fef97812 100644 --- a/lttng-statedump-impl.c +++ b/lttng-statedump-impl.c @@ -1,4 +1,5 @@ -/* +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * * lttng-statedump.c * * Linux Trace Toolkit Next Generation Kernel State Dump @@ -6,20 +7,6 @@ * Copyright 2005 Jean-Hugues Deschenes * Copyright 2006-2012 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 - * * Changes: * Eric Clement: Add listing of network IP interface * 2006, 2007 Mathieu Desnoyers Fix kernel threads @@ -39,9 +26,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -56,7 +41,8 @@ #include #include #include -#include +#include +#include #ifdef CONFIG_LTTNG_HAS_LIST_IRQ #include @@ -69,13 +55,42 @@ #define LTTNG_INSTRUMENTATION #include -DEFINE_TRACE(lttng_statedump_block_device); -DEFINE_TRACE(lttng_statedump_end); -DEFINE_TRACE(lttng_statedump_interrupt); -DEFINE_TRACE(lttng_statedump_file_descriptor); -DEFINE_TRACE(lttng_statedump_start); -DEFINE_TRACE(lttng_statedump_process_state); -DEFINE_TRACE(lttng_statedump_network_interface); +LTTNG_DEFINE_TRACE(lttng_statedump_block_device, + TP_PROTO(struct lttng_session *session, + dev_t dev, const char *diskname), + TP_ARGS(session, dev, diskname)); + +LTTNG_DEFINE_TRACE(lttng_statedump_end, + TP_PROTO(struct lttng_session *session), + TP_ARGS(session)); + +LTTNG_DEFINE_TRACE(lttng_statedump_interrupt, + TP_PROTO(struct lttng_session *session, + unsigned int irq, const char *chip_name, + struct irqaction *action), + TP_ARGS(session, irq, chip_name, action)); + +LTTNG_DEFINE_TRACE(lttng_statedump_file_descriptor, + TP_PROTO(struct lttng_session *session, + struct task_struct *p, int fd, const char *filename, + unsigned int flags, fmode_t fmode), + TP_ARGS(session, p, fd, filename, flags, fmode)); + +LTTNG_DEFINE_TRACE(lttng_statedump_start, + TP_PROTO(struct lttng_session *session), + TP_ARGS(session)); + +LTTNG_DEFINE_TRACE(lttng_statedump_process_state, + TP_PROTO(struct lttng_session *session, + struct task_struct *p, + int type, int mode, int submode, int status, + struct pid_namespace *pid_ns), + TP_ARGS(session, p, type, mode, submode, status, pid_ns)); + +LTTNG_DEFINE_TRACE(lttng_statedump_network_interface, + TP_PROTO(struct lttng_session *session, + struct net_device *dev, struct in_ifaddr *ifa), + TP_ARGS(session, dev, ifa)); struct lttng_fd_ctx { char *page; @@ -121,6 +136,116 @@ enum lttng_process_status { LTTNG_DEAD = 7, }; + +#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,11,0)) + +#define LTTNG_PART_STRUCT_TYPE struct block_device + +static +int lttng_get_part_name(struct gendisk *disk, struct block_device *part, char *name_buf) +{ + const char *p; + + p = bdevname(part, name_buf); + if (!p) + return -ENOSYS; + + return 0; +} + +static +dev_t lttng_get_part_devt(struct block_device *part) +{ + return part->bd_dev; +} + +#else + +#define LTTNG_PART_STRUCT_TYPE struct hd_struct + +static +int lttng_get_part_name(struct gendisk *disk, struct hd_struct *part, char *name_buf) +{ + const char *p; + struct block_device bdev; + + /* + * Create a partial 'struct blockdevice' to use + * 'bdevname()' which is a simple wrapper over + * 'disk_name()' but has the honor to be EXPORT_SYMBOL. + */ + bdev.bd_disk = disk; + bdev.bd_part = part; + + p = bdevname(&bdev, name_buf); + if (!p) + return -ENOSYS; + + return 0; +} + +static +dev_t lttng_get_part_devt(struct hd_struct *part) +{ + return part_devt(part); +} +#endif + +#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,12,0)) +static +int lttng_statedump_each_block_device(struct lttng_session *session, struct gendisk *disk) +{ + struct block_device *part; + unsigned long idx; + int ret = 0; + + /* Include partition 0 */ + idx = 0; + + rcu_read_lock(); + xa_for_each(&disk->part_tbl, idx, part) { + char name_buf[BDEVNAME_SIZE]; + + /* Exclude non-partitions bdev and empty partitions. */ + if (bdev_is_partition(part) && !bdev_nr_sectors(part)) + continue; + + if (lttng_get_part_name(disk, part, name_buf) == -ENOSYS) { + ret = -ENOSYS; + goto end; + } + trace_lttng_statedump_block_device(session, lttng_get_part_devt(part), + name_buf); + } +end: + rcu_read_unlock(); + return ret; +} +#else +static +int lttng_statedump_each_block_device(struct lttng_session *session, struct gendisk *disk) +{ + struct disk_part_iter piter; + LTTNG_PART_STRUCT_TYPE *part; + + disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0); + + while ((part = disk_part_iter_next(&piter))) { + char name_buf[BDEVNAME_SIZE]; + + if (lttng_get_part_name(disk, part, name_buf) == -ENOSYS) { + disk_part_iter_exit(&piter); + return -ENOSYS; + } + trace_lttng_statedump_block_device(session, lttng_get_part_devt(part), + name_buf); + } + disk_part_iter_exit(&piter); + + return 0; +} +#endif + static int lttng_enumerate_block_devices(struct lttng_session *session) { @@ -128,19 +253,21 @@ int lttng_enumerate_block_devices(struct lttng_session *session) struct device_type *ptr_disk_type; struct class_dev_iter iter; struct device *dev; + int ret = 0; ptr_block_class = wrapper_get_block_class(); - if (!ptr_block_class) - return -ENOSYS; + if (!ptr_block_class) { + ret = -ENOSYS; + goto end; + } ptr_disk_type = wrapper_get_disk_type(); if (!ptr_disk_type) { - return -ENOSYS; + ret = -ENOSYS; + goto end; } 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; /* * Don't show empty devices or things that have been @@ -150,24 +277,11 @@ int lttng_enumerate_block_devices(struct lttng_session *session) (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) continue; - 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); + ret = lttng_statedump_each_block_device(session, disk); } class_dev_iter_exit(&iter); - return 0; +end: + return ret; } #ifdef CONFIG_INET @@ -342,7 +456,7 @@ int lttng_enumerate_vm_maps(struct lttng_session *session) #ifdef CONFIG_LTTNG_HAS_LIST_IRQ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) +#if (LTTNG_LINUX_VERSION_CODE < LTTNG_KERNEL_VERSION(2,6,39)) #define irq_desc_get_chip(desc) get_irq_desc_chip(desc) #endif @@ -397,7 +511,7 @@ void lttng_statedump_process_ns(struct lttng_session *session, do { trace_lttng_statedump_process_state(session, p, type, mode, submode, status, pid_ns); - pid_ns = pid_ns->parent; + pid_ns = pid_ns ? pid_ns->parent : NULL; } while (pid_ns); } @@ -422,7 +536,7 @@ int lttng_enumerate_process_states(struct lttng_session *session) status = LTTNG_ZOMBIE; else if (p->exit_state == EXIT_DEAD) status = LTTNG_DEAD; - else if (p->state == TASK_RUNNING) { + else if (lttng_task_is_running(p)) { /* Is this a forked child that has not run yet? */ if (list_empty(&p->rt.run_list)) status = LTTNG_WAIT_FORK; @@ -433,7 +547,7 @@ int lttng_enumerate_process_states(struct lttng_session *session) * was really running at this time. */ status = LTTNG_WAIT_CPU; - } else if (p->state & + } else if (lttng_get_task_state(p) & (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)) { /* Task is waiting for something to complete */ status = LTTNG_WAIT; @@ -560,7 +674,7 @@ module_exit(lttng_statedump_exit); MODULE_LICENSE("GPL and additional rights"); MODULE_AUTHOR("Jean-Hugues Deschenes"); -MODULE_DESCRIPTION("Linux Trace Toolkit Next Generation Statedump"); +MODULE_DESCRIPTION("LTTng statedump provider"); MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "." __stringify(LTTNG_MODULES_MINOR_VERSION) "." __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)