Merge pull request #35732 from rhvgoyal/error-info

devmapper: Log fstype and mount options during mount error
diff --git a/MAINTAINERS b/MAINTAINERS
index d81caba..a896687 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -368,7 +368,7 @@
 
 	[people.mlaventure]
 	Name = "Kenfe-Mickaël Laventure"
-	Email = "mickael.laventure@docker.com"
+	Email = "mickael.laventure@gmail.com"
 	GitHub = "mlaventure"
 
 	[people.moxiegirl]
@@ -465,4 +465,3 @@
 	Name = "Yong Tang"
 	Email = "yong.tang.github@outlook.com"
 	GitHub = "yongtang"
-
diff --git a/api/common.go b/api/common.go
index af34d0b..693d0a4 100644
--- a/api/common.go
+++ b/api/common.go
@@ -3,7 +3,7 @@
 // Common constants for daemon and client.
 const (
 	// DefaultVersion of Current REST API
-	DefaultVersion string = "1.35"
+	DefaultVersion string = "1.36"
 
 	// NoBaseImageSpecifier is the symbol used by the FROM
 	// command to specify that no base image is to be used.
diff --git a/api/server/router/container/container_routes.go b/api/server/router/container/container_routes.go
index d845fdd..b7848a3 100644
--- a/api/server/router/container/container_routes.go
+++ b/api/server/router/container/container_routes.go
@@ -593,7 +593,11 @@
 	close(done)
 	select {
 	case <-started:
-		logrus.Errorf("Error attaching websocket: %s", err)
+		if err != nil {
+			logrus.Errorf("Error attaching websocket: %s", err)
+		} else {
+			logrus.Debug("websocket connection was closed by client")
+		}
 		return nil
 	default:
 	}
diff --git a/api/swagger.yaml b/api/swagger.yaml
index b1533f6..73ea1a3 100644
--- a/api/swagger.yaml
+++ b/api/swagger.yaml
@@ -19,10 +19,10 @@
 consumes:
   - "application/json"
   - "text/plain"
-basePath: "/v1.35"
+basePath: "/v1.36"
 info:
   title: "Docker Engine API"
-  version: "1.35"
+  version: "1.36"
   x-logo:
     url: "https://docs.docker.com/images/logo-docker-main.png"
   description: |
@@ -49,8 +49,8 @@
     the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
     is returned.
 
-    If you omit the version-prefix, the current version of the API (v1.35) is used.
-    For example, calling `/info` is the same as calling `/v1.35/info`. Using the
+    If you omit the version-prefix, the current version of the API (v1.36) is used.
+    For example, calling `/info` is the same as calling `/v1.36/info`. Using the
     API without a version-prefix is deprecated and will be removed in a future release.
 
     Engine releases in the near future should support this version of the API,
diff --git a/cmd/dockerd/config.go b/cmd/dockerd/config.go
index c4ae197..c7da6ee 100644
--- a/cmd/dockerd/config.go
+++ b/cmd/dockerd/config.go
@@ -92,6 +92,8 @@
 	flags.Var(insecureRegistries, "insecure-registry", "Enable insecure registry communication")
 
 	if runtime.GOOS != "windows" {
+		// TODO: Remove this flag after 3 release cycles (18.03)
 		flags.BoolVar(&options.V2Only, "disable-legacy-registry", true, "Disable contacting legacy registries")
+		flags.MarkHidden("disable-legacy-registry")
 	}
 }
diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go
index 02a0314..d73b63a 100644
--- a/cmd/dockerd/daemon.go
+++ b/cmd/dockerd/daemon.go
@@ -6,6 +6,7 @@
 	"fmt"
 	"os"
 	"path/filepath"
+	"runtime"
 	"strings"
 	"time"
 
@@ -472,8 +473,15 @@
 		return nil, err
 	}
 
-	if !conf.V2Only {
-		logrus.Warnf(`The "disable-legacy-registry" option is deprecated and wil be removed in Docker v17.12. Interacting with legacy (v1) registries will no longer be supported in Docker v17.12"`)
+	if runtime.GOOS != "windows" {
+		if flags.Changed("disable-legacy-registry") {
+			// TODO: Remove this error after 3 release cycles (18.03)
+			return nil, errors.New("ERROR: The '--disable-legacy-registry' flag has been removed. Interacting with legacy (v1) registries is no longer supported")
+		}
+		if !conf.V2Only {
+			// TODO: Remove this error after 3 release cycles (18.03)
+			return nil, errors.New("ERROR: The 'disable-legacy-registry' configuration option has been removed. Interacting with legacy (v1) registries is no longer supported")
+		}
 	}
 
 	if flags.Changed("graph") {
diff --git a/cmd/dockerd/daemon_unix_test.go b/cmd/dockerd/daemon_unix_test.go
index 475ff9e..41c392e 100644
--- a/cmd/dockerd/daemon_unix_test.go
+++ b/cmd/dockerd/daemon_unix_test.go
@@ -97,15 +97,3 @@
 
 	assert.True(t, loadedConfig.EnableUserlandProxy)
 }
-
-func TestLoadDaemonConfigWithLegacyRegistryOptions(t *testing.T) {
-	content := `{"disable-legacy-registry": false}`
-	tempFile := fs.NewFile(t, "config", fs.WithContent(content))
-	defer tempFile.Remove()
-
-	opts := defaultOptions(tempFile.Path())
-	loadedConfig, err := loadDaemonCliConfig(opts)
-	require.NoError(t, err)
-	require.NotNil(t, loadedConfig)
-	assert.False(t, loadedConfig.V2Only)
-}
diff --git a/docs/api/version-history.md b/docs/api/version-history.md
index 5056c0d..0fdf464 100644
--- a/docs/api/version-history.md
+++ b/docs/api/version-history.md
@@ -13,6 +13,11 @@
      will be rejected.
 -->
 
+## v1.36 API changes
+
+[Docker Engine API v1.36](https://docs.docker.com/engine/api/v1.36/) documentation
+
+
 ## v1.35 API changes
 
 [Docker Engine API v1.35](https://docs.docker.com/engine/api/v1.35/) documentation
@@ -23,6 +28,18 @@
   configuration is only used for Windows containers.
 * `GET /containers/(name)/logs` now supports an additional query parameter: `until`,
   which returns log lines that occurred before the specified timestamp.
+* `POST /containers/{id}/exec` now accepts a `WorkingDir` property to set the
+  work-dir for the exec process, independent of the container's work-dir.
+* `Get /version` now returns a `Platform.Name` field, which can be used by products
+  using Moby as a foundation to return information about the platform.
+* `Get /version` now returns a `Components` field, which can be used to return
+  information about the components used. Information about the engine itself is
+  now included as a "Component" version, and contains all information from the
+  top-level `Version`, `GitCommit`, `APIVersion`, `MinAPIVersion`, `GoVersion`,
+  `Os`, `Arch`, `BuildTime`, `KernelVersion`, and `Experimental` fields. Going
+  forward, the information from the `Components` section is preferred over their
+  top-level counterparts.
+
 
 ## v1.34 API changes
 
diff --git a/docs/contributing/set-up-dev-env.md b/docs/contributing/set-up-dev-env.md
index 28bea5b..c2c8389 100644
--- a/docs/contributing/set-up-dev-env.md
+++ b/docs/contributing/set-up-dev-env.md
@@ -129,13 +129,14 @@
 
    ```none
    Successfully built 3d872560918e
+   Successfully tagged docker-dev:dry-run-test
    docker run --rm -i --privileged -e BUILDFLAGS -e KEEPBUNDLE -e DOCKER_BUILD_GOGC -e DOCKER_BUILD_PKGS -e DOCKER_CLIENTONLY -e DOCKER_DEBUG -e DOCKER_EXPERIMENTAL -e DOCKER_GITCOMMIT -e DOCKER_GRAPHDRIVER=devicemapper -e DOCKER_INCREMENTAL_BINARY -e DOCKER_REMAP_ROOT -e DOCKER_STORAGE_OPTS -e DOCKER_USERLANDPROXY -e TESTDIRS -e TESTFLAGS -e TIMEOUT -v "home/ubuntu/repos/docker/bundles:/go/src/github.com/moby/moby/bundles" -t "docker-dev:dry-run-test" bash
    root@f31fa223770f:/go/src/github.com/docker/docker#
    ```
 
    At this point, your prompt reflects the container's BASH shell.
 
-5. List the contents of the current directory (`/go/src/github.com/moby/moby`).
+5. List the contents of the current directory (`/go/src/github.com/docker/docker`).
 
    You should see the image's source from the  `/go/src/github.com/docker/docker`
    directory.
diff --git a/integration-cli/docker_api_logs_test.go b/integration-cli/docker_api_logs_test.go
index 0672e32..41164df 100644
--- a/integration-cli/docker_api_logs_test.go
+++ b/integration-cli/docker_api_logs_test.go
@@ -151,7 +151,7 @@
 
 func (s *DockerSuite) TestLogsAPIUntil(c *check.C) {
 	name := "logsuntil"
-	dockerCmd(c, "run", "--name", name, "busybox", "/bin/sh", "-c", "for i in $(seq 1 3); do echo log$i; sleep 0.5; done")
+	dockerCmd(c, "run", "--name", name, "busybox", "/bin/sh", "-c", "for i in $(seq 1 3); do echo log$i; done")
 
 	client, err := request.NewClient()
 	if err != nil {
diff --git a/integration-cli/docker_cli_logout_test.go b/integration-cli/docker_cli_logout_test.go
index 5076ceb..e0752f4 100644
--- a/integration-cli/docker_cli_logout_test.go
+++ b/integration-cli/docker_cli_logout_test.go
@@ -13,9 +13,7 @@
 )
 
 func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithExternalAuth(c *check.C) {
-
-	// @TODO TestLogoutWithExternalAuth expects docker to fall back to a v1 registry, so has to be updated for v17.12, when v1 registries are no longer supported
-	s.d.StartWithBusybox(c, "--disable-legacy-registry=false")
+	s.d.StartWithBusybox(c)
 
 	osPath := os.Getenv("PATH")
 	defer os.Setenv("PATH", osPath)
@@ -62,7 +60,7 @@
 	// check I cannot pull anymore
 	out, err := s.d.Cmd("--config", tmp, "pull", repoName)
 	c.Assert(err, check.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Error: image dockercli/busybox:authtest not found")
+	c.Assert(out, checker.Contains, "no basic auth credentials")
 }
 
 // #23100
diff --git a/integration-cli/docker_cli_pull_test.go b/integration-cli/docker_cli_pull_test.go
index 613cdb3..0e88b1e 100644
--- a/integration-cli/docker_cli_pull_test.go
+++ b/integration-cli/docker_cli_pull_test.go
@@ -259,18 +259,6 @@
 	c.Assert(err, checker.NotNil, check.Commentf("image was pulled after client disconnected"))
 }
 
-func (s *DockerRegistryAuthHtpasswdSuite) TestPullNoCredentialsNotFound(c *check.C) {
-	// @TODO TestPullNoCredentialsNotFound expects docker to fall back to a v1 registry, so has to be updated for v17.12, when v1 registries are no longer supported
-	s.d.StartWithBusybox(c, "--disable-legacy-registry=false")
-
-	// we don't care about the actual image, we just want to see image not found
-	// because that means v2 call returned 401 and we fell back to v1 which usually
-	// gives a 404 (in this case the test registry doesn't handle v1 at all)
-	out, err := s.d.Cmd("pull", privateRegistryURL+"/busybox")
-	c.Assert(err, check.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Error: image busybox:latest not found")
-}
-
 // Regression test for https://github.com/docker/docker/issues/26429
 func (s *DockerSuite) TestPullLinuxImageFailsOnWindows(c *check.C) {
 	testRequires(c, DaemonIsWindows, Network)
diff --git a/integration-cli/docker_cli_v2_only_test.go b/integration-cli/docker_cli_v2_only_test.go
index b82cdbd..3757341 100644
--- a/integration-cli/docker_cli_v2_only_test.go
+++ b/integration-cli/docker_cli_v2_only_test.go
@@ -22,7 +22,7 @@
 	return f.Name(), nil
 }
 
-// TestV2Only ensures that a daemon by default does not
+// TestV2Only ensures that a daemon does not
 // attempt to contact any v1 registry endpoints.
 func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
 	reg, err := registry.NewMock(c)
@@ -56,65 +56,3 @@
 	s.d.Cmd("push", repoName)
 	s.d.Cmd("pull", repoName)
 }
-
-// TestV1 starts a daemon with legacy registries enabled
-// and ensure v1 endpoints are hit for the following operations:
-// login, push, pull, build & run
-func (s *DockerRegistrySuite) TestV1(c *check.C) {
-	reg, err := registry.NewMock(c)
-	defer reg.Close()
-	c.Assert(err, check.IsNil)
-
-	v2Pings := 0
-	reg.RegisterHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
-		v2Pings++
-		// V2 ping 404 causes fallback to v1
-		w.WriteHeader(404)
-	})
-
-	v1Pings := 0
-	reg.RegisterHandler("/v1/_ping", func(w http.ResponseWriter, r *http.Request) {
-		v1Pings++
-	})
-
-	v1Logins := 0
-	reg.RegisterHandler("/v1/users/", func(w http.ResponseWriter, r *http.Request) {
-		v1Logins++
-	})
-
-	v1Repo := 0
-	reg.RegisterHandler("/v1/repositories/busybox/", func(w http.ResponseWriter, r *http.Request) {
-		v1Repo++
-	})
-
-	reg.RegisterHandler("/v1/repositories/busybox/images", func(w http.ResponseWriter, r *http.Request) {
-		v1Repo++
-	})
-
-	s.d.Start(c, "--insecure-registry", reg.URL(), "--disable-legacy-registry=false")
-
-	tmp, err := ioutil.TempDir("", "integration-cli-")
-	c.Assert(err, check.IsNil)
-	defer os.RemoveAll(tmp)
-
-	dockerfileName, err := makefile(tmp, fmt.Sprintf("FROM %s/busybox", reg.URL()))
-	c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
-
-	s.d.Cmd("build", "--file", dockerfileName, tmp)
-	c.Assert(v1Repo, check.Equals, 1, check.Commentf("Expected v1 repository access after build"))
-
-	repoName := fmt.Sprintf("%s/busybox", reg.URL())
-	s.d.Cmd("run", repoName)
-	c.Assert(v1Repo, check.Equals, 2, check.Commentf("Expected v1 repository access after run"))
-
-	s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.URL())
-	c.Assert(v1Logins, check.Equals, 1, check.Commentf("Expected v1 login attempt"))
-
-	s.d.Cmd("tag", "busybox", repoName)
-	s.d.Cmd("push", repoName)
-
-	c.Assert(v1Repo, check.Equals, 2)
-
-	s.d.Cmd("pull", repoName)
-	c.Assert(v1Repo, check.Equals, 3, check.Commentf("Expected v1 repository access after pull"))
-}
diff --git a/volume/store/store.go b/volume/store/store.go
index fd1ca61..9a511a5 100644
--- a/volume/store/store.go
+++ b/volume/store/store.go
@@ -145,8 +145,9 @@
 	s.globalLock.Lock()
 	v, exists := s.names[name]
 	if exists {
-		if _, err := volumedrivers.ReleaseDriver(v.DriverName()); err != nil {
-			logrus.Errorf("Error dereferencing volume driver: %v", err)
+		driverName := v.DriverName()
+		if _, err := volumedrivers.ReleaseDriver(driverName); err != nil {
+			logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver")
 		}
 	}
 	if err := s.removeMeta(name); err != nil {