daemon: read-copy-update the daemon config

Ensure data-race-free access to the daemon configuration without
locking by mutating a deep copy of the config and atomically storing
a pointer to the copy into the daemon-wide configStore value. Any
operations which need to read from the daemon config must capture the
configStore value only once and pass it around to guarantee a consistent
view of the config.

Signed-off-by: Cory Snider <csnider@mirantis.com>
This commit is contained in:
Cory Snider
2022-08-17 17:13:49 -04:00
parent 742ac6e275
commit 0b592467d9
62 changed files with 1819 additions and 568 deletions

View File

@@ -6,62 +6,46 @@ import (
"bytes"
"strconv"
"github.com/docker/docker/api/types"
"github.com/docker/docker/daemon/config"
)
// reloadPlatform updates configuration with platform specific options
// and updates the passed attributes
func (daemon *Daemon) reloadPlatform(conf *config.Config) (func(attributes map[string]string), error) {
var txns []func()
if conf.IsValueSet("runtimes") {
// Always set the default one
conf.Runtimes[config.StockRuntimeName] = types.Runtime{Path: config.DefaultRuntimeBinary}
if err := daemon.initRuntimes(conf.Runtimes); err != nil {
return nil, err
}
txns = append(txns, func() {
daemon.configStore.Runtimes = conf.Runtimes
})
}
func (daemon *Daemon) reloadPlatform(txn *reloadTxn, newCfg, conf *config.Config, attributes map[string]string) error {
if conf.DefaultRuntime != "" {
txns = append(txns, func() {
daemon.configStore.DefaultRuntime = conf.DefaultRuntime
})
newCfg.DefaultRuntime = conf.DefaultRuntime
}
if conf.IsValueSet("runtimes") {
newCfg.Runtimes = conf.Runtimes
txn.OnCommit(func() error { return daemon.initRuntimes(newCfg) })
}
configureRuntimes(newCfg)
if conf.IsValueSet("default-shm-size") {
newCfg.ShmSize = conf.ShmSize
}
return func(attributes map[string]string) {
for _, commit := range txns {
commit()
}
if conf.CgroupNamespaceMode != "" {
newCfg.CgroupNamespaceMode = conf.CgroupNamespaceMode
}
if conf.IsValueSet("default-shm-size") {
daemon.configStore.ShmSize = conf.ShmSize
}
if conf.IpcMode != "" {
newCfg.IpcMode = conf.IpcMode
}
if conf.CgroupNamespaceMode != "" {
daemon.configStore.CgroupNamespaceMode = conf.CgroupNamespaceMode
// Update attributes
var runtimeList bytes.Buffer
for name, rt := range newCfg.Runtimes {
if runtimeList.Len() > 0 {
runtimeList.WriteRune(' ')
}
runtimeList.WriteString(name + ":" + rt.Path)
}
if conf.IpcMode != "" {
daemon.configStore.IpcMode = conf.IpcMode
}
// Update attributes
var runtimeList bytes.Buffer
for name, rt := range daemon.configStore.Runtimes {
if runtimeList.Len() > 0 {
runtimeList.WriteRune(' ')
}
runtimeList.WriteString(name + ":" + rt.Path)
}
attributes["runtimes"] = runtimeList.String()
attributes["default-runtime"] = daemon.configStore.DefaultRuntime
attributes["default-shm-size"] = strconv.FormatInt(int64(daemon.configStore.ShmSize), 10)
attributes["default-ipc-mode"] = daemon.configStore.IpcMode
attributes["default-cgroupns-mode"] = daemon.configStore.CgroupNamespaceMode
}, nil
attributes["runtimes"] = runtimeList.String()
attributes["default-runtime"] = newCfg.DefaultRuntime
attributes["default-shm-size"] = strconv.FormatInt(int64(newCfg.ShmSize), 10)
attributes["default-ipc-mode"] = newCfg.IpcMode
attributes["default-cgroupns-mode"] = newCfg.CgroupNamespaceMode
return nil
}