github.com/lacework-dev/go-moby@v20.10.12+incompatible/volume/service/store.go (about)

     1  package service // import "github.com/docker/docker/volume/service"
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"os"
     8  	"path/filepath"
     9  	"runtime"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/docker/docker/errdefs"
    14  	"github.com/docker/docker/volume"
    15  	"github.com/docker/docker/volume/drivers"
    16  	volumemounts "github.com/docker/docker/volume/mounts"
    17  	"github.com/docker/docker/volume/service/opts"
    18  	"github.com/moby/locker"
    19  	"github.com/pkg/errors"
    20  	"github.com/sirupsen/logrus"
    21  	bolt "go.etcd.io/bbolt"
    22  )
    23  
    24  const (
    25  	volumeDataDir = "volumes"
    26  )
    27  
    28  type volumeWrapper struct {
    29  	volume.Volume
    30  	labels  map[string]string
    31  	scope   string
    32  	options map[string]string
    33  }
    34  
    35  func (v volumeWrapper) Options() map[string]string {
    36  	if v.options == nil {
    37  		return nil
    38  	}
    39  	options := make(map[string]string, len(v.options))
    40  	for key, value := range v.options {
    41  		options[key] = value
    42  	}
    43  	return options
    44  }
    45  
    46  func (v volumeWrapper) Labels() map[string]string {
    47  	if v.labels == nil {
    48  		return nil
    49  	}
    50  
    51  	labels := make(map[string]string, len(v.labels))
    52  	for key, value := range v.labels {
    53  		labels[key] = value
    54  	}
    55  	return labels
    56  }
    57  
    58  func (v volumeWrapper) Scope() string {
    59  	return v.scope
    60  }
    61  
    62  func (v volumeWrapper) CachedPath() string {
    63  	if vv, ok := v.Volume.(interface {
    64  		CachedPath() string
    65  	}); ok {
    66  		return vv.CachedPath()
    67  	}
    68  	return v.Volume.Path()
    69  }
    70  
    71  // NewStore creates a new volume store at the given path
    72  func NewStore(rootPath string, drivers *drivers.Store) (*VolumeStore, error) {
    73  	vs := &VolumeStore{
    74  		locks:   &locker.Locker{},
    75  		names:   make(map[string]volume.Volume),
    76  		refs:    make(map[string]map[string]struct{}),
    77  		labels:  make(map[string]map[string]string),
    78  		options: make(map[string]map[string]string),
    79  		drivers: drivers,
    80  	}
    81  
    82  	if rootPath != "" {
    83  		// initialize metadata store
    84  		volPath := filepath.Join(rootPath, volumeDataDir)
    85  		if err := os.MkdirAll(volPath, 0750); err != nil {
    86  			return nil, err
    87  		}
    88  
    89  		var err error
    90  		vs.db, err = bolt.Open(filepath.Join(volPath, "metadata.db"), 0600, &bolt.Options{Timeout: 1 * time.Second})
    91  		if err != nil {
    92  			return nil, errors.Wrap(err, "error while opening volume store metadata database")
    93  		}
    94  
    95  		// initialize volumes bucket
    96  		if err := vs.db.Update(func(tx *bolt.Tx) error {
    97  			if _, err := tx.CreateBucketIfNotExists(volumeBucketName); err != nil {
    98  				return errors.Wrap(err, "error while setting up volume store metadata database")
    99  			}
   100  			return nil
   101  		}); err != nil {
   102  			return nil, err
   103  		}
   104  	}
   105  
   106  	vs.restore()
   107  
   108  	return vs, nil
   109  }
   110  
   111  func (s *VolumeStore) getNamed(name string) (volume.Volume, bool) {
   112  	s.globalLock.RLock()
   113  	v, exists := s.names[name]
   114  	s.globalLock.RUnlock()
   115  	return v, exists
   116  }
   117  
   118  func (s *VolumeStore) setNamed(v volume.Volume, ref string) {
   119  	name := v.Name()
   120  
   121  	s.globalLock.Lock()
   122  	s.names[name] = v
   123  	if len(ref) > 0 {
   124  		if s.refs[name] == nil {
   125  			s.refs[name] = make(map[string]struct{})
   126  		}
   127  		s.refs[name][ref] = struct{}{}
   128  	}
   129  	s.globalLock.Unlock()
   130  }
   131  
   132  // hasRef returns true if the given name has at least one ref.
   133  // Callers of this function are expected to hold the name lock.
   134  func (s *VolumeStore) hasRef(name string) bool {
   135  	s.globalLock.RLock()
   136  	l := len(s.refs[name])
   137  	s.globalLock.RUnlock()
   138  	return l > 0
   139  }
   140  
   141  // getRefs gets the list of refs for a given name
   142  // Callers of this function are expected to hold the name lock.
   143  func (s *VolumeStore) getRefs(name string) []string {
   144  	s.globalLock.RLock()
   145  	defer s.globalLock.RUnlock()
   146  
   147  	refs := make([]string, 0, len(s.refs[name]))
   148  	for r := range s.refs[name] {
   149  		refs = append(refs, r)
   150  	}
   151  
   152  	return refs
   153  }
   154  
   155  // purge allows the cleanup of internal data on docker in case
   156  // the internal data is out of sync with volumes driver plugins.
   157  func (s *VolumeStore) purge(ctx context.Context, name string) error {
   158  	s.globalLock.Lock()
   159  	defer s.globalLock.Unlock()
   160  
   161  	select {
   162  	case <-ctx.Done():
   163  		return ctx.Err()
   164  	default:
   165  	}
   166  
   167  	v, exists := s.names[name]
   168  	if exists {
   169  		driverName := v.DriverName()
   170  		if _, err := s.drivers.ReleaseDriver(driverName); err != nil {
   171  			logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver")
   172  		}
   173  	}
   174  	if err := s.removeMeta(name); err != nil {
   175  		logrus.Errorf("Error removing volume metadata for volume %q: %v", name, err)
   176  	}
   177  	delete(s.names, name)
   178  	delete(s.refs, name)
   179  	delete(s.labels, name)
   180  	delete(s.options, name)
   181  	return nil
   182  }
   183  
   184  // VolumeStore is responsible for storing and reference counting volumes.
   185  type VolumeStore struct {
   186  	// locks ensures that only one action is being performed on a particular volume at a time without locking the entire store
   187  	// since actions on volumes can be quite slow, this ensures the store is free to handle requests for other volumes.
   188  	locks   *locker.Locker
   189  	drivers *drivers.Store
   190  	// globalLock is used to protect access to mutable structures used by the store object
   191  	globalLock sync.RWMutex
   192  	// names stores the volume name -> volume relationship.
   193  	// This is used for making lookups faster so we don't have to probe all drivers
   194  	names map[string]volume.Volume
   195  	// refs stores the volume name and the list of things referencing it
   196  	refs map[string]map[string]struct{}
   197  	// labels stores volume labels for each volume
   198  	labels map[string]map[string]string
   199  	// options stores volume options for each volume
   200  	options map[string]map[string]string
   201  	db      *bolt.DB
   202  }
   203  
   204  func filterByDriver(names []string) filterFunc {
   205  	return func(v volume.Volume) bool {
   206  		for _, name := range names {
   207  			if name == v.DriverName() {
   208  				return true
   209  			}
   210  		}
   211  		return false
   212  	}
   213  }
   214  
   215  func (s *VolumeStore) byReferenced(referenced bool) filterFunc {
   216  	return func(v volume.Volume) bool {
   217  		return s.hasRef(v.Name()) == referenced
   218  	}
   219  }
   220  
   221  func (s *VolumeStore) filter(ctx context.Context, vols *[]volume.Volume, by By) (warnings []string, err error) {
   222  	// note that this specifically does not support the `FromList` By type.
   223  	switch f := by.(type) {
   224  	case nil:
   225  		if *vols == nil {
   226  			var ls []volume.Volume
   227  			ls, warnings, err = s.list(ctx)
   228  			if err != nil {
   229  				return warnings, err
   230  			}
   231  			*vols = ls
   232  		}
   233  	case byDriver:
   234  		if *vols != nil {
   235  			filter(vols, filterByDriver([]string(f)))
   236  			return nil, nil
   237  		}
   238  		var ls []volume.Volume
   239  		ls, warnings, err = s.list(ctx, []string(f)...)
   240  		if err != nil {
   241  			return nil, err
   242  		}
   243  		*vols = ls
   244  	case ByReferenced:
   245  		// TODO(@cpuguy83): It would be nice to optimize this by looking at the list
   246  		// of referenced volumes, however the locking strategy makes this difficult
   247  		// without either providing inconsistent data or deadlocks.
   248  		if *vols == nil {
   249  			var ls []volume.Volume
   250  			ls, warnings, err = s.list(ctx)
   251  			if err != nil {
   252  				return nil, err
   253  			}
   254  			*vols = ls
   255  		}
   256  		filter(vols, s.byReferenced(bool(f)))
   257  	case andCombinator:
   258  		for _, by := range f {
   259  			w, err := s.filter(ctx, vols, by)
   260  			if err != nil {
   261  				return warnings, err
   262  			}
   263  			warnings = append(warnings, w...)
   264  		}
   265  	case orCombinator:
   266  		for _, by := range f {
   267  			switch by.(type) {
   268  			case byDriver:
   269  				var ls []volume.Volume
   270  				w, err := s.filter(ctx, &ls, by)
   271  				if err != nil {
   272  					return warnings, err
   273  				}
   274  				warnings = append(warnings, w...)
   275  			default:
   276  				ls, w, err := s.list(ctx)
   277  				if err != nil {
   278  					return warnings, err
   279  				}
   280  				warnings = append(warnings, w...)
   281  				w, err = s.filter(ctx, &ls, by)
   282  				if err != nil {
   283  					return warnings, err
   284  				}
   285  				warnings = append(warnings, w...)
   286  				*vols = append(*vols, ls...)
   287  			}
   288  		}
   289  		unique(vols)
   290  	case CustomFilter:
   291  		if *vols == nil {
   292  			var ls []volume.Volume
   293  			ls, warnings, err = s.list(ctx)
   294  			if err != nil {
   295  				return nil, err
   296  			}
   297  			*vols = ls
   298  		}
   299  		filter(vols, filterFunc(f))
   300  	default:
   301  		return nil, errdefs.InvalidParameter(errors.Errorf("unsupported filter: %T", f))
   302  	}
   303  	return warnings, nil
   304  }
   305  
   306  func unique(ls *[]volume.Volume) {
   307  	names := make(map[string]bool, len(*ls))
   308  	filter(ls, func(v volume.Volume) bool {
   309  		if names[v.Name()] {
   310  			return false
   311  		}
   312  		names[v.Name()] = true
   313  		return true
   314  	})
   315  }
   316  
   317  // Find lists volumes filtered by the past in filter.
   318  // If a driver returns a volume that has name which conflicts with another volume from a different driver,
   319  // the first volume is chosen and the conflicting volume is dropped.
   320  func (s *VolumeStore) Find(ctx context.Context, by By) (vols []volume.Volume, warnings []string, err error) {
   321  	logrus.WithField("ByType", fmt.Sprintf("%T", by)).WithField("ByValue", fmt.Sprintf("%+v", by)).Debug("VolumeStore.Find")
   322  	switch f := by.(type) {
   323  	case nil, orCombinator, andCombinator, byDriver, ByReferenced, CustomFilter:
   324  		warnings, err = s.filter(ctx, &vols, by)
   325  	case fromList:
   326  		warnings, err = s.filter(ctx, f.ls, f.by)
   327  	default:
   328  		// Really shouldn't be possible, but makes sure that any new By's are added to this check.
   329  		err = errdefs.InvalidParameter(errors.Errorf("unsupported filter type: %T", f))
   330  	}
   331  	if err != nil {
   332  		return nil, nil, &OpErr{Err: err, Op: "list"}
   333  	}
   334  
   335  	var out []volume.Volume
   336  
   337  	for _, v := range vols {
   338  		name := normalizeVolumeName(v.Name())
   339  
   340  		s.locks.Lock(name)
   341  		storedV, exists := s.getNamed(name)
   342  		// Note: it's not safe to populate the cache here because the volume may have been
   343  		// deleted before we acquire a lock on its name
   344  		if exists && storedV.DriverName() != v.DriverName() {
   345  			logrus.Warnf("Volume name %s already exists for driver %s, not including volume returned by %s", v.Name(), storedV.DriverName(), v.DriverName())
   346  			s.locks.Unlock(v.Name())
   347  			continue
   348  		}
   349  
   350  		out = append(out, v)
   351  		s.locks.Unlock(v.Name())
   352  	}
   353  	return out, warnings, nil
   354  }
   355  
   356  type filterFunc func(volume.Volume) bool
   357  
   358  func filter(vols *[]volume.Volume, fn filterFunc) {
   359  	var evict []int
   360  	for i, v := range *vols {
   361  		if !fn(v) {
   362  			evict = append(evict, i)
   363  		}
   364  	}
   365  
   366  	for n, i := range evict {
   367  		copy((*vols)[i-n:], (*vols)[i-n+1:])
   368  		(*vols)[len(*vols)-1] = nil
   369  		*vols = (*vols)[:len(*vols)-1]
   370  	}
   371  }
   372  
   373  // list goes through each volume driver and asks for its list of volumes.
   374  // TODO(@cpuguy83): plumb context through
   375  func (s *VolumeStore) list(ctx context.Context, driverNames ...string) ([]volume.Volume, []string, error) {
   376  	var (
   377  		ls       = []volume.Volume{} // do not return a nil value as this affects filtering
   378  		warnings []string
   379  	)
   380  
   381  	var dls []volume.Driver
   382  
   383  	all, err := s.drivers.GetAllDrivers()
   384  	if err != nil {
   385  		return nil, nil, err
   386  	}
   387  	if len(driverNames) == 0 {
   388  		dls = all
   389  	} else {
   390  		idx := make(map[string]bool, len(driverNames))
   391  		for _, name := range driverNames {
   392  			idx[name] = true
   393  		}
   394  		for _, d := range all {
   395  			if idx[d.Name()] {
   396  				dls = append(dls, d)
   397  			}
   398  		}
   399  	}
   400  
   401  	type vols struct {
   402  		vols       []volume.Volume
   403  		err        error
   404  		driverName string
   405  	}
   406  	chVols := make(chan vols, len(dls))
   407  
   408  	for _, vd := range dls {
   409  		go func(d volume.Driver) {
   410  			vs, err := d.List()
   411  			if err != nil {
   412  				chVols <- vols{driverName: d.Name(), err: &OpErr{Err: err, Name: d.Name(), Op: "list"}}
   413  				return
   414  			}
   415  			for i, v := range vs {
   416  				s.globalLock.RLock()
   417  				vs[i] = volumeWrapper{v, s.labels[v.Name()], d.Scope(), s.options[v.Name()]}
   418  				s.globalLock.RUnlock()
   419  			}
   420  
   421  			chVols <- vols{vols: vs}
   422  		}(vd)
   423  	}
   424  
   425  	badDrivers := make(map[string]struct{})
   426  	for i := 0; i < len(dls); i++ {
   427  		vs := <-chVols
   428  
   429  		if vs.err != nil {
   430  			warnings = append(warnings, vs.err.Error())
   431  			badDrivers[vs.driverName] = struct{}{}
   432  		}
   433  		ls = append(ls, vs.vols...)
   434  	}
   435  
   436  	if len(badDrivers) > 0 {
   437  		s.globalLock.RLock()
   438  		for _, v := range s.names {
   439  			if _, exists := badDrivers[v.DriverName()]; exists {
   440  				ls = append(ls, v)
   441  			}
   442  		}
   443  		s.globalLock.RUnlock()
   444  	}
   445  	return ls, warnings, nil
   446  }
   447  
   448  // Create creates a volume with the given name and driver
   449  // If the volume needs to be created with a reference to prevent race conditions
   450  // with volume cleanup, make sure to use the `CreateWithReference` option.
   451  func (s *VolumeStore) Create(ctx context.Context, name, driverName string, createOpts ...opts.CreateOption) (volume.Volume, error) {
   452  	var cfg opts.CreateConfig
   453  	for _, o := range createOpts {
   454  		o(&cfg)
   455  	}
   456  
   457  	name = normalizeVolumeName(name)
   458  	s.locks.Lock(name)
   459  	defer s.locks.Unlock(name)
   460  
   461  	select {
   462  	case <-ctx.Done():
   463  		return nil, ctx.Err()
   464  	default:
   465  	}
   466  
   467  	v, err := s.create(ctx, name, driverName, cfg.Options, cfg.Labels)
   468  	if err != nil {
   469  		if _, ok := err.(*OpErr); ok {
   470  			return nil, err
   471  		}
   472  		return nil, &OpErr{Err: err, Name: name, Op: "create"}
   473  	}
   474  
   475  	s.setNamed(v, cfg.Reference)
   476  	return v, nil
   477  }
   478  
   479  // checkConflict checks the local cache for name collisions with the passed in name,
   480  // for existing volumes with the same name but in a different driver.
   481  // This is used by `Create` as a best effort to prevent name collisions for volumes.
   482  // If a matching volume is found that is not a conflict that is returned so the caller
   483  // does not need to perform an additional lookup.
   484  // When no matching volume is found, both returns will be nil
   485  //
   486  // Note: This does not probe all the drivers for name collisions because v1 plugins
   487  // are very slow, particularly if the plugin is down, and cause other issues,
   488  // particularly around locking the store.
   489  // TODO(cpuguy83): With v2 plugins this shouldn't be a problem. Could also potentially
   490  // use a connect timeout for this kind of check to ensure we aren't blocking for a
   491  // long time.
   492  func (s *VolumeStore) checkConflict(ctx context.Context, name, driverName string) (volume.Volume, error) {
   493  	// check the local cache
   494  	v, _ := s.getNamed(name)
   495  	if v == nil {
   496  		return nil, nil
   497  	}
   498  
   499  	vDriverName := v.DriverName()
   500  	var conflict bool
   501  	if driverName != "" {
   502  		// Retrieve canonical driver name to avoid inconsistencies (for example
   503  		// "plugin" vs. "plugin:latest")
   504  		vd, err := s.drivers.GetDriver(driverName)
   505  		if err != nil {
   506  			return nil, err
   507  		}
   508  
   509  		if vDriverName != vd.Name() {
   510  			conflict = true
   511  		}
   512  	}
   513  
   514  	// let's check if the found volume ref
   515  	// is stale by checking with the driver if it still exists
   516  	exists, err := volumeExists(ctx, s.drivers, v)
   517  	if err != nil {
   518  		return nil, errors.Wrapf(errNameConflict, "found reference to volume '%s' in driver '%s', but got an error while checking the driver: %v", name, vDriverName, err)
   519  	}
   520  
   521  	if exists {
   522  		if conflict {
   523  			return nil, errors.Wrapf(errNameConflict, "driver '%s' already has volume '%s'", vDriverName, name)
   524  		}
   525  		return v, nil
   526  	}
   527  
   528  	if s.hasRef(v.Name()) {
   529  		// Containers are referencing this volume but it doesn't seem to exist anywhere.
   530  		// Return a conflict error here, the user can fix this with `docker volume rm -f`
   531  		return nil, errors.Wrapf(errNameConflict, "found references to volume '%s' in driver '%s' but the volume was not found in the driver -- you may need to remove containers referencing this volume or force remove the volume to re-create it", name, vDriverName)
   532  	}
   533  
   534  	// doesn't exist, so purge it from the cache
   535  	s.purge(ctx, name)
   536  	return nil, nil
   537  }
   538  
   539  // volumeExists returns if the volume is still present in the driver.
   540  // An error is returned if there was an issue communicating with the driver.
   541  func volumeExists(ctx context.Context, store *drivers.Store, v volume.Volume) (bool, error) {
   542  	exists, err := lookupVolume(ctx, store, v.DriverName(), v.Name())
   543  	if err != nil {
   544  		return false, err
   545  	}
   546  	return exists != nil, nil
   547  }
   548  
   549  // create asks the given driver to create a volume with the name/opts.
   550  // If a volume with the name is already known, it will ask the stored driver for the volume.
   551  // If the passed in driver name does not match the driver name which is stored
   552  //  for the given volume name, an error is returned after checking if the reference is stale.
   553  // If the reference is stale, it will be purged and this create can continue.
   554  // It is expected that callers of this function hold any necessary locks.
   555  func (s *VolumeStore) create(ctx context.Context, name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
   556  	// Validate the name in a platform-specific manner
   557  
   558  	// volume name validation is specific to the host os and not on container image
   559  	// windows/lcow should have an equivalent volumename validation logic so we create a parser for current host OS
   560  	parser := volumemounts.NewParser(runtime.GOOS)
   561  	err := parser.ValidateVolumeName(name)
   562  	if err != nil {
   563  		return nil, err
   564  	}
   565  
   566  	v, err := s.checkConflict(ctx, name, driverName)
   567  	if err != nil {
   568  		return nil, err
   569  	}
   570  
   571  	if v != nil {
   572  		// there is an existing volume, if we already have this stored locally, return it.
   573  		// TODO: there could be some inconsistent details such as labels here
   574  		if vv, _ := s.getNamed(v.Name()); vv != nil {
   575  			return vv, nil
   576  		}
   577  	}
   578  
   579  	// Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name
   580  	if driverName == "" {
   581  		v, _ = s.getVolume(ctx, name, "")
   582  		if v != nil {
   583  			return v, nil
   584  		}
   585  	}
   586  
   587  	if driverName == "" {
   588  		driverName = volume.DefaultDriverName
   589  	}
   590  	vd, err := s.drivers.CreateDriver(driverName)
   591  	if err != nil {
   592  		return nil, &OpErr{Op: "create", Name: name, Err: err}
   593  	}
   594  
   595  	logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name)
   596  	if v, _ = vd.Get(name); v == nil {
   597  		v, err = vd.Create(name, opts)
   598  		if err != nil {
   599  			if _, err := s.drivers.ReleaseDriver(driverName); err != nil {
   600  				logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver")
   601  			}
   602  			return nil, err
   603  		}
   604  	}
   605  
   606  	s.globalLock.Lock()
   607  	s.labels[name] = labels
   608  	s.options[name] = opts
   609  	s.refs[name] = make(map[string]struct{})
   610  	s.globalLock.Unlock()
   611  
   612  	metadata := volumeMetadata{
   613  		Name:    name,
   614  		Driver:  vd.Name(),
   615  		Labels:  labels,
   616  		Options: opts,
   617  	}
   618  
   619  	if err := s.setMeta(name, metadata); err != nil {
   620  		return nil, err
   621  	}
   622  	return volumeWrapper{v, labels, vd.Scope(), opts}, nil
   623  }
   624  
   625  // Get looks if a volume with the given name exists and returns it if so
   626  func (s *VolumeStore) Get(ctx context.Context, name string, getOptions ...opts.GetOption) (volume.Volume, error) {
   627  	var cfg opts.GetConfig
   628  	for _, o := range getOptions {
   629  		o(&cfg)
   630  	}
   631  	name = normalizeVolumeName(name)
   632  	s.locks.Lock(name)
   633  	defer s.locks.Unlock(name)
   634  
   635  	v, err := s.getVolume(ctx, name, cfg.Driver)
   636  	if err != nil {
   637  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   638  	}
   639  	if cfg.Driver != "" && v.DriverName() != cfg.Driver {
   640  		return nil, &OpErr{Name: name, Op: "get", Err: errdefs.Conflict(errors.New("found volume driver does not match passed in driver"))}
   641  	}
   642  	s.setNamed(v, cfg.Reference)
   643  	return v, nil
   644  }
   645  
   646  // getVolume requests the volume, if the driver info is stored it just accesses that driver,
   647  // if the driver is unknown it probes all drivers until it finds the first volume with that name.
   648  // it is expected that callers of this function hold any necessary locks
   649  func (s *VolumeStore) getVolume(ctx context.Context, name, driverName string) (volume.Volume, error) {
   650  	var meta volumeMetadata
   651  	meta, err := s.getMeta(name)
   652  	if err != nil {
   653  		return nil, err
   654  	}
   655  
   656  	if driverName != "" {
   657  		if meta.Driver == "" {
   658  			meta.Driver = driverName
   659  		}
   660  		if driverName != meta.Driver {
   661  			return nil, errdefs.Conflict(errors.New("provided volume driver does not match stored driver"))
   662  		}
   663  	}
   664  
   665  	if driverName == "" {
   666  		driverName = meta.Driver
   667  	}
   668  	if driverName == "" {
   669  		s.globalLock.RLock()
   670  		select {
   671  		case <-ctx.Done():
   672  			s.globalLock.RUnlock()
   673  			return nil, ctx.Err()
   674  		default:
   675  		}
   676  		v, exists := s.names[name]
   677  		s.globalLock.RUnlock()
   678  		if exists {
   679  			meta.Driver = v.DriverName()
   680  			if err := s.setMeta(name, meta); err != nil {
   681  				return nil, err
   682  			}
   683  		}
   684  	}
   685  
   686  	if meta.Driver != "" {
   687  		vol, err := lookupVolume(ctx, s.drivers, meta.Driver, name)
   688  		if err != nil {
   689  			return nil, err
   690  		}
   691  		if vol == nil {
   692  			s.purge(ctx, name)
   693  			return nil, errNoSuchVolume
   694  		}
   695  
   696  		var scope string
   697  		vd, err := s.drivers.GetDriver(meta.Driver)
   698  		if err == nil {
   699  			scope = vd.Scope()
   700  		}
   701  		return volumeWrapper{vol, meta.Labels, scope, meta.Options}, nil
   702  	}
   703  
   704  	logrus.Debugf("Probing all drivers for volume with name: %s", name)
   705  	drivers, err := s.drivers.GetAllDrivers()
   706  	if err != nil {
   707  		return nil, err
   708  	}
   709  
   710  	for _, d := range drivers {
   711  		select {
   712  		case <-ctx.Done():
   713  			return nil, ctx.Err()
   714  		default:
   715  		}
   716  		v, err := d.Get(name)
   717  		if err != nil || v == nil {
   718  			continue
   719  		}
   720  		meta.Driver = v.DriverName()
   721  		if err := s.setMeta(name, meta); err != nil {
   722  			return nil, err
   723  		}
   724  		return volumeWrapper{v, meta.Labels, d.Scope(), meta.Options}, nil
   725  	}
   726  	return nil, errNoSuchVolume
   727  }
   728  
   729  // lookupVolume gets the specified volume from the specified driver.
   730  // This will only return errors related to communications with the driver.
   731  // If the driver returns an error that is not communication related the
   732  //   error is logged but not returned.
   733  // If the volume is not found it will return `nil, nil``
   734  // TODO(@cpuguy83): plumb through the context to lower level components
   735  func lookupVolume(ctx context.Context, store *drivers.Store, driverName, volumeName string) (volume.Volume, error) {
   736  	if driverName == "" {
   737  		driverName = volume.DefaultDriverName
   738  	}
   739  	vd, err := store.GetDriver(driverName)
   740  	if err != nil {
   741  		return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
   742  	}
   743  	v, err := vd.Get(volumeName)
   744  	if err != nil {
   745  		var nErr net.Error
   746  		if errors.As(err, &nErr) {
   747  			if v != nil {
   748  				volumeName = v.Name()
   749  				driverName = v.DriverName()
   750  			}
   751  			return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
   752  		}
   753  
   754  		// At this point, the error could be anything from the driver, such as "no such volume"
   755  		// Let's not check an error here, and instead check if the driver returned a volume
   756  		logrus.WithError(err).WithField("driver", driverName).WithField("volume", volumeName).Debug("Error while looking up volume")
   757  	}
   758  	return v, nil
   759  }
   760  
   761  // Remove removes the requested volume. A volume is not removed if it has any refs
   762  func (s *VolumeStore) Remove(ctx context.Context, v volume.Volume, rmOpts ...opts.RemoveOption) error {
   763  	var cfg opts.RemoveConfig
   764  	for _, o := range rmOpts {
   765  		o(&cfg)
   766  	}
   767  
   768  	name := v.Name()
   769  	s.locks.Lock(name)
   770  	defer s.locks.Unlock(name)
   771  
   772  	select {
   773  	case <-ctx.Done():
   774  		return ctx.Err()
   775  	default:
   776  	}
   777  
   778  	if s.hasRef(name) {
   779  		return &OpErr{Err: errVolumeInUse, Name: name, Op: "remove", Refs: s.getRefs(name)}
   780  	}
   781  
   782  	v, err := s.getVolume(ctx, name, v.DriverName())
   783  	if err != nil {
   784  		return err
   785  	}
   786  
   787  	vd, err := s.drivers.GetDriver(v.DriverName())
   788  	if err != nil {
   789  		return &OpErr{Err: err, Name: v.DriverName(), Op: "remove"}
   790  	}
   791  
   792  	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
   793  	vol := unwrapVolume(v)
   794  
   795  	err = vd.Remove(vol)
   796  	if err != nil {
   797  		err = &OpErr{Err: err, Name: name, Op: "remove"}
   798  	}
   799  
   800  	if err == nil || cfg.PurgeOnError {
   801  		if e := s.purge(ctx, name); e != nil && err == nil {
   802  			err = e
   803  		}
   804  	}
   805  	return err
   806  }
   807  
   808  // Release releases the specified reference to the volume
   809  func (s *VolumeStore) Release(ctx context.Context, name string, ref string) error {
   810  	s.locks.Lock(name)
   811  	defer s.locks.Unlock(name)
   812  	select {
   813  	case <-ctx.Done():
   814  		return ctx.Err()
   815  	default:
   816  	}
   817  
   818  	s.globalLock.Lock()
   819  	defer s.globalLock.Unlock()
   820  
   821  	select {
   822  	case <-ctx.Done():
   823  		return ctx.Err()
   824  	default:
   825  	}
   826  
   827  	if s.refs[name] != nil {
   828  		delete(s.refs[name], ref)
   829  	}
   830  	return nil
   831  }
   832  
   833  // CountReferences gives a count of all references for a given volume.
   834  func (s *VolumeStore) CountReferences(v volume.Volume) int {
   835  	name := normalizeVolumeName(v.Name())
   836  
   837  	s.locks.Lock(name)
   838  	defer s.locks.Unlock(name)
   839  	s.globalLock.Lock()
   840  	defer s.globalLock.Unlock()
   841  
   842  	return len(s.refs[name])
   843  }
   844  
   845  func unwrapVolume(v volume.Volume) volume.Volume {
   846  	if vol, ok := v.(volumeWrapper); ok {
   847  		return vol.Volume
   848  	}
   849  
   850  	return v
   851  }
   852  
   853  // Shutdown releases all resources used by the volume store
   854  // It does not make any changes to volumes, drivers, etc.
   855  func (s *VolumeStore) Shutdown() error {
   856  	return s.db.Close()
   857  }