cgroup: add tracing points for cgroup v2 freezer
Add cgroup:cgroup_freeze and cgroup:cgroup_unfreeze events, which are using the existing cgroup tracing infrastructure. Add the cgroup_event event class, which is similar to the cgroup class, but contains an additional integer field to store a new value (the level field is dropped). Also add two tracing events: cgroup_notify_populated and cgroup_notify_frozen, which are raised in a generic way using the TRACE_CGROUP_PATH() macro. This allows to trace cgroup state transitions and is generally helpful for debugging the cgroup freezer code. Signed-off-by: Roman Gushchin <guro@fb.com> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
712e351787
commit
4c476d8cff
|
@ -103,6 +103,20 @@ DEFINE_EVENT(cgroup, cgroup_rename,
|
||||||
TP_ARGS(cgrp, path)
|
TP_ARGS(cgrp, path)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DEFINE_EVENT(cgroup, cgroup_freeze,
|
||||||
|
|
||||||
|
TP_PROTO(struct cgroup *cgrp, const char *path),
|
||||||
|
|
||||||
|
TP_ARGS(cgrp, path)
|
||||||
|
);
|
||||||
|
|
||||||
|
DEFINE_EVENT(cgroup, cgroup_unfreeze,
|
||||||
|
|
||||||
|
TP_PROTO(struct cgroup *cgrp, const char *path),
|
||||||
|
|
||||||
|
TP_ARGS(cgrp, path)
|
||||||
|
);
|
||||||
|
|
||||||
DECLARE_EVENT_CLASS(cgroup_migrate,
|
DECLARE_EVENT_CLASS(cgroup_migrate,
|
||||||
|
|
||||||
TP_PROTO(struct cgroup *dst_cgrp, const char *path,
|
TP_PROTO(struct cgroup *dst_cgrp, const char *path,
|
||||||
|
@ -149,6 +163,47 @@ DEFINE_EVENT(cgroup_migrate, cgroup_transfer_tasks,
|
||||||
TP_ARGS(dst_cgrp, path, task, threadgroup)
|
TP_ARGS(dst_cgrp, path, task, threadgroup)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DECLARE_EVENT_CLASS(cgroup_event,
|
||||||
|
|
||||||
|
TP_PROTO(struct cgroup *cgrp, const char *path, int val),
|
||||||
|
|
||||||
|
TP_ARGS(cgrp, path, val),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field( int, root )
|
||||||
|
__field( int, id )
|
||||||
|
__field( int, level )
|
||||||
|
__string( path, path )
|
||||||
|
__field( int, val )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->root = cgrp->root->hierarchy_id;
|
||||||
|
__entry->id = cgrp->id;
|
||||||
|
__entry->level = cgrp->level;
|
||||||
|
__assign_str(path, path);
|
||||||
|
__entry->val = val;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("root=%d id=%d level=%d path=%s val=%d",
|
||||||
|
__entry->root, __entry->id, __entry->level, __get_str(path),
|
||||||
|
__entry->val)
|
||||||
|
);
|
||||||
|
|
||||||
|
DEFINE_EVENT(cgroup_event, cgroup_notify_populated,
|
||||||
|
|
||||||
|
TP_PROTO(struct cgroup *cgrp, const char *path, int val),
|
||||||
|
|
||||||
|
TP_ARGS(cgrp, path, val)
|
||||||
|
);
|
||||||
|
|
||||||
|
DEFINE_EVENT(cgroup_event, cgroup_notify_frozen,
|
||||||
|
|
||||||
|
TP_PROTO(struct cgroup *cgrp, const char *path, int val),
|
||||||
|
|
||||||
|
TP_ARGS(cgrp, path, val)
|
||||||
|
);
|
||||||
|
|
||||||
#endif /* _TRACE_CGROUP_H */
|
#endif /* _TRACE_CGROUP_H */
|
||||||
|
|
||||||
/* This part must be outside protection */
|
/* This part must be outside protection */
|
||||||
|
|
|
@ -816,6 +816,8 @@ static void cgroup_update_populated(struct cgroup *cgrp, bool populated)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cgroup1_check_for_release(cgrp);
|
cgroup1_check_for_release(cgrp);
|
||||||
|
TRACE_CGROUP_PATH(notify_populated, cgrp,
|
||||||
|
cgroup_is_populated(cgrp));
|
||||||
cgroup_file_notify(&cgrp->events_file);
|
cgroup_file_notify(&cgrp->events_file);
|
||||||
|
|
||||||
child = cgrp;
|
child = cgrp;
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "cgroup-internal.h"
|
#include "cgroup-internal.h"
|
||||||
|
|
||||||
|
#include <trace/events/cgroup.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Propagate the cgroup frozen state upwards by the cgroup tree.
|
* Propagate the cgroup frozen state upwards by the cgroup tree.
|
||||||
*/
|
*/
|
||||||
|
@ -28,6 +30,7 @@ static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
|
||||||
cgrp->nr_descendants) {
|
cgrp->nr_descendants) {
|
||||||
set_bit(CGRP_FROZEN, &cgrp->flags);
|
set_bit(CGRP_FROZEN, &cgrp->flags);
|
||||||
cgroup_file_notify(&cgrp->events_file);
|
cgroup_file_notify(&cgrp->events_file);
|
||||||
|
TRACE_CGROUP_PATH(notify_frozen, cgrp, 1);
|
||||||
desc++;
|
desc++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -35,6 +38,7 @@ static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
|
||||||
if (test_bit(CGRP_FROZEN, &cgrp->flags)) {
|
if (test_bit(CGRP_FROZEN, &cgrp->flags)) {
|
||||||
clear_bit(CGRP_FROZEN, &cgrp->flags);
|
clear_bit(CGRP_FROZEN, &cgrp->flags);
|
||||||
cgroup_file_notify(&cgrp->events_file);
|
cgroup_file_notify(&cgrp->events_file);
|
||||||
|
TRACE_CGROUP_PATH(notify_frozen, cgrp, 0);
|
||||||
desc++;
|
desc++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +77,7 @@ void cgroup_update_frozen(struct cgroup *cgrp)
|
||||||
clear_bit(CGRP_FROZEN, &cgrp->flags);
|
clear_bit(CGRP_FROZEN, &cgrp->flags);
|
||||||
}
|
}
|
||||||
cgroup_file_notify(&cgrp->events_file);
|
cgroup_file_notify(&cgrp->events_file);
|
||||||
|
TRACE_CGROUP_PATH(notify_frozen, cgrp, frozen);
|
||||||
|
|
||||||
/* Update the state of ancestor cgroups. */
|
/* Update the state of ancestor cgroups. */
|
||||||
cgroup_propagate_frozen(cgrp, frozen);
|
cgroup_propagate_frozen(cgrp, frozen);
|
||||||
|
@ -189,6 +194,11 @@ static void cgroup_do_freeze(struct cgroup *cgrp, bool freeze)
|
||||||
clear_bit(CGRP_FREEZE, &cgrp->flags);
|
clear_bit(CGRP_FREEZE, &cgrp->flags);
|
||||||
spin_unlock_irq(&css_set_lock);
|
spin_unlock_irq(&css_set_lock);
|
||||||
|
|
||||||
|
if (freeze)
|
||||||
|
TRACE_CGROUP_PATH(freeze, cgrp);
|
||||||
|
else
|
||||||
|
TRACE_CGROUP_PATH(unfreeze, cgrp);
|
||||||
|
|
||||||
css_task_iter_start(&cgrp->self, 0, &it);
|
css_task_iter_start(&cgrp->self, 0, &it);
|
||||||
while ((task = css_task_iter_next(&it))) {
|
while ((task = css_task_iter_next(&it))) {
|
||||||
/*
|
/*
|
||||||
|
@ -312,6 +322,9 @@ void cgroup_freeze(struct cgroup *cgrp, bool freeze)
|
||||||
* In both cases it's better to notify a user, that there is
|
* In both cases it's better to notify a user, that there is
|
||||||
* nothing to wait for.
|
* nothing to wait for.
|
||||||
*/
|
*/
|
||||||
if (!applied)
|
if (!applied) {
|
||||||
|
TRACE_CGROUP_PATH(notify_frozen, cgrp,
|
||||||
|
test_bit(CGRP_FROZEN, &cgrp->flags));
|
||||||
cgroup_file_notify(&cgrp->events_file);
|
cgroup_file_notify(&cgrp->events_file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue