Merge pull request #33236 from cpuguy83/17.03.2_cherry_picks
17.03.2 cherry picks
diff --git a/cli/command/system/info.go b/cli/command/system/info.go
index 94a7aad..ea4af76 100644
--- a/cli/command/system/info.go
+++ b/cli/command/system/info.go
@@ -6,8 +6,6 @@
"strings"
"time"
- "golang.org/x/net/context"
-
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/cli"
@@ -17,6 +15,7 @@
"github.com/docker/docker/utils/templates"
"github.com/docker/go-units"
"github.com/spf13/cobra"
+ "golang.org/x/net/context"
)
type infoOptions struct {
@@ -66,11 +65,6 @@
if info.DriverStatus != nil {
for _, pair := range info.DriverStatus {
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
-
- // print a warning if devicemapper is using a loopback file
- if pair[0] == "Data loop file" {
- fmt.Fprintln(dockerCli.Err(), " WARNING: Usage of loopback devices is strongly discouraged for production use. Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.")
- }
}
}
@@ -228,43 +222,6 @@
fmt.Fprintf(dockerCli.Out(), "Registry: %v\n", info.IndexServerAddress)
}
- // Only output these warnings if the server does not support these features
- if info.OSType != "windows" {
- if !info.MemoryLimit {
- fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support")
- }
- if !info.SwapLimit {
- fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
- }
- if !info.KernelMemory {
- fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support")
- }
- if !info.OomKillDisable {
- fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
- }
- if !info.CPUCfsQuota {
- fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support")
- }
- if !info.CPUCfsPeriod {
- fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support")
- }
- if !info.CPUShares {
- fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support")
- }
- if !info.CPUSet {
- fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support")
- }
- if !info.IPv4Forwarding {
- fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled")
- }
- if !info.BridgeNfIptables {
- fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled")
- }
- if !info.BridgeNfIP6tables {
- fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled")
- }
- }
-
if info.Labels != nil {
fmt.Fprintln(dockerCli.Out(), "Labels:")
for _, attribute := range info.Labels {
@@ -317,11 +274,85 @@
}
}
- fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n", info.LiveRestoreEnabled)
+ fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n\n", info.LiveRestoreEnabled)
+
+ // Only output these warnings if the server does not support these features
+ if info.OSType != "windows" {
+ printStorageDriverWarnings(dockerCli, info)
+
+ if !info.MemoryLimit {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support")
+ }
+ if !info.SwapLimit {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
+ }
+ if !info.KernelMemory {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support")
+ }
+ if !info.OomKillDisable {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
+ }
+ if !info.CPUCfsQuota {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support")
+ }
+ if !info.CPUCfsPeriod {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support")
+ }
+ if !info.CPUShares {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support")
+ }
+ if !info.CPUSet {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support")
+ }
+ if !info.IPv4Forwarding {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled")
+ }
+ if !info.BridgeNfIptables {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled")
+ }
+ if !info.BridgeNfIP6tables {
+ fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled")
+ }
+ }
return nil
}
+func printStorageDriverWarnings(dockerCli *command.DockerCli, info types.Info) {
+ if info.DriverStatus == nil {
+ return
+ }
+
+ for _, pair := range info.DriverStatus {
+ if pair[0] == "Data loop file" {
+ fmt.Fprintf(dockerCli.Err(), "WARNING: %s: usage of loopback devices is strongly discouraged for production use.\n Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.\n", info.Driver)
+ }
+ if pair[0] == "Supports d_type" && pair[1] == "false" {
+ backingFs := getBackingFs(info)
+
+ msg := fmt.Sprintf("WARNING: %s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.\n", info.Driver, backingFs)
+ if backingFs == "xfs" {
+ msg += " Reformat the filesystem with ftype=1 to enable d_type support.\n"
+ }
+ msg += " Running without d_type support will not be supported in future releases."
+ fmt.Fprintln(dockerCli.Err(), msg)
+ }
+ }
+}
+
+func getBackingFs(info types.Info) string {
+ if info.DriverStatus == nil {
+ return ""
+ }
+
+ for _, pair := range info.DriverStatus {
+ if pair[0] == "Backing Filesystem" {
+ return pair[1]
+ }
+ }
+ return ""
+}
+
func formatInfo(dockerCli *command.DockerCli, info types.Info, format string) error {
tmpl, err := templates.Parse(format)
if err != nil {
diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go
index 2296045..68cb072 100644
--- a/daemon/container_operations_unix.go
+++ b/daemon/container_operations_unix.go
@@ -213,6 +213,8 @@
}
}
+ label.Relabel(localMountPath, c.MountLabel, false)
+
// remount secrets ro
if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "remount,ro,"+tmpfsOwnership); err != nil {
return errors.Wrap(err, "unable to remount secret dir as readonly")
diff --git a/daemon/volumes.go b/daemon/volumes.go
index f5ae284..cb7591e 100644
--- a/daemon/volumes.go
+++ b/daemon/volumes.go
@@ -16,7 +16,6 @@
"github.com/docker/docker/container"
"github.com/docker/docker/volume"
"github.com/docker/docker/volume/drivers"
- "github.com/opencontainers/runc/libcontainer/label"
)
var (
@@ -195,9 +194,6 @@
return err
}
- if err := label.Relabel(mp.Source, container.MountLabel, false); err != nil {
- return err
- }
mp.Volume = v
mp.Name = v.Name()
mp.Driver = v.DriverName()
diff --git a/plugin/backend_linux.go b/plugin/backend_linux.go
index 33200d8..a5a3f9b 100644
--- a/plugin/backend_linux.go
+++ b/plugin/backend_linux.go
@@ -575,7 +575,7 @@
func getMounts(root string) ([]string, error) {
infos, err := mount.GetMounts()
if err != nil {
- return nil, errors.Wrap(err, "failed to read mount table while performing recursive unmount")
+ return nil, errors.Wrap(err, "failed to read mount table")
}
var mounts []string
diff --git a/plugin/manager_linux.go b/plugin/manager_linux.go
index ad66616..7e734b7 100644
--- a/plugin/manager_linux.go
+++ b/plugin/manager_linux.go
@@ -171,9 +171,17 @@
pdir := filepath.Join(pm.config.Root, p.PluginObj.ID)
orig := filepath.Join(pdir, "rootfs")
+
+ // Make sure nothing is mounted
+ // This could happen if the plugin was disabled with `-f` with active mounts.
+ // If there is anything in `orig` is still mounted, this should error out.
+ if err := recursiveUnmount(orig); err != nil {
+ return err
+ }
+
backup := orig + "-old"
if err := os.Rename(orig, backup); err != nil {
- return err
+ return errors.Wrap(err, "error backing up plugin data before upgrade")
}
defer func() {
diff --git a/volume/store/store.go b/volume/store/store.go
index 38afd86..02c858a 100644
--- a/volume/store/store.go
+++ b/volume/store/store.go
@@ -519,7 +519,11 @@
if err != nil {
err = errors.Cause(err)
if _, ok := err.(net.Error); ok {
- return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", v.Name(), v.DriverName())
+ if v != nil {
+ volumeName = v.Name()
+ driverName = v.DriverName()
+ }
+ return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
}
// At this point, the error could be anything from the driver, such as "no such volume"
@@ -542,7 +546,7 @@
vd, err := volumedrivers.GetDriver(v.DriverName())
if err != nil {
- return &OpErr{Err: err, Name: vd.Name(), Op: "remove"}
+ return &OpErr{Err: err, Name: v.DriverName(), Op: "remove"}
}
logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
diff --git a/volume/volume.go b/volume/volume.go
index f3227fe..a941d8f 100644
--- a/volume/volume.go
+++ b/volume/volume.go
@@ -124,7 +124,20 @@
// Setup sets up a mount point by either mounting the volume if it is
// configured, or creating the source directory if supplied.
-func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (string, error) {
+func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (path string, err error) {
+ defer func() {
+ if err == nil {
+ if label.RelabelNeeded(m.Mode) {
+ if err = label.Relabel(m.Source, mountLabel, label.IsShared(m.Mode)); err != nil {
+ path = ""
+ err = errors.Wrapf(err, "error setting label on mount source '%s'", m.Source)
+ return
+ }
+ }
+ }
+ return
+ }()
+
if m.Volume != nil {
id := m.ID
if id == "" {
@@ -152,11 +165,6 @@
}
}
}
- if label.RelabelNeeded(m.Mode) {
- if err := label.Relabel(m.Source, mountLabel, label.IsShared(m.Mode)); err != nil {
- return "", errors.Wrapf(err, "error setting label on mount source '%s'", m.Source)
- }
- }
return m.Source, nil
}
@@ -303,10 +311,12 @@
}
case mounttypes.TypeBind:
mp.Source = clean(convertSlash(cfg.Source))
- if cfg.BindOptions != nil {
- if len(cfg.BindOptions.Propagation) > 0 {
- mp.Propagation = cfg.BindOptions.Propagation
- }
+ if cfg.BindOptions != nil && len(cfg.BindOptions.Propagation) > 0 {
+ mp.Propagation = cfg.BindOptions.Propagation
+ } else {
+ // If user did not specify a propagation mode, get
+ // default propagation mode.
+ mp.Propagation = DefaultPropagationMode
}
case mounttypes.TypeTmpfs:
// NOP
diff --git a/volume/volume_test.go b/volume/volume_test.go
index 54df380..18018f4 100644
--- a/volume/volume_test.go
+++ b/volume/volume_test.go
@@ -229,10 +229,10 @@
defer os.RemoveAll(testDir)
cases := []c{
- {mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath}},
- {mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, RW: true}},
- {mount.Mount{Type: mount.TypeBind, Source: testDir + string(os.PathSeparator), Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath}},
- {mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath + string(os.PathSeparator), ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath}},
+ {mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: DefaultPropagationMode}},
+ {mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, RW: true, Propagation: DefaultPropagationMode}},
+ {mount.Mount{Type: mount.TypeBind, Source: testDir + string(os.PathSeparator), Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: DefaultPropagationMode}},
+ {mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath + string(os.PathSeparator), ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: DefaultPropagationMode}},
{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath}, MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: DefaultCopyMode}},
{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath + string(os.PathSeparator)}, MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: DefaultCopyMode}},
}