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