Skip to content

Commit 862e13b

Browse files
committed
linux: honor execCPUAffinity from main configuration file
Closes: https://issues.redhat.com/browse/OCPBUGS-65579 Signed-off-by: Giuseppe Scrivano <[email protected]>
1 parent 993ad9d commit 862e13b

File tree

2 files changed

+74
-9
lines changed

2 files changed

+74
-9
lines changed

src/libcrun/linux.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5078,12 +5078,10 @@ handle_pidfd_receiver (pid_t pid, libcrun_container_t *container, libcrun_error_
50785078
}
50795079

50805080
static bool
5081-
has_exec_cpu_affinity (runtime_spec_schema_config_schema_process *process)
5081+
has_exec_cpu_affinity (runtime_spec_schema_config_schema_process_exec_cpu_affinity *affinity)
50825082
{
5083-
if (process == NULL || process->exec_cpu_affinity == NULL)
5084-
return false;
5085-
return (! is_empty_string (process->exec_cpu_affinity->initial))
5086-
|| (! is_empty_string (process->exec_cpu_affinity->final));
5083+
return affinity && (! is_empty_string (affinity->initial))
5084+
|| (! is_empty_string (affinity->final));
50875085
}
50885086

50895087
pid_t
@@ -5378,6 +5376,7 @@ join_process_parent_helper (libcrun_context_t *context,
53785376
char res;
53795377
pid_t pid;
53805378
cleanup_close int sync_fd = sync_socket_fd;
5379+
runtime_spec_schema_config_schema_process_exec_cpu_affinity *cpu_affinity = NULL;
53815380

53825381
if (terminal_fd)
53835382
*terminal_fd = -1;
@@ -5400,13 +5399,18 @@ join_process_parent_helper (libcrun_context_t *context,
54005399
return crun_make_error (err, errno, "waitpid for exec child pid");
54015400

54025401
if (process && process->exec_cpu_affinity)
5402+
cpu_affinity = process->exec_cpu_affinity;
5403+
else if (container && container->container_def && container->container_def->process && container->container_def->process->exec_cpu_affinity)
5404+
cpu_affinity = container->container_def->process->exec_cpu_affinity;
5405+
5406+
if (cpu_affinity)
54035407
{
5404-
ret = libcrun_set_cpu_affinity_from_string (pid, process->exec_cpu_affinity->initial, err);
5408+
ret = libcrun_set_cpu_affinity_from_string (pid, cpu_affinity->initial, err);
54055409
if (UNLIKELY (ret < 0))
54065410
return ret;
54075411
}
54085412

5409-
if (! has_exec_cpu_affinity (process))
5413+
if (! has_exec_cpu_affinity (cpu_affinity))
54105414
{
54115415
ret = libcrun_reset_cpu_affinity_mask (pid, err);
54125416
if (UNLIKELY (ret < 0))
@@ -5440,9 +5444,9 @@ join_process_parent_helper (libcrun_context_t *context,
54405444
return ret;
54415445
}
54425446

5443-
if (process && process->exec_cpu_affinity)
5447+
if (cpu_affinity)
54445448
{
5445-
ret = libcrun_set_cpu_affinity_from_string (pid, process->exec_cpu_affinity->final, err);
5449+
ret = libcrun_set_cpu_affinity_from_string (pid, cpu_affinity->final, err);
54465450
if (UNLIKELY (ret < 0))
54475451
return ret;
54485452
}

tests/test_exec.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,66 @@ def exec_and_get_affinity_mask(cid, exec_cpu_affinity=None):
477477
shutil.rmtree(tempdir)
478478
return 0
479479

480+
def test_exec_cpu_affinity_config_file():
481+
"""Test that exec honors execCPUAffinity from container configuration when not specified in exec process"""
482+
if len(os.sched_getaffinity(0)) < 4:
483+
return 77
484+
485+
conf = base_config()
486+
conf['process']['args'] = ['/init', 'pause']
487+
# Set execCPUAffinity in the container's main process configuration
488+
conf['process']['execCPUAffinity'] = {"initial": "0-1", "final": "0-2"}
489+
add_all_namespaces(conf)
490+
cid = None
491+
tempdir = tempfile.mkdtemp()
492+
493+
def cpu_mask_from_proc_status(status):
494+
for l in status.split("\n"):
495+
parts = l.split(":")
496+
if parts[0] == "Cpus_allowed_list":
497+
return parts[1].strip()
498+
return ""
499+
500+
def exec_without_cpu_affinity_and_get_mask(cid):
501+
"""Execute a process without specifying execCPUAffinity and get its CPU mask"""
502+
process_file = os.path.join(tempdir, "process.json")
503+
with open(process_file, "w") as f:
504+
process = {
505+
"user": {
506+
"uid": 0,
507+
"gid": 0
508+
},
509+
"terminal": False,
510+
"cwd": "/",
511+
"args": [
512+
"/init",
513+
"cat",
514+
"/proc/self/status"
515+
]
516+
# Note: No execCPUAffinity specified here - should fall back to container config
517+
}
518+
json.dump(process, f)
519+
520+
out = run_crun_command(["exec", "--process", process_file, cid])
521+
return cpu_mask_from_proc_status(out)
522+
523+
try:
524+
_, cid = run_and_get_output(conf, command='run', detach=True)
525+
526+
# Execute without specifying execCPUAffinity - should use container's config final value
527+
mask = exec_without_cpu_affinity_and_get_mask(cid)
528+
if mask != "0-2":
529+
sys.stderr.write("# execCPUAffinity fallback test failed: cpu mask %s != 0-2\n" % mask)
530+
sys.stderr.write("# expected to use container's execCPUAffinity.final value\n")
531+
return -1
532+
533+
return 0
534+
finally:
535+
if cid is not None:
536+
run_crun_command(["delete", "-f", cid])
537+
shutil.rmtree(tempdir)
538+
return 0
539+
480540
def test_exec_getpgrp():
481541
conf = base_config()
482542
add_all_namespaces(conf)
@@ -553,6 +613,7 @@ def test_exec_error_propagation():
553613
"exec_populate_home_env_from_process_uid" : test_exec_populate_home_env_from_process_uid,
554614
"exec-test-uid-tty": test_uid_tty,
555615
"exec-cpu-affinity": test_exec_cpu_affinity,
616+
"exec-cpu-affinity-config-file": test_exec_cpu_affinity_config_file,
556617
"exec-getpgrp": test_exec_getpgrp,
557618
"exec-help" : test_exec_help,
558619
"exec-error-propagation" : test_exec_error_propagation,

0 commit comments

Comments
 (0)