From 7b1edb4cd748bfaac6a321946878ad7aaf7016d8 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Mon, 28 Oct 2019 16:28:43 -0400 Subject: [PATCH 01/16] Add missing include for kernels between 3.8 and 3.15 This is required at least for: v3.13.x v3.11.x v3.9.x v3.8.x Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- lttng-context-mnt-ns.c | 1 + lttng-context-net-ns.c | 1 + 2 files changed, 2 insertions(+) diff --git a/lttng-context-mnt-ns.c b/lttng-context-mnt-ns.c index 98d5b8e6..b5bb955a 100644 --- a/lttng-context-mnt-ns.c +++ b/lttng-context-mnt-ns.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/lttng-context-net-ns.c b/lttng-context-net-ns.c index 24d7ae35..6694037f 100644 --- a/lttng-context-net-ns.c +++ b/lttng-context-net-ns.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include -- 2.34.1 From 96cd8a35f89efd67548e7146b117b107de487bb4 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Tue, 10 Dec 2019 11:41:10 -0500 Subject: [PATCH 02/16] Update .gitignore from upstream Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- .gitignore | 110 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 38e16841..4af69a27 100644 --- a/.gitignore +++ b/.gitignore @@ -7,30 +7,45 @@ # command after changing this file, to see if there are # any tracked files which get ignored after the change. # -# Normal rules +# Normal rules (sorted alphabetically) # .* +*.a +*.asn1.[ch] +*.bin +*.bz2 +*.c.[012]*.* +*.dt.yaml +*.dtb +*.dtb.S +*.dwo +*.elf +*.gcno +*.gz +*.i +*.ko +*.lex.c +*.ll +*.lst +*.lz4 +*.lzma +*.lzo +*.mod +*.mod.c *.o *.o.* -*.a +*.patch *.s -*.ko *.so *.so.dbg -*.mod.c -*.i -*.lst +*.su *.symtypes -*.order +*.tab.[ch] +*.tar +*.xz +Module.symvers modules.builtin -*.elf -*.bin -*.gz -*.bz2 -*.lzma -*.lzo -*.gcno -cscope.* +modules.order # # Top-level generic files @@ -39,25 +54,51 @@ cscope.* /TAGS /linux /vmlinux +/vmlinux.32 +/vmlinux-gdb.py /vmlinuz /System.map /Module.markers +/modules.builtin.modinfo +/modules.nsdeps -# ignore across tree -Module.symvers +# +# RPM spec file (make rpm-pkg) +# +/*.spec + +# +# Debian directory (make deb-pkg) +# +/debian/ + +# +# Snap directory (make snap-pkg) +# +/snap/ + +# +# tar directory (make tar*-pkg) +# +/tar-install/ # -# git files that we don't want to ignore even it they are dot-files +# We don't want to ignore the following even if they are dot-files # +!.clang-format +!.cocciconfig +!.get_maintainer.ignore +!.gitattributes !.gitignore !.mailmap # # Generated include files # -include/config -include/linux/version.h -include/generated +/include/config/ +/include/generated/ +/include/ksym/ +/arch/*/include/generated/ # stgit generated dirs patches-* @@ -76,8 +117,35 @@ GRTAGS GSYMS GTAGS +# id-utils files +ID + *.orig *~ \#*# +# +# Leavings from module signing +# +extra_certificates +signing_key.pem +signing_key.priv +signing_key.x509 +x509.genkey + +# Kconfig presets +/all.config +/alldef.config +/allmod.config +/allno.config +/allrandom.config +/allyes.config + +# Kdevelop4 +*.kdev4 + +# Clang's compilation database file +/compile_commands.json + +# lttng-modules specific /extra_version -- 2.34.1 From 7c1dd1200ff7ee8e77ba24872206e3970b84a582 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Tue, 10 Dec 2019 11:41:11 -0500 Subject: [PATCH 03/16] fix: y2038: itimer: change implementation to timespec64 (v5.5) See upstream commit: commit bd40a175769d411b2a37e1c087082ac7ee2c15bb Author: Arnd Bergmann Date: Thu Nov 7 15:27:39 2019 +0100 y2038: itimer: change implementation to timespec64 There is no 64-bit version of getitimer/setitimer since that is not actually needed. However, the implementation is built around the deprecated 'struct timeval' type. Change the code to use timespec64 internally to reduce the dependencies on timeval and associated helper functions. Minor adjustments in the code are needed to make the native and compat version work the same way, and to keep the range check working after the conversion. Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- instrumentation/events/lttng-module/timer.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/instrumentation/events/lttng-module/timer.h b/instrumentation/events/lttng-module/timer.h index 997084ff..1a45d82b 100644 --- a/instrumentation/events/lttng-module/timer.h +++ b/instrumentation/events/lttng-module/timer.h @@ -294,7 +294,26 @@ LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(timer_hrtimer_class, hrtimer_cancel, * zero, otherwise it is started * @expires: the itimers expiry time */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) +LTTNG_TRACEPOINT_EVENT_MAP(itimer_state, + + timer_itimer_state, + + TP_PROTO(int which, const struct itimerspec64 *const value, + unsigned long long expires), + + TP_ARGS(which, value, expires), + + TP_FIELDS( + ctf_integer(int, which, which) + ctf_integer(unsigned long long, expires, expires) + ctf_integer(long, value_sec, value->it_value.tv_sec) + ctf_integer(long, value_nsec, value->it_value.tv_nsec) + ctf_integer(long, interval_sec, value->it_interval.tv_sec) + ctf_integer(long, interval_nsec, value->it_interval.tv_nsec) + ) +) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)) LTTNG_TRACEPOINT_EVENT_MAP(itimer_state, timer_itimer_state, -- 2.34.1 From 5809d816fc124d598e689d8914a7e064667d2aeb Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Tue, 10 Dec 2019 11:41:13 -0500 Subject: [PATCH 04/16] fix: btrfs block group struct refactor (v5.5) See upstream commits: commit 32da5386d9a4fd5c1155cecf703df104d918954c Author: David Sterba Date: Tue Oct 29 19:20:18 2019 +0100 btrfs: rename btrfs_block_group_cache The type name is misleading, a single entry is named 'cache' while this normally means a collection of objects. Rename that everywhere. Also the identifier was quite long, making function prototypes harder to format. commit b3470b5dbe1300dea94191ae4b7d070be9a5cdc9 Author: David Sterba Date: Wed Oct 23 18:48:22 2019 +0200 btrfs: add dedicated members for start and length of a block group The on-disk format of block group item makes use of the key that stores the offset and length. This is further used in the code, although this makes thing harder to understand. The key is also packed so the offset/length is not properly aligned as u64. Add start (key.objectid) and length (key.offset) members to block group and remove the embedded key. When the item is searched or written, a local variable for key is used. commit bf38be65f3703d5ef3661c0a2802bc28e76b8f19 Author: David Sterba Date: Wed Oct 23 18:48:11 2019 +0200 btrfs: move block_group_item::used to block group For unknown reasons, the member 'used' in the block group struct is stored in the b-tree item and accessed everywhere using the special accessor helper. Let's unify it and make it a regular member and only update the item before writing it to the tree. The item is still being used for flags and chunk_objectid, there's some duplication until the item is removed in following patches. Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- instrumentation/events/lttng-module/btrfs.h | 125 +++++++++++++++++++- 1 file changed, 121 insertions(+), 4 deletions(-) diff --git a/instrumentation/events/lttng-module/btrfs.h b/instrumentation/events/lttng-module/btrfs.h index c548cf21..1ad5fd27 100644 --- a/instrumentation/events/lttng-module/btrfs.h +++ b/instrumentation/events/lttng-module/btrfs.h @@ -20,8 +20,12 @@ struct btrfs_delayed_ref_node; struct btrfs_delayed_tree_ref; struct btrfs_delayed_data_ref; struct btrfs_delayed_ref_head; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) +struct btrfs_block_group; +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) struct btrfs_block_group_cache; +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) struct btrfs_free_cluster; #endif struct map_lookup; @@ -660,7 +664,25 @@ LTTNG_TRACEPOINT_EVENT(btrfs_sync_fs, ) #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) || \ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) +LTTNG_TRACEPOINT_EVENT(btrfs_add_block_group, + + TP_PROTO(const struct btrfs_fs_info *fs_info, + const struct btrfs_block_group *block_group, int create), + + TP_ARGS(fs_info, block_group, create), + + TP_FIELDS( + ctf_array(u8, fsid, lttng_fs_info_fsid, BTRFS_UUID_SIZE) + ctf_integer(u64, offset, block_group->start) + ctf_integer(u64, size, block_group->length) + ctf_integer(u64, flags, block_group->flags) + ctf_integer(u64, bytes_used, block_group->used) + ctf_integer(u64, bytes_super, block_group->bytes_super) + ctf_integer(int, create, create) + ) +) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) || \ LTTNG_SLE_KERNEL_RANGE(4,4,73,5,0,0, 4,4,73,6,0,0) || \ LTTNG_SLE_KERNEL_RANGE(4,4,82,6,0,0, 4,4,82,7,0,0) || \ LTTNG_SLE_KERNEL_RANGE(4,4,92,6,0,0, 4,4,92,7,0,0) || \ @@ -1777,7 +1799,57 @@ LTTNG_TRACEPOINT_EVENT_INSTANCE(btrfs__reserved_extent, btrfs_reserved_extent_f #endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) +LTTNG_TRACEPOINT_EVENT_MAP(find_free_extent, + + btrfs_find_free_extent, + + TP_PROTO(const struct btrfs_fs_info *fs_info, u64 num_bytes, u64 empty_size, + u64 data), + + TP_ARGS(fs_info, num_bytes, empty_size, data), + + TP_FIELDS( + ctf_array(u8, fsid, lttng_fs_info_fsid, BTRFS_UUID_SIZE) + ctf_integer(u64, num_bytes, num_bytes) + ctf_integer(u64, empty_size, empty_size) + ctf_integer(u64, data, data) + ) +) + +LTTNG_TRACEPOINT_EVENT_CLASS(btrfs__reserve_extent, + + TP_PROTO(const struct btrfs_block_group *block_group, u64 start, + u64 len), + + TP_ARGS(block_group, start, len), + + TP_FIELDS( + ctf_array(u8, fsid, block_group->lttng_fs_info_fsid, BTRFS_UUID_SIZE) + ctf_integer(u64, bg_objectid, block_group->start) + ctf_integer(u64, flags, block_group->flags) + ctf_integer(u64, start, start) + ctf_integer(u64, len, len) + ) +) + +LTTNG_TRACEPOINT_EVENT_INSTANCE(btrfs__reserve_extent, btrfs_reserve_extent, + + TP_PROTO(const struct btrfs_block_group *block_group, u64 start, + u64 len), + + TP_ARGS(block_group, start, len) +) + +LTTNG_TRACEPOINT_EVENT_INSTANCE(btrfs__reserve_extent, btrfs_reserve_extent_cluster, + + TP_PROTO(const struct btrfs_block_group *block_group, u64 start, + u64 len), + + TP_ARGS(block_group, start, len) +) + +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)) LTTNG_TRACEPOINT_EVENT_MAP(find_free_extent, btrfs_find_free_extent, @@ -2045,7 +2117,52 @@ LTTNG_TRACEPOINT_EVENT_INSTANCE(btrfs__reserve_extent, btrfs_reserve_extent_clus #endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) || \ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) +LTTNG_TRACEPOINT_EVENT(btrfs_find_cluster, + + TP_PROTO(const struct btrfs_block_group *block_group, u64 start, + u64 bytes, u64 empty_size, u64 min_bytes), + + TP_ARGS(block_group, start, bytes, empty_size, min_bytes), + + TP_FIELDS( + ctf_integer(u64, bg_objectid, block_group->start) + ctf_integer(u64, flags, block_group->flags) + ctf_integer(u64, start, start) + ctf_integer(u64, bytes, bytes) + ctf_integer(u64, empty_size, empty_size) + ctf_integer(u64, min_bytes, min_bytes) + ) +) + +LTTNG_TRACEPOINT_EVENT(btrfs_failed_cluster_setup, + + TP_PROTO(const struct btrfs_block_group *block_group), + + TP_ARGS(block_group), + + TP_FIELDS( + ctf_integer(u64, bg_objectid, block_group->start) + ) +) + +LTTNG_TRACEPOINT_EVENT(btrfs_setup_cluster, + + TP_PROTO(const struct btrfs_block_group *block_group, + const struct btrfs_free_cluster *cluster, u64 size, int bitmap), + + TP_ARGS(block_group, cluster, size, bitmap), + + TP_FIELDS( + ctf_integer(u64, bg_objectid, block_group->start) + ctf_integer(u64, flags, block_group->flags) + ctf_integer(u64, start, cluster->window_start) + ctf_integer(u64, max_size, cluster->max_size) + ctf_integer(u64, size, size) + ctf_integer(int, bitmap, bitmap) + ) +) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) || \ LTTNG_SLE_KERNEL_RANGE(4,4,73,5,0,0, 4,4,73,6,0,0) || \ LTTNG_SLE_KERNEL_RANGE(4,4,82,6,0,0, 4,4,82,7,0,0) || \ LTTNG_SLE_KERNEL_RANGE(4,4,92,6,0,0, 4,4,92,7,0,0) || \ -- 2.34.1 From ae5af8ea3f781227d37bb8633e960e759422942c Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Tue, 10 Dec 2019 11:41:12 -0500 Subject: [PATCH 05/16] fix: btrfs: tracepoints: constify all pointers (v5.5) See upstream commit: commit 1d2e7c7c3ed73cc510a4dc093df2a935092ff5ad Author: David Sterba Date: Thu Oct 17 13:28:57 2019 +0200 btrfs: tracepoints: constify all pointers We don't modify the data passed to tracepoints, some of the declarations are already const, add it to the rest. Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- instrumentation/events/lttng-module/btrfs.h | 39 +++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/instrumentation/events/lttng-module/btrfs.h b/instrumentation/events/lttng-module/btrfs.h index 1ad5fd27..b4f2fe70 100644 --- a/instrumentation/events/lttng-module/btrfs.h +++ b/instrumentation/events/lttng-module/btrfs.h @@ -290,7 +290,26 @@ LTTNG_TRACEPOINT_EVENT(btrfs_get_extent, #endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) +LTTNG_TRACEPOINT_EVENT(btrfs_handle_em_exist, + + TP_PROTO(const struct btrfs_fs_info *fs_info, + const struct extent_map *existing, const struct extent_map *map, + u64 start, u64 len), + + TP_ARGS(fs_info, existing, map, start, len), + + TP_FIELDS( + ctf_array(u8, fsid, lttng_fs_info_fsid, BTRFS_UUID_SIZE) + ctf_integer(u64, e_start, existing->start) + ctf_integer(u64, e_len, existing->len) + ctf_integer(u64, map_start, map->start) + ctf_integer(u64, map_len, map->len) + ctf_integer(u64, start, start) + ctf_integer(u64, len, len) + ) +) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)) LTTNG_TRACEPOINT_EVENT(btrfs_handle_em_exist, TP_PROTO(struct btrfs_fs_info *fs_info, @@ -1642,7 +1661,23 @@ LTTNG_TRACEPOINT_EVENT(btrfs_cow_block, ) #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) || \ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) +LTTNG_TRACEPOINT_EVENT(btrfs_space_reservation, + + TP_PROTO(const struct btrfs_fs_info *fs_info, const char *type, u64 val, + u64 bytes, int reserve), + + TP_ARGS(fs_info, type, val, bytes, reserve), + + TP_FIELDS( + ctf_array(u8, fsid, lttng_fs_info_fsid, BTRFS_UUID_SIZE) + ctf_string(type, type) + ctf_integer(u64, val, val) + ctf_integer(u64, bytes, bytes) + ctf_integer(int, reserve, reserve) + ) +) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) || \ LTTNG_SLE_KERNEL_RANGE(4,4,73,5,0,0, 4,4,73,6,0,0) || \ LTTNG_SLE_KERNEL_RANGE(4,4,82,6,0,0, 4,4,82,7,0,0) || \ LTTNG_SLE_KERNEL_RANGE(4,4,92,6,0,0, 4,4,92,7,0,0) || \ -- 2.34.1 From bb0eb66dd8cd35e2837fbb408667ab3f73c624e6 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Tue, 10 Dec 2019 11:41:14 -0500 Subject: [PATCH 06/16] fix: ext4: Reserve revoke credits for freed blocks (v5.5) See upstream commit: commit 83448bdfb59731c2f54784ed3f4a93ff95be6e7e Author: Jan Kara Date: Tue Nov 5 17:44:29 2019 +0100 ext4: Reserve revoke credits for freed blocks So far we have reserved only relatively high fixed amount of revoke credits for each transaction. We over-reserved by large amount for most cases but when freeing large directories or files with data journalling, the fixed amount is not enough. In fact the worst case estimate is inconveniently large (maximum extent size) for freeing of one extent. We fix this by doing proper estimate of the amount of blocks that need to be revoked when removing blocks from the inode due to truncate or hole punching and otherwise reserve just a small amount of revoke credits for each transaction to accommodate freeing of xattrs block or so. Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- instrumentation/events/lttng-module/ext4.h | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/instrumentation/events/lttng-module/ext4.h b/instrumentation/events/lttng-module/ext4.h index b2ca8a7c..17809d21 100644 --- a/instrumentation/events/lttng-module/ext4.h +++ b/instrumentation/events/lttng-module/ext4.h @@ -1255,7 +1255,36 @@ LTTNG_TRACEPOINT_EVENT(ext4_load_inode, ) ) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) + +LTTNG_TRACEPOINT_EVENT(ext4_journal_start, + TP_PROTO(struct super_block *sb, int blocks, int rsv_blocks, + int revoke_creds, unsigned long IP), + + TP_ARGS(sb, blocks, rsv_blocks, revoke_creds, IP), + + TP_FIELDS( + ctf_integer(dev_t, dev, sb->s_dev) + ctf_integer(unsigned long, ip, IP) + ctf_integer(int, blocks, blocks) + ctf_integer(int, rsv_blocks, rsv_blocks) + ctf_integer(int, revoke_creds, revoke_creds) + ) +) + +LTTNG_TRACEPOINT_EVENT(ext4_journal_start_reserved, + TP_PROTO(struct super_block *sb, int blocks, unsigned long IP), + + TP_ARGS(sb, blocks, IP), + + TP_FIELDS( + ctf_integer(dev_t, dev, sb->s_dev) + ctf_integer(unsigned long, ip, IP) + ctf_integer(int, blocks, blocks) + ) +) + +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)) LTTNG_TRACEPOINT_EVENT(ext4_journal_start, TP_PROTO(struct super_block *sb, int blocks, int rsv_blocks, -- 2.34.1 From 1ff7013bcf7f068cf4371d12d758f9c0fd16a619 Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Thu, 5 Dec 2019 15:35:32 +0800 Subject: [PATCH 07/16] Fix: SUNRPC: Fix oops when trace sunrpc_task events in nfs client See upstream commit : commit 2ca310fc4160ed0420da65534a21ae77b24326a8 Author: Ditang Chen Date: Fri, 7 Mar 2014 13:27:57 +0800 Subject: SUNRPC: Fix oops when trace sunrpc_task events in nfs client When tracking sunrpc_task events in nfs client, the clnt pointer may be NULL. [ 139.269266] BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 [ 139.269915] IP: [] ftrace_raw_event_rpc_task_running+0x86/0xf0 [sunrpc] [ 139.269915] PGD 1d293067 PUD 1d294067 PMD 0 [ 139.269915] Oops: 0000 [#1] SMP [ 139.269915] Modules linked in: nfsv4 dns_resolver nfs lockd sunrpc fscache sg ppdev e1000 serio_raw pcspkr parport_pc parport i2c_piix4 i2c_core microcode xfs libcrc32c sd_mod sr_mod cdrom ata_generic crc_t10dif crct10dif_common pata_acpi ahci libahci ata_piix libata dm_mirror dm_region_hash dm_log dm_mod [ 139.269915] CPU: 0 PID: 59 Comm: kworker/0:2 Not tainted 3.10.0-84.el7.x86_64 #1 [ 139.269915] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 139.269915] Workqueue: rpciod rpc_async_schedule [sunrpc] [ 139.269915] task: ffff88001b598000 ti: ffff88001b632000 task.ti: ffff88001b632000 [ 139.269915] RIP: 0010:[] [] ftrace_raw_event_rpc_task_running+0x86/0xf0 [sunrpc] [ 139.269915] RSP: 0018:ffff88001b633d70 EFLAGS: 00010206 [ 139.269915] RAX: ffff88001dfc5338 RBX: ffff88001cc37a00 RCX: ffff88001dfc5334 [ 139.269915] RDX: ffff88001dfc5338 RSI: 0000000000000000 RDI: ffff88001dfc533c [ 139.269915] RBP: ffff88001b633db0 R08: 000000000000002c R09: 000000000000000a [ 139.269915] R10: 0000000000062180 R11: 00000020759fb9dc R12: ffffffffa0292c20 [ 139.269915] R13: ffff88001dfc5334 R14: 0000000000000000 R15: 0000000000000000 [ 139.269915] FS: 0000000000000000(0000) GS:ffff88001fc00000(0000) knlGS:0000000000000000 [ 139.269915] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 139.269915] CR2: 0000000000000004 CR3: 000000001d290000 CR4: 00000000000006f0 [ 139.269915] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 139.269915] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 139.269915] Stack: [ 139.269915] 000000001b633d98 0000000000000246 ffff88001df1dc00 ffff88001cc37a00 [ 139.269915] ffff88001bc35e60 0000000000000000 ffff88001ffa0a48 ffff88001bc35ee0 [ 139.269915] ffff88001b633e08 ffffffffa02704b5 0000000000010000 ffff88001cc37a70 [ 139.269915] Call Trace: [ 139.269915] [] __rpc_execute+0x1d5/0x400 [sunrpc] [ 139.269915] [] rpc_async_schedule+0x26/0x30 [sunrpc] [ 139.269915] [] process_one_work+0x17b/0x460 [ 139.269915] [] worker_thread+0x11b/0x400 [ 139.269915] [] ? rescuer_thread+0x3e0/0x3e0 [ 139.269915] [] kthread+0xc0/0xd0 [ 139.269915] [] ? kthread_create_on_node+0x110/0x110 [ 139.269915] [] ret_from_fork+0x7c/0xb0 [ 139.269915] [] ? kthread_create_on_node+0x110/0x110 [ 139.269915] Code: 4c 8b 45 c8 48 8d 7d d0 89 4d c4 41 89 c9 b9 28 00 00 00 e8 9d b4 e9 e0 48 85 c0 49 89 c5 74 a2 48 89 c7 e8 9d 3f e9 e0 48 89 c2 <41> 8b 46 04 48 8b 7d d0 4c 89 e9 4c 89 e6 89 42 0c 0f b7 83 d4 [ 139.269915] RIP [] ftrace_raw_event_rpc_task_running+0x86/0xf0 [sunrpc] [ 139.269915] RSP [ 139.269915] CR2: 0000000000000004 [ 140.946406] ---[ end trace ba486328b98d7622 ]--- Signed-off-by: Quanyang Wang Signed-off-by: Mathieu Desnoyers --- instrumentation/events/lttng-module/rpc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/events/lttng-module/rpc.h b/instrumentation/events/lttng-module/rpc.h index 3798e8ef..fb131060 100644 --- a/instrumentation/events/lttng-module/rpc.h +++ b/instrumentation/events/lttng-module/rpc.h @@ -139,7 +139,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_running, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client->cl_clid) + ctf_integer(unsigned int, client_id, task->tk_client ? task->tk_client->cl_clid : -1) ctf_integer_hex(const void *, action, action) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) @@ -208,7 +208,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_running, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client->cl_clid) + ctf_integer(unsigned int, client_id, task->tk_client ? task->tk_client->cl_clid : -1) ctf_integer_hex(const void *, action, action) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) -- 2.34.1 From 032a74d83b263c4faead8e4c25d497fb8ea07b6e Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 12 Dec 2019 10:29:02 -0500 Subject: [PATCH 08/16] Fix: sunrpc: null rpc_clnt dereference in rpc_task_queued tracepoint Based on upstream Linux commit: commit 0be283f676a1e7b208db0c992283197ef8b52158 Author: Benjamin Coddington Date: Tue Jan 23 09:32:35 2018 -0500 SUNRPC: Fix null rpc_clnt dereference in rpc_task_queued tracepoint Backchannel tasks will not have a reference to the rpc_clnt. Return -1 for cl_clid in that case. Signed-off-by: Benjamin Coddington Signed-off-by: Trond Myklebust Signed-off-by: Mathieu Desnoyers --- instrumentation/events/lttng-module/rpc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/events/lttng-module/rpc.h b/instrumentation/events/lttng-module/rpc.h index fb131060..68c622c0 100644 --- a/instrumentation/events/lttng-module/rpc.h +++ b/instrumentation/events/lttng-module/rpc.h @@ -176,7 +176,8 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_queued, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client->cl_clid) + ctf_integer(unsigned int, client_id, task->tk_client ? + task->tk_client->cl_clid : -1) ctf_integer(unsigned long, timeout, task->tk_timeout) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) -- 2.34.1 From 70389e422dd3146161089d454f525367c9046ecd Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 12 Dec 2019 10:29:37 -0500 Subject: [PATCH 09/16] Fix: sunrpc: use signed integer for client id Within include/linux/sunrpc/clnt.h:struct rpc_cltn, the cl_clid field is an unsigned integer, which is the type expected by the tracepoint signature. However, looking into net/sunrpc/clnt.c:rpc_alloc_clid(), its allocation considers negative signed integer as errors. Therefore, in order to properly show "-1" in the trace output (rather than MAX_INT) when called with a NULL task->tk_client, move to a signed integer as backing type for the client_id field. Signed-off-by: Mathieu Desnoyers --- instrumentation/events/lttng-module/rpc.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/instrumentation/events/lttng-module/rpc.h b/instrumentation/events/lttng-module/rpc.h index 68c622c0..2d06e557 100644 --- a/instrumentation/events/lttng-module/rpc.h +++ b/instrumentation/events/lttng-module/rpc.h @@ -18,7 +18,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_status, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client->cl_clid) + ctf_integer(int, client_id, task->tk_client->cl_clid) ctf_integer(int, status, task->tk_status) ) ) @@ -43,7 +43,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_status, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client->cl_clid) + ctf_integer(int, client_id, task->tk_client->cl_clid) ctf_integer(int, status, task->tk_status) ) ) @@ -100,7 +100,7 @@ LTTNG_TRACEPOINT_EVENT(rpc_connect_status, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client->cl_clid) + ctf_integer(int, client_id, task->tk_client->cl_clid) ctf_integer(int, status, task->tk_status) ) ) @@ -112,7 +112,7 @@ LTTNG_TRACEPOINT_EVENT(rpc_connect_status, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client->cl_clid) + ctf_integer(int, client_id, task->tk_client->cl_clid) ctf_integer(int, status, status) ) ) @@ -139,7 +139,8 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_running, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client ? task->tk_client->cl_clid : -1) + ctf_integer(int, client_id, task->tk_client ? + task->tk_client->cl_clid : -1) ctf_integer_hex(const void *, action, action) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) @@ -176,7 +177,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_queued, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client ? + ctf_integer(int, client_id, task->tk_client ? task->tk_client->cl_clid : -1) ctf_integer(unsigned long, timeout, task->tk_timeout) ctf_integer(unsigned long, runstate, task->tk_runstate) @@ -209,7 +210,8 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_running, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client ? task->tk_client->cl_clid : -1) + ctf_integer(int, client_id, task->tk_client ? + task->tk_client->cl_clid : -1) ctf_integer_hex(const void *, action, action) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) @@ -246,7 +248,8 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_queued, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(unsigned int, client_id, task->tk_client->cl_clid) + ctf_integer(int, client_id, task->tk_client ? + task->tk_client->cl_clid : -1) ctf_integer(unsigned long, timeout, task->tk_timeout) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) -- 2.34.1 From b6903d57e4c3234ec5b1c7f72e232023cdee0fab Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 12 Dec 2019 10:39:38 -0500 Subject: [PATCH 10/16] sunrpc: introduce lttng_get_clid helper Introduce the lttng_get_clid helper to always check for NULL pointer when getting the client id. While not always strictly needed depending on the tracepoint callsite, prefer robustness of instrumentation and always check for NULL rather than play whack-a-mole. Signed-off-by: Mathieu Desnoyers --- instrumentation/events/lttng-module/rpc.h | 43 ++++++++++++++++------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/instrumentation/events/lttng-module/rpc.h b/instrumentation/events/lttng-module/rpc.h index 2d06e557..ceaf9dbf 100644 --- a/instrumentation/events/lttng-module/rpc.h +++ b/instrumentation/events/lttng-module/rpc.h @@ -9,6 +9,29 @@ #include #include +#ifndef ONCE_LTTNG_RPC_H +#define ONCE_LTTNG_RPC_H + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)) +static inline +int lttng_get_clid(const struct rpc_task *task) +{ + struct rpc_clnt *tk_client; + + tk_client = task->tk_client; + if (!tk_client) + return -1; + /* + * The cl_clid field is always initialized to positive signed + * integers. Negative signed integer values are treated as + * errors. + */ + return (int) tk_client->cl_clid; +} +#endif /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)) */ + +#endif /* ONCE_LTTNG_RPC_H */ + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)) LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_status, @@ -18,7 +41,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_status, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(int, client_id, task->tk_client->cl_clid) + ctf_integer(int, client_id, lttng_get_clid(task)) ctf_integer(int, status, task->tk_status) ) ) @@ -43,7 +66,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_status, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(int, client_id, task->tk_client->cl_clid) + ctf_integer(int, client_id, lttng_get_clid(task)) ctf_integer(int, status, task->tk_status) ) ) @@ -100,7 +123,7 @@ LTTNG_TRACEPOINT_EVENT(rpc_connect_status, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(int, client_id, task->tk_client->cl_clid) + ctf_integer(int, client_id, lttng_get_clid(task)) ctf_integer(int, status, task->tk_status) ) ) @@ -112,7 +135,7 @@ LTTNG_TRACEPOINT_EVENT(rpc_connect_status, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(int, client_id, task->tk_client->cl_clid) + ctf_integer(int, client_id, lttng_get_clid(task)) ctf_integer(int, status, status) ) ) @@ -139,8 +162,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_running, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(int, client_id, task->tk_client ? - task->tk_client->cl_clid : -1) + ctf_integer(int, client_id, lttng_get_clid(task)) ctf_integer_hex(const void *, action, action) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) @@ -177,8 +199,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_queued, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(int, client_id, task->tk_client ? - task->tk_client->cl_clid : -1) + ctf_integer(int, client_id, lttng_get_clid(task)) ctf_integer(unsigned long, timeout, task->tk_timeout) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) @@ -210,8 +231,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_running, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(int, client_id, task->tk_client ? - task->tk_client->cl_clid : -1) + ctf_integer(int, client_id, lttng_get_clid(task)) ctf_integer_hex(const void *, action, action) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) @@ -248,8 +268,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(rpc_task_queued, TP_FIELDS( ctf_integer(unsigned int, task_id, task->tk_pid) - ctf_integer(int, client_id, task->tk_client ? - task->tk_client->cl_clid : -1) + ctf_integer(int, client_id, lttng_get_clid(task)) ctf_integer(unsigned long, timeout, task->tk_timeout) ctf_integer(unsigned long, runstate, task->tk_runstate) ctf_integer(int, status, task->tk_status) -- 2.34.1 From ac4a87e53febd0dfc438ce75948e57d649d3b113 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 23 Oct 2019 12:56:59 -0400 Subject: [PATCH 11/16] lttng-clear: stop tracing required Require that tracing is stopped when buffers are cleared. Update comments and warning checks to that effect. Signed-off-by: Mathieu Desnoyers --- lib/ringbuffer/frontend_internal.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/ringbuffer/frontend_internal.h b/lib/ringbuffer/frontend_internal.h index a1bfe558..04838614 100644 --- a/lib/ringbuffer/frontend_internal.h +++ b/lib/ringbuffer/frontend_internal.h @@ -189,7 +189,12 @@ void lib_ring_buffer_reserve_push_reader(struct lib_ring_buffer *buf, /* * Move consumed position to the beginning of subbuffer in which the - * write offset is. + * write offset is. Should only be used on ring buffers that are not + * actively being written into, because clear_reader does not take into + * account the commit counters when moving the consumed position, which + * can make concurrent trace producers or consumers observe consumed + * position further than the write offset, which breaks ring buffer + * algorithm guarantees. */ static inline void lib_ring_buffer_clear_reader(struct lib_ring_buffer *buf, @@ -201,12 +206,10 @@ void lib_ring_buffer_clear_reader(struct lib_ring_buffer *buf, do { offset = v_read(config, &buf->offset); consumed_old = atomic_long_read(&buf->consumed); - if (unlikely(subbuf_trunc(offset, chan) - - subbuf_trunc(consumed_old, chan) - > 0)) - consumed_new = subbuf_trunc(offset, chan); - else - return; + CHAN_WARN_ON(chan, (long) (subbuf_trunc(offset, chan) + - subbuf_trunc(consumed_old, chan)) + < 0); + consumed_new = subbuf_trunc(offset, chan); } while (unlikely(atomic_long_cmpxchg(&buf->consumed, consumed_old, consumed_new) != consumed_old)); } -- 2.34.1 From 436f640717bab63240d9a624846d947e150a2cee Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 17 Dec 2019 09:27:54 -0500 Subject: [PATCH 12/16] lttng-abi: Document ioctl numbers reserved by lttng-abi-old.h Document the ioctl numbers reserved by lttng-abi-old.h in the (relatively) new lttng-abi.h, so they are taken into account when assining numbers to new lttng ioctl commands. Signed-off-by: Mathieu Desnoyers --- lttng-abi.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lttng-abi.h b/lttng-abi.h index f61a6a15..9d345f4a 100644 --- a/lttng-abi.h +++ b/lttng-abi.h @@ -209,6 +209,7 @@ struct lttng_kernel_filter_bytecode { } __attribute__((packed)); /* LTTng file descriptor ioctl */ +/* lttng-abi-old.h reserve 0x40, 0x41, 0x42, 0x43, and 0x44. */ #define LTTNG_KERNEL_SESSION _IO(0xF6, 0x45) #define LTTNG_KERNEL_TRACER_VERSION \ _IOR(0xF6, 0x46, struct lttng_kernel_tracer_version) @@ -221,6 +222,7 @@ struct lttng_kernel_filter_bytecode { _IOR(0xF6, 0x4B, struct lttng_kernel_tracer_abi_version) /* Session FD ioctl */ +/* lttng-abi-old.h reserve 0x50, 0x51, 0x52, and 0x53. */ #define LTTNG_KERNEL_METADATA \ _IOW(0xF6, 0x54, struct lttng_kernel_channel) #define LTTNG_KERNEL_CHANNEL \ @@ -239,7 +241,7 @@ struct lttng_kernel_filter_bytecode { #define LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS _IO(0xF6, 0x58) #define LTTNG_KERNEL_SESSION_METADATA_REGEN _IO(0xF6, 0x59) -/* 0x5A and 0x5B are reserved for a future ABI-breaking cleanup. */ +/* lttng-abi-old.h reserve 0x5A and 0x5B. */ #define LTTNG_KERNEL_SESSION_STATEDUMP _IO(0xF6, 0x5C) #define LTTNG_KERNEL_SESSION_SET_NAME \ _IOR(0xF6, 0x5D, struct lttng_kernel_session_name) @@ -247,6 +249,7 @@ struct lttng_kernel_filter_bytecode { _IOR(0xF6, 0x5E, struct lttng_kernel_session_creation_time) /* Channel FD ioctl */ +/* lttng-abi-old.h reserve 0x60 and 0x61. */ #define LTTNG_KERNEL_STREAM _IO(0xF6, 0x62) #define LTTNG_KERNEL_EVENT \ _IOW(0xF6, 0x63, struct lttng_kernel_event) @@ -254,10 +257,12 @@ struct lttng_kernel_filter_bytecode { _IOWR(0xF6, 0x64, struct lttng_kernel_syscall_mask) /* Event and Channel FD ioctl */ +/* lttng-abi-old.h reserve 0x70. */ #define LTTNG_KERNEL_CONTEXT \ _IOW(0xF6, 0x71, struct lttng_kernel_context) /* Event, Channel and Session ioctl */ +/* lttng-abi-old.h reserve 0x80 and 0x81. */ #define LTTNG_KERNEL_ENABLE _IO(0xF6, 0x82) #define LTTNG_KERNEL_DISABLE _IO(0xF6, 0x83) -- 2.34.1 From d1f652f8d4f6d1de8f6d32ae8711d6469c38892c Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 17 Dec 2019 10:17:01 -0500 Subject: [PATCH 13/16] ID tracker: implement vpid/uid/vuid/gid/vgid trackers Co-developed-by: Jonathan Rajotte Signed-off-by: Jonathan Rajotte Signed-off-by: Mathieu Desnoyers --- Makefile | 2 +- lttng-abi.c | 78 ++++++++- lttng-abi.h | 25 +++ lttng-events.c | 245 +++++++++++++++------------ lttng-events.h | 59 +++++-- lttng-tracker-id.c | 192 +++++++++++++++++++++ lttng-tracker-pid.c | 145 ---------------- probes/lttng-tracepoint-event-impl.h | 51 +++++- 8 files changed, 518 insertions(+), 279 deletions(-) create mode 100644 lttng-tracker-id.c delete mode 100644 lttng-tracker-pid.c diff --git a/Makefile b/Makefile index 709b5dc0..4a6ddbc5 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ ifneq ($(KERNELRELEASE),) lttng-context-hostname.o wrapper/random.o \ probes/lttng.o wrapper/trace-clock.o \ wrapper/page_alloc.o \ - lttng-tracker-pid.o \ + lttng-tracker-id.o \ lttng-filter.o lttng-filter-interpreter.o \ lttng-filter-specialize.o \ lttng-filter-validator.o \ diff --git a/lttng-abi.c b/lttng-abi.c index 5c6f384d..4df3d673 100644 --- a/lttng-abi.c +++ b/lttng-abi.c @@ -525,6 +525,27 @@ int lttng_abi_session_set_creation_time(struct lttng_session *session, return 0; } +static +enum tracker_type get_tracker_type(struct lttng_kernel_tracker_args *tracker) +{ + switch (tracker->type) { + case LTTNG_KERNEL_TRACKER_PID: + return TRACKER_PID; + case LTTNG_KERNEL_TRACKER_VPID: + return TRACKER_VPID; + case LTTNG_KERNEL_TRACKER_UID: + return TRACKER_UID; + case LTTNG_KERNEL_TRACKER_VUID: + return TRACKER_VUID; + case LTTNG_KERNEL_TRACKER_GID: + return TRACKER_GID; + case LTTNG_KERNEL_TRACKER_VGID: + return TRACKER_VGID; + default: + return TRACKER_UNKNOWN; + } +} + /** * lttng_session_ioctl - lttng session fd ioctl * @@ -542,9 +563,13 @@ int lttng_abi_session_set_creation_time(struct lttng_session *session, * LTTNG_KERNEL_METADATA * Returns a LTTng metadata file descriptor * LTTNG_KERNEL_SESSION_TRACK_PID - * Add PID to session tracker + * Add PID to session PID tracker * LTTNG_KERNEL_SESSION_UNTRACK_PID - * Remove PID from session tracker + * Remove PID from session PID tracker + * LTTNG_KERNEL_SESSION_TRACK_ID + * Add ID to tracker + * LTTNG_KERNEL_SESSION_UNTRACK_ID + * Remove ID from tracker * * The returned channel will be deleted when its file descriptor is closed. */ @@ -617,11 +642,54 @@ long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) METADATA_CHANNEL); } case LTTNG_KERNEL_SESSION_TRACK_PID: - return lttng_session_track_pid(session, (int) arg); + return lttng_session_track_id(session, TRACKER_PID, (int) arg); case LTTNG_KERNEL_SESSION_UNTRACK_PID: - return lttng_session_untrack_pid(session, (int) arg); + return lttng_session_untrack_id(session, TRACKER_PID, (int) arg); + case LTTNG_KERNEL_SESSION_TRACK_ID: + { + struct lttng_kernel_tracker_args tracker; + enum tracker_type tracker_type; + + if (copy_from_user(&tracker, + (struct lttng_kernel_tracker_args __user *) arg, + sizeof(struct lttng_kernel_tracker_args))) + return -EFAULT; + tracker_type = get_tracker_type(&tracker); + if (tracker_type == TRACKER_UNKNOWN) + return -EINVAL; + return lttng_session_track_id(session, tracker_type, tracker.id); + } + case LTTNG_KERNEL_SESSION_UNTRACK_ID: + { + struct lttng_kernel_tracker_args tracker; + enum tracker_type tracker_type; + + if (copy_from_user(&tracker, + (struct lttng_kernel_tracker_args __user *) arg, + sizeof(struct lttng_kernel_tracker_args))) + return -EFAULT; + tracker_type = get_tracker_type(&tracker); + if (tracker_type == TRACKER_UNKNOWN) + return -EINVAL; + return lttng_session_untrack_id(session, tracker_type, + tracker.id); + } case LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS: - return lttng_session_list_tracker_pids(session); + return lttng_session_list_tracker_ids(session, TRACKER_PID); + case LTTNG_KERNEL_SESSION_LIST_TRACKER_IDS: + { + struct lttng_kernel_tracker_args tracker; + enum tracker_type tracker_type; + + if (copy_from_user(&tracker, + (struct lttng_kernel_tracker_args __user *) arg, + sizeof(struct lttng_kernel_tracker_args))) + return -EFAULT; + tracker_type = get_tracker_type(&tracker); + if (tracker_type == TRACKER_UNKNOWN) + return -EINVAL; + return lttng_session_list_tracker_ids(session, tracker_type); + } case LTTNG_KERNEL_SESSION_METADATA_REGEN: return lttng_session_metadata_regenerate(session); case LTTNG_KERNEL_SESSION_STATEDUMP: diff --git a/lttng-abi.h b/lttng-abi.h index 9d345f4a..5c5d8256 100644 --- a/lttng-abi.h +++ b/lttng-abi.h @@ -208,6 +208,22 @@ struct lttng_kernel_filter_bytecode { char data[0]; } __attribute__((packed)); +enum lttng_kernel_tracker_type { + LTTNG_KERNEL_TRACKER_UNKNOWN = -1, + + LTTNG_KERNEL_TRACKER_PID = 0, + LTTNG_KERNEL_TRACKER_VPID = 1, + LTTNG_KERNEL_TRACKER_UID = 2, + LTTNG_KERNEL_TRACKER_VUID = 3, + LTTNG_KERNEL_TRACKER_GID = 4, + LTTNG_KERNEL_TRACKER_VGID = 5, +}; + +struct lttng_kernel_tracker_args { + enum lttng_kernel_tracker_type type; + int32_t id; +}; + /* LTTng file descriptor ioctl */ /* lttng-abi-old.h reserve 0x40, 0x41, 0x42, 0x43, and 0x44. */ #define LTTNG_KERNEL_SESSION _IO(0xF6, 0x45) @@ -233,6 +249,7 @@ struct lttng_kernel_filter_bytecode { _IOR(0xF6, 0x58, int32_t) #define LTTNG_KERNEL_SESSION_UNTRACK_PID \ _IOR(0xF6, 0x59, int32_t) + /* * ioctl 0x58 and 0x59 are duplicated here. It works, since _IOR vs _IO * are generating two different ioctl numbers, but this was not done on @@ -270,6 +287,14 @@ struct lttng_kernel_filter_bytecode { #define LTTNG_KERNEL_FILTER _IO(0xF6, 0x90) #define LTTNG_KERNEL_ADD_CALLSITE _IO(0xF6, 0x91) +/* Session FD ioctl (continued) */ +#define LTTNG_KERNEL_SESSION_LIST_TRACKER_IDS \ + _IOR(0xF6, 0xA0, struct lttng_kernel_tracker_args) +#define LTTNG_KERNEL_SESSION_TRACK_ID \ + _IOR(0xF6, 0xA1, struct lttng_kernel_tracker_args) +#define LTTNG_KERNEL_SESSION_UNTRACK_ID \ + _IOR(0xF6, 0xA2, struct lttng_kernel_tracker_args) + /* * LTTng-specific ioctls for the lib ringbuffer. * diff --git a/lttng-events.c b/lttng-events.c index 4588153b..1ccbffd6 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -149,6 +149,18 @@ struct lttng_session *lttng_session_create(void) for (i = 0; i < LTTNG_EVENT_HT_SIZE; i++) INIT_HLIST_HEAD(&session->events_ht.table[i]); list_add(&session->list, &sessions); + session->pid_tracker.session = session; + session->pid_tracker.tracker_type = TRACKER_PID; + session->vpid_tracker.session = session; + session->vpid_tracker.tracker_type = TRACKER_VPID; + session->uid_tracker.session = session; + session->uid_tracker.tracker_type = TRACKER_UID; + session->vuid_tracker.session = session; + session->vuid_tracker.tracker_type = TRACKER_VUID; + session->gid_tracker.session = session; + session->gid_tracker.tracker_type = TRACKER_GID; + session->vgid_tracker.session = session; + session->vgid_tracker.tracker_type = TRACKER_VGID; mutex_unlock(&sessions_mutex); return session; @@ -199,8 +211,12 @@ void lttng_session_destroy(struct lttng_session *session) } list_for_each_entry(metadata_stream, &session->metadata_cache->metadata_stream, list) _lttng_metadata_channel_hangup(metadata_stream); - if (session->pid_tracker) - lttng_pid_tracker_destroy(session->pid_tracker); + lttng_id_tracker_destroy(&session->pid_tracker, false); + lttng_id_tracker_destroy(&session->vpid_tracker, false); + lttng_id_tracker_destroy(&session->uid_tracker, false); + lttng_id_tracker_destroy(&session->vuid_tracker, false); + lttng_id_tracker_destroy(&session->gid_tracker, false); + lttng_id_tracker_destroy(&session->vgid_tracker, false); kref_put(&session->metadata_cache->refcount, metadata_cache_destroy); list_del(&session->list); mutex_unlock(&sessions_mutex); @@ -930,91 +946,85 @@ void _lttng_event_destroy(struct lttng_event *event) kmem_cache_free(event_cache, event); } -int lttng_session_track_pid(struct lttng_session *session, int pid) +struct lttng_id_tracker *get_tracker(struct lttng_session *session, + enum tracker_type tracker_type) +{ + switch (tracker_type) { + case TRACKER_PID: + return &session->pid_tracker; + case TRACKER_VPID: + return &session->vpid_tracker; + case TRACKER_UID: + return &session->uid_tracker; + case TRACKER_VUID: + return &session->vuid_tracker; + case TRACKER_GID: + return &session->gid_tracker; + case TRACKER_VGID: + return &session->vgid_tracker; + default: + WARN_ON_ONCE(1); + return NULL; + } +} + +int lttng_session_track_id(struct lttng_session *session, + enum tracker_type tracker_type, int id) { + struct lttng_id_tracker *tracker; int ret; - if (pid < -1) + tracker = get_tracker(session, tracker_type); + if (!tracker) + return -EINVAL; + if (id < -1) return -EINVAL; mutex_lock(&sessions_mutex); - if (pid == -1) { - /* track all pids: destroy tracker. */ - if (session->pid_tracker) { - struct lttng_pid_tracker *lpf; - - lpf = session->pid_tracker; - rcu_assign_pointer(session->pid_tracker, NULL); - synchronize_trace(); - lttng_pid_tracker_destroy(lpf); - } + if (id == -1) { + /* track all ids: destroy tracker. */ + lttng_id_tracker_destroy(tracker, true); ret = 0; } else { - if (!session->pid_tracker) { - struct lttng_pid_tracker *lpf; - - lpf = lttng_pid_tracker_create(); - if (!lpf) { - ret = -ENOMEM; - goto unlock; - } - ret = lttng_pid_tracker_add(lpf, pid); - rcu_assign_pointer(session->pid_tracker, lpf); - } else { - ret = lttng_pid_tracker_add(session->pid_tracker, pid); - } + ret = lttng_id_tracker_add(tracker, id); } -unlock: mutex_unlock(&sessions_mutex); return ret; } -int lttng_session_untrack_pid(struct lttng_session *session, int pid) +int lttng_session_untrack_id(struct lttng_session *session, + enum tracker_type tracker_type, int id) { + struct lttng_id_tracker *tracker; int ret; - if (pid < -1) + tracker = get_tracker(session, tracker_type); + if (!tracker) + return -EINVAL; + if (id < -1) return -EINVAL; mutex_lock(&sessions_mutex); - if (pid == -1) { - /* untrack all pids: replace by empty tracker. */ - struct lttng_pid_tracker *old_lpf = session->pid_tracker; - struct lttng_pid_tracker *lpf; - - lpf = lttng_pid_tracker_create(); - if (!lpf) { - ret = -ENOMEM; - goto unlock; - } - rcu_assign_pointer(session->pid_tracker, lpf); - synchronize_trace(); - if (old_lpf) - lttng_pid_tracker_destroy(old_lpf); - ret = 0; + if (id == -1) { + /* untrack all ids: replace by empty tracker. */ + ret = lttng_id_tracker_empty_set(tracker); } else { - if (!session->pid_tracker) { - ret = -ENOENT; - goto unlock; - } - ret = lttng_pid_tracker_del(session->pid_tracker, pid); + ret = lttng_id_tracker_del(tracker, id); } -unlock: mutex_unlock(&sessions_mutex); return ret; } static -void *pid_list_start(struct seq_file *m, loff_t *pos) +void *id_list_start(struct seq_file *m, loff_t *pos) { - struct lttng_session *session = m->private; - struct lttng_pid_tracker *lpf; - struct lttng_pid_hash_node *e; + struct lttng_id_tracker *id_tracker = m->private; + struct lttng_id_tracker_rcu *id_tracker_p = id_tracker->p; + struct lttng_id_hash_node *e; int iter = 0, i; mutex_lock(&sessions_mutex); - lpf = session->pid_tracker; - if (lpf) { - for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) { - struct hlist_head *head = &lpf->pid_hash[i]; + if (id_tracker_p) { + for (i = 0; i < LTTNG_ID_TABLE_SIZE; i++) { + struct hlist_head *head = &id_tracker_p->id_hash[i]; lttng_hlist_for_each_entry(e, head, hlist) { if (iter++ >= *pos) @@ -1022,9 +1032,9 @@ void *pid_list_start(struct seq_file *m, loff_t *pos) } } } else { - /* PID tracker disabled. */ + /* ID tracker disabled. */ if (iter >= *pos && iter == 0) { - return session; /* empty tracker */ + return id_tracker_p; /* empty tracker */ } iter++; } @@ -1034,18 +1044,17 @@ void *pid_list_start(struct seq_file *m, loff_t *pos) /* Called with sessions_mutex held. */ static -void *pid_list_next(struct seq_file *m, void *p, loff_t *ppos) +void *id_list_next(struct seq_file *m, void *p, loff_t *ppos) { - struct lttng_session *session = m->private; - struct lttng_pid_tracker *lpf; - struct lttng_pid_hash_node *e; + struct lttng_id_tracker *id_tracker = m->private; + struct lttng_id_tracker_rcu *id_tracker_p = id_tracker->p; + struct lttng_id_hash_node *e; int iter = 0, i; (*ppos)++; - lpf = session->pid_tracker; - if (lpf) { - for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) { - struct hlist_head *head = &lpf->pid_hash[i]; + if (id_tracker_p) { + for (i = 0; i < LTTNG_ID_TABLE_SIZE; i++) { + struct hlist_head *head = &id_tracker_p->id_hash[i]; lttng_hlist_for_each_entry(e, head, hlist) { if (iter++ >= *ppos) @@ -1053,9 +1062,9 @@ void *pid_list_next(struct seq_file *m, void *p, loff_t *ppos) } } } else { - /* PID tracker disabled. */ + /* ID tracker disabled. */ if (iter >= *ppos && iter == 0) - return session; /* empty tracker */ + return p; /* empty tracker */ iter++; } @@ -1064,67 +1073,91 @@ void *pid_list_next(struct seq_file *m, void *p, loff_t *ppos) } static -void pid_list_stop(struct seq_file *m, void *p) +void id_list_stop(struct seq_file *m, void *p) { mutex_unlock(&sessions_mutex); } static -int pid_list_show(struct seq_file *m, void *p) +int id_list_show(struct seq_file *m, void *p) { - int pid; + struct lttng_id_tracker *id_tracker = m->private; + struct lttng_id_tracker_rcu *id_tracker_p = id_tracker->p; + int id; - if (p == m->private) { + if (p == id_tracker_p) { /* Tracker disabled. */ - pid = -1; + id = -1; } else { - const struct lttng_pid_hash_node *e = p; + const struct lttng_id_hash_node *e = p; - pid = lttng_pid_tracker_get_node_pid(e); + id = lttng_id_tracker_get_node_id(e); + } + switch (id_tracker->tracker_type) { + case TRACKER_PID: + seq_printf(m, "process { pid = %d; };\n", id); + break; + case TRACKER_VPID: + seq_printf(m, "process { vpid = %d; };\n", id); + break; + case TRACKER_UID: + seq_printf(m, "user { uid = %d; };\n", id); + break; + case TRACKER_VUID: + seq_printf(m, "user { vuid = %d; };\n", id); + break; + case TRACKER_GID: + seq_printf(m, "group { gid = %d; };\n", id); + break; + case TRACKER_VGID: + seq_printf(m, "group { vgid = %d; };\n", id); + break; + default: + seq_printf(m, "UNKNOWN { field = %d };\n", id); } - seq_printf(m, "process { pid = %d; };\n", pid); return 0; } static -const struct seq_operations lttng_tracker_pids_list_seq_ops = { - .start = pid_list_start, - .next = pid_list_next, - .stop = pid_list_stop, - .show = pid_list_show, +const struct seq_operations lttng_tracker_ids_list_seq_ops = { + .start = id_list_start, + .next = id_list_next, + .stop = id_list_stop, + .show = id_list_show, }; static -int lttng_tracker_pids_list_open(struct inode *inode, struct file *file) +int lttng_tracker_ids_list_open(struct inode *inode, struct file *file) { - return seq_open(file, <tng_tracker_pids_list_seq_ops); + return seq_open(file, <tng_tracker_ids_list_seq_ops); } static -int lttng_tracker_pids_list_release(struct inode *inode, struct file *file) +int lttng_tracker_ids_list_release(struct inode *inode, struct file *file) { struct seq_file *m = file->private_data; - struct lttng_session *session = m->private; + struct lttng_id_tracker *id_tracker = m->private; int ret; - WARN_ON_ONCE(!session); + WARN_ON_ONCE(!id_tracker); ret = seq_release(inode, file); - if (!ret && session) - fput(session->file); + if (!ret) + fput(id_tracker->session->file); return ret; } -const struct file_operations lttng_tracker_pids_list_fops = { +const struct file_operations lttng_tracker_ids_list_fops = { .owner = THIS_MODULE, - .open = lttng_tracker_pids_list_open, + .open = lttng_tracker_ids_list_open, .read = seq_read, .llseek = seq_lseek, - .release = lttng_tracker_pids_list_release, + .release = lttng_tracker_ids_list_release, }; -int lttng_session_list_tracker_pids(struct lttng_session *session) +int lttng_session_list_tracker_ids(struct lttng_session *session, + enum tracker_type tracker_type) { - struct file *tracker_pids_list_file; + struct file *tracker_ids_list_file; struct seq_file *m; int file_fd, ret; @@ -1134,30 +1167,32 @@ int lttng_session_list_tracker_pids(struct lttng_session *session) goto fd_error; } - tracker_pids_list_file = anon_inode_getfile("[lttng_tracker_pids_list]", - <tng_tracker_pids_list_fops, + tracker_ids_list_file = anon_inode_getfile("[lttng_tracker_ids_list]", + <tng_tracker_ids_list_fops, NULL, O_RDWR); - if (IS_ERR(tracker_pids_list_file)) { - ret = PTR_ERR(tracker_pids_list_file); + if (IS_ERR(tracker_ids_list_file)) { + ret = PTR_ERR(tracker_ids_list_file); goto file_error; } if (!atomic_long_add_unless(&session->file->f_count, 1, LONG_MAX)) { ret = -EOVERFLOW; goto refcount_error; } - ret = lttng_tracker_pids_list_fops.open(NULL, tracker_pids_list_file); + ret = lttng_tracker_ids_list_fops.open(NULL, tracker_ids_list_file); if (ret < 0) goto open_error; - m = tracker_pids_list_file->private_data; - m->private = session; - fd_install(file_fd, tracker_pids_list_file); + m = tracker_ids_list_file->private_data; + + m->private = get_tracker(session, tracker_type); + BUG_ON(!m->private); + fd_install(file_fd, tracker_ids_list_file); return file_fd; open_error: atomic_long_dec(&session->file->f_count); refcount_error: - fput(tracker_pids_list_file); + fput(tracker_ids_list_file); file_error: put_unused_fd(file_fd); fd_error: diff --git a/lttng-events.h b/lttng-events.h index cdb520e8..78b427a3 100644 --- a/lttng-events.h +++ b/lttng-events.h @@ -489,19 +489,36 @@ struct lttng_dynamic_len_stack { DECLARE_PER_CPU(struct lttng_dynamic_len_stack, lttng_dynamic_len_stack); /* - * struct lttng_pid_tracker declared in header due to deferencing of *v + * struct lttng_id_tracker declared in header due to deferencing of *v * in RCU_INITIALIZER(v). */ -#define LTTNG_PID_HASH_BITS 6 -#define LTTNG_PID_TABLE_SIZE (1 << LTTNG_PID_HASH_BITS) +#define LTTNG_ID_HASH_BITS 6 +#define LTTNG_ID_TABLE_SIZE (1 << LTTNG_ID_HASH_BITS) -struct lttng_pid_tracker { - struct hlist_head pid_hash[LTTNG_PID_TABLE_SIZE]; +enum tracker_type { + TRACKER_PID, + TRACKER_VPID, + TRACKER_UID, + TRACKER_VUID, + TRACKER_GID, + TRACKER_VGID, + + TRACKER_UNKNOWN, +}; + +struct lttng_id_tracker_rcu { + struct hlist_head id_hash[LTTNG_ID_TABLE_SIZE]; +}; + +struct lttng_id_tracker { + struct lttng_session *session; + enum tracker_type tracker_type; + struct lttng_id_tracker_rcu *p; /* RCU dereferenced. */ }; -struct lttng_pid_hash_node { +struct lttng_id_hash_node { struct hlist_node hlist; - int pid; + int id; }; struct lttng_session { @@ -514,7 +531,12 @@ struct lttng_session { unsigned int free_chan_id; /* Next chan ID to allocate */ uuid_le uuid; /* Trace session unique ID */ struct lttng_metadata_cache *metadata_cache; - struct lttng_pid_tracker *pid_tracker; + struct lttng_id_tracker pid_tracker; + struct lttng_id_tracker vpid_tracker; + struct lttng_id_tracker uid_tracker; + struct lttng_id_tracker vuid_tracker; + struct lttng_id_tracker gid_tracker; + struct lttng_id_tracker vgid_tracker; unsigned int metadata_dumped:1, tstate:1; /* Transient enable state */ /* List of enablers */ @@ -611,17 +633,20 @@ void lttng_probes_exit(void); int lttng_metadata_output_channel(struct lttng_metadata_stream *stream, struct channel *chan); -int lttng_pid_tracker_get_node_pid(const struct lttng_pid_hash_node *node); -struct lttng_pid_tracker *lttng_pid_tracker_create(void); -void lttng_pid_tracker_destroy(struct lttng_pid_tracker *lpf); -bool lttng_pid_tracker_lookup(struct lttng_pid_tracker *lpf, int pid); -int lttng_pid_tracker_add(struct lttng_pid_tracker *lpf, int pid); -int lttng_pid_tracker_del(struct lttng_pid_tracker *lpf, int pid); +int lttng_id_tracker_get_node_id(const struct lttng_id_hash_node *node); +int lttng_id_tracker_empty_set(struct lttng_id_tracker *lf); +void lttng_id_tracker_destroy(struct lttng_id_tracker *lf, bool rcu); +bool lttng_id_tracker_lookup(struct lttng_id_tracker_rcu *p, int id); +int lttng_id_tracker_add(struct lttng_id_tracker *lf, int id); +int lttng_id_tracker_del(struct lttng_id_tracker *lf, int id); -int lttng_session_track_pid(struct lttng_session *session, int pid); -int lttng_session_untrack_pid(struct lttng_session *session, int pid); +int lttng_session_track_id(struct lttng_session *session, + enum tracker_type tracker_type, int id); +int lttng_session_untrack_id(struct lttng_session *session, + enum tracker_type tracker_type, int id); -int lttng_session_list_tracker_pids(struct lttng_session *session); +int lttng_session_list_tracker_ids(struct lttng_session *session, + enum tracker_type tracker_type); void lttng_clock_ref(void); void lttng_clock_unref(void); diff --git a/lttng-tracker-id.c b/lttng-tracker-id.c new file mode 100644 index 00000000..9a4b98b2 --- /dev/null +++ b/lttng-tracker-id.c @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * lttng-tracker-pid.c + * + * LTTng Process ID tracking. + * + * Copyright (C) 2014 Mathieu Desnoyers + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Hash table is allocated and freed when there are no possible + * concurrent lookups (ensured by the alloc/free caller). However, + * there can be concurrent RCU lookups vs add/del operations. + * + * Concurrent updates of the PID hash table are forbidden: the caller + * must ensure mutual exclusion. This is currently done by holding the + * sessions_mutex across calls to create, destroy, add, and del + * functions of this API. + */ +int lttng_id_tracker_get_node_id(const struct lttng_id_hash_node *node) +{ + return node->id; +} + +/* + * Lookup performed from RCU read-side critical section (RCU sched), + * protected by preemption off at the tracepoint call site. + * Return true if found, false if not found. + */ +bool lttng_id_tracker_lookup(struct lttng_id_tracker_rcu *p, int id) +{ + struct hlist_head *head; + struct lttng_id_hash_node *e; + uint32_t hash = hash_32(id, 32); + + head = &p->id_hash[hash & (LTTNG_ID_TABLE_SIZE - 1)]; + lttng_hlist_for_each_entry_rcu(e, head, hlist) { + if (id == e->id) + return true; /* Found */ + } + return false; +} +EXPORT_SYMBOL_GPL(lttng_id_tracker_lookup); + +static struct lttng_id_tracker_rcu *lttng_id_tracker_rcu_create(void) +{ + struct lttng_id_tracker_rcu *tracker; + + tracker = kzalloc(sizeof(struct lttng_id_tracker_rcu), GFP_KERNEL); + if (!tracker) + return NULL; + return tracker; +} + +/* + * Tracker add and del operations support concurrent RCU lookups. + */ +int lttng_id_tracker_add(struct lttng_id_tracker *lf, int id) +{ + struct hlist_head *head; + struct lttng_id_hash_node *e; + struct lttng_id_tracker_rcu *p = lf->p; + uint32_t hash = hash_32(id, 32); + bool allocated = false; + + if (!p) { + p = lttng_id_tracker_rcu_create(); + if (!p) + return -ENOMEM; + allocated = true; + } + head = &p->id_hash[hash & (LTTNG_ID_TABLE_SIZE - 1)]; + lttng_hlist_for_each_entry(e, head, hlist) { + if (id == e->id) + return -EEXIST; + } + e = kmalloc(sizeof(struct lttng_id_hash_node), GFP_KERNEL); + if (!e) + return -ENOMEM; + e->id = id; + hlist_add_head_rcu(&e->hlist, head); + if (allocated) { + rcu_assign_pointer(lf->p, p); + } + return 0; +} + +static +void id_tracker_del_node_rcu(struct lttng_id_hash_node *e) +{ + hlist_del_rcu(&e->hlist); + /* + * We choose to use a heavyweight synchronize on removal here, + * since removal of an ID from the tracker mask is a rare + * operation, and we don't want to use more cache lines than + * what we really need when doing the ID lookups, so we don't + * want to afford adding a rcu_head field to those pid hash + * node. + */ + synchronize_trace(); + kfree(e); +} + +/* + * This removal is only used on destroy, so it does not need to support + * concurrent RCU lookups. + */ +static +void id_tracker_del_node(struct lttng_id_hash_node *e) +{ + hlist_del(&e->hlist); + kfree(e); +} + +int lttng_id_tracker_del(struct lttng_id_tracker *lf, int id) +{ + struct hlist_head *head; + struct lttng_id_hash_node *e; + struct lttng_id_tracker_rcu *p = lf->p; + uint32_t hash = hash_32(id, 32); + + if (!p) + return -ENOENT; + head = &p->id_hash[hash & (LTTNG_ID_TABLE_SIZE - 1)]; + /* + * No need of _safe iteration, because we stop traversal as soon + * as we remove the entry. + */ + lttng_hlist_for_each_entry(e, head, hlist) { + if (id == e->id) { + id_tracker_del_node_rcu(e); + return 0; + } + } + return -ENOENT; /* Not found */ +} + +static void lttng_id_tracker_rcu_destroy(struct lttng_id_tracker_rcu *p) +{ + int i; + + if (!p) + return; + for (i = 0; i < LTTNG_ID_TABLE_SIZE; i++) { + struct hlist_head *head = &p->id_hash[i]; + struct lttng_id_hash_node *e; + struct hlist_node *tmp; + + lttng_hlist_for_each_entry_safe(e, tmp, head, hlist) + id_tracker_del_node(e); + } + kfree(p); +} + +int lttng_id_tracker_empty_set(struct lttng_id_tracker *lf) +{ + struct lttng_id_tracker_rcu *p, *oldp; + + p = lttng_id_tracker_rcu_create(); + if (!p) + return -ENOMEM; + oldp = lf->p; + rcu_assign_pointer(lf->p, p); + synchronize_trace(); + lttng_id_tracker_rcu_destroy(oldp); + return 0; +} + +void lttng_id_tracker_destroy(struct lttng_id_tracker *lf, bool rcu) +{ + struct lttng_id_tracker_rcu *p = lf->p; + + if (!lf->p) + return; + rcu_assign_pointer(lf->p, NULL); + if (rcu) + synchronize_trace(); + lttng_id_tracker_rcu_destroy(p); +} diff --git a/lttng-tracker-pid.c b/lttng-tracker-pid.c deleted file mode 100644 index 747aec20..00000000 --- a/lttng-tracker-pid.c +++ /dev/null @@ -1,145 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) - * - * lttng-tracker-pid.c - * - * LTTng Process ID tracking. - * - * Copyright (C) 2014 Mathieu Desnoyers - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * Hash table is allocated and freed when there are no possible - * concurrent lookups (ensured by the alloc/free caller). However, - * there can be concurrent RCU lookups vs add/del operations. - * - * Concurrent updates of the PID hash table are forbidden: the caller - * must ensure mutual exclusion. This is currently done by holding the - * sessions_mutex across calls to create, destroy, add, and del - * functions of this API. - */ -int lttng_pid_tracker_get_node_pid(const struct lttng_pid_hash_node *node) -{ - return node->pid; -} - -/* - * Lookup performed from RCU read-side critical section (RCU sched), - * protected by preemption off at the tracepoint call site. - * Return 1 if found, 0 if not found. - */ -bool lttng_pid_tracker_lookup(struct lttng_pid_tracker *lpf, int pid) -{ - struct hlist_head *head; - struct lttng_pid_hash_node *e; - uint32_t hash = hash_32(pid, 32); - - head = &lpf->pid_hash[hash & (LTTNG_PID_TABLE_SIZE - 1)]; - lttng_hlist_for_each_entry_rcu(e, head, hlist) { - if (pid == e->pid) - return 1; /* Found */ - } - return 0; -} -EXPORT_SYMBOL_GPL(lttng_pid_tracker_lookup); - -/* - * Tracker add and del operations support concurrent RCU lookups. - */ -int lttng_pid_tracker_add(struct lttng_pid_tracker *lpf, int pid) -{ - struct hlist_head *head; - struct lttng_pid_hash_node *e; - uint32_t hash = hash_32(pid, 32); - - head = &lpf->pid_hash[hash & (LTTNG_PID_TABLE_SIZE - 1)]; - lttng_hlist_for_each_entry(e, head, hlist) { - if (pid == e->pid) - return -EEXIST; - } - e = kmalloc(sizeof(struct lttng_pid_hash_node), GFP_KERNEL); - if (!e) - return -ENOMEM; - e->pid = pid; - hlist_add_head_rcu(&e->hlist, head); - return 0; -} - -static -void pid_tracker_del_node_rcu(struct lttng_pid_hash_node *e) -{ - hlist_del_rcu(&e->hlist); - /* - * We choose to use a heavyweight synchronize on removal here, - * since removal of a PID from the tracker mask is a rare - * operation, and we don't want to use more cache lines than - * what we really need when doing the PID lookups, so we don't - * want to afford adding a rcu_head field to those pid hash - * node. - */ - synchronize_trace(); - kfree(e); -} - -/* - * This removal is only used on destroy, so it does not need to support - * concurrent RCU lookups. - */ -static -void pid_tracker_del_node(struct lttng_pid_hash_node *e) -{ - hlist_del(&e->hlist); - kfree(e); -} - -int lttng_pid_tracker_del(struct lttng_pid_tracker *lpf, int pid) -{ - struct hlist_head *head; - struct lttng_pid_hash_node *e; - uint32_t hash = hash_32(pid, 32); - - head = &lpf->pid_hash[hash & (LTTNG_PID_TABLE_SIZE - 1)]; - /* - * No need of _safe iteration, because we stop traversal as soon - * as we remove the entry. - */ - lttng_hlist_for_each_entry(e, head, hlist) { - if (pid == e->pid) { - pid_tracker_del_node_rcu(e); - return 0; - } - } - return -ENOENT; /* Not found */ -} - -struct lttng_pid_tracker *lttng_pid_tracker_create(void) -{ - return kzalloc(sizeof(struct lttng_pid_tracker), GFP_KERNEL); -} - -void lttng_pid_tracker_destroy(struct lttng_pid_tracker *lpf) -{ - int i; - - for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) { - struct hlist_head *head = &lpf->pid_hash[i]; - struct lttng_pid_hash_node *e; - struct hlist_node *tmp; - - lttng_hlist_for_each_entry_safe(e, tmp, head, hlist) - pid_tracker_del_node(e); - } - kfree(lpf); -} diff --git a/probes/lttng-tracepoint-event-impl.h b/probes/lttng-tracepoint-event-impl.h index 3fe9d995..39454fb3 100644 --- a/probes/lttng-tracepoint-event-impl.h +++ b/probes/lttng-tracepoint-event-impl.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -1127,7 +1128,7 @@ static void __event_probe__##_name(void *__data, _proto) \ struct probe_local_vars __tp_locvar; \ struct probe_local_vars *tp_locvar __attribute__((unused)) = \ &__tp_locvar; \ - struct lttng_pid_tracker *__lpf; \ + struct lttng_id_tracker_rcu *__lf; \ \ if (!_TP_SESSION_CHECK(session, __session)) \ return; \ @@ -1137,8 +1138,27 @@ static void __event_probe__##_name(void *__data, _proto) \ return; \ if (unlikely(!READ_ONCE(__event->enabled))) \ return; \ - __lpf = lttng_rcu_dereference(__session->pid_tracker); \ - if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->tgid))) \ + __lf = lttng_rcu_dereference(__session->pid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, current->tgid))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vpid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, task_tgid_vnr(current)))) \ + return; \ + __lf = lttng_rcu_dereference(__session->uid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kuid(&init_user_ns, current_uid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vuid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kuid(current_user_ns(), current_uid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->gid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kgid(&init_user_ns, current_gid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vgid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kgid(current_user_ns(), current_gid())))) \ return; \ __orig_dynamic_len_offset = this_cpu_ptr(<tng_dynamic_len_stack)->offset; \ __dynamic_len_idx = __orig_dynamic_len_offset; \ @@ -1201,7 +1221,7 @@ static void __event_probe__##_name(void *__data) \ struct probe_local_vars __tp_locvar; \ struct probe_local_vars *tp_locvar __attribute__((unused)) = \ &__tp_locvar; \ - struct lttng_pid_tracker *__lpf; \ + struct lttng_id_tracker_rcu *__lf; \ \ if (!_TP_SESSION_CHECK(session, __session)) \ return; \ @@ -1211,8 +1231,27 @@ static void __event_probe__##_name(void *__data) \ return; \ if (unlikely(!READ_ONCE(__event->enabled))) \ return; \ - __lpf = lttng_rcu_dereference(__session->pid_tracker); \ - if (__lpf && likely(!lttng_pid_tracker_lookup(__lpf, current->tgid))) \ + __lf = lttng_rcu_dereference(__session->pid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, current->tgid))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vpid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, task_tgid_vnr(current)))) \ + return; \ + __lf = lttng_rcu_dereference(__session->uid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kuid(&init_user_ns, current_uid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vuid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kuid(current_user_ns(), current_uid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->gid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kgid(&init_user_ns, current_gid())))) \ + return; \ + __lf = lttng_rcu_dereference(__session->vgid_tracker.p); \ + if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ + from_kgid(current_user_ns(), current_gid())))) \ return; \ __orig_dynamic_len_offset = this_cpu_ptr(<tng_dynamic_len_stack)->offset; \ __dynamic_len_idx = __orig_dynamic_len_offset; \ -- 2.34.1 From 9ca756f5210e793d27ad63bf36732e910ed8afec Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Tue, 17 Dec 2019 12:11:10 -0500 Subject: [PATCH 14/16] fix: function prototype in wrapper/mm.h Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- wrapper/mm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrapper/mm.h b/wrapper/mm.h index 672855b1..405248a9 100644 --- a/wrapper/mm.h +++ b/wrapper/mm.h @@ -62,7 +62,7 @@ void wrapper_set_current_oom_origin(void) } static inline -void wrapper_clear_current_oom_origin() +void wrapper_clear_current_oom_origin(void) { return; } -- 2.34.1 From 608416e12e18b55329d670d6a02f0b895b6bff4f Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Tue, 17 Dec 2019 12:11:11 -0500 Subject: [PATCH 15/16] fix: use user ns wrapper code in new id trackers These wrappers are required to translate kuid on kernels prior to v3.5. Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- probes/lttng-tracepoint-event-impl.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/probes/lttng-tracepoint-event-impl.h b/probes/lttng-tracepoint-event-impl.h index 39454fb3..321cdfa4 100644 --- a/probes/lttng-tracepoint-event-impl.h +++ b/probes/lttng-tracepoint-event-impl.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -20,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1146,19 +1146,19 @@ static void __event_probe__##_name(void *__data, _proto) \ return; \ __lf = lttng_rcu_dereference(__session->uid_tracker.p); \ if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ - from_kuid(&init_user_ns, current_uid())))) \ + lttng_current_uid()))) \ return; \ __lf = lttng_rcu_dereference(__session->vuid_tracker.p); \ if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ - from_kuid(current_user_ns(), current_uid())))) \ + lttng_current_vuid()))) \ return; \ __lf = lttng_rcu_dereference(__session->gid_tracker.p); \ if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ - from_kgid(&init_user_ns, current_gid())))) \ + lttng_current_gid()))) \ return; \ __lf = lttng_rcu_dereference(__session->vgid_tracker.p); \ if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ - from_kgid(current_user_ns(), current_gid())))) \ + lttng_current_vgid()))) \ return; \ __orig_dynamic_len_offset = this_cpu_ptr(<tng_dynamic_len_stack)->offset; \ __dynamic_len_idx = __orig_dynamic_len_offset; \ @@ -1239,19 +1239,19 @@ static void __event_probe__##_name(void *__data) \ return; \ __lf = lttng_rcu_dereference(__session->uid_tracker.p); \ if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ - from_kuid(&init_user_ns, current_uid())))) \ + lttng_current_uid()))) \ return; \ __lf = lttng_rcu_dereference(__session->vuid_tracker.p); \ if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ - from_kuid(current_user_ns(), current_uid())))) \ + lttng_current_vuid()))) \ return; \ __lf = lttng_rcu_dereference(__session->gid_tracker.p); \ if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ - from_kgid(&init_user_ns, current_gid())))) \ + lttng_current_gid()))) \ return; \ __lf = lttng_rcu_dereference(__session->vgid_tracker.p); \ if (__lf && likely(!lttng_id_tracker_lookup(__lf, \ - from_kgid(current_user_ns(), current_gid())))) \ + lttng_current_vgid()))) \ return; \ __orig_dynamic_len_offset = this_cpu_ptr(<tng_dynamic_len_stack)->offset; \ __dynamic_len_idx = __orig_dynamic_len_offset; \ -- 2.34.1 From 911ae48dfdce356dbc7e1e2169e9c6b29a826ba8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Thu, 19 Dec 2019 22:11:51 -0500 Subject: [PATCH 16/16] Bump LTTNG_MODULES_ABI_MINOR_VERSION to 5 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit New operations were added to the lttng-modules ABI as part of the 2.12 release cycle to support UID tracking and the "session clear" functionality. This will allow future LTTng-tools versions to check for those capabilities. Signed-off-by: Jérémie Galarneau Signed-off-by: Mathieu Desnoyers --- lttng-abi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lttng-abi.h b/lttng-abi.h index 5c5d8256..1d356ab1 100644 --- a/lttng-abi.h +++ b/lttng-abi.h @@ -17,7 +17,7 @@ * should be increased when an incompatible ABI change is done. */ #define LTTNG_MODULES_ABI_MAJOR_VERSION 2 -#define LTTNG_MODULES_ABI_MINOR_VERSION 4 +#define LTTNG_MODULES_ABI_MINOR_VERSION 5 #define LTTNG_KERNEL_SYM_NAME_LEN 256 #define LTTNG_KERNEL_SESSION_NAME_LEN 256 -- 2.34.1