|
@@ -4,6 +4,7 @@
|
|
package local // import "github.com/docker/docker/volume/local"
|
|
package local // import "github.com/docker/docker/volume/local"
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
+ "context"
|
|
"encoding/json"
|
|
"encoding/json"
|
|
"fmt"
|
|
"fmt"
|
|
"os"
|
|
"os"
|
|
@@ -36,6 +37,8 @@ var (
|
|
// This name is used to create the bind directory, so we need to avoid characters that
|
|
// This name is used to create the bind directory, so we need to avoid characters that
|
|
// would make the path to escape the root directory.
|
|
// would make the path to escape the root directory.
|
|
volumeNameRegex = names.RestrictedNamePattern
|
|
volumeNameRegex = names.RestrictedNamePattern
|
|
|
|
+
|
|
|
|
+ _ volume.LiveRestorer = (*localVolume)(nil)
|
|
)
|
|
)
|
|
|
|
|
|
type activeMount struct {
|
|
type activeMount struct {
|
|
@@ -315,14 +318,17 @@ func (v *localVolume) CachedPath() string {
|
|
func (v *localVolume) Mount(id string) (string, error) {
|
|
func (v *localVolume) Mount(id string) (string, error) {
|
|
v.m.Lock()
|
|
v.m.Lock()
|
|
defer v.m.Unlock()
|
|
defer v.m.Unlock()
|
|
|
|
+ logger := logrus.WithField("volume", v.name)
|
|
if v.needsMount() {
|
|
if v.needsMount() {
|
|
if !v.active.mounted {
|
|
if !v.active.mounted {
|
|
|
|
+ logger.Debug("Mounting volume")
|
|
if err := v.mount(); err != nil {
|
|
if err := v.mount(); err != nil {
|
|
return "", errdefs.System(err)
|
|
return "", errdefs.System(err)
|
|
}
|
|
}
|
|
v.active.mounted = true
|
|
v.active.mounted = true
|
|
}
|
|
}
|
|
v.active.count++
|
|
v.active.count++
|
|
|
|
+ logger.WithField("active mounts", v.active).Debug("Decremented active mount count")
|
|
}
|
|
}
|
|
if err := v.postMount(); err != nil {
|
|
if err := v.postMount(); err != nil {
|
|
return "", err
|
|
return "", err
|
|
@@ -335,6 +341,7 @@ func (v *localVolume) Mount(id string) (string, error) {
|
|
func (v *localVolume) Unmount(id string) error {
|
|
func (v *localVolume) Unmount(id string) error {
|
|
v.m.Lock()
|
|
v.m.Lock()
|
|
defer v.m.Unlock()
|
|
defer v.m.Unlock()
|
|
|
|
+ logger := logrus.WithField("volume", v.name)
|
|
|
|
|
|
// Always decrement the count, even if the unmount fails
|
|
// Always decrement the count, even if the unmount fails
|
|
// Essentially docker doesn't care if this fails, it will send an error, but
|
|
// Essentially docker doesn't care if this fails, it will send an error, but
|
|
@@ -342,12 +349,14 @@ func (v *localVolume) Unmount(id string) error {
|
|
// this volume can never be removed until a daemon restart occurs.
|
|
// this volume can never be removed until a daemon restart occurs.
|
|
if v.needsMount() {
|
|
if v.needsMount() {
|
|
v.active.count--
|
|
v.active.count--
|
|
|
|
+ logger.WithField("active mounts", v.active).Debug("Decremented active mount count")
|
|
}
|
|
}
|
|
|
|
|
|
if v.active.count > 0 {
|
|
if v.active.count > 0 {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ logger.Debug("Unmounting volume")
|
|
return v.unmount()
|
|
return v.unmount()
|
|
}
|
|
}
|
|
|
|
|
|
@@ -355,6 +364,24 @@ func (v *localVolume) Status() map[string]interface{} {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// LiveRestoreVolume restores reference counts for mounts
|
|
|
|
+// It is assumed that the volume is already mounted since this is only called for active, live-restored containers.
|
|
|
|
+func (v *localVolume) LiveRestoreVolume(ctx context.Context, _ string) error {
|
|
|
|
+ v.m.Lock()
|
|
|
|
+ defer v.m.Unlock()
|
|
|
|
+
|
|
|
|
+ if !v.needsMount() {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ v.active.count++
|
|
|
|
+ v.active.mounted = true
|
|
|
|
+ logrus.WithFields(logrus.Fields{
|
|
|
|
+ "volume": v.name,
|
|
|
|
+ "active mounts": v.active,
|
|
|
|
+ }).Debugf("Live restored volume")
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
// getAddress finds out address/hostname from options
|
|
// getAddress finds out address/hostname from options
|
|
func getAddress(opts string) string {
|
|
func getAddress(opts string) string {
|
|
optsList := strings.Split(opts, ",")
|
|
optsList := strings.Split(opts, ",")
|