github.com/rhatdan/docker@v0.7.7-0.20180119204836-47a0dcbcd20a/volume/store/store.go (about)

     1  package store
     2  
     3  import (
     4  	"net"
     5  	"os"
     6  	"path/filepath"
     7  	"runtime"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/pkg/errors"
    12  
    13  	"github.com/boltdb/bolt"
    14  	"github.com/docker/docker/pkg/locker"
    15  	"github.com/docker/docker/volume"
    16  	"github.com/docker/docker/volume/drivers"
    17  	"github.com/sirupsen/logrus"
    18  )
    19  
    20  const (
    21  	volumeDataDir = "volumes"
    22  )
    23  
    24  type volumeWrapper struct {
    25  	volume.Volume
    26  	labels  map[string]string
    27  	scope   string
    28  	options map[string]string
    29  }
    30  
    31  func (v volumeWrapper) Options() map[string]string {
    32  	options := map[string]string{}
    33  	for key, value := range v.options {
    34  		options[key] = value
    35  	}
    36  	return options
    37  }
    38  
    39  func (v volumeWrapper) Labels() map[string]string {
    40  	return v.labels
    41  }
    42  
    43  func (v volumeWrapper) Scope() string {
    44  	return v.scope
    45  }
    46  
    47  func (v volumeWrapper) CachedPath() string {
    48  	if vv, ok := v.Volume.(interface {
    49  		CachedPath() string
    50  	}); ok {
    51  		return vv.CachedPath()
    52  	}
    53  	return v.Volume.Path()
    54  }
    55  
    56  // New initializes a VolumeStore to keep
    57  // reference counting of volumes in the system.
    58  func New(rootPath string) (*VolumeStore, error) {
    59  	vs := &VolumeStore{
    60  		locks:   &locker.Locker{},
    61  		names:   make(map[string]volume.Volume),
    62  		refs:    make(map[string]map[string]struct{}),
    63  		labels:  make(map[string]map[string]string),
    64  		options: make(map[string]map[string]string),
    65  	}
    66  
    67  	if rootPath != "" {
    68  		// initialize metadata store
    69  		volPath := filepath.Join(rootPath, volumeDataDir)
    70  		if err := os.MkdirAll(volPath, 750); err != nil {
    71  			return nil, err
    72  		}
    73  
    74  		dbPath := filepath.Join(volPath, "metadata.db")
    75  
    76  		var err error
    77  		vs.db, err = bolt.Open(dbPath, 0600, &bolt.Options{Timeout: 1 * time.Second})
    78  		if err != nil {
    79  			return nil, errors.Wrap(err, "error while opening volume store metadata database")
    80  		}
    81  
    82  		// initialize volumes bucket
    83  		if err := vs.db.Update(func(tx *bolt.Tx) error {
    84  			if _, err := tx.CreateBucketIfNotExists(volumeBucketName); err != nil {
    85  				return errors.Wrap(err, "error while setting up volume store metadata database")
    86  			}
    87  			return nil
    88  		}); err != nil {
    89  			return nil, err
    90  		}
    91  	}
    92  
    93  	vs.restore()
    94  
    95  	return vs, nil
    96  }
    97  
    98  func (s *VolumeStore) getNamed(name string) (volume.Volume, bool) {
    99  	s.globalLock.RLock()
   100  	v, exists := s.names[name]
   101  	s.globalLock.RUnlock()
   102  	return v, exists
   103  }
   104  
   105  func (s *VolumeStore) setNamed(v volume.Volume, ref string) {
   106  	name := v.Name()
   107  
   108  	s.globalLock.Lock()
   109  	s.names[name] = v
   110  	if len(ref) > 0 {
   111  		if s.refs[name] == nil {
   112  			s.refs[name] = make(map[string]struct{})
   113  		}
   114  		s.refs[name][ref] = struct{}{}
   115  	}
   116  	s.globalLock.Unlock()
   117  }
   118  
   119  // hasRef returns true if the given name has at least one ref.
   120  // Callers of this function are expected to hold the name lock.
   121  func (s *VolumeStore) hasRef(name string) bool {
   122  	s.globalLock.RLock()
   123  	l := len(s.refs[name])
   124  	s.globalLock.RUnlock()
   125  	return l > 0
   126  }
   127  
   128  // getRefs gets the list of refs for a given name
   129  // Callers of this function are expected to hold the name lock.
   130  func (s *VolumeStore) getRefs(name string) []string {
   131  	s.globalLock.RLock()
   132  	defer s.globalLock.RUnlock()
   133  
   134  	refs := make([]string, 0, len(s.refs[name]))
   135  	for r := range s.refs[name] {
   136  		refs = append(refs, r)
   137  	}
   138  
   139  	return refs
   140  }
   141  
   142  // Purge allows the cleanup of internal data on docker in case
   143  // the internal data is out of sync with volumes driver plugins.
   144  func (s *VolumeStore) Purge(name string) {
   145  	s.globalLock.Lock()
   146  	v, exists := s.names[name]
   147  	if exists {
   148  		driverName := v.DriverName()
   149  		if _, err := volumedrivers.ReleaseDriver(driverName); err != nil {
   150  			logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver")
   151  		}
   152  	}
   153  	if err := s.removeMeta(name); err != nil {
   154  		logrus.Errorf("Error removing volume metadata for volume %q: %v", name, err)
   155  	}
   156  	delete(s.names, name)
   157  	delete(s.refs, name)
   158  	delete(s.labels, name)
   159  	delete(s.options, name)
   160  	s.globalLock.Unlock()
   161  }
   162  
   163  // VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts
   164  type VolumeStore struct {
   165  	// locks ensures that only one action is being performed on a particular volume at a time without locking the entire store
   166  	// since actions on volumes can be quite slow, this ensures the store is free to handle requests for other volumes.
   167  	locks *locker.Locker
   168  	// globalLock is used to protect access to mutable structures used by the store object
   169  	globalLock sync.RWMutex
   170  	// names stores the volume name -> volume relationship.
   171  	// This is used for making lookups faster so we don't have to probe all drivers
   172  	names map[string]volume.Volume
   173  	// refs stores the volume name and the list of things referencing it
   174  	refs map[string]map[string]struct{}
   175  	// labels stores volume labels for each volume
   176  	labels map[string]map[string]string
   177  	// options stores volume options for each volume
   178  	options map[string]map[string]string
   179  	db      *bolt.DB
   180  }
   181  
   182  // List proxies to all registered volume drivers to get the full list of volumes
   183  // If a driver returns a volume that has name which conflicts with another volume from a different driver,
   184  // the first volume is chosen and the conflicting volume is dropped.
   185  func (s *VolumeStore) List() ([]volume.Volume, []string, error) {
   186  	vols, warnings, err := s.list()
   187  	if err != nil {
   188  		return nil, nil, &OpErr{Err: err, Op: "list"}
   189  	}
   190  	var out []volume.Volume
   191  
   192  	for _, v := range vols {
   193  		name := normalizeVolumeName(v.Name())
   194  
   195  		s.locks.Lock(name)
   196  		storedV, exists := s.getNamed(name)
   197  		// Note: it's not safe to populate the cache here because the volume may have been
   198  		// deleted before we acquire a lock on its name
   199  		if exists && storedV.DriverName() != v.DriverName() {
   200  			logrus.Warnf("Volume name %s already exists for driver %s, not including volume returned by %s", v.Name(), storedV.DriverName(), v.DriverName())
   201  			s.locks.Unlock(v.Name())
   202  			continue
   203  		}
   204  
   205  		out = append(out, v)
   206  		s.locks.Unlock(v.Name())
   207  	}
   208  	return out, warnings, nil
   209  }
   210  
   211  // list goes through each volume driver and asks for its list of volumes.
   212  func (s *VolumeStore) list() ([]volume.Volume, []string, error) {
   213  	var (
   214  		ls       []volume.Volume
   215  		warnings []string
   216  	)
   217  
   218  	drivers, err := volumedrivers.GetAllDrivers()
   219  	if err != nil {
   220  		return nil, nil, err
   221  	}
   222  
   223  	type vols struct {
   224  		vols       []volume.Volume
   225  		err        error
   226  		driverName string
   227  	}
   228  	chVols := make(chan vols, len(drivers))
   229  
   230  	for _, vd := range drivers {
   231  		go func(d volume.Driver) {
   232  			vs, err := d.List()
   233  			if err != nil {
   234  				chVols <- vols{driverName: d.Name(), err: &OpErr{Err: err, Name: d.Name(), Op: "list"}}
   235  				return
   236  			}
   237  			for i, v := range vs {
   238  				s.globalLock.RLock()
   239  				vs[i] = volumeWrapper{v, s.labels[v.Name()], d.Scope(), s.options[v.Name()]}
   240  				s.globalLock.RUnlock()
   241  			}
   242  
   243  			chVols <- vols{vols: vs}
   244  		}(vd)
   245  	}
   246  
   247  	badDrivers := make(map[string]struct{})
   248  	for i := 0; i < len(drivers); i++ {
   249  		vs := <-chVols
   250  
   251  		if vs.err != nil {
   252  			warnings = append(warnings, vs.err.Error())
   253  			badDrivers[vs.driverName] = struct{}{}
   254  			logrus.Warn(vs.err)
   255  		}
   256  		ls = append(ls, vs.vols...)
   257  	}
   258  
   259  	if len(badDrivers) > 0 {
   260  		s.globalLock.RLock()
   261  		for _, v := range s.names {
   262  			if _, exists := badDrivers[v.DriverName()]; exists {
   263  				ls = append(ls, v)
   264  			}
   265  		}
   266  		s.globalLock.RUnlock()
   267  	}
   268  	return ls, warnings, nil
   269  }
   270  
   271  // CreateWithRef creates a volume with the given name and driver and stores the ref
   272  // This ensures there's no race between creating a volume and then storing a reference.
   273  func (s *VolumeStore) CreateWithRef(name, driverName, ref string, opts, labels map[string]string) (volume.Volume, error) {
   274  	name = normalizeVolumeName(name)
   275  	s.locks.Lock(name)
   276  	defer s.locks.Unlock(name)
   277  
   278  	v, err := s.create(name, driverName, opts, labels)
   279  	if err != nil {
   280  		if _, ok := err.(*OpErr); ok {
   281  			return nil, err
   282  		}
   283  		return nil, &OpErr{Err: err, Name: name, Op: "create"}
   284  	}
   285  
   286  	s.setNamed(v, ref)
   287  	return v, nil
   288  }
   289  
   290  // Create creates a volume with the given name and driver.
   291  // This is just like CreateWithRef() except we don't store a reference while holding the lock.
   292  func (s *VolumeStore) Create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
   293  	return s.CreateWithRef(name, driverName, "", opts, labels)
   294  }
   295  
   296  // checkConflict checks the local cache for name collisions with the passed in name,
   297  // for existing volumes with the same name but in a different driver.
   298  // This is used by `Create` as a best effort to prevent name collisions for volumes.
   299  // If a matching volume is found that is not a conflict that is returned so the caller
   300  // does not need to perform an additional lookup.
   301  // When no matching volume is found, both returns will be nil
   302  //
   303  // Note: This does not probe all the drivers for name collisions because v1 plugins
   304  // are very slow, particularly if the plugin is down, and cause other issues,
   305  // particularly around locking the store.
   306  // TODO(cpuguy83): With v2 plugins this shouldn't be a problem. Could also potentially
   307  // use a connect timeout for this kind of check to ensure we aren't blocking for a
   308  // long time.
   309  func (s *VolumeStore) checkConflict(name, driverName string) (volume.Volume, error) {
   310  	// check the local cache
   311  	v, _ := s.getNamed(name)
   312  	if v == nil {
   313  		return nil, nil
   314  	}
   315  
   316  	vDriverName := v.DriverName()
   317  	var conflict bool
   318  	if driverName != "" {
   319  		// Retrieve canonical driver name to avoid inconsistencies (for example
   320  		// "plugin" vs. "plugin:latest")
   321  		vd, err := volumedrivers.GetDriver(driverName)
   322  		if err != nil {
   323  			return nil, err
   324  		}
   325  
   326  		if vDriverName != vd.Name() {
   327  			conflict = true
   328  		}
   329  	}
   330  
   331  	// let's check if the found volume ref
   332  	// is stale by checking with the driver if it still exists
   333  	exists, err := volumeExists(v)
   334  	if err != nil {
   335  		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)
   336  	}
   337  
   338  	if exists {
   339  		if conflict {
   340  			return nil, errors.Wrapf(errNameConflict, "driver '%s' already has volume '%s'", vDriverName, name)
   341  		}
   342  		return v, nil
   343  	}
   344  
   345  	if s.hasRef(v.Name()) {
   346  		// Containers are referencing this volume but it doesn't seem to exist anywhere.
   347  		// Return a conflict error here, the user can fix this with `docker volume rm -f`
   348  		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)
   349  	}
   350  
   351  	// doesn't exist, so purge it from the cache
   352  	s.Purge(name)
   353  	return nil, nil
   354  }
   355  
   356  // volumeExists returns if the volume is still present in the driver.
   357  // An error is returned if there was an issue communicating with the driver.
   358  func volumeExists(v volume.Volume) (bool, error) {
   359  	exists, err := lookupVolume(v.DriverName(), v.Name())
   360  	if err != nil {
   361  		return false, err
   362  	}
   363  	return exists != nil, nil
   364  }
   365  
   366  // create asks the given driver to create a volume with the name/opts.
   367  // If a volume with the name is already known, it will ask the stored driver for the volume.
   368  // If the passed in driver name does not match the driver name which is stored
   369  //  for the given volume name, an error is returned after checking if the reference is stale.
   370  // If the reference is stale, it will be purged and this create can continue.
   371  // It is expected that callers of this function hold any necessary locks.
   372  func (s *VolumeStore) create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
   373  	// Validate the name in a platform-specific manner
   374  
   375  	// volume name validation is specific to the host os and not on container image
   376  	// windows/lcow should have an equivalent volumename validation logic so we create a parser for current host OS
   377  	parser := volume.NewParser(runtime.GOOS)
   378  	err := parser.ValidateVolumeName(name)
   379  	if err != nil {
   380  		return nil, err
   381  	}
   382  
   383  	v, err := s.checkConflict(name, driverName)
   384  	if err != nil {
   385  		return nil, err
   386  	}
   387  
   388  	if v != nil {
   389  		// there is an existing volume, if we already have this stored locally, return it.
   390  		// TODO: there could be some inconsistent details such as labels here
   391  		if vv, _ := s.getNamed(v.Name()); vv != nil {
   392  			return vv, nil
   393  		}
   394  	}
   395  
   396  	// Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name
   397  	if driverName == "" {
   398  		v, _ = s.getVolume(name)
   399  		if v != nil {
   400  			return v, nil
   401  		}
   402  	}
   403  
   404  	vd, err := volumedrivers.CreateDriver(driverName)
   405  	if err != nil {
   406  		return nil, &OpErr{Op: "create", Name: name, Err: err}
   407  	}
   408  
   409  	logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name)
   410  	if v, _ = vd.Get(name); v == nil {
   411  		v, err = vd.Create(name, opts)
   412  		if err != nil {
   413  			if _, err := volumedrivers.ReleaseDriver(driverName); err != nil {
   414  				logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver")
   415  			}
   416  			return nil, err
   417  		}
   418  	}
   419  
   420  	s.globalLock.Lock()
   421  	s.labels[name] = labels
   422  	s.options[name] = opts
   423  	s.refs[name] = make(map[string]struct{})
   424  	s.globalLock.Unlock()
   425  
   426  	metadata := volumeMetadata{
   427  		Name:    name,
   428  		Driver:  vd.Name(),
   429  		Labels:  labels,
   430  		Options: opts,
   431  	}
   432  
   433  	if err := s.setMeta(name, metadata); err != nil {
   434  		return nil, err
   435  	}
   436  	return volumeWrapper{v, labels, vd.Scope(), opts}, nil
   437  }
   438  
   439  // GetWithRef gets a volume with the given name from the passed in driver and stores the ref
   440  // This is just like Get(), but we store the reference while holding the lock.
   441  // This makes sure there are no races between checking for the existence of a volume and adding a reference for it
   442  func (s *VolumeStore) GetWithRef(name, driverName, ref string) (volume.Volume, error) {
   443  	name = normalizeVolumeName(name)
   444  	s.locks.Lock(name)
   445  	defer s.locks.Unlock(name)
   446  
   447  	vd, err := volumedrivers.GetDriver(driverName)
   448  	if err != nil {
   449  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   450  	}
   451  
   452  	v, err := vd.Get(name)
   453  	if err != nil {
   454  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   455  	}
   456  
   457  	s.setNamed(v, ref)
   458  
   459  	s.globalLock.RLock()
   460  	defer s.globalLock.RUnlock()
   461  	return volumeWrapper{v, s.labels[name], vd.Scope(), s.options[name]}, nil
   462  }
   463  
   464  // Get looks if a volume with the given name exists and returns it if so
   465  func (s *VolumeStore) Get(name string) (volume.Volume, error) {
   466  	name = normalizeVolumeName(name)
   467  	s.locks.Lock(name)
   468  	defer s.locks.Unlock(name)
   469  
   470  	v, err := s.getVolume(name)
   471  	if err != nil {
   472  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   473  	}
   474  	s.setNamed(v, "")
   475  	return v, nil
   476  }
   477  
   478  // getVolume requests the volume, if the driver info is stored it just accesses that driver,
   479  // if the driver is unknown it probes all drivers until it finds the first volume with that name.
   480  // it is expected that callers of this function hold any necessary locks
   481  func (s *VolumeStore) getVolume(name string) (volume.Volume, error) {
   482  	var meta volumeMetadata
   483  	meta, err := s.getMeta(name)
   484  	if err != nil {
   485  		return nil, err
   486  	}
   487  
   488  	driverName := meta.Driver
   489  	if driverName == "" {
   490  		s.globalLock.RLock()
   491  		v, exists := s.names[name]
   492  		s.globalLock.RUnlock()
   493  		if exists {
   494  			meta.Driver = v.DriverName()
   495  			if err := s.setMeta(name, meta); err != nil {
   496  				return nil, err
   497  			}
   498  		}
   499  	}
   500  
   501  	if meta.Driver != "" {
   502  		vol, err := lookupVolume(meta.Driver, name)
   503  		if err != nil {
   504  			return nil, err
   505  		}
   506  		if vol == nil {
   507  			s.Purge(name)
   508  			return nil, errNoSuchVolume
   509  		}
   510  
   511  		var scope string
   512  		vd, err := volumedrivers.GetDriver(meta.Driver)
   513  		if err == nil {
   514  			scope = vd.Scope()
   515  		}
   516  		return volumeWrapper{vol, meta.Labels, scope, meta.Options}, nil
   517  	}
   518  
   519  	logrus.Debugf("Probing all drivers for volume with name: %s", name)
   520  	drivers, err := volumedrivers.GetAllDrivers()
   521  	if err != nil {
   522  		return nil, err
   523  	}
   524  
   525  	for _, d := range drivers {
   526  		v, err := d.Get(name)
   527  		if err != nil || v == nil {
   528  			continue
   529  		}
   530  		meta.Driver = v.DriverName()
   531  		if err := s.setMeta(name, meta); err != nil {
   532  			return nil, err
   533  		}
   534  		return volumeWrapper{v, meta.Labels, d.Scope(), meta.Options}, nil
   535  	}
   536  	return nil, errNoSuchVolume
   537  }
   538  
   539  // lookupVolume gets the specified volume from the specified driver.
   540  // This will only return errors related to communications with the driver.
   541  // If the driver returns an error that is not communication related the
   542  //   error is logged but not returned.
   543  // If the volume is not found it will return `nil, nil``
   544  func lookupVolume(driverName, volumeName string) (volume.Volume, error) {
   545  	vd, err := volumedrivers.GetDriver(driverName)
   546  	if err != nil {
   547  		return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
   548  	}
   549  	v, err := vd.Get(volumeName)
   550  	if err != nil {
   551  		err = errors.Cause(err)
   552  		if _, ok := err.(net.Error); ok {
   553  			if v != nil {
   554  				volumeName = v.Name()
   555  				driverName = v.DriverName()
   556  			}
   557  			return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
   558  		}
   559  
   560  		// At this point, the error could be anything from the driver, such as "no such volume"
   561  		// Let's not check an error here, and instead check if the driver returned a volume
   562  		logrus.WithError(err).WithField("driver", driverName).WithField("volume", volumeName).Warnf("Error while looking up volume")
   563  	}
   564  	return v, nil
   565  }
   566  
   567  // Remove removes the requested volume. A volume is not removed if it has any refs
   568  func (s *VolumeStore) Remove(v volume.Volume) error {
   569  	name := normalizeVolumeName(v.Name())
   570  	s.locks.Lock(name)
   571  	defer s.locks.Unlock(name)
   572  
   573  	if s.hasRef(name) {
   574  		return &OpErr{Err: errVolumeInUse, Name: v.Name(), Op: "remove", Refs: s.getRefs(name)}
   575  	}
   576  
   577  	vd, err := volumedrivers.GetDriver(v.DriverName())
   578  	if err != nil {
   579  		return &OpErr{Err: err, Name: v.DriverName(), Op: "remove"}
   580  	}
   581  
   582  	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
   583  	vol := unwrapVolume(v)
   584  	if err := vd.Remove(vol); err != nil {
   585  		return &OpErr{Err: err, Name: name, Op: "remove"}
   586  	}
   587  
   588  	s.Purge(name)
   589  	return nil
   590  }
   591  
   592  // Dereference removes the specified reference to the volume
   593  func (s *VolumeStore) Dereference(v volume.Volume, ref string) {
   594  	name := v.Name()
   595  
   596  	s.locks.Lock(name)
   597  	defer s.locks.Unlock(name)
   598  
   599  	s.globalLock.Lock()
   600  	defer s.globalLock.Unlock()
   601  
   602  	if s.refs[name] != nil {
   603  		delete(s.refs[name], ref)
   604  	}
   605  }
   606  
   607  // Refs gets the current list of refs for the given volume
   608  func (s *VolumeStore) Refs(v volume.Volume) []string {
   609  	name := v.Name()
   610  
   611  	s.locks.Lock(name)
   612  	defer s.locks.Unlock(name)
   613  
   614  	return s.getRefs(name)
   615  }
   616  
   617  // FilterByDriver returns the available volumes filtered by driver name
   618  func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) {
   619  	vd, err := volumedrivers.GetDriver(name)
   620  	if err != nil {
   621  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   622  	}
   623  	ls, err := vd.List()
   624  	if err != nil {
   625  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   626  	}
   627  	for i, v := range ls {
   628  		options := map[string]string{}
   629  		s.globalLock.RLock()
   630  		for key, value := range s.options[v.Name()] {
   631  			options[key] = value
   632  		}
   633  		ls[i] = volumeWrapper{v, s.labels[v.Name()], vd.Scope(), options}
   634  		s.globalLock.RUnlock()
   635  	}
   636  	return ls, nil
   637  }
   638  
   639  // FilterByUsed returns the available volumes filtered by if they are in use or not.
   640  // `used=true` returns only volumes that are being used, while `used=false` returns
   641  // only volumes that are not being used.
   642  func (s *VolumeStore) FilterByUsed(vols []volume.Volume, used bool) []volume.Volume {
   643  	return s.filter(vols, func(v volume.Volume) bool {
   644  		s.locks.Lock(v.Name())
   645  		hasRef := s.hasRef(v.Name())
   646  		s.locks.Unlock(v.Name())
   647  		return used == hasRef
   648  	})
   649  }
   650  
   651  // filterFunc defines a function to allow filter volumes in the store
   652  type filterFunc func(vol volume.Volume) bool
   653  
   654  // filter returns the available volumes filtered by a filterFunc function
   655  func (s *VolumeStore) filter(vols []volume.Volume, f filterFunc) []volume.Volume {
   656  	var ls []volume.Volume
   657  	for _, v := range vols {
   658  		if f(v) {
   659  			ls = append(ls, v)
   660  		}
   661  	}
   662  	return ls
   663  }
   664  
   665  func unwrapVolume(v volume.Volume) volume.Volume {
   666  	if vol, ok := v.(volumeWrapper); ok {
   667  		return vol.Volume
   668  	}
   669  
   670  	return v
   671  }
   672  
   673  // Shutdown releases all resources used by the volume store
   674  // It does not make any changes to volumes, drivers, etc.
   675  func (s *VolumeStore) Shutdown() error {
   676  	return s.db.Close()
   677  }