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