Skip to content

Commit 4d6eae2

Browse files
authored
Merge pull request #1679 from giuseppe/criu-restore-same-cgroup
criu: migrate all processes to the correct cgroup
2 parents 226d0c2 + c954b1b commit 4d6eae2

8 files changed

+351
-72
lines changed

src/libcrun/cgroup-cgroupfs.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ make_new_sibling_cgroup (char **out, const char *id, libcrun_error_t *err)
9393
char *dir;
9494
int ret;
9595

96-
ret = libcrun_get_current_unified_cgroup (&current_cgroup, false, err);
96+
ret = libcrun_get_cgroup_process (0, &current_cgroup, false, err);
9797
if (UNLIKELY (ret < 0))
9898
return ret;
9999

src/libcrun/cgroup-internal.h

-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ int enter_cgroup_subsystem (pid_t pid, const char *subsystem, const char *path,
5656
libcrun_error_t *err);
5757
int enable_controllers (const char *path, libcrun_error_t *err);
5858
int chown_cgroups (const char *path, uid_t uid, gid_t gid, libcrun_error_t *err);
59-
int destroy_cgroup_path (const char *path, int mode, libcrun_error_t *err);
6059
int cgroup_killall_path (const char *path, int signal, libcrun_error_t *err);
6160

6261
int libcrun_cgroup_read_pids_from_path (const char *path, bool recurse, pid_t **pids, libcrun_error_t *err);

src/libcrun/cgroup-utils.c

+134-45
Original file line numberDiff line numberDiff line change
@@ -161,35 +161,6 @@ move_process_to_cgroup (pid_t pid, const char *subsystem, const char *path, libc
161161
return ret;
162162
}
163163

164-
int
165-
libcrun_get_current_unified_cgroup (char **path, bool absolute, libcrun_error_t *err)
166-
{
167-
cleanup_free char *content = NULL;
168-
size_t content_size;
169-
char *from, *to;
170-
int ret;
171-
172-
ret = read_all_file (PROC_SELF_CGROUP, &content, &content_size, err);
173-
if (UNLIKELY (ret < 0))
174-
return ret;
175-
176-
from = strstr (content, "0::");
177-
if (UNLIKELY (from == NULL))
178-
return crun_make_error (err, 0, "cannot find cgroup2 for the current process");
179-
180-
from += 3;
181-
to = strchr (from, '\n');
182-
if (UNLIKELY (to == NULL))
183-
return crun_make_error (err, 0, "cannot parse `%s`", PROC_SELF_CGROUP);
184-
*to = '\0';
185-
186-
if (absolute)
187-
return append_paths (path, err, CGROUP_ROOT, from, NULL);
188-
189-
*path = xstrdup (from);
190-
return 0;
191-
}
192-
193164
#ifndef CGROUP2_SUPER_MAGIC
194165
# define CGROUP2_SUPER_MAGIC 0x63677270
195166
#endif
@@ -237,10 +208,61 @@ libcrun_get_cgroup_mode (libcrun_error_t *err)
237208
return cgroup_mode;
238209
}
239210

211+
int
212+
libcrun_get_cgroup_process (pid_t pid, char **path, bool absolute, libcrun_error_t *err)
213+
{
214+
cleanup_free char *content = NULL;
215+
char proc_cgroup_file[64];
216+
char *cg_path = NULL;
217+
size_t content_size;
218+
char *controller;
219+
char *saveptr;
220+
int cgroup_mode;
221+
bool has_data;
222+
int ret;
223+
224+
cgroup_mode = libcrun_get_cgroup_mode (err);
225+
if (UNLIKELY (cgroup_mode < 0))
226+
return cgroup_mode;
227+
228+
if (pid == 0)
229+
strcpy (proc_cgroup_file, PROC_SELF_CGROUP);
230+
else
231+
sprintf (proc_cgroup_file, "/proc/%d/cgroup", pid);
232+
233+
ret = read_all_file (proc_cgroup_file, &content, &content_size, err);
234+
if (UNLIKELY (ret < 0))
235+
return ret;
236+
237+
for (has_data = read_proc_cgroup (content, &saveptr, NULL, &controller, &cg_path);
238+
has_data;
239+
has_data = read_proc_cgroup (NULL, &saveptr, NULL, &controller, &cg_path))
240+
{
241+
if (cgroup_mode == CGROUP_MODE_UNIFIED)
242+
{
243+
if (strcmp (controller, "") == 0 && strlen (cg_path) > 0)
244+
goto found;
245+
}
246+
else
247+
{
248+
if (strcmp (controller, "memory"))
249+
goto found;
250+
}
251+
}
252+
253+
return crun_make_error (err, 0, "cannot find cgroup for the process");
254+
255+
found:
256+
if (absolute)
257+
return append_paths (path, err, CGROUP_ROOT, cg_path, NULL);
258+
259+
*path = xstrdup (cg_path);
260+
return 0;
261+
}
262+
240263
static int
241264
read_pids_cgroup (int dfd, bool recurse, pid_t **pids, size_t *n_pids, size_t *allocated, libcrun_error_t *err)
242265
{
243-
__attribute__ ((unused)) cleanup_close int clean_dfd = dfd;
244266
cleanup_close int tasksfd = -1;
245267
cleanup_free char *buffer = NULL;
246268
char *saveptr = NULL;
@@ -287,11 +309,11 @@ read_pids_cgroup (int dfd, bool recurse, pid_t **pids, size_t *n_pids, size_t *a
287309
if (UNLIKELY (dir == NULL))
288310
return crun_make_error (err, errno, "open cgroup sub-directory");
289311
/* Now dir owns the dfd descriptor. */
290-
clean_dfd = -1;
312+
dfd = -1;
291313

292314
for (de = readdir (dir); de; de = readdir (dir))
293315
{
294-
int nfd;
316+
cleanup_close int nfd = -1;
295317

296318
if (strcmp (de->d_name, ".") == 0 || strcmp (de->d_name, "..") == 0)
297319
continue;
@@ -346,22 +368,16 @@ rmdir_all_fd (int dfd)
346368
size_t i, n_pids = 0, allocated = 0;
347369
cleanup_close int child_dfd = -1;
348370
int tmp;
349-
int child_dfd_clone;
350371

351372
child_dfd = openat (dfd, name, O_DIRECTORY | O_CLOEXEC);
352373
if (child_dfd < 0)
353374
return child_dfd;
354375

355-
/* read_pids_cgroup takes ownership for the fd, so dup it. */
356-
child_dfd_clone = dup (child_dfd);
357-
if (LIKELY (child_dfd_clone >= 0))
376+
ret = read_pids_cgroup (child_dfd, true, &pids, &n_pids, &allocated, &tmp_err);
377+
if (UNLIKELY (ret < 0))
358378
{
359-
ret = read_pids_cgroup (child_dfd_clone, true, &pids, &n_pids, &allocated, &tmp_err);
360-
if (UNLIKELY (ret < 0))
361-
{
362-
crun_error_release (&tmp_err);
363-
continue;
364-
}
379+
crun_error_release (&tmp_err);
380+
continue;
365381
}
366382

367383
for (i = 0; i < n_pids; i++)
@@ -394,8 +410,8 @@ int
394410
libcrun_cgroup_read_pids_from_path (const char *path, bool recurse, pid_t **pids, libcrun_error_t *err)
395411
{
396412
cleanup_free char *cgroup_path = NULL;
413+
cleanup_close int dirfd = -1;
397414
size_t n_pids, allocated;
398-
int dirfd;
399415
int mode;
400416
int ret;
401417

@@ -928,7 +944,7 @@ enable_controllers (const char *path, libcrun_error_t *err)
928944
}
929945

930946
int
931-
libcrun_move_process_to_cgroup (pid_t pid, pid_t init_pid, char *path, libcrun_error_t *err)
947+
libcrun_move_process_to_cgroup (pid_t pid, pid_t init_pid, const char *path, bool create_if_missing, libcrun_error_t *err)
932948
{
933949
int cgroup_mode = libcrun_get_cgroup_mode (err);
934950
if (UNLIKELY (cgroup_mode < 0))
@@ -937,7 +953,7 @@ libcrun_move_process_to_cgroup (pid_t pid, pid_t init_pid, char *path, libcrun_e
937953
if (path == NULL || *path == '\0')
938954
return 0;
939955

940-
return enter_cgroup (cgroup_mode, pid, init_pid, path, false, err);
956+
return enter_cgroup (cgroup_mode, pid, init_pid, path, create_if_missing, err);
941957
}
942958

943959
int
@@ -971,3 +987,76 @@ libcrun_get_cgroup_dirfd (struct libcrun_cgroup_status *status, const char *sub_
971987

972988
return cgroupdirfd;
973989
}
990+
991+
int
992+
libcrun_migrate_all_pids_to_cgroup (pid_t init_pid, char *from, char *to, libcrun_error_t *err)
993+
{
994+
cleanup_free pid_t *pids = NULL;
995+
cleanup_close int child_dfd = -1;
996+
int cgroup_mode;
997+
size_t from_len;
998+
size_t i;
999+
int ret;
1000+
1001+
cgroup_mode = libcrun_get_cgroup_mode (err);
1002+
if (cgroup_mode < 0)
1003+
return cgroup_mode;
1004+
1005+
ret = libcrun_cgroup_pause_unpause_path (from, true, err);
1006+
if (UNLIKELY (ret < 0))
1007+
return ret;
1008+
1009+
ret = libcrun_cgroup_read_pids_from_path (from, true, &pids, err);
1010+
if (UNLIKELY (ret < 0))
1011+
return ret;
1012+
1013+
from_len = strlen (from);
1014+
1015+
for (i = 0; pids && pids[i]; i++)
1016+
{
1017+
cleanup_free char *pid_path = NULL;
1018+
cleanup_free char *dest_cgroup = NULL;
1019+
1020+
ret = libcrun_get_cgroup_process (pids[i], &pid_path, false, err);
1021+
if (UNLIKELY (ret < 0))
1022+
return ret;
1023+
1024+
/* Make sure the pid is in the cgroup we are migrating from. */
1025+
if (! has_prefix (pid_path, from))
1026+
return crun_make_error (err, 0, "error migrating pid %d. It is not in the cgroup `%s`", pids[i], from);
1027+
1028+
/* Build the destination cgroup path, keeping the same hierarchy. */
1029+
xasprintf (&dest_cgroup, "%s%s", to, pid_path + from_len);
1030+
1031+
ret = enter_cgroup (cgroup_mode, pids[i], init_pid, dest_cgroup, false, err);
1032+
if (UNLIKELY (ret < 0))
1033+
return ret;
1034+
}
1035+
1036+
ret = libcrun_cgroup_pause_unpause_path (from, false, err);
1037+
if (UNLIKELY (ret < 0))
1038+
return ret;
1039+
1040+
return destroy_cgroup_path (from, cgroup_mode, err);
1041+
}
1042+
1043+
int
1044+
get_cgroup_dirfd_path (int dirfd, char **path, libcrun_error_t *err)
1045+
{
1046+
cleanup_free char *cgroup_path = NULL;
1047+
proc_fd_path_t fd_path;
1048+
ssize_t len;
1049+
1050+
get_proc_self_fd_path (fd_path, dirfd);
1051+
1052+
len = safe_readlinkat (AT_FDCWD, fd_path, &cgroup_path, 0, err);
1053+
if (UNLIKELY (len < 0))
1054+
return len;
1055+
1056+
if (has_prefix (cgroup_path, CGROUP_ROOT))
1057+
{
1058+
*path = xstrdup (cgroup_path + strlen (CGROUP_ROOT));
1059+
return 0;
1060+
}
1061+
return crun_make_error (err, 0, "invalid cgroup path `%s`", cgroup_path);
1062+
}

src/libcrun/cgroup-utils.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,22 @@
2222
#include "cgroup.h"
2323
#include <unistd.h>
2424

25-
int libcrun_move_process_to_cgroup (pid_t pid, pid_t init_pid, char *path, libcrun_error_t *err);
25+
int libcrun_move_process_to_cgroup (pid_t pid, pid_t init_pid, const char *path, bool create_if_missing, libcrun_error_t *err);
2626

2727
int libcrun_cgroups_create_symlinks (int dirfd, libcrun_error_t *err);
2828

29-
int libcrun_get_current_unified_cgroup (char **path, bool absolute, libcrun_error_t *err);
29+
int libcrun_get_cgroup_process (pid_t pid, char **path, bool absolute, libcrun_error_t *err);
3030

3131
int libcrun_get_cgroup_mode (libcrun_error_t *err);
3232

3333
int libcrun_get_cgroup_dirfd (struct libcrun_cgroup_status *status, const char *sub_cgroup, libcrun_error_t *err);
3434

3535
int maybe_make_cgroup_threaded (const char *path, libcrun_error_t *err);
3636

37+
int libcrun_migrate_all_pids_to_cgroup (pid_t init_pid, char *from, char *to, libcrun_error_t *err);
38+
39+
int destroy_cgroup_path (const char *path, int mode, libcrun_error_t *err);
40+
41+
int get_cgroup_dirfd_path (int dirfd, char **path, libcrun_error_t *err);
42+
3743
#endif

0 commit comments

Comments
 (0)