From a12d2da2b7dd789ad96a797247ca6c3a3f3bd76e Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Tue, 7 Jan 2025 19:48:58 -0800 Subject: [PATCH] Fix setting IOPriority on exec Commit bfbd0305b added IOPriority for both Config and Process, but forgot to add a mechanism to overwrite the per-process IOPriority. As a result, runc exec does not take Process.IOPriority into account. Add it, and a test case (which fails before the fix). Signed-off-by: Kir Kolyshkin --- libcontainer/container_linux.go | 4 ++++ libcontainer/init_linux.go | 3 ++- libcontainer/setns_init_linux.go | 2 +- libcontainer/standard_init_linux.go | 2 +- tests/integration/ioprio.bats | 16 +++++++++++++++- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index c9e74188e2b..ab030974f33 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -700,6 +700,7 @@ func (c *Container) newInitConfig(process *Process) *initConfig { AppArmorProfile: c.config.AppArmorProfile, ProcessLabel: c.config.ProcessLabel, Rlimits: c.config.Rlimits, + IOPriority: c.config.IOPriority, CreateConsole: process.ConsoleSocket != nil, ConsoleWidth: process.ConsoleWidth, ConsoleHeight: process.ConsoleHeight, @@ -722,6 +723,9 @@ func (c *Container) newInitConfig(process *Process) *initConfig { if len(process.Rlimits) > 0 { cfg.Rlimits = process.Rlimits } + if process.IOPriority != nil { + cfg.IOPriority = process.IOPriority + } // Set misc properties. diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index 613f6200f3a..03a8103e00e 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -82,6 +82,7 @@ type initConfig struct { NoNewPrivileges bool `json:"no_new_privileges"` ProcessLabel string `json:"process_label"` Rlimits []configs.Rlimit `json:"rlimits"` + IOPriority *configs.IOPriority `json:"io_priority"` // Properties that only exist in container config. // FIXME: they are also passed in Config above. @@ -700,7 +701,7 @@ func setupScheduler(config *configs.Config) error { return nil } -func setupIOPriority(config *configs.Config) error { +func setupIOPriority(config *initConfig) error { const ioprioWhoPgrp = 1 ioprio := config.IOPriority diff --git a/libcontainer/setns_init_linux.go b/libcontainer/setns_init_linux.go index 462662a84ed..aab122f3dc2 100644 --- a/libcontainer/setns_init_linux.go +++ b/libcontainer/setns_init_linux.go @@ -75,7 +75,7 @@ func (l *linuxSetnsInit) Init() error { return err } - if err := setupIOPriority(l.config.Config); err != nil { + if err := setupIOPriority(l.config); err != nil { return err } // Tell our parent that we're ready to exec. This must be done before the diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index bb1eb300188..f005b9f9efe 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -159,7 +159,7 @@ func (l *linuxStandardInit) Init() error { return err } - if err := setupIOPriority(l.config.Config); err != nil { + if err := setupIOPriority(l.config); err != nil { return err } diff --git a/tests/integration/ioprio.bats b/tests/integration/ioprio.bats index a907d782f01..b1ba31f6f46 100644 --- a/tests/integration/ioprio.bats +++ b/tests/integration/ioprio.bats @@ -25,6 +25,20 @@ function teardown() { # Check the process made from the exec command. runc exec test_ioprio ionice [ "$status" -eq 0 ] - [[ "$output" = *'best-effort: prio 4'* ]] + + # Run exec with a different priority. + proc=' +{ + "terminal": false, + "ioPriority": { + "class": "IOPRIO_CLASS_RT", + "priority": 7 + }, + "args": [ "/usr/bin/ionice" ], + "cwd": "/" +}' + runc exec --process <(echo "$proc") test_ioprio + [ "$status" -eq 0 ] + [[ "$output" = *'realtime: prio 7'* ]] }