github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/volume/service/store.go (about)

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