mirror of
https://github.com/troglobit/finit.git
synced 2026-11-08 16:11:10 +00:00
Allow forking sysv/services like podman to move between cgroups
The container monitor that podman forks off when starting a container instance creates subgroups in the cgroup v2 hieararchy that we want to reuse. This patch adds cgroup_move_svc() which we call from the pidfile plugins to relocate the conmon process. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
3 files changed
+131
No files matched your search
@@ -143,6 +143,7 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
|||||||
|
|
||||||
/* Complement log in service.c for non-forking services */
|
/* Complement log in service.c for non-forking services */
|
||||||
logit(LOG_CONSOLE | LOG_NOTICE, "Started %s[%d]", svc_ident(svc, NULL, 0), pid);
|
logit(LOG_CONSOLE | LOG_NOTICE, "Started %s[%d]", svc_ident(svc, NULL, 0), pid);
|
||||||
|
cgroup_move_svc(svc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+127
@@ -88,6 +88,133 @@ int cgroup_watch(const char *group, const char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Derive cgroup name from service (mirrors group_name() in service.c)
|
||||||
|
* For use by plugins that need to determine the cgroup path.
|
||||||
|
*
|
||||||
|
* MUST return the same value that group_name() in service.c returns!
|
||||||
|
*/
|
||||||
|
char *cgroup_svc_name(svc_t *svc, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
/* Use explicit cgroup leaf name if specified */
|
||||||
|
if (svc->cgroup.leafname[0]) {
|
||||||
|
strlcpy(buf, svc->cgroup.leafname, len);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!svc->file[0])
|
||||||
|
return svc_ident(svc, buf, len);
|
||||||
|
|
||||||
|
ptr = strrchr(svc->file, '/');
|
||||||
|
if (ptr)
|
||||||
|
ptr++;
|
||||||
|
else
|
||||||
|
ptr = svc->file;
|
||||||
|
|
||||||
|
strlcpy(buf, ptr, len);
|
||||||
|
|
||||||
|
/* Strip .conf extension - this gives us the cgroup name */
|
||||||
|
ptr = strstr(buf, ".conf");
|
||||||
|
if (ptr)
|
||||||
|
*ptr = 0;
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to move a PID to a service's cgroup.
|
||||||
|
* @group: Top-level cgroup (e.g., "system", "user", "maint")
|
||||||
|
* @name: Service-specific cgroup name (e.g., "dockerd", "nginx")
|
||||||
|
* @pid: Process ID to move
|
||||||
|
* @delegate: If 1, handle potential EBUSY by using supervisor/ subdirectory
|
||||||
|
*
|
||||||
|
* Useful for forking services where child PIDs need to be moved after they appear.
|
||||||
|
*
|
||||||
|
* For delegated cgroups, handles the cgroups v2 "no internal processes" rule:
|
||||||
|
* if the parent has child cgroups, tries to reuse process-named subdirectory or
|
||||||
|
* falls back to supervisor/ subdirectory.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int cgroup_move_pid(const char *group, const char *name, int pid, int delegate)
|
||||||
|
{
|
||||||
|
int rc = 0, reuse = 0;
|
||||||
|
char path[512];
|
||||||
|
|
||||||
|
if (!avail)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Sanity checks */
|
||||||
|
if (!group || !name || pid <= 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disallow path traversal */
|
||||||
|
if (strstr(group, "..") || strstr(name, "..") ||
|
||||||
|
strchr(group, '/') || strchr(name, '/')) {
|
||||||
|
errno = EINVAL;
|
||||||
|
warn("Invalid cgroup path components: group=%s name=%s", group, name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), FINIT_CGPATH "/%s/%s", group, name);
|
||||||
|
if (!fisdir(path)) {
|
||||||
|
warn("Cgroup %s does not exist", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = fnwrite(str("%d", pid), "%s/cgroup.procs", path))) {
|
||||||
|
/*
|
||||||
|
* EBUSY means the cgroup has children (cgroups v2 "no internal processes" rule).
|
||||||
|
* For delegated cgroups, fall back to subdirectory.
|
||||||
|
*/
|
||||||
|
if (errno == EBUSY && delegate) {
|
||||||
|
char comm[64];
|
||||||
|
|
||||||
|
/* Check if subdirectory matching process name, e.g., conmon, exists */
|
||||||
|
readsnf(comm, sizeof(comm), "/proc/%d/comm", pid);
|
||||||
|
strlcat(path, "/", sizeof(path));
|
||||||
|
strlcat(path, comm, sizeof(path));
|
||||||
|
if (fisdir(path))
|
||||||
|
reuse = 1;
|
||||||
|
else
|
||||||
|
snprintf(path, sizeof(path), FINIT_CGPATH "/%s/%s/supervisor", group, name);
|
||||||
|
|
||||||
|
rc = fnwrite(str("%d", pid), "%s/cgroup.procs", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
warn("Failed moving pid %d to cgroup %s", pid, path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reuse) {
|
||||||
|
snprintf(path, sizeof(path), FINIT_CGPATH "/%s/%s/supervisor", group, name);
|
||||||
|
rmdir(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cgroup_move_svc(svc_t *svc)
|
||||||
|
{
|
||||||
|
const char *group = "system";
|
||||||
|
char name[MAX_ARG_LEN];
|
||||||
|
|
||||||
|
if (!avail || !svc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (svc->cgroup.name[0])
|
||||||
|
group = svc->cgroup.name;
|
||||||
|
|
||||||
|
return cgroup_move_pid(group, cgroup_svc_name(svc, name, sizeof(name)),
|
||||||
|
svc->pid, svc->cgroup.delegate);
|
||||||
|
}
|
||||||
|
|
||||||
static void cgset(const char *path, char *ctrl, char *prop)
|
static void cgset(const char *path, char *ctrl, char *prop)
|
||||||
{
|
{
|
||||||
char *val;
|
char *val;
|
||||||
|
|||||||
@@ -53,4 +53,7 @@ char *cgroup_svc_name(svc_t *svc, char *buf, size_t len);
|
|||||||
int cgroup_prepare (svc_t *svc, const char *name);
|
int cgroup_prepare (svc_t *svc, const char *name);
|
||||||
int cgroup_watch (const char *group, const char *name);
|
int cgroup_watch (const char *group, const char *name);
|
||||||
|
|
||||||
|
int cgroup_move_pid(const char *group, const char *name, int pid, int delegate);
|
||||||
|
int cgroup_move_svc(svc_t *svc);
|
||||||
|
|
||||||
#endif /* FINIT_CGROUP_H_ */
|
#endif /* FINIT_CGROUP_H_ */
|
||||||
Reference in new issue
Block a user