Skip to content

Commit

Permalink
Make the priority for picking the storage driver configurable
Browse files Browse the repository at this point in the history
This fixes #1457

Co-authored-by: Valentin Rothberg <vrothberg@redhat.com>
Signed-off-by: Dan Čermák <dcermak@suse.com>
  • Loading branch information
dcermak and vrothberg committed Jan 4, 2023
1 parent 46e9455 commit 6e1ef87
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 26 deletions.
5 changes: 5 additions & 0 deletions docs/containers-storage.conf.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ A common use case for this field is to provide a local storage directory when us
container storage run dir (default: "/run/containers/storage")
Default directory to store all temporary writable content created by container storage programs. The rootless runroot path supports environment variable substitutions (ie. `$HOME/containers/storage`)

**driver_priority**=[]
Priority list for the storage drivers that will be tested one after the other to pick the storage driver if it is not defined.
By default, the storage driver is set via the `driver` option. If it is not defined, then the best driver will be picked according to the current platform. This option allows you to override this internal priority list with a custom one to prefer certain drivers.
Setting this option only has an effect if the local storage has not been initialized yet and the driver name is not set.

### STORAGE OPTIONS TABLE

The `storage.options` table supports the following options:
Expand Down
12 changes: 10 additions & 2 deletions drivers/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ func getBuiltinDriver(name, home string, options Options) (Driver, error) {
type Options struct {
Root string
RunRoot string
DriverPriority []string
DriverOptions []string
UIDMaps []idtools.IDMap
GIDMaps []idtools.IDMap
Expand All @@ -337,7 +338,14 @@ func New(name string, config Options) (Driver, error) {

// Guess for prior driver
driversMap := scanPriorDrivers(config.Root)
for _, name := range priority {

// use the supplied priority list unless it is empty
prioList := config.DriverPriority
if len(prioList) == 0 {
prioList = priority
}

for _, name := range prioList {
if name == "vfs" {
// don't use vfs even if there is state present.
continue
Expand Down Expand Up @@ -372,7 +380,7 @@ func New(name string, config Options) (Driver, error) {
}

// Check for priority drivers first
for _, name := range priority {
for _, name := range prioList {
driver, err := getBuiltinDriver(name, config.Root, config)
if err != nil {
if isDriverNotSupported(err) {
Expand Down
45 changes: 24 additions & 21 deletions store.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,9 @@ type store struct {

// The following fields are only set when constructing store, and must never be modified afterwards.
// They are safe to access without any other locking.
runRoot string
graphDriverName string // Initially set to the user-requested value, possibly ""; updated during store construction, and does not change afterwards.
runRoot string
graphDriverName string // Initially set to the user-requested value, possibly ""; updated during store construction, and does not change afterwards.
graphDriverPriority []string
// graphLock:
// - Ensures that we always reload graphDriver, and the primary layer store, after any process does store.Shutdown. This is necessary
// because (??) the Shutdown may forcibly unmount and clean up, affecting graph driver state in a way only a graph driver
Expand Down Expand Up @@ -723,20 +724,21 @@ func GetStore(options types.StoreOptions) (Store, error) {
autoNsMaxSize = AutoUserNsMaxSize
}
s := &store{
runRoot: options.RunRoot,
graphDriverName: options.GraphDriverName,
graphLock: graphLock,
usernsLock: usernsLock,
graphRoot: options.GraphRoot,
graphOptions: options.GraphDriverOptions,
pullOptions: options.PullOptions,
uidMap: copyIDMap(options.UIDMap),
gidMap: copyIDMap(options.GIDMap),
autoUsernsUser: options.RootAutoNsUser,
autoNsMinSize: autoNsMinSize,
autoNsMaxSize: autoNsMaxSize,
disableVolatile: options.DisableVolatile,
transientStore: options.TransientStore,
runRoot: options.RunRoot,
graphDriverName: options.GraphDriverName,
graphDriverPriority: options.GraphDriverPriority,
graphLock: graphLock,
usernsLock: usernsLock,
graphRoot: options.GraphRoot,
graphOptions: options.GraphDriverOptions,
pullOptions: options.PullOptions,
uidMap: copyIDMap(options.UIDMap),
gidMap: copyIDMap(options.GIDMap),
autoUsernsUser: options.RootAutoNsUser,
autoNsMinSize: autoNsMinSize,
autoNsMaxSize: autoNsMaxSize,
disableVolatile: options.DisableVolatile,
transientStore: options.TransientStore,

additionalUIDs: nil,
additionalGIDs: nil,
Expand Down Expand Up @@ -934,11 +936,12 @@ func (s *store) stopUsingGraphDriver() {
// The caller must hold s.graphLock.
func (s *store) createGraphDriverLocked() (drivers.Driver, error) {
config := drivers.Options{
Root: s.graphRoot,
RunRoot: s.runRoot,
DriverOptions: s.graphOptions,
UIDMaps: s.uidMap,
GIDMaps: s.gidMap,
Root: s.graphRoot,
RunRoot: s.runRoot,
DriverPriority: s.graphDriverPriority,
DriverOptions: s.graphOptions,
UIDMaps: s.uidMap,
GIDMaps: s.gidMap,
}
return drivers.New(s.graphDriverName, config)
}
Expand Down
14 changes: 11 additions & 3 deletions types/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
type TomlConfig struct {
Storage struct {
Driver string `toml:"driver,omitempty"`
DriverPriority []string `toml:"driver_priority,omitempty"`
RunRoot string `toml:"runroot,omitempty"`
GraphRoot string `toml:"graphroot,omitempty"`
RootlessStoragePath string `toml:"rootless_storage_path,omitempty"`
Expand Down Expand Up @@ -213,10 +214,16 @@ type StoreOptions struct {
// RootlessStoragePath is the storage path for rootless users
// default $HOME/.local/share/containers/storage
RootlessStoragePath string `toml:"rootless_storage_path"`
// GraphDriverName is the underlying storage driver that we'll be
// using. It only needs to be specified the first time a Store is
// initialized for a given RunRoot and GraphRoot.
// If the driver is not specified, the best suited driver will be picked
// either from GraphDriverPriority, if specified, or from the platform
// dependent priority list (in that order).
GraphDriverName string `json:"driver,omitempty"`
// GraphDriverPriority is a list of storage drivers that will be tried
// to initialize the Store for a given RunRoot and GraphRoot unless a
// GraphDriverName is set.
// This list can be used to define a custom order in which the drivers
// will be tried.
GraphDriverPriority []string `json:"driver-priority,omitempty"`
// GraphDriverOptions are driver-specific options.
GraphDriverOptions []string `json:"driver-options,omitempty"`
// UIDMap and GIDMap are used for setting up a container's root filesystem
Expand Down Expand Up @@ -383,6 +390,7 @@ func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) erro
if storeOptions.GraphDriverName == "" {
logrus.Errorf("The storage 'driver' option must be set in %s to guarantee proper operation", configFile)
}
storeOptions.GraphDriverPriority = config.Storage.DriverPriority
if config.Storage.RunRoot != "" {
storeOptions.RunRoot = config.Storage.RunRoot
}
Expand Down

0 comments on commit 6e1ef87

Please sign in to comment.