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 }