Skip to content

Commit e4bf49f

Browse files
AkihiroSudalifubang
authored andcommitted
runc update: distinguish nil from zero
Prior to this commit, commands like `runc update --cpuset-cpus=1` were implying to set cpu burst to "0" (which does not mean "leave it as is"). This was failing when the kernel does not support cpu burst: `openat2 /sys/fs/cgroup/runc-cgroups-integration-test/test-cgroup-22167/cpu.max.burst: no such file or directory` Signed-off-by: Akihiro Suda <[email protected]>
1 parent afcb9c2 commit e4bf49f

File tree

1 file changed

+72
-54
lines changed

1 file changed

+72
-54
lines changed

update.go

Lines changed: 72 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -147,30 +147,13 @@ other options are ignored.
147147
}
148148

149149
r := specs.LinuxResources{
150+
// nil and u64Ptr(0) are not interchangeable
150151
Memory: &specs.LinuxMemory{
151-
Limit: i64Ptr(0),
152-
Reservation: i64Ptr(0),
153-
Swap: i64Ptr(0),
154-
Kernel: i64Ptr(0),
155-
KernelTCP: i64Ptr(0),
156-
CheckBeforeUpdate: boolPtr(false),
157-
},
158-
CPU: &specs.LinuxCPU{
159-
Shares: u64Ptr(0),
160-
Quota: i64Ptr(0),
161-
Burst: u64Ptr(0),
162-
Period: u64Ptr(0),
163-
RealtimeRuntime: i64Ptr(0),
164-
RealtimePeriod: u64Ptr(0),
165-
Cpus: "",
166-
Mems: "",
167-
},
168-
BlockIO: &specs.LinuxBlockIO{
169-
Weight: u16Ptr(0),
170-
},
171-
Pids: &specs.LinuxPids{
172-
Limit: 0,
152+
CheckBeforeUpdate: boolPtr(false), // constant
173153
},
154+
CPU: &specs.LinuxCPU{},
155+
BlockIO: &specs.LinuxBlockIO{},
156+
Pids: &specs.LinuxPids{},
174157
}
175158

176159
config := container.Config()
@@ -214,45 +197,45 @@ other options are ignored.
214197

215198
for _, pair := range []struct {
216199
opt string
217-
dest *uint64
200+
dest **uint64
218201
}{
219-
{"cpu-burst", r.CPU.Burst},
220-
{"cpu-period", r.CPU.Period},
221-
{"cpu-rt-period", r.CPU.RealtimePeriod},
222-
{"cpu-share", r.CPU.Shares},
202+
{"cpu-burst", &r.CPU.Burst},
203+
{"cpu-period", &r.CPU.Period},
204+
{"cpu-rt-period", &r.CPU.RealtimePeriod},
205+
{"cpu-share", &r.CPU.Shares},
223206
} {
224207
if val := context.String(pair.opt); val != "" {
225-
var err error
226-
*pair.dest, err = strconv.ParseUint(val, 10, 64)
208+
v, err := strconv.ParseUint(val, 10, 64)
227209
if err != nil {
228210
return fmt.Errorf("invalid value for %s: %w", pair.opt, err)
229211
}
212+
*pair.dest = &v
230213
}
231214
}
232215
for _, pair := range []struct {
233216
opt string
234-
dest *int64
217+
dest **int64
235218
}{
236-
{"cpu-quota", r.CPU.Quota},
237-
{"cpu-rt-runtime", r.CPU.RealtimeRuntime},
219+
{"cpu-quota", &r.CPU.Quota},
220+
{"cpu-rt-runtime", &r.CPU.RealtimeRuntime},
238221
} {
239222
if val := context.String(pair.opt); val != "" {
240-
var err error
241-
*pair.dest, err = strconv.ParseInt(val, 10, 64)
223+
v, err := strconv.ParseInt(val, 10, 64)
242224
if err != nil {
243225
return fmt.Errorf("invalid value for %s: %w", pair.opt, err)
244226
}
227+
*pair.dest = &v
245228
}
246229
}
247230
for _, pair := range []struct {
248231
opt string
249-
dest *int64
232+
dest **int64
250233
}{
251-
{"memory", r.Memory.Limit},
252-
{"memory-swap", r.Memory.Swap},
253-
{"kernel-memory", r.Memory.Kernel}, //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
254-
{"kernel-memory-tcp", r.Memory.KernelTCP},
255-
{"memory-reservation", r.Memory.Reservation},
234+
{"memory", &r.Memory.Limit},
235+
{"memory-swap", &r.Memory.Swap},
236+
{"kernel-memory", &r.Memory.Kernel}, //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
237+
{"kernel-memory-tcp", &r.Memory.KernelTCP},
238+
{"memory-reservation", &r.Memory.Reservation},
256239
} {
257240
if val := context.String(pair.opt); val != "" {
258241
var v int64
@@ -265,19 +248,31 @@ other options are ignored.
265248
} else {
266249
v = -1
267250
}
268-
*pair.dest = v
251+
*pair.dest = &v
269252
}
270253
}
271254

272255
r.Pids.Limit = int64(context.Int("pids-limit"))
273256
}
274257

275-
if *r.Memory.Kernel != 0 || *r.Memory.KernelTCP != 0 { //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
258+
// Fix up values
259+
if r.Memory.Limit != nil && *r.Memory.Limit == -1 && r.Memory.Swap == nil {
260+
// To avoid error "unable to set swap limit without memory limit"
261+
r.Memory.Swap = i64Ptr(0)
262+
}
263+
if r.CPU.Idle != nil && r.CPU.Shares == nil {
264+
// To avoid error "failed to write \"4\": write /sys/fs/cgroup/runc-cgroups-integration-test/test-cgroup-7341/cpu.weight: invalid argument"
265+
r.CPU.Shares = u64Ptr(0)
266+
}
267+
268+
if (r.Memory.Kernel != nil) || (r.Memory.KernelTCP != nil) { //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
276269
logrus.Warn("Kernel memory settings are ignored and will be removed")
277270
}
278271

279272
// Update the values
280-
config.Cgroups.Resources.BlkioWeight = *r.BlockIO.Weight
273+
if r.BlockIO.Weight != nil {
274+
config.Cgroups.Resources.BlkioWeight = *r.BlockIO.Weight
275+
}
281276

282277
// Setting CPU quota and period independently does not make much sense,
283278
// but historically runc allowed it and this needs to be supported
@@ -290,7 +285,16 @@ other options are ignored.
290285
// Here in update, previously set values are available from config.
291286
// If only one of {quota,period} is set and the other is not, leave
292287
// the unset parameter at the old value (don't overwrite config).
293-
p, q := *r.CPU.Period, *r.CPU.Quota
288+
var (
289+
p uint64
290+
q int64
291+
)
292+
if r.CPU.Period != nil {
293+
p = *r.CPU.Period
294+
}
295+
if r.CPU.Quota != nil {
296+
q = *r.CPU.Quota
297+
}
294298
if (p == 0 && q == 0) || (p != 0 && q != 0) {
295299
// both values are either set or unset (0)
296300
config.Cgroups.Resources.CpuPeriod = p
@@ -306,19 +310,33 @@ other options are ignored.
306310
}
307311
}
308312

309-
config.Cgroups.Resources.CpuBurst = r.CPU.Burst
310-
config.Cgroups.Resources.CpuShares = *r.CPU.Shares
311-
// CpuWeight is used for cgroupv2 and should be converted
312-
config.Cgroups.Resources.CpuWeight = cgroups.ConvertCPUSharesToCgroupV2Value(*r.CPU.Shares)
313-
config.Cgroups.Resources.CpuRtPeriod = *r.CPU.RealtimePeriod
314-
config.Cgroups.Resources.CpuRtRuntime = *r.CPU.RealtimeRuntime
313+
config.Cgroups.Resources.CpuBurst = r.CPU.Burst // can be nil
314+
if r.CPU.Shares != nil {
315+
config.Cgroups.Resources.CpuShares = *r.CPU.Shares
316+
// CpuWeight is used for cgroupv2 and should be converted
317+
config.Cgroups.Resources.CpuWeight = cgroups.ConvertCPUSharesToCgroupV2Value(*r.CPU.Shares)
318+
}
319+
if r.CPU.RealtimePeriod != nil {
320+
config.Cgroups.Resources.CpuRtPeriod = *r.CPU.RealtimePeriod
321+
}
322+
if r.CPU.RealtimeRuntime != nil {
323+
config.Cgroups.Resources.CpuRtRuntime = *r.CPU.RealtimeRuntime
324+
}
315325
config.Cgroups.Resources.CpusetCpus = r.CPU.Cpus
316326
config.Cgroups.Resources.CpusetMems = r.CPU.Mems
317-
config.Cgroups.Resources.Memory = *r.Memory.Limit
327+
if r.Memory.Limit != nil {
328+
config.Cgroups.Resources.Memory = *r.Memory.Limit
329+
}
318330
config.Cgroups.Resources.CPUIdle = r.CPU.Idle
319-
config.Cgroups.Resources.MemoryReservation = *r.Memory.Reservation
320-
config.Cgroups.Resources.MemorySwap = *r.Memory.Swap
321-
config.Cgroups.Resources.MemoryCheckBeforeUpdate = *r.Memory.CheckBeforeUpdate
331+
if r.Memory.Reservation != nil {
332+
config.Cgroups.Resources.MemoryReservation = *r.Memory.Reservation
333+
}
334+
if r.Memory.Swap != nil {
335+
config.Cgroups.Resources.MemorySwap = *r.Memory.Swap
336+
}
337+
if r.Memory.CheckBeforeUpdate != nil {
338+
config.Cgroups.Resources.MemoryCheckBeforeUpdate = *r.Memory.CheckBeforeUpdate
339+
}
322340
config.Cgroups.Resources.PidsLimit = r.Pids.Limit
323341
config.Cgroups.Resources.Unified = r.Unified
324342

0 commit comments

Comments
 (0)