Skip to content

Commit ca37d05

Browse files
authored
Merge pull request #365 from giuseppe/cgroupv2-join-init-process-cgroup
cgroup2: try joining initial process cgroup
2 parents 3c3d529 + af2c447 commit ca37d05

File tree

3 files changed

+123
-47
lines changed

3 files changed

+123
-47
lines changed

src/libcrun/cgroup.c

Lines changed: 121 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,13 @@ move_process_to_cgroup (pid_t pid, const char *subsystem, const char *path, libc
348348
}
349349

350350
static int
351-
enter_cgroup_subsystem (pid_t pid, const char *subsystem, const char *path, int ensure_missing, libcrun_error_t *err)
351+
enter_cgroup_subsystem (pid_t pid, const char *subsystem, const char *path, bool create_if_missing, libcrun_error_t *err)
352352
{
353353
cleanup_free char *cgroup_path = NULL;
354354
int ret;
355355

356356
xasprintf (&cgroup_path, "/sys/fs/cgroup/%s%s", subsystem, path ? path : "");
357-
if (ensure_missing)
357+
if (create_if_missing)
358358
{
359359
ret = crun_ensure_directory (cgroup_path, 0755, false, err);
360360
if (UNLIKELY (ret < 0))
@@ -482,54 +482,45 @@ copy_owner (const char *from, const char *to, libcrun_error_t *err)
482482
}
483483

484484
static int
485-
enter_cgroup (int cgroup_mode, pid_t pid, const char *path, bool ensure_missing, libcrun_error_t *err)
485+
read_unified_cgroup_pid (pid_t pid, char **path, libcrun_error_t *err)
486486
{
487-
char pid_str[16];
488487
int ret;
489-
size_t i;
490-
int entered_any = 0;
491-
int rootless;
492-
const cgroups_subsystem_t *subsystems;
488+
char cgroup_path[32];
489+
char *from, *to;
490+
cleanup_free char *content = NULL;
493491

494-
sprintf (pid_str, "%d", pid);
492+
sprintf (cgroup_path, "/proc/%d/cgroup", pid);
495493

496-
if (cgroup_mode == CGROUP_MODE_UNIFIED)
497-
{
498-
cleanup_free char *cgroup_path_procs = NULL;
499-
cleanup_free char *cgroup_path = NULL;
494+
ret = read_all_file (cgroup_path, &content, NULL, err);
495+
if (UNLIKELY (ret < 0))
496+
return ret;
500497

501-
xasprintf (&cgroup_path, "/sys/fs/cgroup/%s", path);
502-
if (ensure_missing)
503-
{
504-
ret = crun_ensure_directory (cgroup_path, 0755, false, err);
505-
if (UNLIKELY (ret < 0))
506-
return ret;
507-
}
498+
from = strstr (content, "0::");
499+
if (UNLIKELY (from == NULL))
500+
return crun_make_error (err, -1, "cannot find cgroup2 for the process %d", pid);
508501

509-
xasprintf (&cgroup_path_procs, "/sys/fs/cgroup/%s/cgroup.procs", path);
510-
ret = write_file (cgroup_path_procs, pid_str, strlen (pid_str), err);
511-
if (UNLIKELY (ret < 0))
512-
{
513-
if (!ensure_missing && (*err)->status == EBUSY)
514-
{
515-
/* There are subdirectories so it is not possible to join the initial
516-
cgroup. Create a subdirectory and use that.
517-
It can still fail if the container creates a subdirectory under
518-
/sys/fs/cgroup/../crun-exec/ */
519-
cleanup_free char *cgroup_crun_exec_path = NULL;
502+
from += 3;
503+
to = strchr (from, '\n');
504+
to = strchr (from, '\n');
505+
if (UNLIKELY (to == NULL))
506+
return crun_make_error (err, -1, "cannot parse `%s`", cgroup_path);
507+
*to = '\0';
520508

521-
xasprintf (&cgroup_crun_exec_path, "%s/crun-exec", path);
509+
*path = xstrdup (from);
510+
return 0;
511+
}
522512

523-
ret = enter_cgroup (cgroup_mode, pid, cgroup_crun_exec_path, true, err);
524-
if (UNLIKELY (ret < 0))
525-
return ret;
513+
static int
514+
enter_cgroup_v1 (int cgroup_mode, pid_t pid, const char *path, bool create_if_missing, libcrun_error_t *err)
515+
{
516+
char pid_str[16];
517+
int ret;
518+
size_t i;
519+
int entered_any = 0;
520+
int rootless;
521+
const cgroups_subsystem_t *subsystems;
526522

527-
return copy_owner (cgroup_path_procs, cgroup_crun_exec_path, err);
528-
}
529-
return ret;
530-
}
531-
return 0;
532-
}
523+
sprintf (pid_str, "%d", pid);
533524

534525
subsystems = libcrun_get_cgroups_subsystems (err);
535526
if (UNLIKELY (subsystems == NULL))
@@ -554,7 +545,7 @@ enter_cgroup (int cgroup_mode, pid_t pid, const char *path, bool ensure_missing,
554545
continue;
555546

556547
entered_any = 1;
557-
ret = enter_cgroup_subsystem (pid, subsystems[i], path, ensure_missing, err);
548+
ret = enter_cgroup_subsystem (pid, subsystems[i], path, create_if_missing, err);
558549
if (UNLIKELY (ret < 0))
559550
{
560551
int errcode = crun_error_get_errno (err);
@@ -570,6 +561,91 @@ enter_cgroup (int cgroup_mode, pid_t pid, const char *path, bool ensure_missing,
570561
return entered_any ? 0 : -1;
571562
}
572563

564+
static int
565+
enter_cgroup_v2 (pid_t pid, pid_t init_pid, const char *path, bool create_if_missing, libcrun_error_t *err)
566+
{
567+
cleanup_free char *cgroup_path_procs = NULL;
568+
cleanup_free char *cgroup_path = NULL;
569+
char pid_str[16];
570+
int repeat;
571+
int ret;
572+
573+
sprintf (pid_str, "%d", pid);
574+
575+
xasprintf (&cgroup_path, "/sys/fs/cgroup/%s", path);
576+
if (create_if_missing)
577+
{
578+
ret = crun_ensure_directory (cgroup_path, 0755, false, err);
579+
if (UNLIKELY (ret < 0))
580+
return ret;
581+
}
582+
583+
xasprintf (&cgroup_path_procs, "/sys/fs/cgroup/%s/cgroup.procs", path);
584+
ret = write_file (cgroup_path_procs, pid_str, strlen (pid_str), err);
585+
if (LIKELY (ret == 0))
586+
return ret;
587+
588+
/* If the cgroup is not being created, try to handle EBUSY. */
589+
if (create_if_missing || crun_error_get_errno (err) != EBUSY)
590+
return ret;
591+
592+
crun_error_release (err);
593+
594+
/* There are subdirectories so it is not possible to join the initial
595+
cgroup. Create a subdirectory and use that.
596+
It can still fail if the container creates a subdirectory under
597+
/sys/fs/cgroup/../crun-exec/ */
598+
for (repeat = 0;; repeat++)
599+
{
600+
cleanup_free char *cgroup_crun_exec_path = NULL;
601+
cleanup_free char *cgroup_sub_path_procs = NULL;
602+
603+
/* There is an init pid, try to join its cgroup. */
604+
if (init_pid > 0)
605+
{
606+
ret = read_unified_cgroup_pid (init_pid, &cgroup_crun_exec_path, err);
607+
if (UNLIKELY (ret < 0))
608+
return ret;
609+
610+
/* Make sure the cgroup is below the initial cgroup specified for the container. */
611+
if (strncmp (path, cgroup_crun_exec_path, strlen (path)))
612+
{
613+
free (cgroup_crun_exec_path);
614+
cgroup_crun_exec_path = NULL;
615+
}
616+
}
617+
618+
/* There is no init_pid to lookup, try a static path. */
619+
if (cgroup_crun_exec_path == NULL)
620+
xasprintf (&cgroup_crun_exec_path, "%s/crun-exec", path);
621+
622+
xasprintf (&cgroup_sub_path_procs, "/sys/fs/cgroup/%s/cgroup.procs", cgroup_crun_exec_path);
623+
624+
ret = write_file (cgroup_sub_path_procs, pid_str, strlen (pid_str), err);
625+
if (UNLIKELY (ret < 0))
626+
{
627+
/* The init process might have moved to a different cgroup, try again. */
628+
if (crun_error_get_errno (err) == EBUSY && init_pid && repeat < 20)
629+
{
630+
crun_error_release (err);
631+
continue;
632+
}
633+
return ret;
634+
}
635+
return copy_owner (cgroup_path_procs, cgroup_crun_exec_path, err);
636+
}
637+
return ret;
638+
}
639+
640+
static int
641+
enter_cgroup (int cgroup_mode, pid_t pid, pid_t init_pid, const char *path, bool create_if_missing, libcrun_error_t *err)
642+
{
643+
if (cgroup_mode == CGROUP_MODE_UNIFIED)
644+
return enter_cgroup_v2 (pid, init_pid, path, create_if_missing, err);
645+
646+
return enter_cgroup_v1 (cgroup_mode, pid, path, create_if_missing, err);
647+
}
648+
573649
int
574650
libcrun_cgroups_create_symlinks (int dirfd, libcrun_error_t *err)
575651
{
@@ -591,7 +667,7 @@ libcrun_cgroups_create_symlinks (int dirfd, libcrun_error_t *err)
591667
}
592668

593669
int
594-
libcrun_move_process_to_cgroup (pid_t pid, char *path, libcrun_error_t *err)
670+
libcrun_move_process_to_cgroup (pid_t pid, pid_t init_pid, char *path, libcrun_error_t *err)
595671
{
596672
int cgroup_mode = libcrun_get_cgroup_mode (err);
597673
if (UNLIKELY (cgroup_mode < 0))
@@ -600,7 +676,7 @@ libcrun_move_process_to_cgroup (pid_t pid, char *path, libcrun_error_t *err)
600676
if (path == NULL || *path == '\0')
601677
return 0;
602678

603-
return enter_cgroup (cgroup_mode, pid, path, false, err);
679+
return enter_cgroup (cgroup_mode, pid, init_pid, path, false, err);
604680
}
605681

606682
#ifdef HAVE_SYSTEMD
@@ -1221,7 +1297,7 @@ libcrun_cgroup_enter_cgroupfs (struct libcrun_cgroup_args *args, libcrun_error_t
12211297
return ret;
12221298
}
12231299

1224-
return enter_cgroup (cgroup_mode, pid, *path, true, err);
1300+
return enter_cgroup (cgroup_mode, pid, 0, *path, true, err);
12251301
}
12261302

12271303
static int

src/libcrun/cgroup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ int libcrun_cgroup_enter (struct libcrun_cgroup_args *args, libcrun_error_t *err
5656
int libcrun_cgroup_killall_signal (char *path, int signal, libcrun_error_t *err);
5757
int libcrun_cgroup_killall (char *path, libcrun_error_t *err);
5858
int libcrun_cgroup_destroy (const char *id, char *path, int manager, libcrun_error_t *err);
59-
int libcrun_move_process_to_cgroup (pid_t pid, char *path, libcrun_error_t *err);
59+
int libcrun_move_process_to_cgroup (pid_t pid, pid_t init_pid, char *path, libcrun_error_t *err);
6060
int libcrun_update_cgroup_resources (int cgroup_mode, runtime_spec_schema_config_linux_resources *resources,
6161
char *path, libcrun_error_t *err);
6262
int libcrun_cgroups_create_symlinks (int dirfd, libcrun_error_t *err);

src/libcrun/linux.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2840,7 +2840,7 @@ join_process_parent_helper (pid_t child_pid,
28402840
if (UNLIKELY (ret < 0))
28412841
return crun_make_error (err, errno, "waitpid for exec child pid");
28422842

2843-
ret = libcrun_move_process_to_cgroup (pid, status->cgroup_path, err);
2843+
ret = libcrun_move_process_to_cgroup (pid, status->pid, status->cgroup_path, err);
28442844
if (UNLIKELY (ret < 0))
28452845
return ret;
28462846

0 commit comments

Comments
 (0)