From 19bbd8dae3fcbbad612f37563bb278d3390a75b6 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 25 Nov 2024 14:50:27 +0100 Subject: [PATCH 1/8] utils: silence compiler warning Signed-off-by: Giuseppe Scrivano --- src/libcrun/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcrun/utils.c b/src/libcrun/utils.c index 8b483250d..bc12207eb 100644 --- a/src/libcrun/utils.c +++ b/src/libcrun/utils.c @@ -1541,7 +1541,7 @@ getsubidrange (uid_t id, int is_uid, uint32_t *from, uint32_t *len) size_t format_default_id_mapping (char **ret, uid_t container_id, uid_t host_uid, uid_t host_id, int is_uid) { - uint32_t from, available; + uint32_t from = 0, available = 0; cleanup_free char *buffer = NULL; size_t written = 0; From 46bd62b117f23cd7baf1b0f74bd6800e09987fa1 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 22 Nov 2024 22:59:54 +0100 Subject: [PATCH 2/8] cgroup: do not stop process on exec the cpu mask is configured on the systemd scope, so there is no time when the process joins the cgroup and runs on unexpected cpus Signed-off-by: Giuseppe Scrivano --- src/libcrun/cgroup.c | 47 -------------------------------------------- 1 file changed, 47 deletions(-) diff --git a/src/libcrun/cgroup.c b/src/libcrun/cgroup.c index 625591d96..dc501a557 100644 --- a/src/libcrun/cgroup.c +++ b/src/libcrun/cgroup.c @@ -100,37 +100,6 @@ find_delegate_cgroup (json_map_string_string *annotations) return NULL; } -static inline void -cleanup_sig_contp (void *p) -{ - pid_t *pp = p; - if (*pp < 0) - return; - - TEMP_FAILURE_RETRY (kill (*pp, SIGCONT)); -} - -static bool -must_stop_proc (runtime_spec_schema_config_linux_resources *resources) -{ - size_t i; - - if (resources == NULL) - return false; - - if (resources->cpu && (resources->cpu->cpus || resources->cpu->mems)) - return true; - - if (resources->unified) - { - for (i = 0; i < resources->unified->len; i++) - if (has_prefix (resources->unified->keys[i], "cpuset.")) - return true; - } - - return false; -} - int libcrun_cgroup_pause_unpause (struct libcrun_cgroup_status *status, const bool pause, libcrun_error_t *err) { @@ -284,7 +253,6 @@ libcrun_cgroup_preenter (struct libcrun_cgroup_args *args, int *dirfd, libcrun_e int libcrun_cgroup_enter (struct libcrun_cgroup_args *args, struct libcrun_cgroup_status **out, libcrun_error_t *err) { - __attribute__ ((unused)) pid_t sigcont_cleanup __attribute__ ((cleanup (cleanup_sig_contp))) = -1; /* status will be filled by the cgroup manager. */ cleanup_cgroup_status struct libcrun_cgroup_status *status = xmalloc0 (sizeof *status); struct libcrun_cgroup_manager *cgroup_manager; @@ -297,21 +265,6 @@ libcrun_cgroup_enter (struct libcrun_cgroup_args *args, struct libcrun_cgroup_st if (UNLIKELY (cgroup_mode < 0)) return cgroup_mode; - /* If the cgroup configuration is limiting what CPUs/memory Nodes are available for the container, - then stop the container process during the cgroup configuration to avoid it being rescheduled on - a CPU that is not allowed. This extra step is required for setting up the sub cgroup with the - systemd driver. The alternative would be to temporarily setup the cpus/mems using d-bus. - */ - if (must_stop_proc (args->resources)) - { - ret = TEMP_FAILURE_RETRY (kill (args->pid, SIGSTOP)); - if (UNLIKELY (ret < 0)) - return crun_make_error (err, errno, "cannot stop container process `%d` with SIGSTOP", args->pid); - - /* Send SIGCONT as soon as the function exits. */ - sigcont_cleanup = args->pid; - } - if (cgroup_mode == CGROUP_MODE_HYBRID) { /* We don't really support hybrid mode, so check that cgroups2 is not using any controller. */ From 42b959b5489e72c5c5d12df0d3a01b5a678db3d2 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Sun, 24 Nov 2024 11:47:54 +0100 Subject: [PATCH 3/8] container: initialize max caps before accessing process block Signed-off-by: Giuseppe Scrivano --- src/libcrun/container.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcrun/container.c b/src/libcrun/container.c index 6574dc543..1b831a636 100644 --- a/src/libcrun/container.c +++ b/src/libcrun/container.c @@ -642,6 +642,10 @@ initialize_security (runtime_spec_schema_config_schema_process *proc, libcrun_er { int ret; + ret = libcrun_init_caps (err); + if (UNLIKELY (ret < 0)) + return ret; + if (UNLIKELY (proc == NULL)) return 0; @@ -656,10 +660,6 @@ initialize_security (runtime_spec_schema_config_schema_process *proc, libcrun_er if (UNLIKELY (ret < 0)) return ret; - ret = libcrun_init_caps (err); - if (UNLIKELY (ret < 0)) - return ret; - return 0; } From 2c8088c4e9c0fa8686a02ecae6a021e66b567f76 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 22 Nov 2024 16:30:32 +0100 Subject: [PATCH 4/8] libocispec: sync Signed-off-by: Giuseppe Scrivano --- libocispec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libocispec b/libocispec index 68211ccc4..5ffd4dd9f 160000 --- a/libocispec +++ b/libocispec @@ -1 +1 @@ -Subproject commit 68211ccc41201c45ad276b04c7f67d61e80b1f7a +Subproject commit 5ffd4dd9fa684e0ffb2f0b5ea4a6cb638b021397 From 047b7485a5cbca4d6ccf70dcb01d61774e754584 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 22 Nov 2024 16:44:46 +0100 Subject: [PATCH 5/8] src: move cpuset_string_to_bitmask to utils Signed-off-by: Giuseppe Scrivano --- src/libcrun/cgroup-systemd.c | 69 ------------------------------------ src/libcrun/cgroup-systemd.h | 2 -- src/libcrun/utils.c | 69 ++++++++++++++++++++++++++++++++++++ src/libcrun/utils.h | 2 ++ 4 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/libcrun/cgroup-systemd.c b/src/libcrun/cgroup-systemd.c index f3b2220c8..4e8b3879d 100644 --- a/src/libcrun/cgroup-systemd.c +++ b/src/libcrun/cgroup-systemd.c @@ -106,75 +106,6 @@ property_missing_p (char **missing_properties, const char *property) return false; } -int -cpuset_string_to_bitmask (const char *str, char **out, size_t *out_size, libcrun_error_t *err) -{ - cleanup_free char *mask = NULL; - size_t mask_size = 0; - const char *p = str; - char *endptr; - - while (*p) - { - long long start_range, end_range; - - if (*p < '0' || *p > '9') - goto invalid_input; - - start_range = strtoll (p, &endptr, 10); - if (start_range < 0) - goto invalid_input; - - p = endptr; - - if (*p != '-') - end_range = start_range; - else - { - p++; - - if (*p < '0' || *p > '9') - goto invalid_input; - - end_range = strtoll (p, &endptr, 10); - - if (end_range < start_range) - goto invalid_input; - - p = endptr; - } - - /* Just set some limit. */ - if (end_range > (1 << 20)) - goto invalid_input; - - if (end_range >= (long long) (mask_size * CHAR_BIT)) - { - size_t new_mask_size = (end_range / CHAR_BIT) + 1; - mask = xrealloc (mask, new_mask_size); - memset (mask + mask_size, 0, new_mask_size - mask_size); - mask_size = new_mask_size; - } - - for (long long i = start_range; i <= end_range; i++) - mask[i / CHAR_BIT] |= (1 << (i % CHAR_BIT)); - - if (*p == ',') - p++; - else if (*p) - goto invalid_input; - } - - *out = mask; - mask = NULL; - *out_size = mask_size; - - return 0; - -invalid_input: - return crun_make_error (err, 0, "cannot parse input `%s`", str); -} - static void get_systemd_scope_and_slice (const char *id, const char *cgroup_path, char **scope, char **slice) { diff --git a/src/libcrun/cgroup-systemd.h b/src/libcrun/cgroup-systemd.h index c84cc7d42..7867c9244 100644 --- a/src/libcrun/cgroup-systemd.h +++ b/src/libcrun/cgroup-systemd.h @@ -24,8 +24,6 @@ #ifdef HAVE_SYSTEMD extern int parse_sd_array (char *s, char **out, char **next, libcrun_error_t *err); -extern int cpuset_string_to_bitmask (const char *str, char **out, size_t *out_size, libcrun_error_t *err); - extern char *get_cgroup_scope_path (const char *cgroup_path, const char *scope); #endif diff --git a/src/libcrun/utils.c b/src/libcrun/utils.c index bc12207eb..a133769d6 100644 --- a/src/libcrun/utils.c +++ b/src/libcrun/utils.c @@ -2571,3 +2571,72 @@ read_dir_entries (const char *path, libcrun_error_t *err) return entries; } + +int +cpuset_string_to_bitmask (const char *str, char **out, size_t *out_size, libcrun_error_t *err) +{ + cleanup_free char *mask = NULL; + size_t mask_size = 0; + const char *p = str; + char *endptr; + + while (*p) + { + long long start_range, end_range; + + if (*p < '0' || *p > '9') + goto invalid_input; + + start_range = strtoll (p, &endptr, 10); + if (start_range < 0) + goto invalid_input; + + p = endptr; + + if (*p != '-') + end_range = start_range; + else + { + p++; + + if (*p < '0' || *p > '9') + goto invalid_input; + + end_range = strtoll (p, &endptr, 10); + + if (end_range < start_range) + goto invalid_input; + + p = endptr; + } + + /* Just set some limit. */ + if (end_range > (1 << 20)) + goto invalid_input; + + if (end_range >= (long long) (mask_size * CHAR_BIT)) + { + size_t new_mask_size = (end_range / CHAR_BIT) + 1; + mask = xrealloc (mask, new_mask_size); + memset (mask + mask_size, 0, new_mask_size - mask_size); + mask_size = new_mask_size; + } + + for (long long i = start_range; i <= end_range; i++) + mask[i / CHAR_BIT] |= (1 << (i % CHAR_BIT)); + + if (*p == ',') + p++; + else if (*p) + goto invalid_input; + } + + *out = mask; + mask = NULL; + *out_size = mask_size; + + return 0; + +invalid_input: + return crun_make_error (err, 0, "cannot parse input `%s`", str); +} diff --git a/src/libcrun/utils.h b/src/libcrun/utils.h index 9e42739dc..584b9ea47 100644 --- a/src/libcrun/utils.h +++ b/src/libcrun/utils.h @@ -473,4 +473,6 @@ validate_options (unsigned int specified_options, unsigned int supported_options return 0; } +extern int cpuset_string_to_bitmask (const char *str, char **out, size_t *out_size, libcrun_error_t *err); + #endif From ef33259c7769e91dbf8eea2eb6aabe8e253b6376 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 22 Nov 2024 22:47:28 +0100 Subject: [PATCH 6/8] linux: honor exec cpu affinity mask Signed-off-by: Giuseppe Scrivano --- src/libcrun/linux.c | 19 ++++++++++++++++++- src/libcrun/scheduler.c | 39 +++++++++++++++++++++++++++++++++++++++ src/libcrun/scheduler.h | 2 ++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/libcrun/linux.c b/src/libcrun/linux.c index 4114567fe..8723c835e 100644 --- a/src/libcrun/linux.c +++ b/src/libcrun/linux.c @@ -5053,6 +5053,13 @@ join_process_parent_helper (libcrun_context_t *context, if (UNLIKELY (ret < 0)) return crun_make_error (err, errno, "waitpid for exec child pid"); + if (process && process->exec_cpu_affinity) + { + ret = libcrun_set_cpu_affinity_from_string (pid, process->exec_cpu_affinity->initial, err); + if (UNLIKELY (ret < 0)) + return ret; + } + if (need_move_to_cgroup) { if (sub_cgroup) @@ -5080,6 +5087,13 @@ join_process_parent_helper (libcrun_context_t *context, return ret; } + if (process && process->exec_cpu_affinity) + { + ret = libcrun_set_cpu_affinity_from_string (pid, process->exec_cpu_affinity->final, err); + if (UNLIKELY (ret < 0)) + return ret; + } + ret = libcrun_apply_intelrdt (context->id, container, pid, LIBCRUN_INTELRDT_MOVE, err); if (UNLIKELY (ret < 0)) return ret; @@ -5307,7 +5321,10 @@ libcrun_join_process (libcrun_context_t *context, memset (&clone3_args, 0, sizeof (clone3_args)); clone3_args.exit_signal = SIGCHLD; - if (cgroup_dirfd < 0) + + /* Do not join the cgroup immediately if an initial CPU affinity mask is specified, so that + the process can set the cpu affinity before joining the target cgroup. */ + if (cgroup_dirfd < 0 || (process->exec_cpu_affinity && process->exec_cpu_affinity->initial)) need_move_to_cgroup = true; else { diff --git a/src/libcrun/scheduler.c b/src/libcrun/scheduler.c index 2bc633343..6d34b25df 100644 --- a/src/libcrun/scheduler.c +++ b/src/libcrun/scheduler.c @@ -162,3 +162,42 @@ libcrun_set_scheduler (pid_t pid, runtime_spec_schema_config_schema_process *pro return 0; } + +int +libcrun_set_cpu_affinity_from_string (pid_t pid, const char *str, libcrun_error_t *err) +{ + cleanup_free char *bitmask = NULL; + int ret, saved_errno; + size_t bitmask_size; + cpu_set_t *cpuset; + size_t alloc_size; + size_t i; + + if (is_empty_string (str)) + return 0; + + ret = cpuset_string_to_bitmask (str, &bitmask, &bitmask_size, err); + if (UNLIKELY (ret < 0)) + return ret; + + alloc_size = CPU_ALLOC_SIZE (bitmask_size * CHAR_BIT); + + cpuset = CPU_ALLOC (alloc_size); + if (UNLIKELY (cpuset == NULL)) + OOM (); + + CPU_ZERO_S (alloc_size, cpuset); + + for (i = 0; i < bitmask_size * CHAR_BIT; i++) + { + if (bitmask[i / CHAR_BIT] & (1 << (i % CHAR_BIT))) + CPU_SET_S (i, alloc_size, cpuset); + } + + ret = sched_setaffinity (pid, alloc_size, cpuset); + saved_errno = errno; + CPU_FREE (cpuset); + if (UNLIKELY (ret < 0)) + return crun_make_error (err, saved_errno, "sched_setaffinity"); + return 0; +} diff --git a/src/libcrun/scheduler.h b/src/libcrun/scheduler.h index 33c80ac8a..6f205fc1f 100644 --- a/src/libcrun/scheduler.h +++ b/src/libcrun/scheduler.h @@ -24,4 +24,6 @@ int libcrun_set_scheduler (pid_t pid, runtime_spec_schema_config_schema_process *process, libcrun_error_t *err); +int libcrun_set_cpu_affinity_from_string (pid_t pid, const char *str, libcrun_error_t *err); + #endif From b941d6c5a1c68ce857a697b0afacb0a007ca8993 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 22 Nov 2024 22:57:52 +0100 Subject: [PATCH 7/8] linux: move reset cpu affinity to scheduler and set it only when there is no exec cpu affinity mask specified. Signed-off-by: Giuseppe Scrivano --- src/libcrun/cgroup-setup.c | 15 --------------- src/libcrun/cgroup.c | 16 ---------------- src/libcrun/container.c | 4 ++++ src/libcrun/linux.c | 16 ++++++++++++++++ src/libcrun/scheduler.c | 24 ++++++++++++++++++++++++ src/libcrun/scheduler.h | 2 ++ 6 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/libcrun/cgroup-setup.c b/src/libcrun/cgroup-setup.c index c84529558..8dd36f729 100644 --- a/src/libcrun/cgroup-setup.c +++ b/src/libcrun/cgroup-setup.c @@ -506,20 +506,5 @@ enter_cgroup (int cgroup_mode, pid_t pid, pid_t init_pid, const char *path, if (UNLIKELY (ret < 0)) return ret; } - /* Reset the inherited cpu affinity. Old kernels do that automatically, but - new kernels remember the affinity that was set before the cgroup move. - This is undesirable, because it inherits the systemd affinity when the container - should really move to the container space cpus. - - The sched_setaffinity call will always return an error (EINVAL or ENODEV) - when used like this. This is expected and part of the backward compatibility. - - See: https://issues.redhat.com/browse/OCPBUGS-15102 */ - ret = sched_setaffinity (pid, 0, NULL); - if (LIKELY (ret < 0)) - { - if (UNLIKELY (! ((errno == EINVAL) || (errno == ENODEV)))) - return crun_make_error (err, errno, "failed to reset affinity"); - } return 0; } diff --git a/src/libcrun/cgroup.c b/src/libcrun/cgroup.c index dc501a557..846023c93 100644 --- a/src/libcrun/cgroup.c +++ b/src/libcrun/cgroup.c @@ -334,22 +334,6 @@ libcrun_cgroup_enter (struct libcrun_cgroup_args *args, struct libcrun_cgroup_st return ret; } } - /* Reset the inherited cpu affinity. Old kernels do that automatically, but - new kernels remember the affinity that was set before the cgroup move. - This is undesirable, because it inherits the systemd affinity when the container - should really move to the container space cpus. - - The sched_setaffinity call will always return an error (EINVAL or ENODEV) - when used like this. This is expected and part of the backward compatibility. - - See: https://issues.redhat.com/browse/OCPBUGS-15102 */ - ret = sched_setaffinity (args->pid, 0, NULL); - if (LIKELY (ret < 0)) - { - if (UNLIKELY (! ((errno == EINVAL) || (errno == ENODEV)))) - return crun_make_error (err, errno, "failed to reset affinity"); - } - success: *out = status; status = NULL; diff --git a/src/libcrun/container.c b/src/libcrun/container.c index 1b831a636..6d549980d 100644 --- a/src/libcrun/container.c +++ b/src/libcrun/container.c @@ -2590,6 +2590,10 @@ libcrun_container_run_internal (libcrun_container_t *container, libcrun_context_ if (UNLIKELY (ret < 0)) goto fail; + ret = libcrun_reset_cpu_affinity_mask (pid, err); + if (UNLIKELY (ret < 0)) + goto fail; + ret = libcrun_set_io_priority (pid, def->process, err); if (UNLIKELY (ret < 0)) goto fail; diff --git a/src/libcrun/linux.c b/src/libcrun/linux.c index 8723c835e..72213de74 100644 --- a/src/libcrun/linux.c +++ b/src/libcrun/linux.c @@ -4738,6 +4738,15 @@ handle_pidfd_receiver (pid_t pid, libcrun_container_t *container, libcrun_error_ return send_fd_to_socket (client_fd, pidfd, err); } +static bool +has_exec_cpu_affinity (runtime_spec_schema_config_schema_process *process) +{ + if (process == NULL || process->exec_cpu_affinity == NULL) + return false; + return (! is_empty_string (process->exec_cpu_affinity->initial)) + || (! is_empty_string (process->exec_cpu_affinity->final)); +} + pid_t libcrun_run_linux_container (libcrun_container_t *container, container_entrypoint_t entrypoint, void *args, int *sync_socket_out, struct libcrun_dirfd_s *cgroup_dirfd, libcrun_error_t *err) @@ -5060,6 +5069,13 @@ join_process_parent_helper (libcrun_context_t *context, return ret; } + if (! has_exec_cpu_affinity (process)) + { + ret = libcrun_reset_cpu_affinity_mask (pid, err); + if (UNLIKELY (ret < 0)) + return ret; + } + if (need_move_to_cgroup) { if (sub_cgroup) diff --git a/src/libcrun/scheduler.c b/src/libcrun/scheduler.c index 6d34b25df..9b917ef86 100644 --- a/src/libcrun/scheduler.c +++ b/src/libcrun/scheduler.c @@ -78,6 +78,30 @@ syscall_sched_setattr (pid_t pid, struct sched_attr_s *attr, unsigned int flags) #endif } +int +libcrun_reset_cpu_affinity_mask (pid_t pid, libcrun_error_t *err) +{ + int ret; + + /* Reset the inherited cpu affinity. Old kernels do that automatically, but + new kernels remember the affinity that was set before the cgroup move. + This is undesirable, because it inherits the systemd affinity when the container + should really move to the container space cpus. + + The sched_setaffinity call will always return an error (EINVAL or ENODEV) + when used like this. This is expected and part of the backward compatibility. + + See: https://issues.redhat.com/browse/OCPBUGS-15102 */ + ret = sched_setaffinity (pid, 0, NULL); + if (LIKELY (ret < 0)) + { + if (UNLIKELY (! ((errno == EINVAL) || (errno == ENODEV)))) + return crun_make_error (err, errno, "failed to reset affinity"); + } + + return 0; +} + int libcrun_set_scheduler (pid_t pid, runtime_spec_schema_config_schema_process *process, libcrun_error_t *err) { diff --git a/src/libcrun/scheduler.h b/src/libcrun/scheduler.h index 6f205fc1f..45d85c88a 100644 --- a/src/libcrun/scheduler.h +++ b/src/libcrun/scheduler.h @@ -26,4 +26,6 @@ int libcrun_set_scheduler (pid_t pid, runtime_spec_schema_config_schema_process int libcrun_set_cpu_affinity_from_string (pid_t pid, const char *str, libcrun_error_t *err); +int libcrun_reset_cpu_affinity_mask (pid_t pid, libcrun_error_t *err); + #endif From fd69065d6a8a5dde0cc10aadfd0754804918802c Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 25 Nov 2024 10:51:06 +0100 Subject: [PATCH 8/8] test: add new test for exec-cpu-affinity Signed-off-by: Giuseppe Scrivano --- tests/test_exec.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tests/test_exec.py b/tests/test_exec.py index fb0cd59e1..8a6b29eb3 100755 --- a/tests/test_exec.py +++ b/tests/test_exec.py @@ -372,6 +372,77 @@ def test_exec_write_pid_file(): shutil.rmtree(tempdir) return 0 +def test_exec_cpu_affinity(): + if len(os.sched_getaffinity(0)) < 4: + return 77 + + conf = base_config() + conf['process']['args'] = ['/init', 'pause'] + add_all_namespaces(conf) + cid = None + tempdir = tempfile.mkdtemp() + + def cpu_mask_from_proc_status(status): + for l in status.split("\n"): + parts = l.split(":") + if parts[0] == "Cpus_allowed_list": + return parts[1].strip() + return "" + + def exec_and_get_affinity_mask(cid, exec_cpu_affinity=None): + process_file = os.path.join(tempdir, "process.json") + with open(process_file, "w") as f: + process = { + "user": { + "uid": 0, + "gid": 0 + }, + "terminal": False, + "cwd" : "/", + "args": [ + "/init", + "cat", + "/proc/self/status" + ] + } + if exec_cpu_affinity is not None: + process["execCPUAffinity"] = exec_cpu_affinity + json.dump(process, f) + + out = run_crun_command(["exec", "--process", process_file, cid]) + return cpu_mask_from_proc_status(out) + + try: + with open("/proc/self/status") as f: + current_cpu_mask = cpu_mask_from_proc_status(f.read()) + _, cid = run_and_get_output(conf, command='run', detach=True) + + mask = exec_and_get_affinity_mask(cid) + if mask != current_cpu_mask: + sys.stderr.write("current cpu mask %s != %s\n" % (current_cpu_mask, mask)) + return -1 + + mask = exec_and_get_affinity_mask(cid, {"initial" : "0-1"}) + if mask != "0-1": + sys.stderr.write("cpu mask %s != 0-1\n" % mask) + return -1 + + mask = exec_and_get_affinity_mask(cid, {"final" : "0-2"}) + if mask != "0-2": + sys.stderr.write("cpu mask %s != 0-2\n" % mask) + return -1 + + mask = exec_and_get_affinity_mask(cid, {"initial" : "1", "final" : "0-3"}) + if mask != "0-3": + sys.stderr.write("cpu mask %s != 0-2\n" % mask) + return -1 + return 0 + finally: + if cid is not None: + run_crun_command(["delete", "-f", cid]) + shutil.rmtree(tempdir) + return 0 + all_tests = { "exec" : test_exec, "exec-not-exists" : test_exec_not_exists, @@ -385,6 +456,7 @@ def test_exec_write_pid_file(): "exec_write_pid_file" : test_exec_write_pid_file, "exec_populate_home_env_from_process_uid" : test_exec_populate_home_env_from_process_uid, "exec-test-uid-tty": test_uid_tty, + "exec-cpu-affinity": test_exec_cpu_affinity, } if __name__ == "__main__":