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