uid_t uid,
gid_t gid) {
- _cleanup_free_ char *fs = NULL, *procs = NULL;
+ _cleanup_free_ char *fs = NULL;
int r;
assert(path);
if (mode != MODE_INVALID)
mode &= 0666;
+ /* For both the legacy and unified hierarchies, "cgroup.procs" is the main entry point for PIDs */
r = cg_get_path(controller, path, "cgroup.procs", &fs);
if (r < 0)
return r;
if (r < 0)
return r;
if (r == 0) {
- /* Compatibility, Always keep values for "tasks" in sync with
- * "cgroup.procs" */
- if (cg_get_path(controller, path, "tasks", &procs) >= 0)
- (void) chmod_and_chown(procs, mode, uid, gid);
+ const char *fn;
+
+ /* Compatibility: on cgroupsv1 always keep values for the legacy files "tasks" and
+ * "cgroup.clone_children" in sync with "cgroup.procs". Since this is legacy stuff, we don't care if
+ * this fails. */
+
+ FOREACH_STRING(fn,
+ "tasks",
+ "cgroup.clone_children") {
+
+ fs = mfree(fs);
+
+ r = cg_get_path(controller, path, fn, &fs);
+ if (r < 0)
+ log_debug_errno(r, "Failed to get path for %s of %s, ignoring: %m", fn, path);
+
+ r = chmod_and_chown(fs, mode, uid, gid);
+ if (r < 0)
+ log_debug_errno(r, "Failed to to change ownership/access mode for %s of %s, ignoring: %m", fn, path);
+ }
+ } else {
+ /* On the unified controller, we want to permit subtree controllers too. */
+
+ fs = mfree(fs);
+ r = cg_get_path(controller, path, "cgroup.subtree_control", &fs);
+ if (r < 0)
+ return r;
+
+ r = chmod_and_chown(fs, mode, uid, gid);
+ if (r < 0)
+ return r;
}
r = cg_hybrid_unified();