Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cgroup: add tracepoints for basic operations

Debugging what goes wrong with cgroup setup can get hairy. Add
tracepoints for cgroup hierarchy mount, cgroup creation/destruction
and task migration operations for better visibility.

Signed-off-by: Tejun Heo <tj@kernel.org>

+188
+163
include/trace/events/cgroup.h
··· 1 + #undef TRACE_SYSTEM 2 + #define TRACE_SYSTEM cgroup 3 + 4 + #if !defined(_TRACE_CGROUP_H) || defined(TRACE_HEADER_MULTI_READ) 5 + #define _TRACE_CGROUP_H 6 + 7 + #include <linux/cgroup.h> 8 + #include <linux/tracepoint.h> 9 + 10 + DECLARE_EVENT_CLASS(cgroup_root, 11 + 12 + TP_PROTO(struct cgroup_root *root), 13 + 14 + TP_ARGS(root), 15 + 16 + TP_STRUCT__entry( 17 + __field( int, root ) 18 + __field( u16, ss_mask ) 19 + __string( name, root->name ) 20 + ), 21 + 22 + TP_fast_assign( 23 + __entry->root = root->hierarchy_id; 24 + __entry->ss_mask = root->subsys_mask; 25 + __assign_str(name, root->name); 26 + ), 27 + 28 + TP_printk("root=%d ss_mask=%#x name=%s", 29 + __entry->root, __entry->ss_mask, __get_str(name)) 30 + ); 31 + 32 + DEFINE_EVENT(cgroup_root, cgroup_setup_root, 33 + 34 + TP_PROTO(struct cgroup_root *root), 35 + 36 + TP_ARGS(root) 37 + ); 38 + 39 + DEFINE_EVENT(cgroup_root, cgroup_destroy_root, 40 + 41 + TP_PROTO(struct cgroup_root *root), 42 + 43 + TP_ARGS(root) 44 + ); 45 + 46 + DEFINE_EVENT(cgroup_root, cgroup_remount, 47 + 48 + TP_PROTO(struct cgroup_root *root), 49 + 50 + TP_ARGS(root) 51 + ); 52 + 53 + DECLARE_EVENT_CLASS(cgroup, 54 + 55 + TP_PROTO(struct cgroup *cgrp), 56 + 57 + TP_ARGS(cgrp), 58 + 59 + TP_STRUCT__entry( 60 + __field( int, root ) 61 + __field( int, id ) 62 + __field( int, level ) 63 + __dynamic_array(char, path, 64 + cgrp->kn ? cgroup_path(cgrp, NULL, 0) + 1 65 + : strlen("(null)")) 66 + ), 67 + 68 + TP_fast_assign( 69 + __entry->root = cgrp->root->hierarchy_id; 70 + __entry->id = cgrp->id; 71 + __entry->level = cgrp->level; 72 + if (cgrp->kn) 73 + cgroup_path(cgrp, __get_dynamic_array(path), 74 + __get_dynamic_array_len(path)); 75 + else 76 + __assign_str(path, "(null)"); 77 + ), 78 + 79 + TP_printk("root=%d id=%d level=%d path=%s", 80 + __entry->root, __entry->id, __entry->level, __get_str(path)) 81 + ); 82 + 83 + DEFINE_EVENT(cgroup, cgroup_mkdir, 84 + 85 + TP_PROTO(struct cgroup *cgroup), 86 + 87 + TP_ARGS(cgroup) 88 + ); 89 + 90 + DEFINE_EVENT(cgroup, cgroup_rmdir, 91 + 92 + TP_PROTO(struct cgroup *cgroup), 93 + 94 + TP_ARGS(cgroup) 95 + ); 96 + 97 + DEFINE_EVENT(cgroup, cgroup_release, 98 + 99 + TP_PROTO(struct cgroup *cgroup), 100 + 101 + TP_ARGS(cgroup) 102 + ); 103 + 104 + DEFINE_EVENT(cgroup, cgroup_rename, 105 + 106 + TP_PROTO(struct cgroup *cgroup), 107 + 108 + TP_ARGS(cgroup) 109 + ); 110 + 111 + DECLARE_EVENT_CLASS(cgroup_migrate, 112 + 113 + TP_PROTO(struct cgroup *dst_cgrp, struct task_struct *task, bool threadgroup), 114 + 115 + TP_ARGS(dst_cgrp, task, threadgroup), 116 + 117 + TP_STRUCT__entry( 118 + __field( int, dst_root ) 119 + __field( int, dst_id ) 120 + __field( int, dst_level ) 121 + __dynamic_array(char, dst_path, 122 + dst_cgrp->kn ? cgroup_path(dst_cgrp, NULL, 0) + 1 123 + : strlen("(null)")) 124 + __field( int, pid ) 125 + __string( comm, task->comm ) 126 + ), 127 + 128 + TP_fast_assign( 129 + __entry->dst_root = dst_cgrp->root->hierarchy_id; 130 + __entry->dst_id = dst_cgrp->id; 131 + __entry->dst_level = dst_cgrp->level; 132 + if (dst_cgrp->kn) 133 + cgroup_path(dst_cgrp, __get_dynamic_array(dst_path), 134 + __get_dynamic_array_len(dst_path)); 135 + else 136 + __assign_str(dst_path, "(null)"); 137 + __entry->pid = task->pid; 138 + __assign_str(comm, task->comm); 139 + ), 140 + 141 + TP_printk("dst_root=%d dst_id=%d dst_level=%d dst_path=%s pid=%d comm=%s", 142 + __entry->dst_root, __entry->dst_id, __entry->dst_level, 143 + __get_str(dst_path), __entry->pid, __get_str(comm)) 144 + ); 145 + 146 + DEFINE_EVENT(cgroup_migrate, cgroup_attach_task, 147 + 148 + TP_PROTO(struct cgroup *dst_cgrp, struct task_struct *task, bool threadgroup), 149 + 150 + TP_ARGS(dst_cgrp, task, threadgroup) 151 + ); 152 + 153 + DEFINE_EVENT(cgroup_migrate, cgroup_transfer_tasks, 154 + 155 + TP_PROTO(struct cgroup *dst_cgrp, struct task_struct *task, bool threadgroup), 156 + 157 + TP_ARGS(dst_cgrp, task, threadgroup) 158 + ); 159 + 160 + #endif /* _TRACE_CGROUP_H */ 161 + 162 + /* This part must be outside protection */ 163 + #include <trace/define_trace.h>
+25
kernel/cgroup.c
··· 64 64 #include <linux/file.h> 65 65 #include <net/sock.h> 66 66 67 + #define CREATE_TRACE_POINTS 68 + #include <trace/events/cgroup.h> 69 + 67 70 /* 68 71 * pidlists linger the following amount before being destroyed. The goal 69 72 * is avoiding frequent destruction in the middle of consecutive read calls ··· 1179 1176 struct cgroup *cgrp = &root->cgrp; 1180 1177 struct cgrp_cset_link *link, *tmp_link; 1181 1178 1179 + trace_cgroup_destroy_root(root); 1180 + 1182 1181 cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp); 1183 1182 1184 1183 BUG_ON(atomic_read(&root->nr_cgrps)); ··· 1879 1874 strcpy(root->release_agent_path, opts.release_agent); 1880 1875 spin_unlock(&release_agent_path_lock); 1881 1876 } 1877 + 1878 + trace_cgroup_remount(root); 1879 + 1882 1880 out_unlock: 1883 1881 kfree(opts.release_agent); 1884 1882 kfree(opts.name); ··· 2038 2030 ret = rebind_subsystems(root, ss_mask); 2039 2031 if (ret) 2040 2032 goto destroy_root; 2033 + 2034 + trace_cgroup_setup_root(root); 2041 2035 2042 2036 /* 2043 2037 * There must be no failure case after here, since rebinding takes ··· 2835 2825 ret = cgroup_migrate(leader, threadgroup, dst_cgrp->root); 2836 2826 2837 2827 cgroup_migrate_finish(&preloaded_csets); 2828 + 2829 + if (!ret) 2830 + trace_cgroup_attach_task(dst_cgrp, leader, threadgroup); 2831 + 2838 2832 return ret; 2839 2833 } 2840 2834 ··· 3601 3587 mutex_lock(&cgroup_mutex); 3602 3588 3603 3589 ret = kernfs_rename(kn, new_parent, new_name_str); 3590 + if (!ret) 3591 + trace_cgroup_rename(cgrp); 3604 3592 3605 3593 mutex_unlock(&cgroup_mutex); 3606 3594 ··· 4371 4355 4372 4356 if (task) { 4373 4357 ret = cgroup_migrate(task, false, to->root); 4358 + if (!ret) 4359 + trace_cgroup_transfer_tasks(to, task, false); 4374 4360 put_task_struct(task); 4375 4361 } 4376 4362 } while (task && !ret); ··· 5038 5020 ss->css_released(css); 5039 5021 } else { 5040 5022 /* cgroup release path */ 5023 + trace_cgroup_release(cgrp); 5024 + 5041 5025 cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id); 5042 5026 cgrp->id = -1; 5043 5027 ··· 5326 5306 if (ret) 5327 5307 goto out_destroy; 5328 5308 5309 + trace_cgroup_mkdir(cgrp); 5310 + 5329 5311 /* let's create and online css's */ 5330 5312 kernfs_activate(kn); 5331 5313 ··· 5502 5480 return 0; 5503 5481 5504 5482 ret = cgroup_destroy_locked(cgrp); 5483 + 5484 + if (!ret) 5485 + trace_cgroup_rmdir(cgrp); 5505 5486 5506 5487 cgroup_kn_unlock(kn); 5507 5488 return ret;