Merge pull request #74 from thaJeztah/18.09_backport_no_more_version_mismatch

[18.09 backport] remove version-checks for containerd and runc
diff --git a/Dockerfile b/Dockerfile
index b3f36fb..5c2bb9e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -24,10 +24,10 @@
 # the case. Therefore, you don't have to disable it anymore.
 #
 
-FROM golang:1.10.3 AS base
+FROM golang:1.10.4 AS base
 # FIXME(vdemeester) this is kept for other script depending on it to not fail right away
 # Remove this once the other scripts uses something else to detect the version
-ENV GO_VERSION 1.10.3
+ENV GO_VERSION 1.10.4
 # allow replacing httpredir or deb mirror
 ARG APT_MIRROR=deb.debian.org
 RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
diff --git a/Dockerfile.e2e b/Dockerfile.e2e
index 663a58a..45c5eec 100644
--- a/Dockerfile.e2e
+++ b/Dockerfile.e2e
@@ -1,5 +1,5 @@
 ## Step 1: Build tests
-FROM golang:1.10.3-alpine3.7 as builder
+FROM golang:1.10.4-alpine3.7 as builder
 
 RUN apk add --update \
     bash \
diff --git a/Dockerfile.simple b/Dockerfile.simple
index b0338ac..1fe426b 100644
--- a/Dockerfile.simple
+++ b/Dockerfile.simple
@@ -42,7 +42,7 @@
 #            will need updating, to avoid errors. Ping #docker-maintainers on IRC
 #            with a heads-up.
 # IMPORTANT: When updating this please note that stdlib archive/tar pkg is vendored
-ENV GO_VERSION 1.10.3
+ENV GO_VERSION 1.10.4
 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" \
 	| tar -xzC /usr/local
 ENV PATH /go/bin:/usr/local/go/bin:$PATH
diff --git a/Dockerfile.windows b/Dockerfile.windows
index 1b2c1f3..2eb7350 100644
--- a/Dockerfile.windows
+++ b/Dockerfile.windows
@@ -161,7 +161,7 @@
 # Environment variable notes:
 #  - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
 #  - FROM_DOCKERFILE is used for detection of building within a container.
-ENV GO_VERSION=1.10.3 `
+ENV GO_VERSION=1.10.4 `
     GIT_VERSION=2.11.1 `
     GOPATH=C:\go `
     FROM_DOCKERFILE=1
diff --git a/api/server/router/build/build_routes.go b/api/server/router/build/build_routes.go
index 60a136a..f41a6d4 100644
--- a/api/server/router/build/build_routes.go
+++ b/api/server/router/build/build_routes.go
@@ -170,6 +170,9 @@
 		return errors.Wrap(err, "could not parse filters")
 	}
 	ksfv := r.FormValue("keep-storage")
+	if ksfv == "" {
+		ksfv = "0"
+	}
 	ks, err := strconv.Atoi(ksfv)
 	if err != nil {
 		return errors.Wrapf(err, "keep-storage is in bytes and expects an integer, got %v", ksfv)
diff --git a/api/swagger.yaml b/api/swagger.yaml
index 1007663..f58a64f 100644
--- a/api/swagger.yaml
+++ b/api/swagger.yaml
@@ -3747,18 +3747,22 @@
         description: |
           HTTP-proxy configured for the daemon. This value is obtained from the
           [`HTTP_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable.
+          Credentials ([user info component](https://tools.ietf.org/html/rfc3986#section-3.2.1)) in the proxy URL
+          are masked in the API response.
 
           Containers do not automatically inherit this configuration.
         type: "string"
-        example: "http://user:pass@proxy.corp.example.com:8080"
+        example: "http://xxxxx:xxxxx@proxy.corp.example.com:8080"
       HttpsProxy:
         description: |
           HTTPS-proxy configured for the daemon. This value is obtained from the
           [`HTTPS_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable.
+          Credentials ([user info component](https://tools.ietf.org/html/rfc3986#section-3.2.1)) in the proxy URL
+          are masked in the API response.
 
           Containers do not automatically inherit this configuration.
         type: "string"
-        example: "https://user:pass@proxy.corp.example.com:4443"
+        example: "https://xxxxx:xxxxx@proxy.corp.example.com:4443"
       NoProxy:
         description: |
           Comma-separated list of domain extensions for which no proxy should be
@@ -9341,7 +9345,10 @@
 
         - name: "version"
           in: "query"
-          description: "The version number of the service object being updated. This is required to avoid conflicting writes."
+          description: "The version number of the service object being updated.
+          This is required to avoid conflicting writes.
+          This version number should be the value as currently set on the service *before* the update.
+          You can find the current version by calling `GET /services/{id}`"
           required: true
           type: "integer"
         - name: "registryAuthFrom"
diff --git a/builder/builder-next/adapters/containerimage/pull.go b/builder/builder-next/adapters/containerimage/pull.go
index f94b4eb..f6e55f4 100644
--- a/builder/builder-next/adapters/containerimage/pull.go
+++ b/builder/builder-next/adapters/containerimage/pull.go
@@ -75,12 +75,12 @@
 
 func (is *imageSource) getResolver(ctx context.Context, rfn resolver.ResolveOptionsFunc, ref string) remotes.Resolver {
 	opt := docker.ResolverOptions{
-		Client:      tracing.DefaultClient,
-		Credentials: is.getCredentialsFromSession(ctx),
+		Client: tracing.DefaultClient,
 	}
 	if rfn != nil {
 		opt = rfn(ref)
 	}
+	opt.Credentials = is.getCredentialsFromSession(ctx)
 	r := docker.NewResolver(opt)
 	return r
 }
diff --git a/builder/builder-next/adapters/snapshot/snapshot.go b/builder/builder-next/adapters/snapshot/snapshot.go
index e5e6942..c1388da 100644
--- a/builder/builder-next/adapters/snapshot/snapshot.go
+++ b/builder/builder-next/adapters/snapshot/snapshot.go
@@ -426,10 +426,11 @@
 }
 
 type mountable struct {
-	mu      sync.Mutex
-	mounts  []mount.Mount
-	acquire func() ([]mount.Mount, error)
-	release func() error
+	mu       sync.Mutex
+	mounts   []mount.Mount
+	acquire  func() ([]mount.Mount, error)
+	release  func() error
+	refCount int
 }
 
 func (m *mountable) Mount() ([]mount.Mount, error) {
@@ -437,6 +438,7 @@
 	defer m.mu.Unlock()
 
 	if m.mounts != nil {
+		m.refCount++
 		return m.mounts, nil
 	}
 
@@ -445,6 +447,7 @@
 		return nil, err
 	}
 	m.mounts = mounts
+	m.refCount = 1
 
 	return m.mounts, nil
 }
@@ -452,6 +455,13 @@
 func (m *mountable) Release() error {
 	m.mu.Lock()
 	defer m.mu.Unlock()
+
+	if m.refCount > 1 {
+		m.refCount--
+		return nil
+	}
+
+	m.refCount = 0
 	if m.release == nil {
 		return nil
 	}
diff --git a/builder/builder-next/builder.go b/builder/builder-next/builder.go
index a51d8ec..1e3c7bd 100644
--- a/builder/builder-next/builder.go
+++ b/builder/builder-next/builder.go
@@ -221,7 +221,9 @@
 
 	id := identity.NewID()
 
-	frontendAttrs := map[string]string{}
+	frontendAttrs := map[string]string{
+		"override-copy-image": "docker.io/docker/dockerfile-copy:v0.1.9@sha256:e8f159d3f00786604b93c675ee2783f8dc194bb565e61ca5788f6a6e9d304061",
+	}
 
 	if opt.Options.Target != "" {
 		frontendAttrs["target"] = opt.Options.Target
@@ -530,20 +532,26 @@
 
 	bkFilter := make([]string, 0, opts.Filters.Len())
 	for cacheField := range cacheFields {
-		values := opts.Filters.Get(cacheField)
-		switch len(values) {
-		case 0:
-			bkFilter = append(bkFilter, cacheField)
-		case 1:
-			bkFilter = append(bkFilter, cacheField+"=="+values[0])
-		default:
-			return client.PruneInfo{}, errMultipleFilterValues
+		if opts.Filters.Include(cacheField) {
+			values := opts.Filters.Get(cacheField)
+			switch len(values) {
+			case 0:
+				bkFilter = append(bkFilter, cacheField)
+			case 1:
+				if cacheField == "id" {
+					bkFilter = append(bkFilter, cacheField+"~="+values[0])
+				} else {
+					bkFilter = append(bkFilter, cacheField+"=="+values[0])
+				}
+			default:
+				return client.PruneInfo{}, errMultipleFilterValues
+			}
 		}
 	}
 	return client.PruneInfo{
 		All:          opts.All,
 		KeepDuration: unusedFor,
 		KeepBytes:    opts.KeepStorage,
-		Filter:       bkFilter,
+		Filter:       []string{strings.Join(bkFilter, ",")},
 	}, nil
 }
diff --git a/builder/fscache/fscache.go b/builder/fscache/fscache.go
index 2216c33..8897fe1 100644
--- a/builder/fscache/fscache.go
+++ b/builder/fscache/fscache.go
@@ -22,6 +22,7 @@
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"github.com/tonistiigi/fsutil"
+	fsutiltypes "github.com/tonistiigi/fsutil/types"
 	bolt "go.etcd.io/bbolt"
 	"golang.org/x/sync/singleflight"
 )
@@ -614,7 +615,7 @@
 	s[i], s[j] = s[j], s[i]
 }
 
-func newTarsumHash(stat *fsutil.Stat) (hash.Hash, error) {
+func newTarsumHash(stat *fsutiltypes.Stat) (hash.Hash, error) {
 	fi := &fsutil.StatInfo{Stat: stat}
 	p := stat.Path
 	if fi.IsDir() {
diff --git a/daemon/cluster/cluster.go b/daemon/cluster/cluster.go
index 35ba5a9..828748b 100644
--- a/daemon/cluster/cluster.go
+++ b/daemon/cluster/cluster.go
@@ -41,6 +41,7 @@
 import (
 	"context"
 	"fmt"
+	"math"
 	"net"
 	"os"
 	"path/filepath"
@@ -67,9 +68,10 @@
 const defaultAddr = "0.0.0.0:2377"
 
 const (
-	initialReconnectDelay = 100 * time.Millisecond
-	maxReconnectDelay     = 30 * time.Second
-	contextPrefix         = "com.docker.swarm"
+	initialReconnectDelay          = 100 * time.Millisecond
+	maxReconnectDelay              = 30 * time.Second
+	contextPrefix                  = "com.docker.swarm"
+	defaultRecvSizeForListResponse = math.MaxInt32 // the max recv limit grpc <1.4.0
 )
 
 // NetworkSubnetsProvider exposes functions for retrieving the subnets
diff --git a/daemon/cluster/listen_addr.go b/daemon/cluster/listen_addr.go
index e1ebfec..44ea5fc 100644
--- a/daemon/cluster/listen_addr.go
+++ b/daemon/cluster/listen_addr.go
@@ -3,6 +3,7 @@
 import (
 	"fmt"
 	"net"
+	"strings"
 )
 
 const (
@@ -87,6 +88,41 @@
 	return systemAddr.String(), listenAddrPort, nil
 }
 
+// validateDefaultAddrPool validates default address pool
+// it also strips white space from the string before validation
+func validateDefaultAddrPool(defaultAddrPool []string, size uint32) error {
+	if defaultAddrPool == nil {
+		// defaultAddrPool is not defined
+		return nil
+	}
+	//if size is not set, then we use default value 24
+	if size == 0 {
+		size = 24
+	}
+	// We allow max value as 29. We can have 8 IP addresses for max value 29
+	// If we allow 30, then we will get only 4 IP addresses. But with latest
+	// libnetwork LB scale implementation, we use total of 4 IP addresses for internal use.
+	// Hence keeping 29 as max value, we will have 8 IP addresses. This will be
+	// smallest subnet that can be used in overlay network.
+	if size > 29 {
+		return fmt.Errorf("subnet size is out of range: %d", size)
+	}
+	for i := range defaultAddrPool {
+		// trim leading and trailing white spaces
+		defaultAddrPool[i] = strings.TrimSpace(defaultAddrPool[i])
+		_, b, err := net.ParseCIDR(defaultAddrPool[i])
+		if err != nil {
+			return fmt.Errorf("invalid base pool %s: %v", defaultAddrPool[i], err)
+		}
+		ones, _ := b.Mask.Size()
+		if size < uint32(ones) {
+			return fmt.Errorf("invalid CIDR: %q. Subnet size is too small for pool: %d", defaultAddrPool[i], size)
+		}
+	}
+
+	return nil
+}
+
 func resolveDataPathAddr(dataPathAddr string) (string, error) {
 	if dataPathAddr == "" {
 		// dataPathAddr is not defined
diff --git a/daemon/cluster/services.go b/daemon/cluster/services.go
index c140376..d82c0f0 100644
--- a/daemon/cluster/services.go
+++ b/daemon/cluster/services.go
@@ -23,6 +23,7 @@
 	gogotypes "github.com/gogo/protobuf/types"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
+	"google.golang.org/grpc"
 )
 
 // GetServices returns all services of a managed swarm cluster.
@@ -67,7 +68,9 @@
 
 	r, err := state.controlClient.ListServices(
 		ctx,
-		&swarmapi.ListServicesRequest{Filters: filters})
+		&swarmapi.ListServicesRequest{Filters: filters},
+		grpc.MaxCallRecvMsgSize(defaultRecvSizeForListResponse),
+	)
 	if err != nil {
 		return nil, err
 	}
diff --git a/daemon/cluster/swarm.go b/daemon/cluster/swarm.go
index d61e22f..65dfe9e 100644
--- a/daemon/cluster/swarm.go
+++ b/daemon/cluster/swarm.go
@@ -92,6 +92,10 @@
 		}
 	}
 
+	//Validate Default Address Pool input
+	if err := validateDefaultAddrPool(req.DefaultAddrPool, req.SubnetSize); err != nil {
+		return "", err
+	}
 	nr, err := c.newNodeRunner(nodeStartConfig{
 		forceNewCluster:    req.ForceNewCluster,
 		autolock:           req.AutoLockManagers,
diff --git a/daemon/cluster/tasks.go b/daemon/cluster/tasks.go
index de1240d..f1001ea 100644
--- a/daemon/cluster/tasks.go
+++ b/daemon/cluster/tasks.go
@@ -8,6 +8,7 @@
 	types "github.com/docker/docker/api/types/swarm"
 	"github.com/docker/docker/daemon/cluster/convert"
 	swarmapi "github.com/docker/swarmkit/api"
+	"google.golang.org/grpc"
 )
 
 // GetTasks returns a list of tasks matching the filter options.
@@ -53,7 +54,9 @@
 
 		r, err = state.controlClient.ListTasks(
 			ctx,
-			&swarmapi.ListTasksRequest{Filters: filters})
+			&swarmapi.ListTasksRequest{Filters: filters},
+			grpc.MaxCallRecvMsgSize(defaultRecvSizeForListResponse),
+		)
 		return err
 	}); err != nil {
 		return nil, err
diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go
index 07f8878..b69eede 100644
--- a/daemon/daemon_unix.go
+++ b/daemon/daemon_unix.go
@@ -482,14 +482,14 @@
 	}
 	cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(resources.CpusetCpus)
 	if err != nil {
-		return warnings, fmt.Errorf("Invalid value %s for cpuset cpus", resources.CpusetCpus)
+		return warnings, errors.Wrapf(err, "Invalid value %s for cpuset cpus", resources.CpusetCpus)
 	}
 	if !cpusAvailable {
 		return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s", resources.CpusetCpus, sysInfo.Cpus)
 	}
 	memsAvailable, err := sysInfo.IsCpusetMemsAvailable(resources.CpusetMems)
 	if err != nil {
-		return warnings, fmt.Errorf("Invalid value %s for cpuset mems", resources.CpusetMems)
+		return warnings, errors.Wrapf(err, "Invalid value %s for cpuset mems", resources.CpusetMems)
 	}
 	if !memsAvailable {
 		return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s", resources.CpusetMems, sysInfo.Mems)
diff --git a/daemon/graphdriver/btrfs/btrfs.go b/daemon/graphdriver/btrfs/btrfs.go
index 4c14191..7ce7ede 100644
--- a/daemon/graphdriver/btrfs/btrfs.go
+++ b/daemon/graphdriver/btrfs/btrfs.go
@@ -29,10 +29,12 @@
 	"github.com/docker/docker/daemon/graphdriver"
 	"github.com/docker/docker/pkg/containerfs"
 	"github.com/docker/docker/pkg/idtools"
+	"github.com/docker/docker/pkg/mount"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/go-units"
 	"github.com/opencontainers/selinux/go-selinux/label"
+	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/sys/unix"
 )
@@ -81,6 +83,15 @@
 		return nil, err
 	}
 
+	// For some reason shared mount propagation between a container
+	// and the host does not work for btrfs, and a remedy is to bind
+	// mount graphdriver home to itself (even without changing the
+	// propagation mode).
+	err = mount.MakeMount(home)
+	if err != nil {
+		return nil, errors.Wrapf(err, "failed to make %s a mount", home)
+	}
+
 	driver := &Driver{
 		home:    home,
 		uidMaps: uidMaps,
@@ -158,7 +169,19 @@
 
 // Cleanup unmounts the home directory.
 func (d *Driver) Cleanup() error {
-	return d.subvolDisableQuota()
+	err := d.subvolDisableQuota()
+	umountErr := mount.Unmount(d.home)
+
+	// in case we have two errors, prefer the one from disableQuota()
+	if err != nil {
+		return err
+	}
+
+	if umountErr != nil {
+		return errors.Wrapf(umountErr, "error unmounting %s", d.home)
+	}
+
+	return nil
 }
 
 func free(p *C.char) {
diff --git a/daemon/info.go b/daemon/info.go
index 9dcfb95..bf84342 100644
--- a/daemon/info.go
+++ b/daemon/info.go
@@ -2,6 +2,7 @@
 
 import (
 	"fmt"
+	"net/url"
 	"os"
 	"runtime"
 	"strings"
@@ -61,8 +62,8 @@
 		ServerVersion:      dockerversion.Version,
 		ClusterStore:       daemon.configStore.ClusterStore,
 		ClusterAdvertise:   daemon.configStore.ClusterAdvertise,
-		HTTPProxy:          sockets.GetProxyEnv("http_proxy"),
-		HTTPSProxy:         sockets.GetProxyEnv("https_proxy"),
+		HTTPProxy:          maskCredentials(sockets.GetProxyEnv("http_proxy")),
+		HTTPSProxy:         maskCredentials(sockets.GetProxyEnv("https_proxy")),
 		NoProxy:            sockets.GetProxyEnv("no_proxy"),
 		LiveRestoreEnabled: daemon.configStore.LiveRestoreEnabled,
 		Isolation:          daemon.defaultIsolation,
@@ -245,3 +246,13 @@
 	}
 	return operatingSystem
 }
+
+func maskCredentials(rawURL string) string {
+	parsedURL, err := url.Parse(rawURL)
+	if err != nil || parsedURL.User == nil {
+		return rawURL
+	}
+	parsedURL.User = url.UserPassword("xxxxx", "xxxxx")
+	maskedURL := parsedURL.String()
+	return maskedURL
+}
diff --git a/daemon/info_test.go b/daemon/info_test.go
new file mode 100644
index 0000000..076373c
--- /dev/null
+++ b/daemon/info_test.go
@@ -0,0 +1,53 @@
+package daemon
+
+import (
+	"testing"
+
+	"gotest.tools/assert"
+)
+
+func TestMaskURLCredentials(t *testing.T) {
+	tests := []struct {
+		rawURL    string
+		maskedURL string
+	}{
+		{
+			rawURL:    "",
+			maskedURL: "",
+		}, {
+			rawURL:    "invalidURL",
+			maskedURL: "invalidURL",
+		}, {
+			rawURL:    "http://proxy.example.com:80/",
+			maskedURL: "http://proxy.example.com:80/",
+		}, {
+			rawURL:    "http://USER:PASSWORD@proxy.example.com:80/",
+			maskedURL: "http://xxxxx:xxxxx@proxy.example.com:80/",
+		}, {
+			rawURL:    "http://PASSWORD:PASSWORD@proxy.example.com:80/",
+			maskedURL: "http://xxxxx:xxxxx@proxy.example.com:80/",
+		}, {
+			rawURL:    "http://USER:@proxy.example.com:80/",
+			maskedURL: "http://xxxxx:xxxxx@proxy.example.com:80/",
+		}, {
+			rawURL:    "http://:PASSWORD@proxy.example.com:80/",
+			maskedURL: "http://xxxxx:xxxxx@proxy.example.com:80/",
+		}, {
+			rawURL:    "http://USER@docker:password@proxy.example.com:80/",
+			maskedURL: "http://xxxxx:xxxxx@proxy.example.com:80/",
+		}, {
+			rawURL:    "http://USER%40docker:password@proxy.example.com:80/",
+			maskedURL: "http://xxxxx:xxxxx@proxy.example.com:80/",
+		}, {
+			rawURL:    "http://USER%40docker:pa%3Fsword@proxy.example.com:80/",
+			maskedURL: "http://xxxxx:xxxxx@proxy.example.com:80/",
+		}, {
+			rawURL:    "http://USER%40docker:pa%3Fsword@proxy.example.com:80/hello%20world",
+			maskedURL: "http://xxxxx:xxxxx@proxy.example.com:80/hello%20world",
+		},
+	}
+	for _, test := range tests {
+		maskedURL := maskCredentials(test.rawURL)
+		assert.Equal(t, maskedURL, test.maskedURL)
+	}
+}
diff --git a/daemon/logger/jsonfilelog/jsonfilelog.go b/daemon/logger/jsonfilelog/jsonfilelog.go
index 476e1d8..bbb8eeb 100644
--- a/daemon/logger/jsonfilelog/jsonfilelog.go
+++ b/daemon/logger/jsonfilelog/jsonfilelog.go
@@ -50,7 +50,7 @@
 			return nil, err
 		}
 		if capval <= 0 {
-			return nil, fmt.Errorf("max-size should be a positive numbler")
+			return nil, fmt.Errorf("max-size must be a positive number")
 		}
 	}
 	var maxFiles = 1
diff --git a/hack/dockerfile/install/proxy.installer b/hack/dockerfile/install/proxy.installer
index ed9ab53..f1d3f93 100755
--- a/hack/dockerfile/install/proxy.installer
+++ b/hack/dockerfile/install/proxy.installer
@@ -3,7 +3,7 @@
 # LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When
 # updating the binary version, consider updating github.com/docker/libnetwork
 # in vendor.conf accordingly
-LIBNETWORK_COMMIT=f30a35b091cc2a431ef9856c75c343f75bb5f2e2
+LIBNETWORK_COMMIT=6da50d1978302f04c3e2089e29112ea24812f05b
 
 install_proxy() {
 	case "$1" in
diff --git a/integration/container/exec_test.go b/integration/container/exec_test.go
index 85f9e05..d33301b 100644
--- a/integration/container/exec_test.go
+++ b/integration/container/exec_test.go
@@ -4,6 +4,7 @@
 	"context"
 	"io/ioutil"
 	"testing"
+	"time"
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/strslice"
@@ -15,6 +16,74 @@
 	"gotest.tools/skip"
 )
 
+// TestExecWithCloseStdin adds case for moby#37870 issue.
+func TestExecWithCloseStdin(t *testing.T) {
+	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.39"), "broken in earlier versions")
+	defer setupTest(t)()
+
+	ctx := context.Background()
+	client := request.NewAPIClient(t)
+
+	// run top with detached mode
+	cID := container.Run(t, ctx, client)
+
+	expected := "closeIO"
+	execResp, err := client.ContainerExecCreate(ctx, cID,
+		types.ExecConfig{
+			AttachStdin:  true,
+			AttachStdout: true,
+			Cmd:          strslice.StrSlice([]string{"sh", "-c", "cat && echo " + expected}),
+		},
+	)
+	assert.NilError(t, err)
+
+	resp, err := client.ContainerExecAttach(ctx, execResp.ID,
+		types.ExecStartCheck{
+			Detach: false,
+			Tty:    false,
+		},
+	)
+	assert.NilError(t, err)
+	defer resp.Close()
+
+	// close stdin to send EOF to cat
+	assert.NilError(t, resp.CloseWrite())
+
+	var (
+		waitCh = make(chan struct{})
+		resCh  = make(chan struct {
+			content string
+			err     error
+		})
+	)
+
+	go func() {
+		close(waitCh)
+		defer close(resCh)
+		r, err := ioutil.ReadAll(resp.Reader)
+
+		resCh <- struct {
+			content string
+			err     error
+		}{
+			content: string(r),
+			err:     err,
+		}
+	}()
+
+	<-waitCh
+	select {
+	case <-time.After(3 * time.Second):
+		t.Fatal("failed to read the content in time")
+	case got := <-resCh:
+		assert.NilError(t, got.err)
+
+		// NOTE: using Contains because no-tty's stream contains UX information
+		// like size, stream type.
+		assert.Assert(t, is.Contains(got.content, expected))
+	}
+}
+
 func TestExec(t *testing.T) {
 	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.35"), "broken in earlier versions")
 	defer setupTest(t)()
diff --git a/integration/network/service_test.go b/integration/network/service_test.go
index 739a8ec..40823da 100644
--- a/integration/network/service_test.go
+++ b/integration/network/service_test.go
@@ -355,7 +355,7 @@
 	d.Stop(t)
 
 	// Clean up , set it back to original one to make sure other tests don't fail
-	ipAddr = []string{"10.10.0.0/8"}
+	ipAddr = []string{"10.0.0.0/8"}
 	ops = append(ops, daemon.WithSwarmDefaultAddrPool(ipAddr))
 	ops = append(ops, daemon.WithSwarmDefaultAddrPoolSubnetSize(24))
 	d = swarm.NewSwarm(t, testEnv, ops...)
diff --git a/libcontainerd/client_daemon.go b/libcontainerd/client_daemon.go
index 60fb335..cb9cb43 100644
--- a/libcontainerd/client_daemon.go
+++ b/libcontainerd/client_daemon.go
@@ -328,6 +328,13 @@
 	return int(t.Pid()), nil
 }
 
+// Exec creates exec process.
+//
+// The containerd client calls Exec to register the exec config in the shim side.
+// When the client calls Start, the shim will create stdin fifo if needs. But
+// for the container main process, the stdin fifo will be created in Create not
+// the Start call. stdinCloseSync channel should be closed after Start exec
+// process.
 func (c *client) Exec(ctx context.Context, containerID, processID string, spec *specs.Process, withStdin bool, attachStdio StdioCallback) (int, error) {
 	ctr := c.getContainer(containerID)
 	if ctr == nil {
@@ -372,7 +379,9 @@
 	ctr.addProcess(processID, p)
 
 	// Signal c.createIO that it can call CloseIO
-	close(stdinCloseSync)
+	//
+	// the stdin of exec process will be created after p.Start in containerd
+	defer close(stdinCloseSync)
 
 	if err = p.Start(ctx); err != nil {
 		p.Delete(context.Background())
diff --git a/pkg/mount/sharedsubtree_linux.go b/pkg/mount/sharedsubtree_linux.go
index 538f663..8a100f0 100644
--- a/pkg/mount/sharedsubtree_linux.go
+++ b/pkg/mount/sharedsubtree_linux.go
@@ -48,18 +48,22 @@
 	return ensureMountedAs(mountPoint, "runbindable")
 }
 
-func ensureMountedAs(mountPoint, options string) error {
-	mounted, err := Mounted(mountPoint)
+// MakeMount ensures that the file or directory given is a mount point,
+// bind mounting it to itself it case it is not.
+func MakeMount(mnt string) error {
+	mounted, err := Mounted(mnt)
 	if err != nil {
 		return err
 	}
-
-	if !mounted {
-		if err := Mount(mountPoint, mountPoint, "none", "bind,rw"); err != nil {
-			return err
-		}
+	if mounted {
+		return nil
 	}
-	if _, err = Mounted(mountPoint); err != nil {
+
+	return Mount(mnt, mnt, "none", "bind")
+}
+
+func ensureMountedAs(mountPoint, options string) error {
+	if err := MakeMount(mountPoint); err != nil {
 		return err
 	}
 
diff --git a/pkg/parsers/parsers.go b/pkg/parsers/parsers.go
index c4186a4..068e524 100644
--- a/pkg/parsers/parsers.go
+++ b/pkg/parsers/parsers.go
@@ -18,6 +18,24 @@
 	return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
 }
 
+// ParseUintListMaximum parses and validates the specified string as the value
+// found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
+// one of the formats below. Note that duplicates are actually allowed in the
+// input string. It returns a `map[int]bool` with available elements from `val`
+// set to `true`. Values larger than `maximum` cause an error if max is non zero,
+// in order to stop the map becoming excessively large.
+// Supported formats:
+//     7
+//     1-6
+//     0,3-4,7,8-10
+//     0-0,0,1-7
+//     03,1-3      <- this is gonna get parsed as [1,2,3]
+//     3,2,1
+//     0-2,3,1
+func ParseUintListMaximum(val string, maximum int) (map[int]bool, error) {
+	return parseUintList(val, maximum)
+}
+
 // ParseUintList parses and validates the specified string as the value
 // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
 // one of the formats below. Note that duplicates are actually allowed in the
@@ -32,6 +50,10 @@
 //     3,2,1
 //     0-2,3,1
 func ParseUintList(val string) (map[int]bool, error) {
+	return parseUintList(val, 0)
+}
+
+func parseUintList(val string, maximum int) (map[int]bool, error) {
 	if val == "" {
 		return map[int]bool{}, nil
 	}
@@ -46,6 +68,9 @@
 			if err != nil {
 				return nil, errInvalidFormat
 			}
+			if maximum != 0 && v > maximum {
+				return nil, fmt.Errorf("value of out range, maximum is %d", maximum)
+			}
 			availableInts[v] = true
 		} else {
 			split := strings.SplitN(r, "-", 2)
@@ -60,6 +85,9 @@
 			if max < min {
 				return nil, errInvalidFormat
 			}
+			if maximum != 0 && max > maximum {
+				return nil, fmt.Errorf("value of out range, maximum is %d", maximum)
+			}
 			for i := min; i <= max; i++ {
 				availableInts[i] = true
 			}
diff --git a/pkg/parsers/parsers_test.go b/pkg/parsers/parsers_test.go
index a70093f..12e5969 100644
--- a/pkg/parsers/parsers_test.go
+++ b/pkg/parsers/parsers_test.go
@@ -68,3 +68,16 @@
 		}
 	}
 }
+
+func TestParseUintListMaximumLimits(t *testing.T) {
+	v := "10,1000"
+	if _, err := ParseUintListMaximum(v, 0); err != nil {
+		t.Fatalf("Expected not to fail, got %v", err)
+	}
+	if _, err := ParseUintListMaximum(v, 1000); err != nil {
+		t.Fatalf("Expected not to fail, got %v", err)
+	}
+	if out, err := ParseUintListMaximum(v, 100); err == nil {
+		t.Fatalf("Expected failure with %s but got %v", v, out)
+	}
+}
diff --git a/pkg/sysinfo/sysinfo.go b/pkg/sysinfo/sysinfo.go
index 8fc0ecc..0f327d5 100644
--- a/pkg/sysinfo/sysinfo.go
+++ b/pkg/sysinfo/sysinfo.go
@@ -117,11 +117,19 @@
 }
 
 func isCpusetListAvailable(provided, available string) (bool, error) {
-	parsedProvided, err := parsers.ParseUintList(provided)
+	parsedAvailable, err := parsers.ParseUintList(available)
 	if err != nil {
 		return false, err
 	}
-	parsedAvailable, err := parsers.ParseUintList(available)
+	// 8192 is the normal maximum number of CPUs in Linux, so accept numbers up to this
+	// or more if we actually have more CPUs.
+	max := 8192
+	for m := range parsedAvailable {
+		if m > max {
+			max = m
+		}
+	}
+	parsedProvided, err := parsers.ParseUintListMaximum(provided, max)
 	if err != nil {
 		return false, err
 	}
diff --git a/profiles/seccomp/default.json b/profiles/seccomp/default.json
index c0f1405..0d954bb 100755
--- a/profiles/seccomp/default.json
+++ b/profiles/seccomp/default.json
@@ -329,7 +329,6 @@
 				"sync_file_range",
 				"syncfs",
 				"sysinfo",
-				"syslog",
 				"tee",
 				"tgkill",
 				"time",
@@ -561,6 +560,7 @@
 				"setdomainname",
 				"sethostname",
 				"setns",
+				"syslog",
 				"umount",
 				"umount2",
 				"unshare"
@@ -762,6 +762,20 @@
 				]
 			},
 			"excludes": {}
+		},
+		{
+			"names": [
+				"syslog"
+			],
+			"action": "SCMP_ACT_ALLOW",
+			"args": [],
+			"comment": "",
+			"includes": {
+				"caps": [
+					"CAP_SYSLOG"
+				]
+			},
+			"excludes": {}
 		}
 	]
 }
\ No newline at end of file
diff --git a/profiles/seccomp/seccomp_default.go b/profiles/seccomp/seccomp_default.go
index 25360a1..6055012 100644
--- a/profiles/seccomp/seccomp_default.go
+++ b/profiles/seccomp/seccomp_default.go
@@ -322,7 +322,6 @@
 				"sync_file_range",
 				"syncfs",
 				"sysinfo",
-				"syslog",
 				"tee",
 				"tgkill",
 				"time",
@@ -492,6 +491,7 @@
 				"setdomainname",
 				"sethostname",
 				"setns",
+				"syslog",
 				"umount",
 				"umount2",
 				"unshare",
@@ -642,6 +642,16 @@
 				Caps: []string{"CAP_SYS_NICE"},
 			},
 		},
+		{
+			Names: []string{
+				"syslog",
+			},
+			Action: types.ActAllow,
+			Args:   []*types.Arg{},
+			Includes: types.Filter{
+				Caps: []string{"CAP_SYSLOG"},
+			},
+		},
 	}
 
 	return &types.Seccomp{
diff --git a/vendor.conf b/vendor.conf
index d6a41a3..b822620 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -1,7 +1,7 @@
 # the following lines are in sorted order, FYI
 github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
-github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55
-github.com/Microsoft/go-winio v0.4.10
+github.com/Microsoft/hcsshim v0.7.6
+github.com/Microsoft/go-winio v0.4.11
 github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
 github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
 github.com/golang/gddo 9b12a26f3fbd7397dee4e20939ddca719d840d2a
@@ -26,8 +26,8 @@
 golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca
 
 # buildkit
-github.com/moby/buildkit 8f4dff0d16ea91cb43315d5f5aa4b27f4fe4e1f2
-github.com/tonistiigi/fsutil b19464cd1b6a00773b4f2eb7acf9c30426f9df42
+github.com/moby/buildkit c7bb575343df0cbfeab8b5b28149630b8153fcc6
+github.com/tonistiigi/fsutil f567071bed2416e4d87d260d3162722651182317
 github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
 github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
 github.com/google/shlex 6f45313302b9c56850fc17f99e40caebce98c716
@@ -37,7 +37,7 @@
 #get libnetwork packages
 
 # When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy accordingly
-github.com/docker/libnetwork a79d3687931697244b8e03485bf7b2042f8ec6b6
+github.com/docker/libnetwork 6da50d1978302f04c3e2089e29112ea24812f05b
 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
@@ -75,8 +75,8 @@
 google.golang.org/grpc v1.12.0
 
 # This does not need to match RUNC_COMMIT as it is used for helper packages but should be newer or equal
-github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd
-github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce # v1.0.1-43-gd810dbc
+github.com/opencontainers/runc 00dc70017d222b178a002ed30e9321b12647af2d
+github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
 github.com/opencontainers/image-spec v1.0.1
 github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
 
@@ -114,24 +114,24 @@
 google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9
 
 # containerd
-github.com/containerd/containerd v1.2.0-rc.0
+github.com/containerd/containerd 0c5f8f63c3368856c320ae8a1c125e703b73b51d # v1.2.0-rc.1
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
-github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537
+github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
 github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
+github.com/containerd/cri 9f39e3289533fc228c5e5fcac0a6dbdd60c6047b # release/1.2 branch
 github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3
 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
-github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
+github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
-github.com/containerd/cri 9f39e3289533fc228c5e5fcac0a6dbdd60c6047b # release/1.2 branch
 
 # cluster
-github.com/docker/swarmkit 3044c576a8a970d3079492b585054f29e96e27f1
+github.com/docker/swarmkit 6186e40fb04a7681e25a9101dbc7418c37ef0c8b # bump_v18.09 branch
 github.com/gogo/protobuf v1.0.0
 github.com/cloudflare/cfssl 1.3.2
 github.com/fernet/fernet-go 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2
 github.com/google/certificate-transparency-go v1.0.20
-golang.org/x/crypto a2144134853fc9a27a7b1e3eb4f19f1a76df13c9
+golang.org/x/crypto 0709b304e793a5edb4a2c0145f281ecdc20838a4
 golang.org/x/time fbb02b2291d28baffd63558aa44b4b56f178d650
 github.com/hashicorp/go-memdb cb9a474f84cc5e41b273b20c6927680b2a8776ad
 github.com/hashicorp/go-immutable-radix 826af9ccf0feeee615d546d69b11f8e98da8c8f1 git://github.com/tonistiigi/go-immutable-radix.git
@@ -144,8 +144,8 @@
 github.com/prometheus/common ebdfc6da46522d58825777cf1f90490a5b1ef1d8
 github.com/prometheus/procfs abf152e5f3e97f2fafac028d2cc06c1feb87ffa5
 github.com/matttproud/golang_protobuf_extensions v1.0.0
-github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9
-github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
+github.com/pkg/errors 645ef00459ed84a119197bfb8d8205042c6df63d # v0.8.0
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
 
 # cli
 github.com/spf13/cobra v0.0.3
@@ -156,7 +156,7 @@
 # metrics
 github.com/docker/go-metrics d466d4f6fd960e01820085bd7e1a24426ee7ef18
 
-github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd
+github.com/opencontainers/selinux b6fa367ed7f534f9ba25391cc2d467085dbb445a
 
 
 # archive/tar (for Go 1.10, see https://github.com/golang/go/issues/24787)
diff --git a/vendor/github.com/Microsoft/go-winio/ea.go b/vendor/github.com/Microsoft/go-winio/ea.go
index b37e930..4051c1b 100644
--- a/vendor/github.com/Microsoft/go-winio/ea.go
+++ b/vendor/github.com/Microsoft/go-winio/ea.go
@@ -1,137 +1,137 @@
-package winio

-

-import (

-	"bytes"

-	"encoding/binary"

-	"errors"

-)

-

-type fileFullEaInformation struct {

-	NextEntryOffset uint32

-	Flags           uint8

-	NameLength      uint8

-	ValueLength     uint16

-}

-

-var (

-	fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})

-

-	errInvalidEaBuffer = errors.New("invalid extended attribute buffer")

-	errEaNameTooLarge  = errors.New("extended attribute name too large")

-	errEaValueTooLarge = errors.New("extended attribute value too large")

-)

-

-// ExtendedAttribute represents a single Windows EA.

-type ExtendedAttribute struct {

-	Name  string

-	Value []byte

-	Flags uint8

-}

-

-func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {

-	var info fileFullEaInformation

-	err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)

-	if err != nil {

-		err = errInvalidEaBuffer

-		return

-	}

-

-	nameOffset := fileFullEaInformationSize

-	nameLen := int(info.NameLength)

-	valueOffset := nameOffset + int(info.NameLength) + 1

-	valueLen := int(info.ValueLength)

-	nextOffset := int(info.NextEntryOffset)

-	if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {

-		err = errInvalidEaBuffer

-		return

-	}

-

-	ea.Name = string(b[nameOffset : nameOffset+nameLen])

-	ea.Value = b[valueOffset : valueOffset+valueLen]

-	ea.Flags = info.Flags

-	if info.NextEntryOffset != 0 {

-		nb = b[info.NextEntryOffset:]

-	}

-	return

-}

-

-// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION

-// buffer retrieved from BackupRead, ZwQueryEaFile, etc.

-func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {

-	for len(b) != 0 {

-		ea, nb, err := parseEa(b)

-		if err != nil {

-			return nil, err

-		}

-

-		eas = append(eas, ea)

-		b = nb

-	}

-	return

-}

-

-func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {

-	if int(uint8(len(ea.Name))) != len(ea.Name) {

-		return errEaNameTooLarge

-	}

-	if int(uint16(len(ea.Value))) != len(ea.Value) {

-		return errEaValueTooLarge

-	}

-	entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))

-	withPadding := (entrySize + 3) &^ 3

-	nextOffset := uint32(0)

-	if !last {

-		nextOffset = withPadding

-	}

-	info := fileFullEaInformation{

-		NextEntryOffset: nextOffset,

-		Flags:           ea.Flags,

-		NameLength:      uint8(len(ea.Name)),

-		ValueLength:     uint16(len(ea.Value)),

-	}

-

-	err := binary.Write(buf, binary.LittleEndian, &info)

-	if err != nil {

-		return err

-	}

-

-	_, err = buf.Write([]byte(ea.Name))

-	if err != nil {

-		return err

-	}

-

-	err = buf.WriteByte(0)

-	if err != nil {

-		return err

-	}

-

-	_, err = buf.Write(ea.Value)

-	if err != nil {

-		return err

-	}

-

-	_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])

-	if err != nil {

-		return err

-	}

-

-	return nil

-}

-

-// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION

-// buffer for use with BackupWrite, ZwSetEaFile, etc.

-func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {

-	var buf bytes.Buffer

-	for i := range eas {

-		last := false

-		if i == len(eas)-1 {

-			last = true

-		}

-

-		err := writeEa(&buf, &eas[i], last)

-		if err != nil {

-			return nil, err

-		}

-	}

-	return buf.Bytes(), nil

-}

+package winio
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+)
+
+type fileFullEaInformation struct {
+	NextEntryOffset uint32
+	Flags           uint8
+	NameLength      uint8
+	ValueLength     uint16
+}
+
+var (
+	fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})
+
+	errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
+	errEaNameTooLarge  = errors.New("extended attribute name too large")
+	errEaValueTooLarge = errors.New("extended attribute value too large")
+)
+
+// ExtendedAttribute represents a single Windows EA.
+type ExtendedAttribute struct {
+	Name  string
+	Value []byte
+	Flags uint8
+}
+
+func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
+	var info fileFullEaInformation
+	err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
+	if err != nil {
+		err = errInvalidEaBuffer
+		return
+	}
+
+	nameOffset := fileFullEaInformationSize
+	nameLen := int(info.NameLength)
+	valueOffset := nameOffset + int(info.NameLength) + 1
+	valueLen := int(info.ValueLength)
+	nextOffset := int(info.NextEntryOffset)
+	if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
+		err = errInvalidEaBuffer
+		return
+	}
+
+	ea.Name = string(b[nameOffset : nameOffset+nameLen])
+	ea.Value = b[valueOffset : valueOffset+valueLen]
+	ea.Flags = info.Flags
+	if info.NextEntryOffset != 0 {
+		nb = b[info.NextEntryOffset:]
+	}
+	return
+}
+
+// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
+// buffer retrieved from BackupRead, ZwQueryEaFile, etc.
+func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
+	for len(b) != 0 {
+		ea, nb, err := parseEa(b)
+		if err != nil {
+			return nil, err
+		}
+
+		eas = append(eas, ea)
+		b = nb
+	}
+	return
+}
+
+func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
+	if int(uint8(len(ea.Name))) != len(ea.Name) {
+		return errEaNameTooLarge
+	}
+	if int(uint16(len(ea.Value))) != len(ea.Value) {
+		return errEaValueTooLarge
+	}
+	entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))
+	withPadding := (entrySize + 3) &^ 3
+	nextOffset := uint32(0)
+	if !last {
+		nextOffset = withPadding
+	}
+	info := fileFullEaInformation{
+		NextEntryOffset: nextOffset,
+		Flags:           ea.Flags,
+		NameLength:      uint8(len(ea.Name)),
+		ValueLength:     uint16(len(ea.Value)),
+	}
+
+	err := binary.Write(buf, binary.LittleEndian, &info)
+	if err != nil {
+		return err
+	}
+
+	_, err = buf.Write([]byte(ea.Name))
+	if err != nil {
+		return err
+	}
+
+	err = buf.WriteByte(0)
+	if err != nil {
+		return err
+	}
+
+	_, err = buf.Write(ea.Value)
+	if err != nil {
+		return err
+	}
+
+	_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION
+// buffer for use with BackupWrite, ZwSetEaFile, etc.
+func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {
+	var buf bytes.Buffer
+	for i := range eas {
+		last := false
+		if i == len(eas)-1 {
+			last = true
+		}
+
+		err := writeEa(&buf, &eas[i], last)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return buf.Bytes(), nil
+}
diff --git a/vendor/github.com/Microsoft/go-winio/vhd/vhd.go b/vendor/github.com/Microsoft/go-winio/vhd/vhd.go
index 32f0701..8fa90e9 100644
--- a/vendor/github.com/Microsoft/go-winio/vhd/vhd.go
+++ b/vendor/github.com/Microsoft/go-winio/vhd/vhd.go
@@ -1,82 +1,108 @@
-// +build windows

-

-package vhd

-

-import "syscall"

-

-//go:generate go run mksyscall_windows.go -output zvhd.go vhd.go

-

-//sys createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.CreateVirtualDisk

-

-type virtualStorageType struct {

-	DeviceID uint32

-	VendorID [16]byte

-}

-

-const virtualDiskAccessNONE uint32 = 0

-const virtualDiskAccessATTACHRO uint32 = 65536

-const virtualDiskAccessATTACHRW uint32 = 131072

-const virtualDiskAccessDETACH uint32 = 262144

-const virtualDiskAccessGETINFO uint32 = 524288

-const virtualDiskAccessCREATE uint32 = 1048576

-const virtualDiskAccessMETAOPS uint32 = 2097152

-const virtualDiskAccessREAD uint32 = 851968

-const virtualDiskAccessALL uint32 = 4128768

-const virtualDiskAccessWRITABLE uint32 = 3276800

-

-const createVirtualDiskFlagNone uint32 = 0

-const createVirtualDiskFlagFullPhysicalAllocation uint32 = 1

-const createVirtualDiskFlagPreventWritesToSourceDisk uint32 = 2

-const createVirtualDiskFlagDoNotCopyMetadataFromParent uint32 = 4

-

-type version2 struct {

-	UniqueID                 [16]byte // GUID

-	MaximumSize              uint64

-	BlockSizeInBytes         uint32

-	SectorSizeInBytes        uint32

-	ParentPath               *uint16 // string

-	SourcePath               *uint16 // string

-	OpenFlags                uint32

-	ParentVirtualStorageType virtualStorageType

-	SourceVirtualStorageType virtualStorageType

-	ResiliencyGUID           [16]byte // GUID

-}

-

-type createVirtualDiskParameters struct {

-	Version  uint32 // Must always be set to 2

-	Version2 version2

-}

-

-// CreateVhdx will create a simple vhdx file at the given path using default values.

-func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {

-	var defaultType virtualStorageType

-

-	parameters := createVirtualDiskParameters{

-		Version: 2,

-		Version2: version2{

-			MaximumSize:      uint64(maxSizeInGb) * 1024 * 1024 * 1024,

-			BlockSizeInBytes: blockSizeInMb * 1024 * 1024,

-		},

-	}

-

-	var handle syscall.Handle

-

-	if err := createVirtualDisk(

-		&defaultType,

-		path,

-		virtualDiskAccessNONE,

-		nil,

-		createVirtualDiskFlagNone,

-		0,

-		&parameters,

-		nil,

-		&handle); err != nil {

-		return err

-	}

-

-	if err := syscall.CloseHandle(handle); err != nil {

-		return err

-	}

-

-	return nil

-}

+// +build windows
+
+package vhd
+
+import "syscall"
+
+//go:generate go run mksyscall_windows.go -output zvhd.go vhd.go
+
+//sys createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.CreateVirtualDisk
+//sys openVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, flags uint32, parameters *uintptr, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.OpenVirtualDisk
+//sys detachVirtualDisk(handle syscall.Handle, flags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = VirtDisk.DetachVirtualDisk
+
+type virtualStorageType struct {
+	DeviceID uint32
+	VendorID [16]byte
+}
+
+const virtualDiskAccessNONE uint32 = 0
+const virtualDiskAccessATTACHRO uint32 = 65536
+const virtualDiskAccessATTACHRW uint32 = 131072
+const virtualDiskAccessDETACH uint32 = 262144
+const virtualDiskAccessGETINFO uint32 = 524288
+const virtualDiskAccessCREATE uint32 = 1048576
+const virtualDiskAccessMETAOPS uint32 = 2097152
+const virtualDiskAccessREAD uint32 = 851968
+const virtualDiskAccessALL uint32 = 4128768
+const virtualDiskAccessWRITABLE uint32 = 3276800
+
+const createVirtualDiskFlagNone uint32 = 0
+const createVirtualDiskFlagFullPhysicalAllocation uint32 = 1
+const createVirtualDiskFlagPreventWritesToSourceDisk uint32 = 2
+const createVirtualDiskFlagDoNotCopyMetadataFromParent uint32 = 4
+
+type version2 struct {
+	UniqueID                 [16]byte // GUID
+	MaximumSize              uint64
+	BlockSizeInBytes         uint32
+	SectorSizeInBytes        uint32
+	ParentPath               *uint16 // string
+	SourcePath               *uint16 // string
+	OpenFlags                uint32
+	ParentVirtualStorageType virtualStorageType
+	SourceVirtualStorageType virtualStorageType
+	ResiliencyGUID           [16]byte // GUID
+}
+
+type createVirtualDiskParameters struct {
+	Version  uint32 // Must always be set to 2
+	Version2 version2
+}
+
+// CreateVhdx will create a simple vhdx file at the given path using default values.
+func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
+	var defaultType virtualStorageType
+
+	parameters := createVirtualDiskParameters{
+		Version: 2,
+		Version2: version2{
+			MaximumSize:      uint64(maxSizeInGb) * 1024 * 1024 * 1024,
+			BlockSizeInBytes: blockSizeInMb * 1024 * 1024,
+		},
+	}
+
+	var handle syscall.Handle
+
+	if err := createVirtualDisk(
+		&defaultType,
+		path,
+		virtualDiskAccessNONE,
+		nil,
+		createVirtualDiskFlagNone,
+		0,
+		&parameters,
+		nil,
+		&handle); err != nil {
+		return err
+	}
+
+	if err := syscall.CloseHandle(handle); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// DetachVhd detaches a VHD attached at the given path.
+func DetachVhd(path string) error {
+	var (
+		defaultType virtualStorageType
+		handle      syscall.Handle
+	)
+
+	if err := openVirtualDisk(
+		&defaultType,
+		path,
+		virtualDiskAccessDETACH,
+		0,
+		nil,
+		&handle); err != nil {
+		return err
+	}
+	defer syscall.CloseHandle(handle)
+
+	if err := detachVirtualDisk(handle, 0, 0); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/vendor/github.com/Microsoft/go-winio/vhd/zvhd.go b/vendor/github.com/Microsoft/go-winio/vhd/zvhd.go
index c450955..73f5259 100644
--- a/vendor/github.com/Microsoft/go-winio/vhd/zvhd.go
+++ b/vendor/github.com/Microsoft/go-winio/vhd/zvhd.go
@@ -40,6 +40,8 @@
 	modVirtDisk = windows.NewLazySystemDLL("VirtDisk.dll")
 
 	procCreateVirtualDisk = modVirtDisk.NewProc("CreateVirtualDisk")
+	procOpenVirtualDisk   = modVirtDisk.NewProc("OpenVirtualDisk")
+	procDetachVirtualDisk = modVirtDisk.NewProc("DetachVirtualDisk")
 )
 
 func createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) {
@@ -62,3 +64,36 @@
 	}
 	return
 }
+
+func openVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, flags uint32, parameters *uintptr, handle *syscall.Handle) (err error) {
+	var _p0 *uint16
+	_p0, err = syscall.UTF16PtrFromString(path)
+	if err != nil {
+		return
+	}
+	return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, flags, parameters, handle)
+}
+
+func _openVirtualDisk(virtualStorageType *virtualStorageType, path *uint16, virtualDiskAccessMask uint32, flags uint32, parameters *uintptr, handle *syscall.Handle) (err error) {
+	r1, _, e1 := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(flags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle)))
+	if r1 != 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func detachVirtualDisk(handle syscall.Handle, flags uint32, providerSpecificFlags uint32) (err error) {
+	r1, _, e1 := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(flags), uintptr(providerSpecificFlags))
+	if r1 != 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go b/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
index 5f0dcfe..f2eedbe 100644
--- a/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
+++ b/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
@@ -6,6 +6,8 @@
 
 // HNSEndpoint represents a network endpoint in HNS
 type HNSEndpoint = hns.HNSEndpoint
+// Namespace represents a Compartment.
+type Namespace = hns.Namespace
 
 //SystemType represents the type of the system on which actions are done
 type SystemType string
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go b/vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go
index c37dec8..e9e45c0 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go
@@ -2,10 +2,16 @@
 
 import (
 	"crypto/rand"
+	"encoding/json"
 	"fmt"
 	"io"
+	"strconv"
+	"strings"
 )
 
+var _ = (json.Marshaler)(&GUID{})
+var _ = (json.Unmarshaler)(&GUID{})
+
 type GUID [16]byte
 
 func New() GUID {
@@ -20,3 +26,44 @@
 func (g GUID) String() string {
 	return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:])
 }
+
+func FromString(s string) GUID {
+	if len(s) != 36 {
+		panic(fmt.Sprintf("invalid GUID length: %d", len(s)))
+	}
+	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
+		panic("invalid GUID format")
+	}
+	indexOrder := [16]int{
+		0, 2, 4, 6,
+		9, 11,
+		14, 16,
+		19, 21,
+		24, 26, 28, 30, 32, 34,
+	}
+	byteOrder := [16]int{
+		3, 2, 1, 0,
+		5, 4,
+		7, 6,
+		8, 9,
+		10, 11, 12, 13, 14, 15,
+	}
+	var g GUID
+	for i, x := range indexOrder {
+		b, err := strconv.ParseInt(s[x:x+2], 16, 16)
+		if err != nil {
+			panic(err)
+		}
+		g[byteOrder[i]] = byte(b)
+	}
+	return g
+}
+
+func (g GUID) MarshalJSON() ([]byte, error) {
+	return json.Marshal(g.String())
+}
+
+func (g *GUID) UnmarshalJSON(data []byte) error {
+	*g = FromString(strings.Trim(string(data), "\""))
+	return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
index 0de4a70..8294d66 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
@@ -2,6 +2,7 @@
 
 import (
 	"encoding/json"
+	"fmt"
 	"io"
 	"sync"
 	"syscall"
@@ -83,7 +84,10 @@
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("TerminateProcess %s: %d", process.SystemID(), process.Pid()), &completed)
 	err := hcsTerminateProcess(process.handle, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return makeProcessError(process, operation, err, events)
@@ -177,7 +181,10 @@
 		resultp     *uint16
 		propertiesp *uint16
 	)
+	completed := false
+	go syscallWatcher(fmt.Sprintf("GetProcessProperties %s: %d", process.SystemID(), process.Pid()), &completed)
 	err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, makeProcessError(process, operation, err, events)
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
index 41ff287..57afd5e 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
@@ -2,6 +2,7 @@
 
 import (
 	"encoding/json"
+	"fmt"
 	"os"
 	"strconv"
 	"sync"
@@ -63,7 +64,10 @@
 		resultp  *uint16
 		identity syscall.Handle
 	)
+	completed := false
+	go syscallWatcher(fmt.Sprintf("CreateCompleteSystem %s: %s", id, hcsDocument), &completed)
 	createError := hcsCreateComputeSystem(id, hcsDocument, identity, &computeSystem.handle, &resultp)
+	completed = true
 
 	if createError == nil || IsPending(createError) {
 		if err := computeSystem.registerCallback(); err != nil {
@@ -74,7 +78,7 @@
 		}
 	}
 
-	events, err := processAsyncHcsResult(createError, resultp, computeSystem.callbackNumber, hcsNotificationSystemCreateCompleted, &timeout.Duration)
+	events, err := processAsyncHcsResult(createError, resultp, computeSystem.callbackNumber, hcsNotificationSystemCreateCompleted, &timeout.SystemCreate)
 	if err != nil {
 		if err == ErrTimeout {
 			// Terminate the compute system if it still exists. We're okay to
@@ -135,7 +139,10 @@
 		resultp         *uint16
 		computeSystemsp *uint16
 	)
+	completed := false
+	go syscallWatcher(fmt.Sprintf("GetComputeSystems %s:", query), &completed)
 	err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, &HcsError{Op: operation, Err: err, Events: events}
@@ -192,8 +199,11 @@
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("StartComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsStartComputeSystem(computeSystem.handle, "", &resultp)
-	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.Duration)
+	completed = true
+	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.SystemStart)
 	if err != nil {
 		return makeSystemError(computeSystem, "Start", "", err, events)
 	}
@@ -219,7 +229,10 @@
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("ShutdownComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsShutdownComputeSystem(computeSystem.handle, "", &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return makeSystemError(computeSystem, "Shutdown", "", err, events)
@@ -242,7 +255,10 @@
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("TerminateComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsTerminateComputeSystem(computeSystem.handle, "", &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return makeSystemError(computeSystem, "Terminate", "", err, events)
@@ -291,7 +307,10 @@
 	}
 
 	var resultp, propertiesp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("GetComputeSystemProperties %s:", computeSystem.ID()), &completed)
 	err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, makeSystemError(computeSystem, "Properties", "", err, events)
@@ -320,8 +339,11 @@
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("PauseComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsPauseComputeSystem(computeSystem.handle, "", &resultp)
-	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.Duration)
+	completed = true
+	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.SystemPause)
 	if err != nil {
 		return makeSystemError(computeSystem, "Pause", "", err, events)
 	}
@@ -342,8 +364,11 @@
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("ResumeComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsResumeComputeSystem(computeSystem.handle, "", &resultp)
-	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.Duration)
+	completed = true
+	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.SystemResume)
 	if err != nil {
 		return makeSystemError(computeSystem, "Resume", "", err, events)
 	}
@@ -375,7 +400,10 @@
 	configuration := string(configurationb)
 	logrus.Debugf(title+" config=%s", configuration)
 
+	completed := false
+	go syscallWatcher(fmt.Sprintf("CreateProcess %s: %s", computeSystem.ID(), configuration), &completed)
 	err = hcsCreateProcess(computeSystem.handle, configuration, &processInfo, &processHandle, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, makeSystemError(computeSystem, "CreateProcess", configuration, err, events)
@@ -415,7 +443,10 @@
 		return nil, makeSystemError(computeSystem, "OpenProcess", "", ErrAlreadyClosed, nil)
 	}
 
+	completed := false
+	go syscallWatcher(fmt.Sprintf("OpenProcess %s: %d", computeSystem.ID(), pid), &completed)
 	err := hcsOpenProcess(computeSystem.handle, uint32(pid), &processHandle, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, makeSystemError(computeSystem, "OpenProcess", "", err, events)
@@ -451,7 +482,11 @@
 		return makeSystemError(computeSystem, "Close", "", err, nil)
 	}
 
-	if err := hcsCloseComputeSystem(computeSystem.handle); err != nil {
+	completed := false
+	go syscallWatcher(fmt.Sprintf("CloseComputeSystem %s:", computeSystem.ID()), &completed)
+	err := hcsCloseComputeSystem(computeSystem.handle)
+	completed = true
+	if err != nil {
 		return makeSystemError(computeSystem, "Close", "", err, nil)
 	}
 
@@ -537,7 +572,10 @@
 	logrus.Debugf(title + " " + requestString)
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("ModifyComputeSystem %s: %s", computeSystem.ID(), requestString), &completed)
 	err = hcsModifyComputeSystem(computeSystem.handle, requestString, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return makeSystemError(computeSystem, "Modify", requestString, err, events)
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go
new file mode 100644
index 0000000..6b94bc9
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go
@@ -0,0 +1,30 @@
+package hcs
+
+import (
+	"time"
+
+	"github.com/Microsoft/hcsshim/internal/timeout"
+	"github.com/sirupsen/logrus"
+)
+
+// syscallWatcher is used as a very simple goroutine around calls into
+// the platform. In some cases, we have seen HCS APIs not returning due to
+// various bugs, and the goroutine making the syscall ends up not returning,
+// prior to its async callback. By spinning up a syscallWatcher, it allows
+// us to at least log a warning if a syscall doesn't complete in a reasonable
+// amount of time.
+//
+// Usage is:
+//
+// completed := false
+// go syscallWatcher("some description", &completed)
+// <syscall>
+// completed = true
+//
+func syscallWatcher(description string, syscallCompleted *bool) {
+	time.Sleep(timeout.SyscallWatcher)
+	if *syscallCompleted {
+		return
+	}
+	logrus.Warnf("%s: Did not complete within %s. This may indicate a platform issue. If it appears to be making no forward progress, obtain the stacks and see is there is a syscall stuck in the platform API for a significant length of time.", description, timeout.SyscallWatcher)
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go
index 32f4e07..2f5bf8f 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go
@@ -1,4 +1,4 @@
-// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
+// Code generated by 'go generate'; DO NOT EDIT.
 
 package interop
 
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go
index 776adbe..709b9d3 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go
@@ -1,4 +1,4 @@
-// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
+// Code generated by 'go generate'; DO NOT EDIT.
 
 package safefile
 
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go b/vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go
index e4253f4..ff3b657 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go
@@ -6,21 +6,65 @@
 	"time"
 )
 
-// Duration is the default time to wait for various operations.
-// - Waiting for async notifications from HCS
-// - Waiting for processes to launch through
-// - Waiting to copy data to/from a launched processes stdio pipes.
-//
-// This can be overridden through environment variable `HCS_TIMEOUT_SECONDS`
+var (
+	// defaultTimeout is the timeout for most operations that is not overridden.
+	defaultTimeout = 4 * time.Minute
 
-var Duration = 4 * time.Minute
+	// defaultTimeoutTestdRetry is the retry loop timeout for testd to respond
+	// for a disk to come online in LCOW.
+	defaultTimeoutTestdRetry = 5 * time.Second
+)
+
+// External variables for HCSShim consumers to use.
+var (
+	// SystemCreate is the timeout for creating a compute system
+	SystemCreate time.Duration = defaultTimeout
+
+	// SystemStart is the timeout for starting a compute system
+	SystemStart time.Duration = defaultTimeout
+
+	// SystemPause is the timeout for pausing a compute system
+	SystemPause time.Duration = defaultTimeout
+
+	// SystemResume is the timeout for resuming a compute system
+	SystemResume time.Duration = defaultTimeout
+
+	// SyscallWatcher is the timeout before warning of a potential stuck platform syscall.
+	SyscallWatcher time.Duration = defaultTimeout
+
+	// Tar2VHD is the timeout for the tar2vhd operation to complete
+	Tar2VHD time.Duration = defaultTimeout
+
+	// ExternalCommandToStart is the timeout for external commands to start
+	ExternalCommandToStart = defaultTimeout
+
+	// ExternalCommandToComplete is the timeout for external commands to complete.
+	// Generally this means copying data from their stdio pipes.
+	ExternalCommandToComplete = defaultTimeout
+
+	// TestDRetryLoop is the timeout for testd retry loop when onlining a SCSI disk in LCOW
+	TestDRetryLoop = defaultTimeoutTestdRetry
+)
 
 func init() {
-	envTimeout := os.Getenv("HCSSHIM_TIMEOUT_SECONDS")
+	SystemCreate = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMCREATE", SystemCreate)
+	SystemStart = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMSTART", SystemStart)
+	SystemPause = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMPAUSE", SystemPause)
+	SystemResume = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMRESUME", SystemResume)
+	SyscallWatcher = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSCALLWATCHER", SyscallWatcher)
+	Tar2VHD = durationFromEnvironment("HCSSHIM_TIMEOUT_TAR2VHD", Tar2VHD)
+	ExternalCommandToStart = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDSTART", ExternalCommandToStart)
+	ExternalCommandToComplete = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDCOMPLETE", ExternalCommandToComplete)
+	TestDRetryLoop = durationFromEnvironment("HCSSHIM_TIMEOUT_TESTDRETRYLOOP", TestDRetryLoop)
+}
+
+func durationFromEnvironment(env string, defaultValue time.Duration) time.Duration {
+	envTimeout := os.Getenv(env)
 	if len(envTimeout) > 0 {
 		e, err := strconv.Atoi(envTimeout)
 		if err == nil && e > 0 {
-			Duration = time.Second * time.Duration(e)
+			return time.Second * time.Duration(e)
 		}
 	}
+	return defaultValue
 }
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go
index a381784..d158177 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go
@@ -9,15 +9,15 @@
 // the parent layer provided.
 func CreateLayer(path, parent string) error {
 	title := "hcsshim::CreateLayer "
-	logrus.Debugf(title+"Flavour %d ID %s parent %s", path, parent)
+	logrus.Debugf(title+"ID %s parent %s", path, parent)
 
 	err := createLayer(&stdDriverInfo, path, parent)
 	if err != nil {
-		err = hcserror.Errorf(err, title, "path=%s parent=%s flavour=%d", path, parent)
+		err = hcserror.Errorf(err, title, "path=%s parent=%s", path, parent)
 		logrus.Error(err)
 		return err
 	}
 
-	logrus.Debugf(title+" - succeeded path=%s parent=%s flavour=%d", path, parent)
+	logrus.Debugf(title+"- succeeded path=%s parent=%s", path, parent)
 	return nil
 }
diff --git a/vendor/github.com/containerd/containerd/archive/compression/compression.go b/vendor/github.com/containerd/containerd/archive/compression/compression.go
index bd64e03..60c80e9 100644
--- a/vendor/github.com/containerd/containerd/archive/compression/compression.go
+++ b/vendor/github.com/containerd/containerd/archive/compression/compression.go
@@ -92,6 +92,36 @@
 	return nil
 }
 
+type bufferedReader struct {
+	buf *bufio.Reader
+}
+
+func newBufferedReader(r io.Reader) *bufferedReader {
+	buf := bufioReader32KPool.Get().(*bufio.Reader)
+	buf.Reset(r)
+	return &bufferedReader{buf}
+}
+
+func (r *bufferedReader) Read(p []byte) (n int, err error) {
+	if r.buf == nil {
+		return 0, io.EOF
+	}
+	n, err = r.buf.Read(p)
+	if err == io.EOF {
+		r.buf.Reset(nil)
+		bufioReader32KPool.Put(r.buf)
+		r.buf = nil
+	}
+	return
+}
+
+func (r *bufferedReader) Peek(n int) ([]byte, error) {
+	if r.buf == nil {
+		return nil, io.EOF
+	}
+	return r.buf.Peek(n)
+}
+
 // DetectCompression detects the compression algorithm of the source.
 func DetectCompression(source []byte) Compression {
 	for compression, m := range map[Compression][]byte{
@@ -110,8 +140,7 @@
 
 // DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive.
 func DecompressStream(archive io.Reader) (DecompressReadCloser, error) {
-	buf := bufioReader32KPool.Get().(*bufio.Reader)
-	buf.Reset(archive)
+	buf := newBufferedReader(archive)
 	bs, err := buf.Peek(10)
 	if err != nil && err != io.EOF {
 		// Note: we'll ignore any io.EOF error because there are some odd
@@ -123,15 +152,12 @@
 		return nil, err
 	}
 
-	closer := func() error {
-		buf.Reset(nil)
-		bufioReader32KPool.Put(buf)
-		return nil
-	}
 	switch compression := DetectCompression(bs); compression {
 	case Uncompressed:
-		readBufWrapper := &readCloserWrapper{buf, compression, closer}
-		return readBufWrapper, nil
+		return &readCloserWrapper{
+			Reader:      buf,
+			compression: compression,
+		}, nil
 	case Gzip:
 		ctx, cancel := context.WithCancel(context.Background())
 		gzReader, err := gzipDecompress(ctx, buf)
@@ -140,12 +166,15 @@
 			return nil, err
 		}
 
-		readBufWrapper := &readCloserWrapper{gzReader, compression, func() error {
-			cancel()
-			return closer()
-		}}
+		return &readCloserWrapper{
+			Reader:      gzReader,
+			compression: compression,
+			closer: func() error {
+				cancel()
+				return gzReader.Close()
+			},
+		}, nil
 
-		return readBufWrapper, nil
 	default:
 		return nil, fmt.Errorf("unsupported compression format %s", (&compression).Extension())
 	}
diff --git a/vendor/github.com/containerd/containerd/container_opts.go b/vendor/github.com/containerd/containerd/container_opts.go
index 580715f..ca4bf67 100644
--- a/vendor/github.com/containerd/containerd/container_opts.go
+++ b/vendor/github.com/containerd/containerd/container_opts.go
@@ -76,6 +76,23 @@
 	}
 }
 
+// WithImageStopSignal sets a well-known containerd label (StopSignalLabel)
+// on the container for storing the stop signal specified in the OCI image
+// config
+func WithImageStopSignal(image Image, defaultSignal string) NewContainerOpts {
+	return func(ctx context.Context, _ *Client, c *containers.Container) error {
+		if c.Labels == nil {
+			c.Labels = make(map[string]string)
+		}
+		stopSignal, err := GetOCIStopSignal(ctx, image, defaultSignal)
+		if err != nil {
+			return err
+		}
+		c.Labels[StopSignalLabel] = stopSignal
+		return nil
+	}
+}
+
 // WithSnapshotter sets the provided snapshotter for use by the container
 //
 // This option must appear before other snapshotter options to have an effect.
diff --git a/vendor/github.com/containerd/containerd/containers/containers.go b/vendor/github.com/containerd/containerd/containers/containers.go
index e6a5627..a658b57 100644
--- a/vendor/github.com/containerd/containerd/containers/containers.go
+++ b/vendor/github.com/containerd/containerd/containers/containers.go
@@ -28,12 +28,12 @@
 //
 // The resources specified in this object are used to create tasks from the container.
 type Container struct {
-	// ID uniquely identifies the container in a nameapace.
+	// ID uniquely identifies the container in a namespace.
 	//
 	// This property is required and cannot be changed after creation.
 	ID string
 
-	// Labels provide metadata extension for a contaienr.
+	// Labels provide metadata extension for a container.
 	//
 	// These are optional and fully mutable.
 	Labels map[string]string
diff --git a/vendor/github.com/containerd/containerd/image.go b/vendor/github.com/containerd/containerd/image.go
index f12cd59..62fba9d 100644
--- a/vendor/github.com/containerd/containerd/image.go
+++ b/vendor/github.com/containerd/containerd/image.go
@@ -37,6 +37,8 @@
 	Name() string
 	// Target descriptor for the image content
 	Target() ocispec.Descriptor
+	// Labels of the image
+	Labels() map[string]string
 	// Unpack unpacks the image's content into a snapshot
 	Unpack(context.Context, string) error
 	// RootFS returns the unpacked diffids that make up images rootfs.
@@ -86,6 +88,10 @@
 	return i.i.Target
 }
 
+func (i *image) Labels() map[string]string {
+	return i.i.Labels
+}
+
 func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) {
 	provider := i.client.ContentStore()
 	return i.i.RootFS(ctx, provider, i.platform)
diff --git a/vendor/github.com/containerd/containerd/images/archive/importer.go b/vendor/github.com/containerd/containerd/images/archive/importer.go
index 59514c6..c1522df 100644
--- a/vendor/github.com/containerd/containerd/images/archive/importer.go
+++ b/vendor/github.com/containerd/containerd/images/archive/importer.go
@@ -115,6 +115,10 @@
 		return idx, nil
 	}
 
+	if mfsts == nil {
+		return ocispec.Descriptor{}, errors.Errorf("unrecognized image format")
+	}
+
 	for name, linkname := range symlinks {
 		desc, ok := blobs[linkname]
 		if !ok {
@@ -123,7 +127,11 @@
 		blobs[name] = desc
 	}
 
-	var idx ocispec.Index
+	idx := ocispec.Index{
+		Versioned: specs.Versioned{
+			SchemaVersion: 2,
+		},
+	}
 	for _, mfst := range mfsts {
 		config, ok := blobs[mfst.Config]
 		if !ok {
diff --git a/vendor/github.com/containerd/containerd/images/image.go b/vendor/github.com/containerd/containerd/images/image.go
index 4d6979d..f72684d 100644
--- a/vendor/github.com/containerd/containerd/images/image.go
+++ b/vendor/github.com/containerd/containerd/images/image.go
@@ -129,6 +129,13 @@
 
 // Manifest resolves a manifest from the image for the given platform.
 //
+// When a manifest descriptor inside of a manifest index does not have
+// a platform defined, the platform from the image config is considered.
+//
+// If the descriptor points to a non-index manifest, then the manifest is
+// unmarshalled and returned without considering the platform inside of the
+// config.
+//
 // TODO(stevvooe): This violates the current platform agnostic approach to this
 // package by returning a specific manifest type. We'll need to refactor this
 // to return a manifest descriptor or decide that we want to bring the API in
@@ -152,7 +159,7 @@
 				return nil, err
 			}
 
-			if platform != nil {
+			if desc.Digest != image.Digest && platform != nil {
 				if desc.Platform != nil && !platform.Match(*desc.Platform) {
 					return nil, nil
 				}
diff --git a/vendor/github.com/containerd/containerd/metadata/content.go b/vendor/github.com/containerd/containerd/metadata/content.go
index ac44400..f51b0aa 100644
--- a/vendor/github.com/containerd/containerd/metadata/content.go
+++ b/vendor/github.com/containerd/containerd/metadata/content.go
@@ -553,7 +553,9 @@
 	nw.l.RLock()
 	defer nw.l.RUnlock()
 
-	return update(ctx, nw.db, func(tx *bolt.Tx) error {
+	var innerErr error
+
+	if err := update(ctx, nw.db, func(tx *bolt.Tx) error {
 		bkt := getIngestsBucket(tx, nw.namespace)
 		if bkt != nil {
 			if err := bkt.DeleteBucket([]byte(nw.ref)); err != nil && err != bolt.ErrBucketNotFound {
@@ -562,13 +564,20 @@
 		}
 		dgst, err := nw.commit(ctx, tx, size, expected, opts...)
 		if err != nil {
-			return err
+			if !errdefs.IsAlreadyExists(err) {
+				return err
+			}
+			innerErr = err
 		}
 		if err := removeIngestLease(ctx, tx, nw.ref); err != nil {
 			return err
 		}
 		return addContentLease(ctx, tx, dgst)
-	})
+	}); err != nil {
+		return err
+	}
+
+	return innerErr
 }
 
 func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, expected digest.Digest, opts ...content.Opt) (digest.Digest, error) {
@@ -611,7 +620,7 @@
 	bkt, err := createBlobBucket(tx, nw.namespace, actual)
 	if err != nil {
 		if err == bolt.ErrBucketExists {
-			return "", errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual)
+			return actual, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual)
 		}
 		return "", err
 	}
diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts.go b/vendor/github.com/containerd/containerd/oci/spec_opts.go
index a1694cb..8b599f8 100644
--- a/vendor/github.com/containerd/containerd/oci/spec_opts.go
+++ b/vendor/github.com/containerd/containerd/oci/spec_opts.go
@@ -654,6 +654,10 @@
 // The passed in user can be either a uid or a username.
 func WithAdditionalGIDs(userstr string) SpecOpts {
 	return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) {
+		// For LCOW additional GID's not supported
+		if s.Windows != nil {
+			return nil
+		}
 		setProcess(s)
 		setAdditionalGids := func(root string) error {
 			var username string
@@ -1011,3 +1015,14 @@
 	WithApparmorProfile(""),
 	WithSeccompUnconfined,
 )
+
+// WithWindowsHyperV sets the Windows.HyperV section for HyperV isolation of containers.
+func WithWindowsHyperV(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
+	if s.Windows == nil {
+		s.Windows = &specs.Windows{}
+	}
+	if s.Windows.HyperV == nil {
+		s.Windows.HyperV = &specs.WindowsHyperV{}
+	}
+	return nil
+}
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go b/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
new file mode 100644
index 0000000..bb691f1
--- /dev/null
+++ b/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
@@ -0,0 +1,317 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package docker
+
+import (
+	"context"
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/log"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+	"golang.org/x/net/context/ctxhttp"
+)
+
+type dockerAuthorizer struct {
+	credentials func(string) (string, string, error)
+
+	client *http.Client
+	mu     sync.Mutex
+
+	auth map[string]string
+}
+
+// NewAuthorizer creates a Docker authorizer using the provided function to
+// get credentials for the token server or basic auth.
+func NewAuthorizer(client *http.Client, f func(string) (string, string, error)) Authorizer {
+	if client == nil {
+		client = http.DefaultClient
+	}
+	return &dockerAuthorizer{
+		credentials: f,
+		client:      client,
+		auth:        map[string]string{},
+	}
+}
+
+func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
+	// TODO: Lookup matching challenge and scope rather than just host
+	if auth := a.getAuth(req.URL.Host); auth != "" {
+		req.Header.Set("Authorization", auth)
+	}
+
+	return nil
+}
+
+func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.Response) error {
+	last := responses[len(responses)-1]
+	host := last.Request.URL.Host
+	for _, c := range parseAuthHeader(last.Header) {
+		if c.scheme == bearerAuth {
+			if err := invalidAuthorization(c, responses); err != nil {
+				// TODO: Clear token
+				a.setAuth(host, "")
+				return err
+			}
+
+			// TODO(dmcg): Store challenge, not token
+			// Move token fetching to authorize
+			if err := a.setTokenAuth(ctx, host, c.parameters); err != nil {
+				return err
+			}
+
+			return nil
+		} else if c.scheme == basicAuth {
+			// TODO: Resolve credentials on authorize
+			username, secret, err := a.credentials(host)
+			if err != nil {
+				return err
+			}
+			if username != "" && secret != "" {
+				auth := username + ":" + secret
+				a.setAuth(host, fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(auth))))
+				return nil
+			}
+		}
+	}
+
+	return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
+}
+
+func (a *dockerAuthorizer) getAuth(host string) string {
+	a.mu.Lock()
+	defer a.mu.Unlock()
+
+	return a.auth[host]
+}
+
+func (a *dockerAuthorizer) setAuth(host string, auth string) bool {
+	a.mu.Lock()
+	defer a.mu.Unlock()
+
+	changed := a.auth[host] != auth
+	a.auth[host] = auth
+
+	return changed
+}
+
+func (a *dockerAuthorizer) setTokenAuth(ctx context.Context, host string, params map[string]string) error {
+	realm, ok := params["realm"]
+	if !ok {
+		return errors.New("no realm specified for token auth challenge")
+	}
+
+	realmURL, err := url.Parse(realm)
+	if err != nil {
+		return errors.Wrap(err, "invalid token auth challenge realm")
+	}
+
+	to := tokenOptions{
+		realm:   realmURL.String(),
+		service: params["service"],
+	}
+
+	to.scopes = getTokenScopes(ctx, params)
+	if len(to.scopes) == 0 {
+		return errors.Errorf("no scope specified for token auth challenge")
+	}
+
+	if a.credentials != nil {
+		to.username, to.secret, err = a.credentials(host)
+		if err != nil {
+			return err
+		}
+	}
+
+	var token string
+	if to.secret != "" {
+		// Credential information is provided, use oauth POST endpoint
+		token, err = a.fetchTokenWithOAuth(ctx, to)
+		if err != nil {
+			return errors.Wrap(err, "failed to fetch oauth token")
+		}
+	} else {
+		// Do request anonymously
+		token, err = a.fetchToken(ctx, to)
+		if err != nil {
+			return errors.Wrap(err, "failed to fetch anonymous token")
+		}
+	}
+	a.setAuth(host, fmt.Sprintf("Bearer %s", token))
+
+	return nil
+}
+
+type tokenOptions struct {
+	realm    string
+	service  string
+	scopes   []string
+	username string
+	secret   string
+}
+
+type postTokenResponse struct {
+	AccessToken  string    `json:"access_token"`
+	RefreshToken string    `json:"refresh_token"`
+	ExpiresIn    int       `json:"expires_in"`
+	IssuedAt     time.Time `json:"issued_at"`
+	Scope        string    `json:"scope"`
+}
+
+func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
+	form := url.Values{}
+	form.Set("scope", strings.Join(to.scopes, " "))
+	form.Set("service", to.service)
+	// TODO: Allow setting client_id
+	form.Set("client_id", "containerd-client")
+
+	if to.username == "" {
+		form.Set("grant_type", "refresh_token")
+		form.Set("refresh_token", to.secret)
+	} else {
+		form.Set("grant_type", "password")
+		form.Set("username", to.username)
+		form.Set("password", to.secret)
+	}
+
+	resp, err := ctxhttp.PostForm(ctx, a.client, to.realm, form)
+	if err != nil {
+		return "", err
+	}
+	defer resp.Body.Close()
+
+	// Registries without support for POST may return 404 for POST /v2/token.
+	// As of September 2017, GCR is known to return 404.
+	// As of February 2018, JFrog Artifactory is known to return 401.
+	if (resp.StatusCode == 405 && to.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
+		return a.fetchToken(ctx, to)
+	} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
+		b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
+		log.G(ctx).WithFields(logrus.Fields{
+			"status": resp.Status,
+			"body":   string(b),
+		}).Debugf("token request failed")
+		// TODO: handle error body and write debug output
+		return "", errors.Errorf("unexpected status: %s", resp.Status)
+	}
+
+	decoder := json.NewDecoder(resp.Body)
+
+	var tr postTokenResponse
+	if err = decoder.Decode(&tr); err != nil {
+		return "", fmt.Errorf("unable to decode token response: %s", err)
+	}
+
+	return tr.AccessToken, nil
+}
+
+type getTokenResponse struct {
+	Token        string    `json:"token"`
+	AccessToken  string    `json:"access_token"`
+	ExpiresIn    int       `json:"expires_in"`
+	IssuedAt     time.Time `json:"issued_at"`
+	RefreshToken string    `json:"refresh_token"`
+}
+
+// getToken fetches a token using a GET request
+func (a *dockerAuthorizer) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
+	req, err := http.NewRequest("GET", to.realm, nil)
+	if err != nil {
+		return "", err
+	}
+
+	reqParams := req.URL.Query()
+
+	if to.service != "" {
+		reqParams.Add("service", to.service)
+	}
+
+	for _, scope := range to.scopes {
+		reqParams.Add("scope", scope)
+	}
+
+	if to.secret != "" {
+		req.SetBasicAuth(to.username, to.secret)
+	}
+
+	req.URL.RawQuery = reqParams.Encode()
+
+	resp, err := ctxhttp.Do(ctx, a.client, req)
+	if err != nil {
+		return "", err
+	}
+	defer resp.Body.Close()
+
+	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
+		// TODO: handle error body and write debug output
+		return "", errors.Errorf("unexpected status: %s", resp.Status)
+	}
+
+	decoder := json.NewDecoder(resp.Body)
+
+	var tr getTokenResponse
+	if err = decoder.Decode(&tr); err != nil {
+		return "", fmt.Errorf("unable to decode token response: %s", err)
+	}
+
+	// `access_token` is equivalent to `token` and if both are specified
+	// the choice is undefined.  Canonicalize `access_token` by sticking
+	// things in `token`.
+	if tr.AccessToken != "" {
+		tr.Token = tr.AccessToken
+	}
+
+	if tr.Token == "" {
+		return "", ErrNoToken
+	}
+
+	return tr.Token, nil
+}
+
+func invalidAuthorization(c challenge, responses []*http.Response) error {
+	errStr := c.parameters["error"]
+	if errStr == "" {
+		return nil
+	}
+
+	n := len(responses)
+	if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
+		return nil
+	}
+
+	return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr)
+}
+
+func sameRequest(r1, r2 *http.Request) bool {
+	if r1.Method != r2.Method {
+		return false
+	}
+	if *r1.URL != *r2.URL {
+		return false
+	}
+	return true
+}
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go
index f0a677c..5cccdec 100644
--- a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go
+++ b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go
@@ -18,18 +18,13 @@
 
 import (
 	"context"
-	"encoding/json"
-	"fmt"
-	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"path"
 	"strconv"
 	"strings"
-	"sync"
-	"time"
 
+	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/images"
 	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/reference"
@@ -51,19 +46,37 @@
 	ErrInvalidAuthorization = errors.New("authorization failed")
 )
 
-type dockerResolver struct {
-	credentials func(string) (string, string, error)
-	host        func(string) (string, error)
-	plainHTTP   bool
-	client      *http.Client
-	tracker     StatusTracker
+// Authorizer is used to authorize HTTP requests based on 401 HTTP responses.
+// An Authorizer is responsible for caching tokens or credentials used by
+// requests.
+type Authorizer interface {
+	// Authorize sets the appropriate `Authorization` header on the given
+	// request.
+	//
+	// If no authorization is found for the request, the request remains
+	// unmodified. It may also add an `Authorization` header as
+	//  "bearer <some bearer token>"
+	//  "basic <base64 encoded credentials>"
+	Authorize(context.Context, *http.Request) error
+
+	// AddResponses adds a 401 response for the authorizer to consider when
+	// authorizing requests. The last response should be unauthorized and
+	// the previous requests are used to consider redirects and retries
+	// that may have led to the 401.
+	//
+	// If response is not handled, returns `ErrNotImplemented`
+	AddResponses(context.Context, []*http.Response) error
 }
 
 // ResolverOptions are used to configured a new Docker register resolver
 type ResolverOptions struct {
+	// Authorizer is used to authorize registry requests
+	Authorizer Authorizer
+
 	// Credentials provides username and secret given a host.
 	// If username is empty but a secret is given, that secret
 	// is interpretted as a long lived token.
+	// Deprecated: use Authorizer
 	Credentials func(string) (string, string, error)
 
 	// Host provides the hostname given a namespace.
@@ -89,22 +102,31 @@
 	return ns, nil
 }
 
+type dockerResolver struct {
+	auth      Authorizer
+	host      func(string) (string, error)
+	plainHTTP bool
+	client    *http.Client
+	tracker   StatusTracker
+}
+
 // NewResolver returns a new resolver to a Docker registry
 func NewResolver(options ResolverOptions) remotes.Resolver {
-	tracker := options.Tracker
-	if tracker == nil {
-		tracker = NewInMemoryTracker()
+	if options.Tracker == nil {
+		options.Tracker = NewInMemoryTracker()
 	}
-	host := options.Host
-	if host == nil {
-		host = DefaultHost
+	if options.Host == nil {
+		options.Host = DefaultHost
+	}
+	if options.Authorizer == nil {
+		options.Authorizer = NewAuthorizer(options.Client, options.Credentials)
 	}
 	return &dockerResolver{
-		credentials: options.Credentials,
-		host:        host,
-		plainHTTP:   options.PlainHTTP,
-		client:      options.Client,
-		tracker:     tracker,
+		auth:      options.Authorizer,
+		host:      options.Host,
+		plainHTTP: options.PlainHTTP,
+		client:    options.Client,
+		tracker:   options.Tracker,
 	}
 }
 
@@ -272,18 +294,14 @@
 	refspec reference.Spec
 	base    url.URL
 
-	client           *http.Client
-	useBasic         bool
-	username, secret string
-	token            string
-	mu               sync.Mutex
+	client *http.Client
+	auth   Authorizer
 }
 
 func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
 	var (
-		err              error
-		base             url.URL
-		username, secret string
+		err  error
+		base url.URL
 	)
 
 	host := refspec.Hostname()
@@ -300,61 +318,40 @@
 		base.Scheme = "http"
 	}
 
-	if r.credentials != nil {
-		username, secret, err = r.credentials(base.Host)
-		if err != nil {
-			return nil, err
-		}
-	}
-
 	prefix := strings.TrimPrefix(refspec.Locator, host+"/")
 	base.Path = path.Join("/v2", prefix)
 
 	return &dockerBase{
-		refspec:  refspec,
-		base:     base,
-		client:   r.client,
-		username: username,
-		secret:   secret,
+		refspec: refspec,
+		base:    base,
+		client:  r.client,
+		auth:    r.auth,
 	}, nil
 }
 
-func (r *dockerBase) getToken() string {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-
-	return r.token
-}
-
-func (r *dockerBase) setToken(token string) bool {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-
-	changed := r.token != token
-	r.token = token
-
-	return changed
-}
-
 func (r *dockerBase) url(ps ...string) string {
 	url := r.base
 	url.Path = path.Join(url.Path, path.Join(ps...))
 	return url.String()
 }
 
-func (r *dockerBase) authorize(req *http.Request) {
-	token := r.getToken()
-	if r.useBasic {
-		req.SetBasicAuth(r.username, r.secret)
-	} else if token != "" {
-		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
+func (r *dockerBase) authorize(ctx context.Context, req *http.Request) error {
+	// Check if has header for host
+	if r.auth != nil {
+		if err := r.auth.Authorize(ctx, req); err != nil {
+			return err
+		}
 	}
+
+	return nil
 }
 
 func (r *dockerBase) doRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
 	ctx = log.WithLogger(ctx, log.G(ctx).WithField("url", req.URL.String()))
 	log.G(ctx).WithField("request.headers", req.Header).WithField("request.method", req.Method).Debug("do request")
-	r.authorize(req)
+	if err := r.authorize(ctx, req); err != nil {
+		return nil, errors.Wrap(err, "failed to authorize")
+	}
 	resp, err := ctxhttp.Do(ctx, r.client, req)
 	if err != nil {
 		return nil, errors.Wrap(err, "failed to do request")
@@ -392,23 +389,14 @@
 	last := responses[len(responses)-1]
 	if last.StatusCode == http.StatusUnauthorized {
 		log.G(ctx).WithField("header", last.Header.Get("WWW-Authenticate")).Debug("Unauthorized")
-		for _, c := range parseAuthHeader(last.Header) {
-			if c.scheme == bearerAuth {
-				if err := invalidAuthorization(c, responses); err != nil {
-					r.setToken("")
-					return nil, err
-				}
-				if err := r.setTokenAuth(ctx, c.parameters); err != nil {
-					return nil, err
-				}
+		if r.auth != nil {
+			if err := r.auth.AddResponses(ctx, responses); err == nil {
 				return copyRequest(req)
-			} else if c.scheme == basicAuth {
-				if r.username != "" && r.secret != "" {
-					r.useBasic = true
-				}
-				return copyRequest(req)
+			} else if !errdefs.IsNotImplemented(err) {
+				return nil, err
 			}
 		}
+
 		return nil, nil
 	} else if last.StatusCode == http.StatusMethodNotAllowed && req.Method == http.MethodHead {
 		// Support registries which have not properly implemented the HEAD method for
@@ -424,30 +412,6 @@
 	return nil, nil
 }
 
-func invalidAuthorization(c challenge, responses []*http.Response) error {
-	errStr := c.parameters["error"]
-	if errStr == "" {
-		return nil
-	}
-
-	n := len(responses)
-	if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
-		return nil
-	}
-
-	return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr)
-}
-
-func sameRequest(r1, r2 *http.Request) bool {
-	if r1.Method != r2.Method {
-		return false
-	}
-	if *r1.URL != *r2.URL {
-		return false
-	}
-	return true
-}
-
 func copyRequest(req *http.Request) (*http.Request, error) {
 	ireq := *req
 	if ireq.GetBody != nil {
@@ -459,167 +423,3 @@
 	}
 	return &ireq, nil
 }
-
-func (r *dockerBase) setTokenAuth(ctx context.Context, params map[string]string) error {
-	realm, ok := params["realm"]
-	if !ok {
-		return errors.New("no realm specified for token auth challenge")
-	}
-
-	realmURL, err := url.Parse(realm)
-	if err != nil {
-		return fmt.Errorf("invalid token auth challenge realm: %s", err)
-	}
-
-	to := tokenOptions{
-		realm:   realmURL.String(),
-		service: params["service"],
-	}
-
-	to.scopes = getTokenScopes(ctx, params)
-	if len(to.scopes) == 0 {
-		return errors.Errorf("no scope specified for token auth challenge")
-	}
-
-	var token string
-	if r.secret != "" {
-		// Credential information is provided, use oauth POST endpoint
-		token, err = r.fetchTokenWithOAuth(ctx, to)
-		if err != nil {
-			return errors.Wrap(err, "failed to fetch oauth token")
-		}
-	} else {
-		// Do request anonymously
-		token, err = r.fetchToken(ctx, to)
-		if err != nil {
-			return errors.Wrap(err, "failed to fetch anonymous token")
-		}
-	}
-	r.setToken(token)
-
-	return nil
-}
-
-type tokenOptions struct {
-	realm   string
-	service string
-	scopes  []string
-}
-
-type postTokenResponse struct {
-	AccessToken  string    `json:"access_token"`
-	RefreshToken string    `json:"refresh_token"`
-	ExpiresIn    int       `json:"expires_in"`
-	IssuedAt     time.Time `json:"issued_at"`
-	Scope        string    `json:"scope"`
-}
-
-func (r *dockerBase) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
-	form := url.Values{}
-	form.Set("scope", strings.Join(to.scopes, " "))
-	form.Set("service", to.service)
-	// TODO: Allow setting client_id
-	form.Set("client_id", "containerd-dist-tool")
-
-	if r.username == "" {
-		form.Set("grant_type", "refresh_token")
-		form.Set("refresh_token", r.secret)
-	} else {
-		form.Set("grant_type", "password")
-		form.Set("username", r.username)
-		form.Set("password", r.secret)
-	}
-
-	resp, err := ctxhttp.PostForm(ctx, r.client, to.realm, form)
-	if err != nil {
-		return "", err
-	}
-	defer resp.Body.Close()
-
-	// Registries without support for POST may return 404 for POST /v2/token.
-	// As of September 2017, GCR is known to return 404.
-	// As of February 2018, JFrog Artifactory is known to return 401.
-	if (resp.StatusCode == 405 && r.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
-		return r.fetchToken(ctx, to)
-	} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
-		b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
-		log.G(ctx).WithFields(logrus.Fields{
-			"status": resp.Status,
-			"body":   string(b),
-		}).Debugf("token request failed")
-		// TODO: handle error body and write debug output
-		return "", errors.Errorf("unexpected status: %s", resp.Status)
-	}
-
-	decoder := json.NewDecoder(resp.Body)
-
-	var tr postTokenResponse
-	if err = decoder.Decode(&tr); err != nil {
-		return "", fmt.Errorf("unable to decode token response: %s", err)
-	}
-
-	return tr.AccessToken, nil
-}
-
-type getTokenResponse struct {
-	Token        string    `json:"token"`
-	AccessToken  string    `json:"access_token"`
-	ExpiresIn    int       `json:"expires_in"`
-	IssuedAt     time.Time `json:"issued_at"`
-	RefreshToken string    `json:"refresh_token"`
-}
-
-// getToken fetches a token using a GET request
-func (r *dockerBase) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
-	req, err := http.NewRequest("GET", to.realm, nil)
-	if err != nil {
-		return "", err
-	}
-
-	reqParams := req.URL.Query()
-
-	if to.service != "" {
-		reqParams.Add("service", to.service)
-	}
-
-	for _, scope := range to.scopes {
-		reqParams.Add("scope", scope)
-	}
-
-	if r.secret != "" {
-		req.SetBasicAuth(r.username, r.secret)
-	}
-
-	req.URL.RawQuery = reqParams.Encode()
-
-	resp, err := ctxhttp.Do(ctx, r.client, req)
-	if err != nil {
-		return "", err
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
-		// TODO: handle error body and write debug output
-		return "", errors.Errorf("unexpected status: %s", resp.Status)
-	}
-
-	decoder := json.NewDecoder(resp.Body)
-
-	var tr getTokenResponse
-	if err = decoder.Decode(&tr); err != nil {
-		return "", fmt.Errorf("unable to decode token response: %s", err)
-	}
-
-	// `access_token` is equivalent to `token` and if both are specified
-	// the choice is undefined.  Canonicalize `access_token` by sticking
-	// things in `token`.
-	if tr.AccessToken != "" {
-		tr.Token = tr.AccessToken
-	}
-
-	if tr.Token == "" {
-		return "", ErrNoToken
-	}
-
-	return tr.Token, nil
-}
diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go
index 37a567e..d73866a 100644
--- a/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go
+++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go
@@ -46,6 +46,9 @@
 		return nil, err
 	}
 	path = filepath.Join(path, id)
+	if err := os.Mkdir(path, 0711); err != nil {
+		return nil, err
+	}
 	defer func() {
 		if err != nil {
 			os.RemoveAll(path)
@@ -60,10 +63,6 @@
 			os.RemoveAll(workDir)
 		}
 	}()
-
-	if err := os.Mkdir(path, 0711); err != nil {
-		return nil, err
-	}
 	if err := os.Mkdir(filepath.Join(path, "rootfs"), 0711); err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/containerd/containerd/signal_map_linux.go b/vendor/github.com/containerd/containerd/signal_map_linux.go
new file mode 100644
index 0000000..5540110
--- /dev/null
+++ b/vendor/github.com/containerd/containerd/signal_map_linux.go
@@ -0,0 +1,60 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package containerd
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var signalMap = map[string]syscall.Signal{
+	"ABRT":   unix.SIGABRT,
+	"ALRM":   unix.SIGALRM,
+	"BUS":    unix.SIGBUS,
+	"CHLD":   unix.SIGCHLD,
+	"CLD":    unix.SIGCLD,
+	"CONT":   unix.SIGCONT,
+	"FPE":    unix.SIGFPE,
+	"HUP":    unix.SIGHUP,
+	"ILL":    unix.SIGILL,
+	"INT":    unix.SIGINT,
+	"IO":     unix.SIGIO,
+	"IOT":    unix.SIGIOT,
+	"KILL":   unix.SIGKILL,
+	"PIPE":   unix.SIGPIPE,
+	"POLL":   unix.SIGPOLL,
+	"PROF":   unix.SIGPROF,
+	"PWR":    unix.SIGPWR,
+	"QUIT":   unix.SIGQUIT,
+	"SEGV":   unix.SIGSEGV,
+	"STKFLT": unix.SIGSTKFLT,
+	"STOP":   unix.SIGSTOP,
+	"SYS":    unix.SIGSYS,
+	"TERM":   unix.SIGTERM,
+	"TRAP":   unix.SIGTRAP,
+	"TSTP":   unix.SIGTSTP,
+	"TTIN":   unix.SIGTTIN,
+	"TTOU":   unix.SIGTTOU,
+	"URG":    unix.SIGURG,
+	"USR1":   unix.SIGUSR1,
+	"USR2":   unix.SIGUSR2,
+	"VTALRM": unix.SIGVTALRM,
+	"WINCH":  unix.SIGWINCH,
+	"XCPU":   unix.SIGXCPU,
+	"XFSZ":   unix.SIGXFSZ,
+}
diff --git a/vendor/github.com/containerd/containerd/signal_map_unix.go b/vendor/github.com/containerd/containerd/signal_map_unix.go
new file mode 100644
index 0000000..62ccba9
--- /dev/null
+++ b/vendor/github.com/containerd/containerd/signal_map_unix.go
@@ -0,0 +1,58 @@
+// +build darwin freebsd solaris
+
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package containerd
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var signalMap = map[string]syscall.Signal{
+	"ABRT":   unix.SIGABRT,
+	"ALRM":   unix.SIGALRM,
+	"BUS":    unix.SIGBUS,
+	"CHLD":   unix.SIGCHLD,
+	"CONT":   unix.SIGCONT,
+	"FPE":    unix.SIGFPE,
+	"HUP":    unix.SIGHUP,
+	"ILL":    unix.SIGILL,
+	"INT":    unix.SIGINT,
+	"IO":     unix.SIGIO,
+	"IOT":    unix.SIGIOT,
+	"KILL":   unix.SIGKILL,
+	"PIPE":   unix.SIGPIPE,
+	"PROF":   unix.SIGPROF,
+	"QUIT":   unix.SIGQUIT,
+	"SEGV":   unix.SIGSEGV,
+	"STOP":   unix.SIGSTOP,
+	"SYS":    unix.SIGSYS,
+	"TERM":   unix.SIGTERM,
+	"TRAP":   unix.SIGTRAP,
+	"TSTP":   unix.SIGTSTP,
+	"TTIN":   unix.SIGTTIN,
+	"TTOU":   unix.SIGTTOU,
+	"URG":    unix.SIGURG,
+	"USR1":   unix.SIGUSR1,
+	"USR2":   unix.SIGUSR2,
+	"VTALRM": unix.SIGVTALRM,
+	"WINCH":  unix.SIGWINCH,
+	"XCPU":   unix.SIGXCPU,
+	"XFSZ":   unix.SIGXFSZ,
+}
diff --git a/vendor/github.com/containerd/containerd/signal_map_windows.go b/vendor/github.com/containerd/containerd/signal_map_windows.go
new file mode 100644
index 0000000..ef17a8f
--- /dev/null
+++ b/vendor/github.com/containerd/containerd/signal_map_windows.go
@@ -0,0 +1,39 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package containerd
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/windows"
+)
+
+var signalMap = map[string]syscall.Signal{
+	"HUP":    syscall.Signal(windows.SIGHUP),
+	"INT":    syscall.Signal(windows.SIGINT),
+	"QUIT":   syscall.Signal(windows.SIGQUIT),
+	"SIGILL": syscall.Signal(windows.SIGILL),
+	"TRAP":   syscall.Signal(windows.SIGTRAP),
+	"ABRT":   syscall.Signal(windows.SIGABRT),
+	"BUS":    syscall.Signal(windows.SIGBUS),
+	"FPE":    syscall.Signal(windows.SIGFPE),
+	"KILL":   syscall.Signal(windows.SIGKILL),
+	"SEGV":   syscall.Signal(windows.SIGSEGV),
+	"PIPE":   syscall.Signal(windows.SIGPIPE),
+	"ALRM":   syscall.Signal(windows.SIGALRM),
+	"TERM":   syscall.Signal(windows.SIGTERM),
+}
diff --git a/vendor/github.com/containerd/containerd/signals.go b/vendor/github.com/containerd/containerd/signals.go
new file mode 100644
index 0000000..32c3430
--- /dev/null
+++ b/vendor/github.com/containerd/containerd/signals.go
@@ -0,0 +1,105 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package containerd
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"strconv"
+	"strings"
+	"syscall"
+
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/images"
+	"github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+// StopSignalLabel is a well-known containerd label for storing the stop
+// signal specified in the OCI image config
+const StopSignalLabel = "io.containerd.image.config.stop-signal"
+
+// GetStopSignal retrieves the container stop signal, specified by the
+// well-known containerd label (StopSignalLabel)
+func GetStopSignal(ctx context.Context, container Container, defaultSignal syscall.Signal) (syscall.Signal, error) {
+	labels, err := container.Labels(ctx)
+	if err != nil {
+		return -1, err
+	}
+
+	if stopSignal, ok := labels[StopSignalLabel]; ok {
+		return ParseSignal(stopSignal)
+	}
+
+	return defaultSignal, nil
+}
+
+// GetOCIStopSignal retrieves the stop signal specified in the OCI image config
+func GetOCIStopSignal(ctx context.Context, image Image, defaultSignal string) (string, error) {
+	_, err := ParseSignal(defaultSignal)
+	if err != nil {
+		return "", err
+	}
+	ic, err := image.Config(ctx)
+	if err != nil {
+		return "", err
+	}
+	var (
+		ociimage v1.Image
+		config   v1.ImageConfig
+	)
+	switch ic.MediaType {
+	case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config:
+		p, err := content.ReadBlob(ctx, image.ContentStore(), ic)
+		if err != nil {
+			return "", err
+		}
+
+		if err := json.Unmarshal(p, &ociimage); err != nil {
+			return "", err
+		}
+		config = ociimage.Config
+	default:
+		return "", fmt.Errorf("unknown image config media type %s", ic.MediaType)
+	}
+
+	if config.StopSignal == "" {
+		return defaultSignal, nil
+	}
+
+	return config.StopSignal, nil
+}
+
+// ParseSignal parses a given string into a syscall.Signal
+// it checks that the signal exists in the platform-appropriate signalMap
+func ParseSignal(rawSignal string) (syscall.Signal, error) {
+	s, err := strconv.Atoi(rawSignal)
+	if err == nil {
+		sig := syscall.Signal(s)
+		for _, msig := range signalMap {
+			if sig == msig {
+				return sig, nil
+			}
+		}
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
+	}
+	signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
+	if !ok {
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
+	}
+	return signal, nil
+}
diff --git a/vendor/github.com/containerd/containerd/vendor.conf b/vendor/github.com/containerd/containerd/vendor.conf
index 1bcd620..c4cd8f1 100644
--- a/vendor/github.com/containerd/containerd/vendor.conf
+++ b/vendor/github.com/containerd/containerd/vendor.conf
@@ -4,7 +4,7 @@
 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
 github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244
-github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537
+github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
 github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
 github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
@@ -20,7 +20,7 @@
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
 github.com/golang/protobuf v1.1.0
 github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
-github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd
+github.com/opencontainers/runc 00dc70017d222b178a002ed30e9321b12647af2d
 github.com/sirupsen/logrus v1.0.0
 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
 golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
@@ -33,10 +33,10 @@
 github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
 github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
 github.com/Microsoft/go-winio v0.4.10
-github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55
+github.com/Microsoft/hcsshim v0.7.6
 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
-github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
+github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
 gotest.tools v2.1.0
 github.com/google/go-cmp v0.1.0
diff --git a/vendor/github.com/containerd/continuity/context.go b/vendor/github.com/containerd/continuity/context.go
index 45b73dc..75c9859 100644
--- a/vendor/github.com/containerd/continuity/context.go
+++ b/vendor/github.com/containerd/continuity/context.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import (
diff --git a/vendor/github.com/containerd/continuity/devices/devices.go b/vendor/github.com/containerd/continuity/devices/devices.go
index 7086407..e4d4a03 100644
--- a/vendor/github.com/containerd/continuity/devices/devices.go
+++ b/vendor/github.com/containerd/continuity/devices/devices.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package devices
 
 import "fmt"
diff --git a/vendor/github.com/containerd/continuity/devices/devices_unix.go b/vendor/github.com/containerd/continuity/devices/devices_unix.go
index 97fe6b1..520a5a6 100644
--- a/vendor/github.com/containerd/continuity/devices/devices_unix.go
+++ b/vendor/github.com/containerd/continuity/devices/devices_unix.go
@@ -1,5 +1,21 @@
 // +build linux darwin freebsd solaris
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package devices
 
 import (
diff --git a/vendor/github.com/containerd/continuity/devices/devices_windows.go b/vendor/github.com/containerd/continuity/devices/devices_windows.go
index 6099d1d..04627c8 100644
--- a/vendor/github.com/containerd/continuity/devices/devices_windows.go
+++ b/vendor/github.com/containerd/continuity/devices/devices_windows.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package devices
 
 import (
diff --git a/vendor/github.com/containerd/continuity/digests.go b/vendor/github.com/containerd/continuity/digests.go
index 355b080..bf92275 100644
--- a/vendor/github.com/containerd/continuity/digests.go
+++ b/vendor/github.com/containerd/continuity/digests.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import (
diff --git a/vendor/github.com/containerd/continuity/driver/driver.go b/vendor/github.com/containerd/continuity/driver/driver.go
index 6a0f76d..327e96a 100644
--- a/vendor/github.com/containerd/continuity/driver/driver.go
+++ b/vendor/github.com/containerd/continuity/driver/driver.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package driver
 
 import (
diff --git a/vendor/github.com/containerd/continuity/driver/driver_unix.go b/vendor/github.com/containerd/continuity/driver/driver_unix.go
index c7d4e6b..6cb5d10 100644
--- a/vendor/github.com/containerd/continuity/driver/driver_unix.go
+++ b/vendor/github.com/containerd/continuity/driver/driver_unix.go
@@ -1,5 +1,21 @@
 // +build linux darwin freebsd solaris
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package driver
 
 import (
@@ -13,7 +29,11 @@
 )
 
 func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error {
-	return devices.Mknod(path, mode, major, minor)
+	err := devices.Mknod(path, mode, major, minor)
+	if err != nil {
+		err = &os.PathError{Op: "mknod", Path: path, Err: err}
+	}
+	return err
 }
 
 func (d *driver) Mkfifo(path string, mode os.FileMode) error {
@@ -22,7 +42,11 @@
 	}
 	// mknod with a mode that has ModeNamedPipe set creates a fifo, not a
 	// device.
-	return devices.Mknod(path, mode, 0, 0)
+	err := devices.Mknod(path, mode, 0, 0)
+	if err != nil {
+		err = &os.PathError{Op: "mkfifo", Path: path, Err: err}
+	}
+	return err
 }
 
 // Getxattr returns all of the extended attributes for the file at path p.
diff --git a/vendor/github.com/containerd/continuity/driver/driver_windows.go b/vendor/github.com/containerd/continuity/driver/driver_windows.go
index 21c9cf9..f1dcea3 100644
--- a/vendor/github.com/containerd/continuity/driver/driver_windows.go
+++ b/vendor/github.com/containerd/continuity/driver/driver_windows.go
@@ -1,18 +1,33 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package driver
 
 import (
 	"os"
 
 	"github.com/containerd/continuity/sysx"
-	"github.com/pkg/errors"
 )
 
 func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error {
-	return errors.Wrap(ErrNotSupported, "cannot create device node on Windows")
+	return &os.PathError{Op: "mknod", Path: path, Err: ErrNotSupported}
 }
 
 func (d *driver) Mkfifo(path string, mode os.FileMode) error {
-	return errors.Wrap(ErrNotSupported, "cannot create fifo on Windows")
+	return &os.PathError{Op: "mkfifo", Path: path, Err: ErrNotSupported}
 }
 
 // Lchmod changes the mode of an file not following symlinks.
diff --git a/vendor/github.com/containerd/continuity/driver/lchmod_linux.go b/vendor/github.com/containerd/continuity/driver/lchmod_linux.go
index 39ffe9c..06be285 100644
--- a/vendor/github.com/containerd/continuity/driver/lchmod_linux.go
+++ b/vendor/github.com/containerd/continuity/driver/lchmod_linux.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package driver
 
 import (
@@ -15,5 +31,9 @@
 		return nil
 	}
 
-	return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0)
+	err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0)
+	if err != nil {
+		err = &os.PathError{Op: "lchmod", Path: path, Err: err}
+	}
+	return err
 }
diff --git a/vendor/github.com/containerd/continuity/driver/lchmod_unix.go b/vendor/github.com/containerd/continuity/driver/lchmod_unix.go
index 1b539f7..b8877a8 100644
--- a/vendor/github.com/containerd/continuity/driver/lchmod_unix.go
+++ b/vendor/github.com/containerd/continuity/driver/lchmod_unix.go
@@ -1,5 +1,21 @@
 // +build darwin freebsd solaris
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package driver
 
 import (
@@ -10,5 +26,9 @@
 
 // Lchmod changes the mode of a file not following symlinks.
 func (d *driver) Lchmod(path string, mode os.FileMode) error {
-	return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
+	err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
+	if err != nil {
+		err = &os.PathError{Op: "lchmod", Path: path, Err: err}
+	}
+	return err
 }
diff --git a/vendor/github.com/containerd/continuity/driver/utils.go b/vendor/github.com/containerd/continuity/driver/utils.go
index 9e0edd7..0c688d1 100644
--- a/vendor/github.com/containerd/continuity/driver/utils.go
+++ b/vendor/github.com/containerd/continuity/driver/utils.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package driver
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/copy.go b/vendor/github.com/containerd/continuity/fs/copy.go
index 2ac474b..42df6a9 100644
--- a/vendor/github.com/containerd/continuity/fs/copy.go
+++ b/vendor/github.com/containerd/continuity/fs/copy.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/copy_linux.go b/vendor/github.com/containerd/continuity/fs/copy_linux.go
index b244e31..e041b56 100644
--- a/vendor/github.com/containerd/continuity/fs/copy_linux.go
+++ b/vendor/github.com/containerd/continuity/fs/copy_linux.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/copy_unix.go b/vendor/github.com/containerd/continuity/fs/copy_unix.go
index 29cbb81..1a8ae5e 100644
--- a/vendor/github.com/containerd/continuity/fs/copy_unix.go
+++ b/vendor/github.com/containerd/continuity/fs/copy_unix.go
@@ -1,5 +1,21 @@
 // +build solaris darwin freebsd
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/copy_windows.go b/vendor/github.com/containerd/continuity/fs/copy_windows.go
index 6fb3de5..be8e648 100644
--- a/vendor/github.com/containerd/continuity/fs/copy_windows.go
+++ b/vendor/github.com/containerd/continuity/fs/copy_windows.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/diff.go b/vendor/github.com/containerd/continuity/fs/diff.go
index f2300e8..e64f9e7 100644
--- a/vendor/github.com/containerd/continuity/fs/diff.go
+++ b/vendor/github.com/containerd/continuity/fs/diff.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/diff_unix.go b/vendor/github.com/containerd/continuity/fs/diff_unix.go
index 3751814..7913af2 100644
--- a/vendor/github.com/containerd/continuity/fs/diff_unix.go
+++ b/vendor/github.com/containerd/continuity/fs/diff_unix.go
@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/diff_windows.go b/vendor/github.com/containerd/continuity/fs/diff_windows.go
index 8eed365..4bfa72d 100644
--- a/vendor/github.com/containerd/continuity/fs/diff_windows.go
+++ b/vendor/github.com/containerd/continuity/fs/diff_windows.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/dtype_linux.go b/vendor/github.com/containerd/continuity/fs/dtype_linux.go
index cc06573..10510d8 100644
--- a/vendor/github.com/containerd/continuity/fs/dtype_linux.go
+++ b/vendor/github.com/containerd/continuity/fs/dtype_linux.go
@@ -1,5 +1,21 @@
 // +build linux
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/du.go b/vendor/github.com/containerd/continuity/fs/du.go
index f8fc9a9..fccc985 100644
--- a/vendor/github.com/containerd/continuity/fs/du.go
+++ b/vendor/github.com/containerd/continuity/fs/du.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import "context"
diff --git a/vendor/github.com/containerd/continuity/fs/du_unix.go b/vendor/github.com/containerd/continuity/fs/du_unix.go
index 9f6bc55..e22ffbe 100644
--- a/vendor/github.com/containerd/continuity/fs/du_unix.go
+++ b/vendor/github.com/containerd/continuity/fs/du_unix.go
@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/du_windows.go b/vendor/github.com/containerd/continuity/fs/du_windows.go
index faa443f..8f25ec5 100644
--- a/vendor/github.com/containerd/continuity/fs/du_windows.go
+++ b/vendor/github.com/containerd/continuity/fs/du_windows.go
@@ -1,5 +1,21 @@
 // +build windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/hardlink.go b/vendor/github.com/containerd/continuity/fs/hardlink.go
index 38da938..762aa45 100644
--- a/vendor/github.com/containerd/continuity/fs/hardlink.go
+++ b/vendor/github.com/containerd/continuity/fs/hardlink.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import "os"
diff --git a/vendor/github.com/containerd/continuity/fs/hardlink_unix.go b/vendor/github.com/containerd/continuity/fs/hardlink_unix.go
index a6f9977..f95f090 100644
--- a/vendor/github.com/containerd/continuity/fs/hardlink_unix.go
+++ b/vendor/github.com/containerd/continuity/fs/hardlink_unix.go
@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/hardlink_windows.go b/vendor/github.com/containerd/continuity/fs/hardlink_windows.go
index ad8845a..7485547 100644
--- a/vendor/github.com/containerd/continuity/fs/hardlink_windows.go
+++ b/vendor/github.com/containerd/continuity/fs/hardlink_windows.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import "os"
diff --git a/vendor/github.com/containerd/continuity/fs/path.go b/vendor/github.com/containerd/continuity/fs/path.go
index 13fb826..9959817 100644
--- a/vendor/github.com/containerd/continuity/fs/path.go
+++ b/vendor/github.com/containerd/continuity/fs/path.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
@@ -232,12 +248,6 @@
 	if err != nil {
 		return "", false, err
 	}
-	if filepath.IsAbs(newpath) && strings.HasPrefix(newpath, root) {
-		newpath = newpath[:len(root)]
-		if !strings.HasPrefix(newpath, "/") {
-			newpath = "/" + newpath
-		}
-	}
 	*linksWalked++
 	return newpath, true, nil
 }
diff --git a/vendor/github.com/containerd/continuity/fs/stat_bsd.go b/vendor/github.com/containerd/continuity/fs/stat_bsd.go
index a1b776f..cb7400a 100644
--- a/vendor/github.com/containerd/continuity/fs/stat_bsd.go
+++ b/vendor/github.com/containerd/continuity/fs/stat_bsd.go
@@ -1,5 +1,21 @@
 // +build darwin freebsd
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/stat_linux.go b/vendor/github.com/containerd/continuity/fs/stat_linux.go
index 1dbb021..4a678dd 100644
--- a/vendor/github.com/containerd/continuity/fs/stat_linux.go
+++ b/vendor/github.com/containerd/continuity/fs/stat_linux.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import (
diff --git a/vendor/github.com/containerd/continuity/fs/time.go b/vendor/github.com/containerd/continuity/fs/time.go
index c336f4d..cde4561 100644
--- a/vendor/github.com/containerd/continuity/fs/time.go
+++ b/vendor/github.com/containerd/continuity/fs/time.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package fs
 
 import "time"
diff --git a/vendor/github.com/containerd/continuity/groups_unix.go b/vendor/github.com/containerd/continuity/groups_unix.go
index e15c14f..022d8ab 100644
--- a/vendor/github.com/containerd/continuity/groups_unix.go
+++ b/vendor/github.com/containerd/continuity/groups_unix.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import (
diff --git a/vendor/github.com/containerd/continuity/hardlinks.go b/vendor/github.com/containerd/continuity/hardlinks.go
index 8b39bd0..d493dd7 100644
--- a/vendor/github.com/containerd/continuity/hardlinks.go
+++ b/vendor/github.com/containerd/continuity/hardlinks.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import (
diff --git a/vendor/github.com/containerd/continuity/hardlinks_unix.go b/vendor/github.com/containerd/continuity/hardlinks_unix.go
index 1d81a3f..a15d175 100644
--- a/vendor/github.com/containerd/continuity/hardlinks_unix.go
+++ b/vendor/github.com/containerd/continuity/hardlinks_unix.go
@@ -1,5 +1,21 @@
 // +build linux darwin freebsd solaris
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import (
diff --git a/vendor/github.com/containerd/continuity/hardlinks_windows.go b/vendor/github.com/containerd/continuity/hardlinks_windows.go
index be516c5..5893f4e 100644
--- a/vendor/github.com/containerd/continuity/hardlinks_windows.go
+++ b/vendor/github.com/containerd/continuity/hardlinks_windows.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import "os"
diff --git a/vendor/github.com/containerd/continuity/ioutils.go b/vendor/github.com/containerd/continuity/ioutils.go
index 3a25bde..503640e 100644
--- a/vendor/github.com/containerd/continuity/ioutils.go
+++ b/vendor/github.com/containerd/continuity/ioutils.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import (
diff --git a/vendor/github.com/containerd/continuity/manifest.go b/vendor/github.com/containerd/continuity/manifest.go
index f704f04..8074bbf 100644
--- a/vendor/github.com/containerd/continuity/manifest.go
+++ b/vendor/github.com/containerd/continuity/manifest.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import (
diff --git a/vendor/github.com/containerd/continuity/pathdriver/path_driver.go b/vendor/github.com/containerd/continuity/pathdriver/path_driver.go
index b43d55f..b0d5a6b 100644
--- a/vendor/github.com/containerd/continuity/pathdriver/path_driver.go
+++ b/vendor/github.com/containerd/continuity/pathdriver/path_driver.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package pathdriver
 
 import (
diff --git a/vendor/github.com/containerd/continuity/proto/gen.go b/vendor/github.com/containerd/continuity/proto/gen.go
index 8f26ff5..63ce10f 100644
--- a/vendor/github.com/containerd/continuity/proto/gen.go
+++ b/vendor/github.com/containerd/continuity/proto/gen.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package proto
 
 //go:generate protoc --go_out=. manifest.proto
diff --git a/vendor/github.com/containerd/continuity/resource.go b/vendor/github.com/containerd/continuity/resource.go
index 3643eff..d2f52bd 100644
--- a/vendor/github.com/containerd/continuity/resource.go
+++ b/vendor/github.com/containerd/continuity/resource.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import (
diff --git a/vendor/github.com/containerd/continuity/resource_unix.go b/vendor/github.com/containerd/continuity/resource_unix.go
index 4144643..0e103cc 100644
--- a/vendor/github.com/containerd/continuity/resource_unix.go
+++ b/vendor/github.com/containerd/continuity/resource_unix.go
@@ -1,5 +1,21 @@
 // +build linux darwin freebsd solaris
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import (
diff --git a/vendor/github.com/containerd/continuity/resource_windows.go b/vendor/github.com/containerd/continuity/resource_windows.go
index 7b44414..f980180 100644
--- a/vendor/github.com/containerd/continuity/resource_windows.go
+++ b/vendor/github.com/containerd/continuity/resource_windows.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package continuity
 
 import "os"
diff --git a/vendor/github.com/containerd/continuity/syscallx/syscall_unix.go b/vendor/github.com/containerd/continuity/syscallx/syscall_unix.go
index 4205d1e..0bfa6a0 100644
--- a/vendor/github.com/containerd/continuity/syscallx/syscall_unix.go
+++ b/vendor/github.com/containerd/continuity/syscallx/syscall_unix.go
@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package syscallx
 
 import "syscall"
diff --git a/vendor/github.com/containerd/continuity/syscallx/syscall_windows.go b/vendor/github.com/containerd/continuity/syscallx/syscall_windows.go
index 9637a28..2ba8149 100644
--- a/vendor/github.com/containerd/continuity/syscallx/syscall_windows.go
+++ b/vendor/github.com/containerd/continuity/syscallx/syscall_windows.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package syscallx
 
 import (
diff --git a/vendor/github.com/containerd/continuity/sysx/file_posix.go b/vendor/github.com/containerd/continuity/sysx/file_posix.go
index d0784f8..e28f3a1 100644
--- a/vendor/github.com/containerd/continuity/sysx/file_posix.go
+++ b/vendor/github.com/containerd/continuity/sysx/file_posix.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package sysx
 
 import (
diff --git a/vendor/github.com/containerd/continuity/sysx/nodata_linux.go b/vendor/github.com/containerd/continuity/sysx/nodata_linux.go
index fc47ddb..28ce5d8 100644
--- a/vendor/github.com/containerd/continuity/sysx/nodata_linux.go
+++ b/vendor/github.com/containerd/continuity/sysx/nodata_linux.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package sysx
 
 import (
diff --git a/vendor/github.com/containerd/continuity/sysx/nodata_solaris.go b/vendor/github.com/containerd/continuity/sysx/nodata_solaris.go
index 53cc8e0..e0575f4 100644
--- a/vendor/github.com/containerd/continuity/sysx/nodata_solaris.go
+++ b/vendor/github.com/containerd/continuity/sysx/nodata_solaris.go
@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package sysx
 
 import (
diff --git a/vendor/github.com/containerd/continuity/sysx/nodata_unix.go b/vendor/github.com/containerd/continuity/sysx/nodata_unix.go
index 7e68512..b26f5b3 100644
--- a/vendor/github.com/containerd/continuity/sysx/nodata_unix.go
+++ b/vendor/github.com/containerd/continuity/sysx/nodata_unix.go
@@ -1,5 +1,21 @@
 // +build darwin freebsd
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package sysx
 
 import (
diff --git a/vendor/github.com/containerd/continuity/sysx/xattr.go b/vendor/github.com/containerd/continuity/sysx/xattr.go
index a59efee..9e4326d 100644
--- a/vendor/github.com/containerd/continuity/sysx/xattr.go
+++ b/vendor/github.com/containerd/continuity/sysx/xattr.go
@@ -1,5 +1,21 @@
 // +build linux darwin
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package sysx
 
 import (
diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go b/vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go
index 4f6a12e..c9ef3a1 100644
--- a/vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go
+++ b/vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go
@@ -1,5 +1,21 @@
 // +build !linux,!darwin
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package sysx
 
 import (
diff --git a/vendor/github.com/containerd/ttrpc/client.go b/vendor/github.com/containerd/ttrpc/client.go
index ede2e6b..e40592d 100644
--- a/vendor/github.com/containerd/ttrpc/client.go
+++ b/vendor/github.com/containerd/ttrpc/client.go
@@ -110,12 +110,16 @@
 	}
 
 	select {
+	case <-ctx.Done():
+		return ctx.Err()
 	case c.calls <- call:
 	case <-c.done:
 		return c.err
 	}
 
 	select {
+	case <-ctx.Done():
+		return ctx.Err()
 	case err := <-errs:
 		return filterCloseErr(err)
 	case <-c.done:
diff --git a/vendor/github.com/containerd/ttrpc/server.go b/vendor/github.com/containerd/ttrpc/server.go
index 1a518b1..263cb45 100644
--- a/vendor/github.com/containerd/ttrpc/server.go
+++ b/vendor/github.com/containerd/ttrpc/server.go
@@ -127,13 +127,13 @@
 
 func (s *Server) Shutdown(ctx context.Context) error {
 	s.mu.Lock()
-	lnerr := s.closeListeners()
 	select {
 	case <-s.done:
 	default:
 		// protected by mutex
 		close(s.done)
 	}
+	lnerr := s.closeListeners()
 	s.mu.Unlock()
 
 	ticker := time.NewTicker(200 * time.Millisecond)
diff --git a/vendor/github.com/docker/libnetwork/controller.go b/vendor/github.com/docker/libnetwork/controller.go
index f956ddb..2896011 100644
--- a/vendor/github.com/docker/libnetwork/controller.go
+++ b/vendor/github.com/docker/libnetwork/controller.go
@@ -700,6 +700,9 @@
 	return nil
 }
 
+// XXX  This should be made driver agnostic.  See comment below.
+const overlayDSROptionString = "dsr"
+
 // NewNetwork creates a new network of the specified network type. The options
 // are network specific and modeled in a generic way.
 func (c *controller) NewNetwork(networkType, name string, id string, options ...NetworkOption) (Network, error) {
@@ -723,15 +726,16 @@
 	defaultIpam := defaultIpamForNetworkType(networkType)
 	// Construct the network object
 	network := &network{
-		name:        name,
-		networkType: networkType,
-		generic:     map[string]interface{}{netlabel.GenericData: make(map[string]string)},
-		ipamType:    defaultIpam,
-		id:          id,
-		created:     time.Now(),
-		ctrlr:       c,
-		persist:     true,
-		drvOnce:     &sync.Once{},
+		name:             name,
+		networkType:      networkType,
+		generic:          map[string]interface{}{netlabel.GenericData: make(map[string]string)},
+		ipamType:         defaultIpam,
+		id:               id,
+		created:          time.Now(),
+		ctrlr:            c,
+		persist:          true,
+		drvOnce:          &sync.Once{},
+		loadBalancerMode: loadBalancerModeDefault,
 	}
 
 	network.processOptions(options...)
@@ -829,6 +833,21 @@
 		}
 	}()
 
+	// XXX If the driver type is "overlay" check the options for DSR
+	// being set.  If so, set the network's load balancing mode to DSR.
+	// This should really be done in a network option, but due to
+	// time pressure to get this in without adding changes to moby,
+	// swarm and CLI, it is being implemented as a driver-specific
+	// option.  Unfortunately, drivers can't influence the core
+	// "libnetwork.network" data type.  Hence we need this hack code
+	// to implement in this manner.
+	if gval, ok := network.generic[netlabel.GenericData]; ok && network.networkType == "overlay" {
+		optMap := gval.(map[string]string)
+		if _, ok := optMap[overlayDSROptionString]; ok {
+			network.loadBalancerMode = loadBalancerModeDSR
+		}
+	}
+
 addToStore:
 	// First store the endpoint count, then the network. To avoid to
 	// end up with a datastore containing a network and not an epCnt,
diff --git a/vendor/github.com/docker/libnetwork/ipvs/constants.go b/vendor/github.com/docker/libnetwork/ipvs/constants.go
index d36bec0..b6b7f2b 100644
--- a/vendor/github.com/docker/libnetwork/ipvs/constants.go
+++ b/vendor/github.com/docker/libnetwork/ipvs/constants.go
@@ -145,3 +145,23 @@
 	// addresses.
 	SourceHashing = "sh"
 )
+
+const (
+	// ConnFwdMask is a mask for the fwd methods
+	ConnFwdMask = 0x0007
+
+	// ConnFwdMasq denotes forwarding via masquerading/NAT
+	ConnFwdMasq = 0x0000
+
+	// ConnFwdLocalNode denotes forwarding to a local node
+	ConnFwdLocalNode = 0x0001
+
+	// ConnFwdTunnel denotes forwarding via a tunnel
+	ConnFwdTunnel = 0x0002
+
+	// ConnFwdDirectRoute denotes forwarding via direct routing
+	ConnFwdDirectRoute = 0x0003
+
+	// ConnFwdBypass denotes forwarding while bypassing the cache
+	ConnFwdBypass = 0x0004
+)
diff --git a/vendor/github.com/docker/libnetwork/network.go b/vendor/github.com/docker/libnetwork/network.go
index 052aa8f..0a4a227 100644
--- a/vendor/github.com/docker/libnetwork/network.go
+++ b/vendor/github.com/docker/libnetwork/network.go
@@ -199,43 +199,50 @@
 }
 
 type network struct {
-	ctrlr          *controller
-	name           string
-	networkType    string
-	id             string
-	created        time.Time
-	scope          string // network data scope
-	labels         map[string]string
-	ipamType       string
-	ipamOptions    map[string]string
-	addrSpace      string
-	ipamV4Config   []*IpamConf
-	ipamV6Config   []*IpamConf
-	ipamV4Info     []*IpamInfo
-	ipamV6Info     []*IpamInfo
-	enableIPv6     bool
-	postIPv6       bool
-	epCnt          *endpointCnt
-	generic        options.Generic
-	dbIndex        uint64
-	dbExists       bool
-	persist        bool
-	stopWatchCh    chan struct{}
-	drvOnce        *sync.Once
-	resolverOnce   sync.Once
-	resolver       []Resolver
-	internal       bool
-	attachable     bool
-	inDelete       bool
-	ingress        bool
-	driverTables   []networkDBTable
-	dynamic        bool
-	configOnly     bool
-	configFrom     string
-	loadBalancerIP net.IP
+	ctrlr            *controller
+	name             string
+	networkType      string
+	id               string
+	created          time.Time
+	scope            string // network data scope
+	labels           map[string]string
+	ipamType         string
+	ipamOptions      map[string]string
+	addrSpace        string
+	ipamV4Config     []*IpamConf
+	ipamV6Config     []*IpamConf
+	ipamV4Info       []*IpamInfo
+	ipamV6Info       []*IpamInfo
+	enableIPv6       bool
+	postIPv6         bool
+	epCnt            *endpointCnt
+	generic          options.Generic
+	dbIndex          uint64
+	dbExists         bool
+	persist          bool
+	stopWatchCh      chan struct{}
+	drvOnce          *sync.Once
+	resolverOnce     sync.Once
+	resolver         []Resolver
+	internal         bool
+	attachable       bool
+	inDelete         bool
+	ingress          bool
+	driverTables     []networkDBTable
+	dynamic          bool
+	configOnly       bool
+	configFrom       string
+	loadBalancerIP   net.IP
+	loadBalancerMode string
 	sync.Mutex
 }
 
+const (
+	loadBalancerModeNAT     = "NAT"
+	loadBalancerModeDSR     = "DSR"
+	loadBalancerModeDefault = loadBalancerModeNAT
+)
+
 func (n *network) Name() string {
 	n.Lock()
 	defer n.Unlock()
@@ -475,6 +482,7 @@
 	dstN.configOnly = n.configOnly
 	dstN.configFrom = n.configFrom
 	dstN.loadBalancerIP = n.loadBalancerIP
+	dstN.loadBalancerMode = n.loadBalancerMode
 
 	// copy labels
 	if dstN.labels == nil {
@@ -592,6 +600,7 @@
 	netMap["configOnly"] = n.configOnly
 	netMap["configFrom"] = n.configFrom
 	netMap["loadBalancerIP"] = n.loadBalancerIP
+	netMap["loadBalancerMode"] = n.loadBalancerMode
 	return json.Marshal(netMap)
 }
 
@@ -705,6 +714,10 @@
 	if v, ok := netMap["loadBalancerIP"]; ok {
 		n.loadBalancerIP = net.ParseIP(v.(string))
 	}
+	n.loadBalancerMode = loadBalancerModeDefault
+	if v, ok := netMap["loadBalancerMode"]; ok {
+		n.loadBalancerMode = v.(string)
+	}
 	// Reconcile old networks with the recently added `--ipv6` flag
 	if !n.enableIPv6 {
 		n.enableIPv6 = len(n.ipamV6Info) > 0
diff --git a/vendor/github.com/docker/libnetwork/osl/namespace_linux.go b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
index 45c4685..bfc5d31 100644
--- a/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
+++ b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
@@ -384,6 +384,36 @@
 	return n.nlHandle.AddrDel(iface, &netlink.Addr{IPNet: ip})
 }
 
+func (n *networkNamespace) DisableARPForVIP(srcName string) (Err error) {
+	dstName := ""
+	for _, i := range n.Interfaces() {
+		if i.SrcName() == srcName {
+			dstName = i.DstName()
+			break
+		}
+	}
+	if dstName == "" {
+		return fmt.Errorf("failed to find interface %s in sandbox", srcName)
+	}
+
+	err := n.InvokeFunc(func() {
+		path := filepath.Join("/proc/sys/net/ipv4/conf", dstName, "arp_ignore")
+		if err := ioutil.WriteFile(path, []byte{'1', '\n'}, 0644); err != nil {
+			Err = fmt.Errorf("Failed to set %s to 1: %v", path, err)
+			return
+		}
+		path = filepath.Join("/proc/sys/net/ipv4/conf", dstName, "arp_announce")
+		if err := ioutil.WriteFile(path, []byte{'2', '\n'}, 0644); err != nil {
+			Err = fmt.Errorf("Failed to set %s to 2: %v", path, err)
+			return
+		}
+	})
+	if err != nil {
+		return err
+	}
+	return
+}
+
 func (n *networkNamespace) InvokeFunc(f func()) error {
 	return nsInvoke(n.nsPath(), func(nsFD int) error { return nil }, func(callerFD int) error {
 		f()
diff --git a/vendor/github.com/docker/libnetwork/osl/sandbox.go b/vendor/github.com/docker/libnetwork/osl/sandbox.go
index 5019e06..198cf64 100644
--- a/vendor/github.com/docker/libnetwork/osl/sandbox.go
+++ b/vendor/github.com/docker/libnetwork/osl/sandbox.go
@@ -51,6 +51,10 @@
 	// RemoveAliasIP removes the passed IP address from the named interface
 	RemoveAliasIP(ifName string, ip *net.IPNet) error
 
+	// DisableARPForVIP disables ARP replies and requests for VIP addresses
+	// on a particular interface
+	DisableARPForVIP(ifName string) error
+
 	// Add a static route to the sandbox.
 	AddStaticRoute(*types.StaticRoute) error
 
diff --git a/vendor/github.com/docker/libnetwork/sandbox.go b/vendor/github.com/docker/libnetwork/sandbox.go
index d98f359..03c9215 100644
--- a/vendor/github.com/docker/libnetwork/sandbox.go
+++ b/vendor/github.com/docker/libnetwork/sandbox.go
@@ -742,8 +742,17 @@
 
 	ep.Lock()
 	joinInfo := ep.joinInfo
+	vip := ep.virtualIP
+	lbModeIsDSR := ep.network.loadBalancerMode == loadBalancerModeDSR
 	ep.Unlock()
 
+	if len(vip) > 0 && lbModeIsDSR {
+		ipNet := &net.IPNet{IP: vip, Mask: net.CIDRMask(32, 32)}
+		if err := osSbox.RemoveAliasIP(osSbox.GetLoopbackIfaceName(), ipNet); err != nil {
+			logrus.WithError(err).Debugf("failed to remove virtual ip %v to loopback", ipNet)
+		}
+	}
+
 	if joinInfo == nil {
 		return
 	}
@@ -831,6 +840,7 @@
 	ep.Lock()
 	joinInfo := ep.joinInfo
 	i := ep.iface
+	lbModeIsDSR := ep.network.loadBalancerMode == loadBalancerModeDSR
 	ep.Unlock()
 
 	if ep.needResolver() {
@@ -854,6 +864,18 @@
 		if err := sb.osSbox.AddInterface(i.srcName, i.dstPrefix, ifaceOptions...); err != nil {
 			return fmt.Errorf("failed to add interface %s to sandbox: %v", i.srcName, err)
 		}
+
+		if len(ep.virtualIP) > 0 && lbModeIsDSR {
+			if sb.loadBalancerNID == "" {
+				if err := sb.osSbox.DisableARPForVIP(i.srcName); err != nil {
+					return fmt.Errorf("failed disable ARP for VIP: %v", err)
+				}
+			}
+			ipNet := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)}
+			if err := sb.osSbox.AddAliasIP(sb.osSbox.GetLoopbackIfaceName(), ipNet); err != nil {
+				return fmt.Errorf("failed to add virtual ip %v to loopback: %v", ipNet, err)
+			}
+		}
 	}
 
 	if joinInfo != nil {
diff --git a/vendor/github.com/docker/libnetwork/service_linux.go b/vendor/github.com/docker/libnetwork/service_linux.go
index a97d24b..562c3f7 100644
--- a/vendor/github.com/docker/libnetwork/service_linux.go
+++ b/vendor/github.com/docker/libnetwork/service_linux.go
@@ -143,7 +143,7 @@
 		}
 
 		logrus.Debugf("Creating service for vip %s fwMark %d ingressPorts %#v in sbox %.7s (%.7s)", lb.vip, lb.fwMark, lb.service.ingressPorts, sb.ID(), sb.ContainerID())
-		if err := invokeFWMarker(sb.Key(), lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, false); err != nil {
+		if err := invokeFWMarker(sb.Key(), lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, false, n.loadBalancerMode); err != nil {
 			logrus.Errorf("Failed to add firewall mark rule in sbox %.7s (%.7s): %v", sb.ID(), sb.ContainerID(), err)
 			return
 		}
@@ -159,6 +159,9 @@
 		Address:       ip,
 		Weight:        1,
 	}
+	if n.loadBalancerMode == loadBalancerModeDSR {
+		d.ConnectionFlags = ipvs.ConnFwdDirectRoute
+	}
 
 	// Remove the sched name before using the service to add
 	// destination.
@@ -204,6 +207,9 @@
 		Address:       ip,
 		Weight:        1,
 	}
+	if n.loadBalancerMode == loadBalancerModeDSR {
+		d.ConnectionFlags = ipvs.ConnFwdDirectRoute
+	}
 
 	if fullRemove {
 		if err := i.DelDestination(s, d); err != nil && err != syscall.ENOENT {
@@ -233,7 +239,7 @@
 			}
 		}
 
-		if err := invokeFWMarker(sb.Key(), lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, true); err != nil {
+		if err := invokeFWMarker(sb.Key(), lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, true, n.loadBalancerMode); err != nil {
 			logrus.Errorf("Failed to delete firewall mark rule in sbox %.7s (%.7s): %v", sb.ID(), sb.ContainerID(), err)
 		}
 
@@ -544,7 +550,7 @@
 
 // Invoke fwmarker reexec routine to mark vip destined packets with
 // the passed firewall mark.
-func invokeFWMarker(path string, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, eIP *net.IPNet, isDelete bool) error {
+func invokeFWMarker(path string, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, eIP *net.IPNet, isDelete bool, lbMode string) error {
 	var ingressPortsFile string
 
 	if len(ingressPorts) != 0 {
@@ -564,7 +570,7 @@
 
 	cmd := &exec.Cmd{
 		Path:   reexec.Self(),
-		Args:   append([]string{"fwmarker"}, path, vip.String(), fmt.Sprintf("%d", fwMark), addDelOpt, ingressPortsFile, eIP.String()),
+		Args:   append([]string{"fwmarker"}, path, vip.String(), fmt.Sprintf("%d", fwMark), addDelOpt, ingressPortsFile, eIP.String(), lbMode),
 		Stdout: os.Stdout,
 		Stderr: os.Stderr,
 	}
@@ -581,7 +587,7 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if len(os.Args) < 7 {
+	if len(os.Args) < 8 {
 		logrus.Error("invalid number of arguments..")
 		os.Exit(1)
 	}
@@ -623,7 +629,8 @@
 		os.Exit(5)
 	}
 
-	if addDelOpt == "-A" {
+	lbMode := os.Args[7]
+	if addDelOpt == "-A" && lbMode == loadBalancerModeNAT {
 		eIP, subnet, err := net.ParseCIDR(os.Args[6])
 		if err != nil {
 			logrus.Errorf("Failed to parse endpoint IP %s: %v", os.Args[6], err)
diff --git a/vendor/github.com/docker/swarmkit/agent/agent.go b/vendor/github.com/docker/swarmkit/agent/agent.go
index 4d8f99c..743072f 100644
--- a/vendor/github.com/docker/swarmkit/agent/agent.go
+++ b/vendor/github.com/docker/swarmkit/agent/agent.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"context"
 	"math/rand"
 	"reflect"
 	"sync"
@@ -11,7 +12,6 @@
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
 	"github.com/pkg/errors"
-	"golang.org/x/net/context"
 )
 
 const (
diff --git a/vendor/github.com/docker/swarmkit/agent/errors.go b/vendor/github.com/docker/swarmkit/agent/errors.go
index 29f8ff1..f5514d8 100644
--- a/vendor/github.com/docker/swarmkit/agent/errors.go
+++ b/vendor/github.com/docker/swarmkit/agent/errors.go
@@ -13,10 +13,5 @@
 	errAgentStarted    = errors.New("agent: already started")
 	errAgentNotStarted = errors.New("agent: not started")
 
-	errTaskNoController         = errors.New("agent: no task controller")
-	errTaskNotAssigned          = errors.New("agent: task not assigned")
-	errTaskStatusUpdateNoChange = errors.New("agent: no change in task status")
-	errTaskUnknown              = errors.New("agent: task unknown")
-
-	errTaskInvalid = errors.New("task: invalid")
+	errTaskUnknown = errors.New("agent: task unknown")
 )
diff --git a/vendor/github.com/docker/swarmkit/agent/exec/controller.go b/vendor/github.com/docker/swarmkit/agent/exec/controller.go
index c9e9343..b617d37 100644
--- a/vendor/github.com/docker/swarmkit/agent/exec/controller.go
+++ b/vendor/github.com/docker/swarmkit/agent/exec/controller.go
@@ -1,6 +1,7 @@
 package exec
 
 import (
+	"context"
 	"fmt"
 	"time"
 
@@ -10,7 +11,6 @@
 	"github.com/docker/swarmkit/protobuf/ptypes"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 )
 
 // Controller controls execution of a task.
diff --git a/vendor/github.com/docker/swarmkit/agent/exec/controller_stub.go b/vendor/github.com/docker/swarmkit/agent/exec/controller_stub.go
index 076955f..dd16ce4 100644
--- a/vendor/github.com/docker/swarmkit/agent/exec/controller_stub.go
+++ b/vendor/github.com/docker/swarmkit/agent/exec/controller_stub.go
@@ -1,10 +1,11 @@
 package exec
 
 import (
-	"github.com/docker/swarmkit/api"
-	"golang.org/x/net/context"
+	"context"
 	"runtime"
 	"strings"
+
+	"github.com/docker/swarmkit/api"
 )
 
 // StubController implements the Controller interface,
diff --git a/vendor/github.com/docker/swarmkit/agent/exec/executor.go b/vendor/github.com/docker/swarmkit/agent/exec/executor.go
index 8c3fd03..26c1bfc 100644
--- a/vendor/github.com/docker/swarmkit/agent/exec/executor.go
+++ b/vendor/github.com/docker/swarmkit/agent/exec/executor.go
@@ -1,8 +1,9 @@
 package exec
 
 import (
+	"context"
+
 	"github.com/docker/swarmkit/api"
-	"golang.org/x/net/context"
 )
 
 // Executor provides controllers for tasks.
diff --git a/vendor/github.com/docker/swarmkit/agent/helpers.go b/vendor/github.com/docker/swarmkit/agent/helpers.go
index 5fdf166..5e95d93 100644
--- a/vendor/github.com/docker/swarmkit/agent/helpers.go
+++ b/vendor/github.com/docker/swarmkit/agent/helpers.go
@@ -1,6 +1,6 @@
 package agent
 
-import "golang.org/x/net/context"
+import "context"
 
 // runctx blocks until the function exits, closed is closed, or the context is
 // cancelled. Call as part of go statement.
diff --git a/vendor/github.com/docker/swarmkit/agent/reporter.go b/vendor/github.com/docker/swarmkit/agent/reporter.go
index 73e6ab3..2afb757 100644
--- a/vendor/github.com/docker/swarmkit/agent/reporter.go
+++ b/vendor/github.com/docker/swarmkit/agent/reporter.go
@@ -1,12 +1,12 @@
 package agent
 
 import (
+	"context"
 	"reflect"
 	"sync"
 
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
-	"golang.org/x/net/context"
 )
 
 // StatusReporter receives updates to task status. Method may be called
diff --git a/vendor/github.com/docker/swarmkit/agent/resource.go b/vendor/github.com/docker/swarmkit/agent/resource.go
index 8e88d2c..32be069 100644
--- a/vendor/github.com/docker/swarmkit/agent/resource.go
+++ b/vendor/github.com/docker/swarmkit/agent/resource.go
@@ -1,8 +1,9 @@
 package agent
 
 import (
+	"context"
+
 	"github.com/docker/swarmkit/api"
-	"golang.org/x/net/context"
 )
 
 type resourceAllocator struct {
diff --git a/vendor/github.com/docker/swarmkit/agent/session.go b/vendor/github.com/docker/swarmkit/agent/session.go
index 8c01d08..5269535 100644
--- a/vendor/github.com/docker/swarmkit/agent/session.go
+++ b/vendor/github.com/docker/swarmkit/agent/session.go
@@ -1,6 +1,7 @@
 package agent
 
 import (
+	"context"
 	"errors"
 	"sync"
 	"time"
@@ -9,7 +10,6 @@
 	"github.com/docker/swarmkit/connectionbroker"
 	"github.com/docker/swarmkit/log"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -17,7 +17,6 @@
 
 var (
 	dispatcherRPCTimeout = 5 * time.Second
-	errSessionDisconnect = errors.New("agent: session disconnect") // instructed to disconnect
 	errSessionClosed     = errors.New("agent: session closed")
 )
 
@@ -137,7 +136,7 @@
 	// `ctx` is done and hence fail to propagate the timeout error to the agent.
 	// If the error is not propogated to the agent, the agent will not close
 	// the session or rebuild a new session.
-	sessionCtx, cancelSession := context.WithCancel(ctx)
+	sessionCtx, cancelSession := context.WithCancel(ctx) // nolint: vet
 
 	// Need to run Session in a goroutine since there's no way to set a
 	// timeout for an individual Recv call in a stream.
@@ -160,7 +159,7 @@
 	select {
 	case err := <-errChan:
 		if err != nil {
-			return err
+			return err // nolint: vet
 		}
 	case <-time.After(dispatcherRPCTimeout):
 		cancelSession()
diff --git a/vendor/github.com/docker/swarmkit/agent/task.go b/vendor/github.com/docker/swarmkit/agent/task.go
index 95fe931..17c713c 100644
--- a/vendor/github.com/docker/swarmkit/agent/task.go
+++ b/vendor/github.com/docker/swarmkit/agent/task.go
@@ -1,6 +1,7 @@
 package agent
 
 import (
+	"context"
 	"sync"
 	"time"
 
@@ -8,7 +9,6 @@
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api/equality"
 	"github.com/docker/swarmkit/log"
-	"golang.org/x/net/context"
 )
 
 // taskManager manages all aspects of task execution and reporting for an agent
diff --git a/vendor/github.com/docker/swarmkit/agent/worker.go b/vendor/github.com/docker/swarmkit/agent/worker.go
index 8125145..efe538a 100644
--- a/vendor/github.com/docker/swarmkit/agent/worker.go
+++ b/vendor/github.com/docker/swarmkit/agent/worker.go
@@ -1,6 +1,7 @@
 package agent
 
 import (
+	"context"
 	"sync"
 
 	"github.com/docker/swarmkit/agent/exec"
@@ -9,7 +10,6 @@
 	"github.com/docker/swarmkit/watch"
 	"github.com/sirupsen/logrus"
 	bolt "go.etcd.io/bbolt"
-	"golang.org/x/net/context"
 )
 
 // Worker implements the core task management logic and persistence. It
diff --git a/vendor/github.com/docker/swarmkit/api/genericresource/resource_management.go b/vendor/github.com/docker/swarmkit/api/genericresource/resource_management.go
index a89a118..506257a 100644
--- a/vendor/github.com/docker/swarmkit/api/genericresource/resource_management.go
+++ b/vendor/github.com/docker/swarmkit/api/genericresource/resource_management.go
@@ -2,6 +2,7 @@
 
 import (
 	"fmt"
+
 	"github.com/docker/swarmkit/api"
 )
 
diff --git a/vendor/github.com/docker/swarmkit/api/genericresource/validate.go b/vendor/github.com/docker/swarmkit/api/genericresource/validate.go
index eee3706..0ad49ff 100644
--- a/vendor/github.com/docker/swarmkit/api/genericresource/validate.go
+++ b/vendor/github.com/docker/swarmkit/api/genericresource/validate.go
@@ -2,6 +2,7 @@
 
 import (
 	"fmt"
+
 	"github.com/docker/swarmkit/api"
 )
 
diff --git a/vendor/github.com/docker/swarmkit/ca/auth.go b/vendor/github.com/docker/swarmkit/ca/auth.go
index df4547f..e0ff898 100644
--- a/vendor/github.com/docker/swarmkit/ca/auth.go
+++ b/vendor/github.com/docker/swarmkit/ca/auth.go
@@ -1,6 +1,7 @@
 package ca
 
 import (
+	"context"
 	"crypto/tls"
 	"crypto/x509/pkix"
 	"strings"
@@ -9,7 +10,6 @@
 
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/peer"
diff --git a/vendor/github.com/docker/swarmkit/ca/certificates.go b/vendor/github.com/docker/swarmkit/ca/certificates.go
index ad2be2c..dd0297a 100644
--- a/vendor/github.com/docker/swarmkit/ca/certificates.go
+++ b/vendor/github.com/docker/swarmkit/ca/certificates.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"context"
 	"crypto"
 	"crypto/ecdsa"
 	"crypto/elliptic"
@@ -31,7 +32,6 @@
 	"github.com/docker/swarmkit/ioutils"
 	"github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/credentials"
diff --git a/vendor/github.com/docker/swarmkit/ca/config.go b/vendor/github.com/docker/swarmkit/ca/config.go
index 4a7230a..4befee5 100644
--- a/vendor/github.com/docker/swarmkit/ca/config.go
+++ b/vendor/github.com/docker/swarmkit/ca/config.go
@@ -1,6 +1,7 @@
 package ca
 
 import (
+	"context"
 	cryptorand "crypto/rand"
 	"crypto/tls"
 	"crypto/x509"
@@ -23,8 +24,6 @@
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"google.golang.org/grpc/credentials"
-
-	"golang.org/x/net/context"
 )
 
 const (
@@ -32,7 +31,6 @@
 	rootCAKeyFilename   = "swarm-root-ca.key"
 	nodeTLSCertFilename = "swarm-node.crt"
 	nodeTLSKeyFilename  = "swarm-node.key"
-	nodeCSRFilename     = "swarm-node.csr"
 
 	// DefaultRootCN represents the root CN that we should create roots CAs with by default
 	DefaultRootCN = "swarm-ca"
@@ -626,10 +624,10 @@
 	if maxValidity-minValidity < 1 {
 		randomExpiry = minValidity
 	} else {
-		randomExpiry = rand.Intn(maxValidity-minValidity) + int(minValidity)
+		randomExpiry = rand.Intn(maxValidity-minValidity) + minValidity
 	}
 
-	expiry := validFrom.Add(time.Duration(randomExpiry) * time.Minute).Sub(time.Now())
+	expiry := time.Until(validFrom.Add(time.Duration(randomExpiry) * time.Minute))
 	if expiry < 0 {
 		return 0
 	}
diff --git a/vendor/github.com/docker/swarmkit/ca/external.go b/vendor/github.com/docker/swarmkit/ca/external.go
index 789361e..6b81204 100644
--- a/vendor/github.com/docker/swarmkit/ca/external.go
+++ b/vendor/github.com/docker/swarmkit/ca/external.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"context"
 	cryptorand "crypto/rand"
 	"crypto/tls"
 	"crypto/x509"
@@ -21,7 +22,6 @@
 	"github.com/docker/swarmkit/log"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"golang.org/x/net/context/ctxhttp"
 )
 
diff --git a/vendor/github.com/docker/swarmkit/ca/forward.go b/vendor/github.com/docker/swarmkit/ca/forward.go
index a05cf53..7ad7c7d 100644
--- a/vendor/github.com/docker/swarmkit/ca/forward.go
+++ b/vendor/github.com/docker/swarmkit/ca/forward.go
@@ -1,7 +1,8 @@
 package ca
 
 import (
-	"golang.org/x/net/context"
+	"context"
+
 	"google.golang.org/grpc/metadata"
 	"google.golang.org/grpc/peer"
 )
diff --git a/vendor/github.com/docker/swarmkit/ca/renewer.go b/vendor/github.com/docker/swarmkit/ca/renewer.go
index 2a2fae7..e5d165f 100644
--- a/vendor/github.com/docker/swarmkit/ca/renewer.go
+++ b/vendor/github.com/docker/swarmkit/ca/renewer.go
@@ -1,6 +1,7 @@
 package ca
 
 import (
+	"context"
 	"sync"
 	"time"
 
@@ -9,7 +10,6 @@
 	"github.com/docker/swarmkit/log"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 )
 
 // RenewTLSExponentialBackoff sets the exponential backoff when trying to renew TLS certificates that have expired
diff --git a/vendor/github.com/docker/swarmkit/ca/server.go b/vendor/github.com/docker/swarmkit/ca/server.go
index a456df7..c3e8999 100644
--- a/vendor/github.com/docker/swarmkit/ca/server.go
+++ b/vendor/github.com/docker/swarmkit/ca/server.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"context"
 	"crypto/subtle"
 	"crypto/x509"
 	"sync"
@@ -15,7 +16,6 @@
 	gogotypes "github.com/gogo/protobuf/types"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/ca/transport.go b/vendor/github.com/docker/swarmkit/ca/transport.go
index 35943af..69c4379 100644
--- a/vendor/github.com/docker/swarmkit/ca/transport.go
+++ b/vendor/github.com/docker/swarmkit/ca/transport.go
@@ -1,6 +1,7 @@
 package ca
 
 import (
+	"context"
 	"crypto/tls"
 	"crypto/x509"
 	"crypto/x509/pkix"
@@ -9,7 +10,6 @@
 	"sync"
 
 	"github.com/pkg/errors"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/credentials"
 )
 
@@ -18,12 +18,6 @@
 	alpnProtoStr = []string{"h2"}
 )
 
-type timeoutError struct{}
-
-func (timeoutError) Error() string   { return "mutablecredentials: Dial timed out" }
-func (timeoutError) Timeout() bool   { return true }
-func (timeoutError) Temporary() bool { return true }
-
 // MutableTLSCreds is the credentials required for authenticating a connection using TLS.
 type MutableTLSCreds struct {
 	// Mutex for the tls config
diff --git a/vendor/github.com/docker/swarmkit/log/context.go b/vendor/github.com/docker/swarmkit/log/context.go
index ac4f848..cc1d590 100644
--- a/vendor/github.com/docker/swarmkit/log/context.go
+++ b/vendor/github.com/docker/swarmkit/log/context.go
@@ -1,10 +1,10 @@
 package log
 
 import (
+	"context"
 	"path"
 
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 )
 
 var (
diff --git a/vendor/github.com/docker/swarmkit/log/grpc.go b/vendor/github.com/docker/swarmkit/log/grpc.go
index 0417c94..bced5cf 100644
--- a/vendor/github.com/docker/swarmkit/log/grpc.go
+++ b/vendor/github.com/docker/swarmkit/log/grpc.go
@@ -1,8 +1,9 @@
 package log
 
 import (
+	"context"
+
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/grpclog"
 )
 
diff --git a/vendor/github.com/docker/swarmkit/manager/allocator/allocator.go b/vendor/github.com/docker/swarmkit/manager/allocator/allocator.go
index e8b7e88..b4cc1c9 100644
--- a/vendor/github.com/docker/swarmkit/manager/allocator/allocator.go
+++ b/vendor/github.com/docker/swarmkit/manager/allocator/allocator.go
@@ -1,6 +1,7 @@
 package allocator
 
 import (
+	"context"
 	"sync"
 
 	"github.com/docker/docker/pkg/plugingetter"
@@ -9,7 +10,6 @@
 	"github.com/docker/swarmkit/manager/allocator/cnmallocator"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 )
 
 // Allocator controls how the allocation stage in the manager is handled.
diff --git a/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/networkallocator.go b/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/networkallocator.go
index 7a78640..c1ffc06 100644
--- a/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/networkallocator.go
+++ b/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/networkallocator.go
@@ -1,6 +1,7 @@
 package cnmallocator
 
 import (
+	"context"
 	"fmt"
 	"net"
 	"strings"
@@ -16,7 +17,6 @@
 	"github.com/docker/swarmkit/manager/allocator/networkallocator"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 )
 
 const (
@@ -815,8 +815,7 @@
 
 	d, drvcap := na.drvRegistry.Driver(dName)
 	if d == nil {
-		var err error
-		err = na.loadDriver(dName)
+		err := na.loadDriver(dName)
 		if err != nil {
 			return nil, err
 		}
diff --git a/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/portallocator.go b/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/portallocator.go
index 113f900..81447cb 100644
--- a/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/portallocator.go
+++ b/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/portallocator.go
@@ -407,12 +407,12 @@
 	}
 	defer func() {
 		if err != nil {
-			ps.dynamicPortSpace.Release(uint64(swarmPort))
+			ps.dynamicPortSpace.Release(swarmPort)
 		}
 	}()
 
 	// Make sure we allocate the same port from the master space.
-	if err = ps.masterPortSpace.GetSpecificID(uint64(swarmPort)); err != nil {
+	if err = ps.masterPortSpace.GetSpecificID(swarmPort); err != nil {
 		return
 	}
 
diff --git a/vendor/github.com/docker/swarmkit/manager/allocator/network.go b/vendor/github.com/docker/swarmkit/manager/allocator/network.go
index e4d5b61..f917162 100644
--- a/vendor/github.com/docker/swarmkit/manager/allocator/network.go
+++ b/vendor/github.com/docker/swarmkit/manager/allocator/network.go
@@ -1,6 +1,7 @@
 package allocator
 
 import (
+	"context"
 	"fmt"
 	"time"
 
@@ -13,7 +14,6 @@
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/protobuf/ptypes"
 	"github.com/pkg/errors"
-	"golang.org/x/net/context"
 )
 
 const (
@@ -998,6 +998,10 @@
 		}
 
 		if lbAttachment == nil {
+			// if we're restoring state, we should not add an attachment here.
+			if existingAddressesOnly {
+				continue
+			}
 			lbAttachment = &api.NetworkAttachment{}
 			node.Attachments = append(node.Attachments, lbAttachment)
 		}
diff --git a/vendor/github.com/docker/swarmkit/manager/constraint/constraint.go b/vendor/github.com/docker/swarmkit/manager/constraint/constraint.go
index 9f13217..6c49c07 100644
--- a/vendor/github.com/docker/swarmkit/manager/constraint/constraint.go
+++ b/vendor/github.com/docker/swarmkit/manager/constraint/constraint.go
@@ -56,7 +56,7 @@
 			part0 := strings.TrimSpace(parts[0])
 			// validate key
 			matched := alphaNumeric.MatchString(part0)
-			if matched == false {
+			if !matched {
 				return nil, fmt.Errorf("key '%s' is invalid", part0)
 			}
 
@@ -64,7 +64,7 @@
 
 			// validate Value
 			matched = valuePattern.MatchString(part1)
-			if matched == false {
+			if !matched {
 				return nil, fmt.Errorf("value '%s' is invalid", part1)
 			}
 			// TODO(dongluochen): revisit requirements to see if globing or regex are useful
diff --git a/vendor/github.com/docker/swarmkit/manager/controlapi/cluster.go b/vendor/github.com/docker/swarmkit/manager/controlapi/cluster.go
index ad24804..4865b81 100644
--- a/vendor/github.com/docker/swarmkit/manager/controlapi/cluster.go
+++ b/vendor/github.com/docker/swarmkit/manager/controlapi/cluster.go
@@ -1,6 +1,7 @@
 package controlapi
 
 import (
+	"context"
 	"strings"
 	"time"
 
@@ -10,7 +11,6 @@
 	"github.com/docker/swarmkit/manager/encryption"
 	"github.com/docker/swarmkit/manager/state/store"
 	gogotypes "github.com/gogo/protobuf/types"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/manager/controlapi/config.go b/vendor/github.com/docker/swarmkit/manager/controlapi/config.go
index ae08885..bc8726f 100644
--- a/vendor/github.com/docker/swarmkit/manager/controlapi/config.go
+++ b/vendor/github.com/docker/swarmkit/manager/controlapi/config.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"context"
 	"strings"
 
 	"github.com/docker/swarmkit/api"
@@ -9,7 +10,6 @@
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/manager/controlapi/network.go b/vendor/github.com/docker/swarmkit/manager/controlapi/network.go
index 481b0cf..d3047fe 100644
--- a/vendor/github.com/docker/swarmkit/manager/controlapi/network.go
+++ b/vendor/github.com/docker/swarmkit/manager/controlapi/network.go
@@ -1,6 +1,7 @@
 package controlapi
 
 import (
+	"context"
 	"net"
 
 	"github.com/docker/docker/pkg/plugingetter"
@@ -11,7 +12,6 @@
 	"github.com/docker/swarmkit/manager/allocator"
 	"github.com/docker/swarmkit/manager/allocator/networkallocator"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/manager/controlapi/node.go b/vendor/github.com/docker/swarmkit/manager/controlapi/node.go
index b2d15df..68a759f 100644
--- a/vendor/github.com/docker/swarmkit/manager/controlapi/node.go
+++ b/vendor/github.com/docker/swarmkit/manager/controlapi/node.go
@@ -1,6 +1,7 @@
 package controlapi
 
 import (
+	"context"
 	"crypto/x509"
 	"encoding/pem"
 
@@ -8,7 +9,6 @@
 	"github.com/docker/swarmkit/manager/state/raft/membership"
 	"github.com/docker/swarmkit/manager/state/store"
 	gogotypes "github.com/gogo/protobuf/types"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/manager/controlapi/secret.go b/vendor/github.com/docker/swarmkit/manager/controlapi/secret.go
index fdcd2c4..f3d87d1 100644
--- a/vendor/github.com/docker/swarmkit/manager/controlapi/secret.go
+++ b/vendor/github.com/docker/swarmkit/manager/controlapi/secret.go
@@ -1,6 +1,7 @@
 package controlapi
 
 import (
+	"context"
 	"crypto/subtle"
 	"strings"
 
@@ -10,7 +11,6 @@
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/manager/controlapi/service.go b/vendor/github.com/docker/swarmkit/manager/controlapi/service.go
index 3912052..17bc250 100644
--- a/vendor/github.com/docker/swarmkit/manager/controlapi/service.go
+++ b/vendor/github.com/docker/swarmkit/manager/controlapi/service.go
@@ -1,6 +1,7 @@
 package controlapi
 
 import (
+	"context"
 	"errors"
 	"reflect"
 	"strings"
@@ -18,7 +19,6 @@
 	"github.com/docker/swarmkit/protobuf/ptypes"
 	"github.com/docker/swarmkit/template"
 	gogotypes "github.com/gogo/protobuf/types"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
@@ -197,7 +197,7 @@
 		if err != nil {
 			return err
 		}
-		if interval != 0 && interval < time.Duration(minimumDuration) {
+		if interval != 0 && interval < minimumDuration {
 			return status.Errorf(codes.InvalidArgument, "ContainerSpec: Interval in HealthConfig cannot be less than %s", minimumDuration)
 		}
 	}
@@ -207,7 +207,7 @@
 		if err != nil {
 			return err
 		}
-		if timeout != 0 && timeout < time.Duration(minimumDuration) {
+		if timeout != 0 && timeout < minimumDuration {
 			return status.Errorf(codes.InvalidArgument, "ContainerSpec: Timeout in HealthConfig cannot be less than %s", minimumDuration)
 		}
 	}
@@ -217,7 +217,7 @@
 		if err != nil {
 			return err
 		}
-		if sp != 0 && sp < time.Duration(minimumDuration) {
+		if sp != 0 && sp < minimumDuration {
 			return status.Errorf(codes.InvalidArgument, "ContainerSpec: StartPeriod in HealthConfig cannot be less than %s", minimumDuration)
 		}
 	}
diff --git a/vendor/github.com/docker/swarmkit/manager/controlapi/task.go b/vendor/github.com/docker/swarmkit/manager/controlapi/task.go
index dc56e74..5f85f9a 100644
--- a/vendor/github.com/docker/swarmkit/manager/controlapi/task.go
+++ b/vendor/github.com/docker/swarmkit/manager/controlapi/task.go
@@ -1,11 +1,12 @@
 package controlapi
 
 import (
+	"context"
+
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api/naming"
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go b/vendor/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go
index 569ab26..6149806 100644
--- a/vendor/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go
+++ b/vendor/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go
@@ -1,6 +1,7 @@
 package dispatcher
 
 import (
+	"context"
 	"fmt"
 	"net"
 	"strconv"
@@ -21,7 +22,6 @@
 	gogotypes "github.com/gogo/protobuf/types"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
@@ -1090,14 +1090,10 @@
 				task.Status.State = api.TaskStateOrphaned
 			}
 
-			if err := batch.Update(func(tx store.Tx) error {
-				err := store.UpdateTask(tx, task)
-				if err != nil {
-					return err
-				}
-
-				return nil
-			}); err != nil {
+			err := batch.Update(func(tx store.Tx) error {
+				return store.UpdateTask(tx, task)
+			})
+			if err != nil {
 				return err
 			}
 
diff --git a/vendor/github.com/docker/swarmkit/manager/dispatcher/nodes.go b/vendor/github.com/docker/swarmkit/manager/dispatcher/nodes.go
index cf35bb8..fae6dc5 100644
--- a/vendor/github.com/docker/swarmkit/manager/dispatcher/nodes.go
+++ b/vendor/github.com/docker/swarmkit/manager/dispatcher/nodes.go
@@ -156,7 +156,7 @@
 		return 0, err
 	}
 	period := s.periodChooser.Choose() // base period for node
-	grace := period * time.Duration(s.gracePeriodMultiplierNormal)
+	grace := period * s.gracePeriodMultiplierNormal
 	rn.mu.Lock()
 	rn.Heartbeat.Update(grace)
 	rn.Heartbeat.Beat()
diff --git a/vendor/github.com/docker/swarmkit/manager/health/health.go b/vendor/github.com/docker/swarmkit/manager/health/health.go
index ef6658b..d75cbf4 100644
--- a/vendor/github.com/docker/swarmkit/manager/health/health.go
+++ b/vendor/github.com/docker/swarmkit/manager/health/health.go
@@ -8,10 +8,10 @@
 package health
 
 import (
+	"context"
 	"sync"
 
 	"github.com/docker/swarmkit/api"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/manager/keymanager/keymanager.go b/vendor/github.com/docker/swarmkit/manager/keymanager/keymanager.go
index e61979c..7a5d7bf 100644
--- a/vendor/github.com/docker/swarmkit/manager/keymanager/keymanager.go
+++ b/vendor/github.com/docker/swarmkit/manager/keymanager/keymanager.go
@@ -6,6 +6,7 @@
 // which is used to exchange service discovery and overlay network control
 // plane information. It can also be used to encrypt overlay data traffic.
 import (
+	"context"
 	cryptorand "crypto/rand"
 	"encoding/binary"
 	"sync"
@@ -15,7 +16,6 @@
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/pkg/errors"
-	"golang.org/x/net/context"
 )
 
 const (
diff --git a/vendor/github.com/docker/swarmkit/manager/logbroker/broker.go b/vendor/github.com/docker/swarmkit/manager/logbroker/broker.go
index dfc898e..c19438a 100644
--- a/vendor/github.com/docker/swarmkit/manager/logbroker/broker.go
+++ b/vendor/github.com/docker/swarmkit/manager/logbroker/broker.go
@@ -1,6 +1,7 @@
 package logbroker
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"io"
@@ -14,7 +15,6 @@
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/watch"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/manager/logbroker/subscription.go b/vendor/github.com/docker/swarmkit/manager/logbroker/subscription.go
index b9c9c7b..883ddce 100644
--- a/vendor/github.com/docker/swarmkit/manager/logbroker/subscription.go
+++ b/vendor/github.com/docker/swarmkit/manager/logbroker/subscription.go
@@ -1,6 +1,7 @@
 package logbroker
 
 import (
+	"context"
 	"fmt"
 	"strings"
 	"sync"
@@ -11,7 +12,6 @@
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/watch"
-	"golang.org/x/net/context"
 )
 
 type subscription struct {
diff --git a/vendor/github.com/docker/swarmkit/manager/manager.go b/vendor/github.com/docker/swarmkit/manager/manager.go
index 106c8e2..08b158d 100644
--- a/vendor/github.com/docker/swarmkit/manager/manager.go
+++ b/vendor/github.com/docker/swarmkit/manager/manager.go
@@ -1,6 +1,7 @@
 package manager
 
 import (
+	"context"
 	"crypto/tls"
 	"fmt"
 	"net"
@@ -45,7 +46,6 @@
 	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials"
 )
@@ -1002,9 +1002,7 @@
 			cluster = store.GetCluster(tx, clusterID)
 		})
 		if cluster.DefaultAddressPool != nil {
-			for _, address := range cluster.DefaultAddressPool {
-				m.config.NetworkConfig.DefaultAddrPool = append(m.config.NetworkConfig.DefaultAddrPool, address)
-			}
+			m.config.NetworkConfig.DefaultAddrPool = append(m.config.NetworkConfig.DefaultAddrPool, cluster.DefaultAddressPool...)
 			m.config.NetworkConfig.SubnetSize = cluster.SubnetSize
 		}
 	}
diff --git a/vendor/github.com/docker/swarmkit/manager/metrics/collector.go b/vendor/github.com/docker/swarmkit/manager/metrics/collector.go
index 3847437..5539a89 100644
--- a/vendor/github.com/docker/swarmkit/manager/metrics/collector.go
+++ b/vendor/github.com/docker/swarmkit/manager/metrics/collector.go
@@ -188,7 +188,6 @@
 	if newNode != nil {
 		nodesMetric.WithValues(strings.ToLower(newNode.Status.State.String())).Inc(1)
 	}
-	return
 }
 
 func (c *Collector) handleTaskEvent(event events.Event) {
@@ -218,8 +217,6 @@
 			strings.ToLower(newTask.Status.State.String()),
 		).Inc(1)
 	}
-
-	return
 }
 
 func (c *Collector) handleServiceEvent(event events.Event) {
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/global/global.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/global/global.go
index 2b20813..715781e 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/global/global.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/global/global.go
@@ -1,6 +1,8 @@
 package global
 
 import (
+	"context"
+
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/constraint"
@@ -9,7 +11,6 @@
 	"github.com/docker/swarmkit/manager/orchestrator/taskinit"
 	"github.com/docker/swarmkit/manager/orchestrator/update"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 )
 
 type globalService struct {
@@ -585,11 +586,3 @@
 		NodeID:    t.NodeID,
 	}
 }
-
-func isTaskCompleted(t *api.Task, restartPolicy api.RestartPolicy_RestartCondition) bool {
-	if t == nil || t.DesiredState <= api.TaskStateRunning {
-		return false
-	}
-	return restartPolicy == api.RestartOnNone ||
-		(restartPolicy == api.RestartOnFailure && t.Status.State == api.TaskStateCompleted)
-}
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/replicated.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/replicated.go
index 18b8e24..dc45528 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/replicated.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/replicated.go
@@ -1,12 +1,13 @@
 package replicated
 
 import (
+	"context"
+
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/manager/orchestrator/restart"
 	"github.com/docker/swarmkit/manager/orchestrator/update"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 )
 
 // An Orchestrator runs a reconciliation loop to create and destroy
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/services.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/services.go
index 04aea87..b5e6bb1 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/services.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/services.go
@@ -1,6 +1,7 @@
 package replicated
 
 import (
+	"context"
 	"sort"
 
 	"github.com/docker/go-events"
@@ -8,7 +9,6 @@
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 )
 
 // This file provices service-level orchestration. It observes changes to
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/slot.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/slot.go
index cee9fe1..1160d4c 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/slot.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/slot.go
@@ -1,10 +1,11 @@
 package replicated
 
 import (
+	"context"
+
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 )
 
 type slotsByRunningState []orchestrator.Slot
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/tasks.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/tasks.go
index 66000e5..b6336aa 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/tasks.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/replicated/tasks.go
@@ -1,13 +1,14 @@
 package replicated
 
 import (
+	"context"
+
 	"github.com/docker/go-events"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/orchestrator/taskinit"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 )
 
 // This file provides task-level orchestration. It observes changes to task
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/restart/restart.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/restart/restart.go
index 6af44b7..c034183 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/restart/restart.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/restart/restart.go
@@ -2,6 +2,7 @@
 
 import (
 	"container/list"
+	"context"
 	"errors"
 	"sync"
 	"time"
@@ -14,7 +15,6 @@
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	gogotypes "github.com/gogo/protobuf/types"
-	"golang.org/x/net/context"
 )
 
 const defaultOldTaskTimeout = time.Minute
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/service.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/service.go
index 7356c38..037e493 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/service.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/service.go
@@ -1,10 +1,11 @@
 package orchestrator
 
 import (
+	"context"
+
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 )
 
 // IsReplicatedService checks if a service is a replicated service.
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/taskinit/init.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/taskinit/init.go
index b893428..be319cc 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/taskinit/init.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/taskinit/init.go
@@ -1,6 +1,7 @@
 package taskinit
 
 import (
+	"context"
 	"sort"
 	"time"
 
@@ -11,7 +12,6 @@
 	"github.com/docker/swarmkit/manager/orchestrator/restart"
 	"github.com/docker/swarmkit/manager/state/store"
 	gogotypes "github.com/gogo/protobuf/types"
-	"golang.org/x/net/context"
 )
 
 // InitHandler defines orchestrator's action to fix tasks at start.
@@ -80,7 +80,7 @@
 				}
 				if err == nil {
 					restartTime := timestamp.Add(restartDelay)
-					calculatedRestartDelay := restartTime.Sub(time.Now())
+					calculatedRestartDelay := time.Until(restartTime)
 					if calculatedRestartDelay < restartDelay {
 						restartDelay = calculatedRestartDelay
 					}
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/taskreaper/task_reaper.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/taskreaper/task_reaper.go
index cbeb321..5d2d2c7 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/taskreaper/task_reaper.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/taskreaper/task_reaper.go
@@ -1,6 +1,7 @@
 package taskreaper
 
 import (
+	"context"
 	"sort"
 	"sync"
 	"time"
@@ -10,7 +11,6 @@
 	"github.com/docker/swarmkit/manager/orchestrator"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 )
 
 const (
diff --git a/vendor/github.com/docker/swarmkit/manager/orchestrator/update/updater.go b/vendor/github.com/docker/swarmkit/manager/orchestrator/update/updater.go
index 5a7d612..7c977db 100644
--- a/vendor/github.com/docker/swarmkit/manager/orchestrator/update/updater.go
+++ b/vendor/github.com/docker/swarmkit/manager/orchestrator/update/updater.go
@@ -1,14 +1,13 @@
 package update
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"reflect"
 	"sync"
 	"time"
 
-	"golang.org/x/net/context"
-
 	"github.com/docker/go-events"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api/defaults"
diff --git a/vendor/github.com/docker/swarmkit/manager/raftselector/raftselector.go b/vendor/github.com/docker/swarmkit/manager/raftselector/raftselector.go
index 89e7918..47adcf0 100644
--- a/vendor/github.com/docker/swarmkit/manager/raftselector/raftselector.go
+++ b/vendor/github.com/docker/swarmkit/manager/raftselector/raftselector.go
@@ -1,10 +1,9 @@
 package raftselector
 
 import (
+	"context"
 	"errors"
 
-	"golang.org/x/net/context"
-
 	"google.golang.org/grpc"
 )
 
diff --git a/vendor/github.com/docker/swarmkit/manager/resourceapi/allocator.go b/vendor/github.com/docker/swarmkit/manager/resourceapi/allocator.go
index ec19fba..545e4de 100644
--- a/vendor/github.com/docker/swarmkit/manager/resourceapi/allocator.go
+++ b/vendor/github.com/docker/swarmkit/manager/resourceapi/allocator.go
@@ -1,6 +1,7 @@
 package resourceapi
 
 import (
+	"context"
 	"errors"
 	"time"
 
@@ -9,7 +10,6 @@
 	"github.com/docker/swarmkit/identity"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/protobuf/ptypes"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
diff --git a/vendor/github.com/docker/swarmkit/manager/role_manager.go b/vendor/github.com/docker/swarmkit/manager/role_manager.go
index e5cf27b..a68bc3f 100644
--- a/vendor/github.com/docker/swarmkit/manager/role_manager.go
+++ b/vendor/github.com/docker/swarmkit/manager/role_manager.go
@@ -1,6 +1,7 @@
 package manager
 
 import (
+	"context"
 	"time"
 
 	"github.com/docker/swarmkit/api"
@@ -9,7 +10,6 @@
 	"github.com/docker/swarmkit/manager/state/raft/membership"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/pivotal-golang/clock"
-	"golang.org/x/net/context"
 )
 
 const (
diff --git a/vendor/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go b/vendor/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go
index 78fa630..3094402 100644
--- a/vendor/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go
+++ b/vendor/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go
@@ -1,12 +1,12 @@
 package scheduler
 
 import (
+	"context"
 	"time"
 
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api/genericresource"
 	"github.com/docker/swarmkit/log"
-	"golang.org/x/net/context"
 )
 
 // hostPortSpec specifies a used host port.
diff --git a/vendor/github.com/docker/swarmkit/manager/scheduler/scheduler.go b/vendor/github.com/docker/swarmkit/manager/scheduler/scheduler.go
index 9e708ed..939fc6f 100644
--- a/vendor/github.com/docker/swarmkit/manager/scheduler/scheduler.go
+++ b/vendor/github.com/docker/swarmkit/manager/scheduler/scheduler.go
@@ -1,6 +1,7 @@
 package scheduler
 
 import (
+	"context"
 	"time"
 
 	"github.com/docker/swarmkit/api"
@@ -9,7 +10,6 @@
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/protobuf/ptypes"
-	"golang.org/x/net/context"
 )
 
 const (
diff --git a/vendor/github.com/docker/swarmkit/manager/state/proposer.go b/vendor/github.com/docker/swarmkit/manager/state/proposer.go
index 4967f98..8d53f57 100644
--- a/vendor/github.com/docker/swarmkit/manager/state/proposer.go
+++ b/vendor/github.com/docker/swarmkit/manager/state/proposer.go
@@ -1,8 +1,9 @@
 package state
 
 import (
+	"context"
+
 	"github.com/docker/swarmkit/api"
-	"golang.org/x/net/context"
 )
 
 // A Change includes a version number and a set of store actions from a
diff --git a/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go b/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go
index 38c61c7..a1193b7 100644
--- a/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go
+++ b/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go
@@ -1,6 +1,7 @@
 package raft
 
 import (
+	"context"
 	"fmt"
 	"io"
 	"math"
@@ -30,7 +31,6 @@
 	"github.com/pivotal-golang/clock"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context"
 	"golang.org/x/time/rate"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
@@ -1182,11 +1182,8 @@
 	}
 
 	nquorum := (len(members)-1)/2 + 1
-	if nreachable < nquorum {
-		return false
-	}
 
-	return true
+	return nreachable >= nquorum
 }
 
 func (n *Node) removeMember(ctx context.Context, id uint64) error {
@@ -1591,10 +1588,7 @@
 	defer cancel()
 	_, err := n.processInternalRaftRequest(ctx, &api.InternalRaftRequest{Action: storeAction}, cb)
 
-	if err != nil {
-		return err
-	}
-	return nil
+	return err
 }
 
 // GetVersion returns the sequence information for the current raft round.
diff --git a/vendor/github.com/docker/swarmkit/manager/state/raft/storage.go b/vendor/github.com/docker/swarmkit/manager/state/raft/storage.go
index 547b775..915cc3f 100644
--- a/vendor/github.com/docker/swarmkit/manager/state/raft/storage.go
+++ b/vendor/github.com/docker/swarmkit/manager/state/raft/storage.go
@@ -1,6 +1,7 @@
 package raft
 
 import (
+	"context"
 	"fmt"
 
 	"github.com/coreos/etcd/raft"
@@ -13,7 +14,6 @@
 	"github.com/docker/swarmkit/manager/state/raft/storage"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/pkg/errors"
-	"golang.org/x/net/context"
 )
 
 var (
diff --git a/vendor/github.com/docker/swarmkit/manager/state/raft/storage/storage.go b/vendor/github.com/docker/swarmkit/manager/state/raft/storage/storage.go
index bbd262f..64d8218 100644
--- a/vendor/github.com/docker/swarmkit/manager/state/raft/storage/storage.go
+++ b/vendor/github.com/docker/swarmkit/manager/state/raft/storage/storage.go
@@ -1,13 +1,12 @@
 package storage
 
 import (
+	"context"
 	"fmt"
 	"os"
 	"path/filepath"
 	"sync"
 
-	"golang.org/x/net/context"
-
 	"github.com/coreos/etcd/pkg/fileutil"
 	"github.com/coreos/etcd/raft/raftpb"
 	"github.com/coreos/etcd/snap"
diff --git a/vendor/github.com/docker/swarmkit/manager/state/raft/storage/walwrap.go b/vendor/github.com/docker/swarmkit/manager/state/raft/storage/walwrap.go
index 3c1208c..d115597 100644
--- a/vendor/github.com/docker/swarmkit/manager/state/raft/storage/walwrap.go
+++ b/vendor/github.com/docker/swarmkit/manager/state/raft/storage/walwrap.go
@@ -1,6 +1,7 @@
 package storage
 
 import (
+	"context"
 	"io"
 	"io/ioutil"
 	"os"
@@ -14,7 +15,6 @@
 	"github.com/docker/swarmkit/log"
 	"github.com/docker/swarmkit/manager/encryption"
 	"github.com/pkg/errors"
-	"golang.org/x/net/context"
 )
 
 // This package wraps the github.com/coreos/etcd/wal package, and encrypts
diff --git a/vendor/github.com/docker/swarmkit/manager/state/raft/transport/peer.go b/vendor/github.com/docker/swarmkit/manager/state/raft/transport/peer.go
index 644e295..6fb3952 100644
--- a/vendor/github.com/docker/swarmkit/manager/state/raft/transport/peer.go
+++ b/vendor/github.com/docker/swarmkit/manager/state/raft/transport/peer.go
@@ -1,12 +1,11 @@
 package transport
 
 import (
+	"context"
 	"fmt"
 	"sync"
 	"time"
 
-	"golang.org/x/net/context"
-
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 
diff --git a/vendor/github.com/docker/swarmkit/manager/state/raft/transport/transport.go b/vendor/github.com/docker/swarmkit/manager/state/raft/transport/transport.go
index b741c4a..6bd0bc3 100644
--- a/vendor/github.com/docker/swarmkit/manager/state/raft/transport/transport.go
+++ b/vendor/github.com/docker/swarmkit/manager/state/raft/transport/transport.go
@@ -3,12 +3,12 @@
 package transport
 
 import (
+	"context"
+	"math"
 	"net"
 	"sync"
 	"time"
 
-	"golang.org/x/net/context"
-
 	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials"
@@ -355,6 +355,15 @@
 			return net.DialTimeout("tcp", addr, timeout)
 		}))
 
+	// TODO(dperny): this changes the max received message size for outgoing
+	// client connections. this means if the server sends a message larger than
+	// this, we will still accept and unmarshal it. i'm unsure what the
+	// potential consequences are of setting this to be effectively unbounded,
+	// so after docker/swarmkit#2774 is fixed, we should remove this option
+	grpcOptions = append(grpcOptions, grpc.WithDefaultCallOptions(
+		grpc.MaxCallRecvMsgSize(math.MaxInt32),
+	))
+
 	cc, err := grpc.Dial(addr, grpcOptions...)
 	if err != nil {
 		return nil, err
diff --git a/vendor/github.com/docker/swarmkit/manager/state/raft/util.go b/vendor/github.com/docker/swarmkit/manager/state/raft/util.go
index da44dca..75872fe 100644
--- a/vendor/github.com/docker/swarmkit/manager/state/raft/util.go
+++ b/vendor/github.com/docker/swarmkit/manager/state/raft/util.go
@@ -1,10 +1,9 @@
 package raft
 
 import (
+	"context"
 	"time"
 
-	"golang.org/x/net/context"
-
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
diff --git a/vendor/github.com/docker/swarmkit/manager/state/store/memory.go b/vendor/github.com/docker/swarmkit/manager/state/store/memory.go
index 423f04c..d0319c7 100644
--- a/vendor/github.com/docker/swarmkit/manager/state/store/memory.go
+++ b/vendor/github.com/docker/swarmkit/manager/state/store/memory.go
@@ -1,6 +1,7 @@
 package store
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"runtime"
@@ -18,7 +19,6 @@
 	"github.com/docker/swarmkit/watch"
 	gogotypes "github.com/gogo/protobuf/types"
 	memdb "github.com/hashicorp/go-memdb"
-	"golang.org/x/net/context"
 )
 
 const (
@@ -689,7 +689,7 @@
 		}
 		return []memdb.ResultIterator{it}, nil
 	case bySlot:
-		it, err := tx.memDBTx.Get(table, indexSlot, v.serviceID+"\x00"+strconv.FormatUint(uint64(v.slot), 10))
+		it, err := tx.memDBTx.Get(table, indexSlot, v.serviceID+"\x00"+strconv.FormatUint(v.slot, 10))
 		if err != nil {
 			return nil, err
 		}
diff --git a/vendor/github.com/docker/swarmkit/manager/watchapi/server.go b/vendor/github.com/docker/swarmkit/manager/watchapi/server.go
index 6d49dca..eb086b8 100644
--- a/vendor/github.com/docker/swarmkit/manager/watchapi/server.go
+++ b/vendor/github.com/docker/swarmkit/manager/watchapi/server.go
@@ -1,11 +1,11 @@
 package watchapi
 
 import (
+	"context"
 	"errors"
 	"sync"
 
 	"github.com/docker/swarmkit/manager/state/store"
-	"golang.org/x/net/context"
 )
 
 var (
diff --git a/vendor/github.com/docker/swarmkit/node/node.go b/vendor/github.com/docker/swarmkit/node/node.go
index 6cbf265..92bd748 100644
--- a/vendor/github.com/docker/swarmkit/node/node.go
+++ b/vendor/github.com/docker/swarmkit/node/node.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"context"
 	"crypto/tls"
 	"encoding/json"
 	"io/ioutil"
@@ -35,7 +36,6 @@
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	bolt "go.etcd.io/bbolt"
-	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/status"
@@ -1204,19 +1204,16 @@
 	s.c.Broadcast()
 	if err := s.save(); err != nil {
 		logrus.Errorf("error writing cluster state file: %v", err)
-		return
 	}
-	return
 }
+
 func (s *persistentRemotes) Remove(peers ...api.Peer) {
 	s.Lock()
 	defer s.Unlock()
 	s.Remotes.Remove(peers...)
 	if err := s.save(); err != nil {
 		logrus.Errorf("error writing cluster state file: %v", err)
-		return
 	}
-	return
 }
 
 func (s *persistentRemotes) save() error {
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md
index 68c8c46..499c583 100644
--- a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md
@@ -3,6 +3,8 @@
 [![Travis Build](https://travis-ci.org/grpc-ecosystem/go-grpc-prometheus.svg)](https://travis-ci.org/grpc-ecosystem/go-grpc-prometheus)
 [![Go Report Card](https://goreportcard.com/badge/github.com/grpc-ecosystem/go-grpc-prometheus)](http://goreportcard.com/report/grpc-ecosystem/go-grpc-prometheus)
 [![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/grpc-ecosystem/go-grpc-prometheus)
+[![SourceGraph](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-prometheus/-/badge.svg)](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-prometheus/?badge)
+[![codecov](https://codecov.io/gh/grpc-ecosystem/go-grpc-prometheus/branch/master/graph/badge.svg)](https://codecov.io/gh/grpc-ecosystem/go-grpc-prometheus)
 [![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
 
 [Prometheus](https://prometheus.io/) monitoring for your [gRPC Go](https://github.com/grpc/grpc-go) servers and clients.
@@ -36,7 +38,7 @@
     // After all your registrations, make sure all of the Prometheus metrics are initialized.
     grpc_prometheus.Register(myServer)
     // Register Prometheus metrics handler.    
-    http.Handle("/metrics", prometheus.Handler())
+    http.Handle("/metrics", promhttp.Handler())
 ...
 ```
 
@@ -47,8 +49,8 @@
 ...
    clientConn, err = grpc.Dial(
        address,
-		   grpc.WithUnaryInterceptor(UnaryClientInterceptor),
-		   grpc.WithStreamInterceptor(StreamClientInterceptor)
+		   grpc.WithUnaryInterceptor(grpc_prometheus.UnaryClientInterceptor),
+		   grpc.WithStreamInterceptor(grpc_prometheus.StreamClientInterceptor)
    )
    client = pb_testproto.NewTestServiceClient(clientConn)
    resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
@@ -116,7 +118,7 @@
 grpc_server_msg_sent_total{grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 20
 ```
 
-After the call completes, it's status (`OK` or other [gRPC status code](https://github.com/grpc/grpc-go/blob/master/codes/codes.go)) 
+After the call completes, its status (`OK` or other [gRPC status code](https://github.com/grpc/grpc-go/blob/master/codes/codes.go)) 
 and the relevant call labels increment the `grpc_server_handled_total` counter.
 
 ```jsoniq
@@ -126,8 +128,8 @@
 ## Histograms
 
 [Prometheus histograms](https://prometheus.io/docs/concepts/metric_types/#histogram) are a great way
-to measure latency distributions of your RPCs. However since it is bad practice to have metrics
-of [high cardinality](https://prometheus.io/docs/practices/instrumentation/#do-not-overuse-labels))
+to measure latency distributions of your RPCs. However, since it is bad practice to have metrics
+of [high cardinality](https://prometheus.io/docs/practices/instrumentation/#do-not-overuse-labels)
 the latency monitoring metrics are disabled by default. To enable them please call the following
 in your server initialization code:
 
@@ -135,8 +137,8 @@
 grpc_prometheus.EnableHandlingTimeHistogram()
 ```
 
-After the call completes, it's handling time will be recorded in a [Prometheus histogram](https://prometheus.io/docs/concepts/metric_types/#histogram)
-variable `grpc_server_handling_seconds`. It contains three sub-metrics:
+After the call completes, its handling time will be recorded in a [Prometheus histogram](https://prometheus.io/docs/concepts/metric_types/#histogram)
+variable `grpc_server_handling_seconds`. The histogram variable contains three sub-metrics:
 
  * `grpc_server_handling_seconds_count` - the count of all completed RPCs by status and method 
  * `grpc_server_handling_seconds_sum` - cumulative time of RPCs by status and method, useful for 
@@ -166,7 +168,7 @@
 
 ## Useful query examples
 
-Prometheus philosophy is to provide the most detailed metrics possible to the monitoring system, and
+Prometheus philosophy is to provide raw metrics to the monitoring system, and
 let the aggregations be handled there. The verbosity of above metrics make it possible to have that
 flexibility. Here's a couple of useful monitoring queries:
 
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go
index d9e87b2..751a4c7 100644
--- a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go
@@ -6,67 +6,34 @@
 package grpc_prometheus
 
 import (
-	"io"
-
-	"golang.org/x/net/context"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/codes"
+	prom "github.com/prometheus/client_golang/prometheus"
 )
 
-// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs.
-func UnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
-	monitor := newClientReporter(Unary, method)
-	monitor.SentMessage()
-	err := invoker(ctx, method, req, reply, cc, opts...)
-	if err != nil {
-		monitor.ReceivedMessage()
-	}
-	monitor.Handled(grpc.Code(err))
-	return err
+var (
+	// DefaultClientMetrics is the default instance of ClientMetrics. It is
+	// intended to be used in conjunction the default Prometheus metrics
+	// registry.
+	DefaultClientMetrics = NewClientMetrics()
+
+	// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs.
+	UnaryClientInterceptor = DefaultClientMetrics.UnaryClientInterceptor()
+
+	// StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs.
+	StreamClientInterceptor = DefaultClientMetrics.StreamClientInterceptor()
+)
+
+func init() {
+	prom.MustRegister(DefaultClientMetrics.clientStartedCounter)
+	prom.MustRegister(DefaultClientMetrics.clientHandledCounter)
+	prom.MustRegister(DefaultClientMetrics.clientStreamMsgReceived)
+	prom.MustRegister(DefaultClientMetrics.clientStreamMsgSent)
 }
 
-// StreamServerInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs.
-func StreamClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
-	monitor := newClientReporter(clientStreamType(desc), method)
-	clientStream, err := streamer(ctx, desc, cc, method, opts...)
-	if err != nil {
-		monitor.Handled(grpc.Code(err))
-		return nil, err
-	}
-	return &monitoredClientStream{clientStream, monitor}, nil
-}
-
-func clientStreamType(desc *grpc.StreamDesc) grpcType {
-	if desc.ClientStreams && !desc.ServerStreams {
-		return ClientStream
-	} else if !desc.ClientStreams && desc.ServerStreams {
-		return ServerStream
-	}
-	return BidiStream
-}
-
-// monitoredClientStream wraps grpc.ClientStream allowing each Sent/Recv of message to increment counters.
-type monitoredClientStream struct {
-	grpc.ClientStream
-	monitor *clientReporter
-}
-
-func (s *monitoredClientStream) SendMsg(m interface{}) error {
-	err := s.ClientStream.SendMsg(m)
-	if err == nil {
-		s.monitor.SentMessage()
-	}
-	return err
-}
-
-func (s *monitoredClientStream) RecvMsg(m interface{}) error {
-	err := s.ClientStream.RecvMsg(m)
-	if err == nil {
-		s.monitor.ReceivedMessage()
-	} else if err == io.EOF {
-		s.monitor.Handled(codes.OK)
-	} else {
-		s.monitor.Handled(grpc.Code(err))
-	}
-	return err
+// EnableClientHandlingTimeHistogram turns on recording of handling time of
+// RPCs. Histogram metrics can be very expensive for Prometheus to retain and
+// query. This function acts on the DefaultClientMetrics variable and the
+// default Prometheus metrics registry.
+func EnableClientHandlingTimeHistogram(opts ...HistogramOption) {
+	DefaultClientMetrics.EnableClientHandlingTimeHistogram(opts...)
+	prom.Register(DefaultClientMetrics.clientHandledHistogram)
 }
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_metrics.go b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_metrics.go
new file mode 100644
index 0000000..9b476f9
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_metrics.go
@@ -0,0 +1,170 @@
+package grpc_prometheus
+
+import (
+	"io"
+
+	prom "github.com/prometheus/client_golang/prometheus"
+	"golang.org/x/net/context"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+// ClientMetrics represents a collection of metrics to be registered on a
+// Prometheus metrics registry for a gRPC client.
+type ClientMetrics struct {
+	clientStartedCounter          *prom.CounterVec
+	clientHandledCounter          *prom.CounterVec
+	clientStreamMsgReceived       *prom.CounterVec
+	clientStreamMsgSent           *prom.CounterVec
+	clientHandledHistogramEnabled bool
+	clientHandledHistogramOpts    prom.HistogramOpts
+	clientHandledHistogram        *prom.HistogramVec
+}
+
+// NewClientMetrics returns a ClientMetrics object. Use a new instance of
+// ClientMetrics when not using the default Prometheus metrics registry, for
+// example when wanting to control which metrics are added to a registry as
+// opposed to automatically adding metrics via init functions.
+func NewClientMetrics(counterOpts ...CounterOption) *ClientMetrics {
+	opts := counterOptions(counterOpts)
+	return &ClientMetrics{
+		clientStartedCounter: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_client_started_total",
+				Help: "Total number of RPCs started on the client.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+
+		clientHandledCounter: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_client_handled_total",
+				Help: "Total number of RPCs completed by the client, regardless of success or failure.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}),
+
+		clientStreamMsgReceived: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_client_msg_received_total",
+				Help: "Total number of RPC stream messages received by the client.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+
+		clientStreamMsgSent: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_client_msg_sent_total",
+				Help: "Total number of gRPC stream messages sent by the client.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+
+		clientHandledHistogramEnabled: false,
+		clientHandledHistogramOpts: prom.HistogramOpts{
+			Name:    "grpc_client_handling_seconds",
+			Help:    "Histogram of response latency (seconds) of the gRPC until it is finished by the application.",
+			Buckets: prom.DefBuckets,
+		},
+		clientHandledHistogram: nil,
+	}
+}
+
+// Describe sends the super-set of all possible descriptors of metrics
+// collected by this Collector to the provided channel and returns once
+// the last descriptor has been sent.
+func (m *ClientMetrics) Describe(ch chan<- *prom.Desc) {
+	m.clientStartedCounter.Describe(ch)
+	m.clientHandledCounter.Describe(ch)
+	m.clientStreamMsgReceived.Describe(ch)
+	m.clientStreamMsgSent.Describe(ch)
+	if m.clientHandledHistogramEnabled {
+		m.clientHandledHistogram.Describe(ch)
+	}
+}
+
+// Collect is called by the Prometheus registry when collecting
+// metrics. The implementation sends each collected metric via the
+// provided channel and returns once the last metric has been sent.
+func (m *ClientMetrics) Collect(ch chan<- prom.Metric) {
+	m.clientStartedCounter.Collect(ch)
+	m.clientHandledCounter.Collect(ch)
+	m.clientStreamMsgReceived.Collect(ch)
+	m.clientStreamMsgSent.Collect(ch)
+	if m.clientHandledHistogramEnabled {
+		m.clientHandledHistogram.Collect(ch)
+	}
+}
+
+// EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs.
+// Histogram metrics can be very expensive for Prometheus to retain and query.
+func (m *ClientMetrics) EnableClientHandlingTimeHistogram(opts ...HistogramOption) {
+	for _, o := range opts {
+		o(&m.clientHandledHistogramOpts)
+	}
+	if !m.clientHandledHistogramEnabled {
+		m.clientHandledHistogram = prom.NewHistogramVec(
+			m.clientHandledHistogramOpts,
+			[]string{"grpc_type", "grpc_service", "grpc_method"},
+		)
+	}
+	m.clientHandledHistogramEnabled = true
+}
+
+// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs.
+func (m *ClientMetrics) UnaryClientInterceptor() func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+	return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+		monitor := newClientReporter(m, Unary, method)
+		monitor.SentMessage()
+		err := invoker(ctx, method, req, reply, cc, opts...)
+		if err != nil {
+			monitor.ReceivedMessage()
+		}
+		st, _ := status.FromError(err)
+		monitor.Handled(st.Code())
+		return err
+	}
+}
+
+// StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs.
+func (m *ClientMetrics) StreamClientInterceptor() func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+	return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+		monitor := newClientReporter(m, clientStreamType(desc), method)
+		clientStream, err := streamer(ctx, desc, cc, method, opts...)
+		if err != nil {
+			st, _ := status.FromError(err)
+			monitor.Handled(st.Code())
+			return nil, err
+		}
+		return &monitoredClientStream{clientStream, monitor}, nil
+	}
+}
+
+func clientStreamType(desc *grpc.StreamDesc) grpcType {
+	if desc.ClientStreams && !desc.ServerStreams {
+		return ClientStream
+	} else if !desc.ClientStreams && desc.ServerStreams {
+		return ServerStream
+	}
+	return BidiStream
+}
+
+// monitoredClientStream wraps grpc.ClientStream allowing each Sent/Recv of message to increment counters.
+type monitoredClientStream struct {
+	grpc.ClientStream
+	monitor *clientReporter
+}
+
+func (s *monitoredClientStream) SendMsg(m interface{}) error {
+	err := s.ClientStream.SendMsg(m)
+	if err == nil {
+		s.monitor.SentMessage()
+	}
+	return err
+}
+
+func (s *monitoredClientStream) RecvMsg(m interface{}) error {
+	err := s.ClientStream.RecvMsg(m)
+	if err == nil {
+		s.monitor.ReceivedMessage()
+	} else if err == io.EOF {
+		s.monitor.Handled(codes.OK)
+	} else {
+		st, _ := status.FromError(err)
+		s.monitor.Handled(st.Code())
+	}
+	return err
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go
index 16b7615..cbf1532 100644
--- a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go
@@ -7,105 +7,40 @@
 	"time"
 
 	"google.golang.org/grpc/codes"
-
-	prom "github.com/prometheus/client_golang/prometheus"
 )
 
-var (
-	clientStartedCounter = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "client",
-			Name:      "started_total",
-			Help:      "Total number of RPCs started on the client.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	clientHandledCounter = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "client",
-			Name:      "handled_total",
-			Help:      "Total number of RPCs completed by the client, regardless of success or failure.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"})
-
-	clientStreamMsgReceived = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "client",
-			Name:      "msg_received_total",
-			Help:      "Total number of RPC stream messages received by the client.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	clientStreamMsgSent = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "client",
-			Name:      "msg_sent_total",
-			Help:      "Total number of gRPC stream messages sent by the client.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	clientHandledHistogramEnabled = false
-	clientHandledHistogramOpts    = prom.HistogramOpts{
-		Namespace: "grpc",
-		Subsystem: "client",
-		Name:      "handling_seconds",
-		Help:      "Histogram of response latency (seconds) of the gRPC until it is finished by the application.",
-		Buckets:   prom.DefBuckets,
-	}
-	clientHandledHistogram *prom.HistogramVec
-)
-
-func init() {
-	prom.MustRegister(clientStartedCounter)
-	prom.MustRegister(clientHandledCounter)
-	prom.MustRegister(clientStreamMsgReceived)
-	prom.MustRegister(clientStreamMsgSent)
-}
-
-// EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs.
-// Histogram metrics can be very expensive for Prometheus to retain and query.
-func EnableClientHandlingTimeHistogram(opts ...HistogramOption) {
-	for _, o := range opts {
-		o(&clientHandledHistogramOpts)
-	}
-	if !clientHandledHistogramEnabled {
-		clientHandledHistogram = prom.NewHistogramVec(
-			clientHandledHistogramOpts,
-			[]string{"grpc_type", "grpc_service", "grpc_method"},
-		)
-		prom.Register(clientHandledHistogram)
-	}
-	clientHandledHistogramEnabled = true
-}
-
 type clientReporter struct {
+	metrics     *ClientMetrics
 	rpcType     grpcType
 	serviceName string
 	methodName  string
 	startTime   time.Time
 }
 
-func newClientReporter(rpcType grpcType, fullMethod string) *clientReporter {
-	r := &clientReporter{rpcType: rpcType}
-	if clientHandledHistogramEnabled {
+func newClientReporter(m *ClientMetrics, rpcType grpcType, fullMethod string) *clientReporter {
+	r := &clientReporter{
+		metrics: m,
+		rpcType: rpcType,
+	}
+	if r.metrics.clientHandledHistogramEnabled {
 		r.startTime = time.Now()
 	}
 	r.serviceName, r.methodName = splitMethodName(fullMethod)
-	clientStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.clientStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 	return r
 }
 
 func (r *clientReporter) ReceivedMessage() {
-	clientStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.clientStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 }
 
 func (r *clientReporter) SentMessage() {
-	clientStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.clientStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 }
 
 func (r *clientReporter) Handled(code codes.Code) {
-	clientHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc()
-	if clientHandledHistogramEnabled {
-		clientHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds())
+	r.metrics.clientHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc()
+	if r.metrics.clientHandledHistogramEnabled {
+		r.metrics.clientHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds())
 	}
 }
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/metric_options.go b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/metric_options.go
new file mode 100644
index 0000000..9d51aec
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/metric_options.go
@@ -0,0 +1,41 @@
+package grpc_prometheus
+
+import (
+	prom "github.com/prometheus/client_golang/prometheus"
+)
+
+// A CounterOption lets you add options to Counter metrics using With* funcs.
+type CounterOption func(*prom.CounterOpts)
+
+type counterOptions []CounterOption
+
+func (co counterOptions) apply(o prom.CounterOpts) prom.CounterOpts {
+	for _, f := range co {
+		f(&o)
+	}
+	return o
+}
+
+// WithConstLabels allows you to add ConstLabels to Counter metrics.
+func WithConstLabels(labels prom.Labels) CounterOption {
+	return func(o *prom.CounterOpts) {
+		o.ConstLabels = labels
+	}
+}
+
+// A HistogramOption lets you add options to Histogram metrics using With*
+// funcs.
+type HistogramOption func(*prom.HistogramOpts)
+
+// WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on.
+func WithHistogramBuckets(buckets []float64) HistogramOption {
+	return func(o *prom.HistogramOpts) { o.Buckets = buckets }
+}
+
+// WithHistogramConstLabels allows you to add custom ConstLabels to
+// histograms metrics.
+func WithHistogramConstLabels(labels prom.Labels) HistogramOption {
+	return func(o *prom.HistogramOpts) {
+		o.ConstLabels = labels
+	}
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go
index f85c8c2..322f990 100644
--- a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go
@@ -6,69 +6,43 @@
 package grpc_prometheus
 
 import (
-	"golang.org/x/net/context"
+	prom "github.com/prometheus/client_golang/prometheus"
 	"google.golang.org/grpc"
 )
 
-// PreregisterServices takes a gRPC server and pre-initializes all counters to 0.
-// This allows for easier monitoring in Prometheus (no missing metrics), and should be called *after* all services have
-// been registered with the server.
+var (
+	// DefaultServerMetrics is the default instance of ServerMetrics. It is
+	// intended to be used in conjunction the default Prometheus metrics
+	// registry.
+	DefaultServerMetrics = NewServerMetrics()
+
+	// UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs.
+	UnaryServerInterceptor = DefaultServerMetrics.UnaryServerInterceptor()
+
+	// StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs.
+	StreamServerInterceptor = DefaultServerMetrics.StreamServerInterceptor()
+)
+
+func init() {
+	prom.MustRegister(DefaultServerMetrics.serverStartedCounter)
+	prom.MustRegister(DefaultServerMetrics.serverHandledCounter)
+	prom.MustRegister(DefaultServerMetrics.serverStreamMsgReceived)
+	prom.MustRegister(DefaultServerMetrics.serverStreamMsgSent)
+}
+
+// Register takes a gRPC server and pre-initializes all counters to 0. This
+// allows for easier monitoring in Prometheus (no missing metrics), and should
+// be called *after* all services have been registered with the server. This
+// function acts on the DefaultServerMetrics variable.
 func Register(server *grpc.Server) {
-	serviceInfo := server.GetServiceInfo()
-	for serviceName, info := range serviceInfo {
-		for _, mInfo := range info.Methods {
-			preRegisterMethod(serviceName, &mInfo)
-		}
-	}
+	DefaultServerMetrics.InitializeMetrics(server)
 }
 
-// UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs.
-func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
-	monitor := newServerReporter(Unary, info.FullMethod)
-	monitor.ReceivedMessage()
-	resp, err := handler(ctx, req)
-	monitor.Handled(grpc.Code(err))
-	if err == nil {
-		monitor.SentMessage()
-	}
-	return resp, err
-}
-
-// StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs.
-func StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
-	monitor := newServerReporter(streamRpcType(info), info.FullMethod)
-	err := handler(srv, &monitoredServerStream{ss, monitor})
-	monitor.Handled(grpc.Code(err))
-	return err
-}
-
-func streamRpcType(info *grpc.StreamServerInfo) grpcType {
-	if info.IsClientStream && !info.IsServerStream {
-		return ClientStream
-	} else if !info.IsClientStream && info.IsServerStream {
-		return ServerStream
-	}
-	return BidiStream
-}
-
-// monitoredStream wraps grpc.ServerStream allowing each Sent/Recv of message to increment counters.
-type monitoredServerStream struct {
-	grpc.ServerStream
-	monitor *serverReporter
-}
-
-func (s *monitoredServerStream) SendMsg(m interface{}) error {
-	err := s.ServerStream.SendMsg(m)
-	if err == nil {
-		s.monitor.SentMessage()
-	}
-	return err
-}
-
-func (s *monitoredServerStream) RecvMsg(m interface{}) error {
-	err := s.ServerStream.RecvMsg(m)
-	if err == nil {
-		s.monitor.ReceivedMessage()
-	}
-	return err
+// EnableHandlingTimeHistogram turns on recording of handling time
+// of RPCs. Histogram metrics can be very expensive for Prometheus
+// to retain and query. This function acts on the DefaultServerMetrics
+// variable and the default Prometheus metrics registry.
+func EnableHandlingTimeHistogram(opts ...HistogramOption) {
+	DefaultServerMetrics.EnableHandlingTimeHistogram(opts...)
+	prom.Register(DefaultServerMetrics.serverHandledHistogram)
 }
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_metrics.go b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_metrics.go
new file mode 100644
index 0000000..5b1467e
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_metrics.go
@@ -0,0 +1,185 @@
+package grpc_prometheus
+
+import (
+	prom "github.com/prometheus/client_golang/prometheus"
+	"golang.org/x/net/context"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/status"
+)
+
+// ServerMetrics represents a collection of metrics to be registered on a
+// Prometheus metrics registry for a gRPC server.
+type ServerMetrics struct {
+	serverStartedCounter          *prom.CounterVec
+	serverHandledCounter          *prom.CounterVec
+	serverStreamMsgReceived       *prom.CounterVec
+	serverStreamMsgSent           *prom.CounterVec
+	serverHandledHistogramEnabled bool
+	serverHandledHistogramOpts    prom.HistogramOpts
+	serverHandledHistogram        *prom.HistogramVec
+}
+
+// NewServerMetrics returns a ServerMetrics object. Use a new instance of
+// ServerMetrics when not using the default Prometheus metrics registry, for
+// example when wanting to control which metrics are added to a registry as
+// opposed to automatically adding metrics via init functions.
+func NewServerMetrics(counterOpts ...CounterOption) *ServerMetrics {
+	opts := counterOptions(counterOpts)
+	return &ServerMetrics{
+		serverStartedCounter: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_server_started_total",
+				Help: "Total number of RPCs started on the server.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+		serverHandledCounter: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_server_handled_total",
+				Help: "Total number of RPCs completed on the server, regardless of success or failure.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}),
+		serverStreamMsgReceived: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_server_msg_received_total",
+				Help: "Total number of RPC stream messages received on the server.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+		serverStreamMsgSent: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_server_msg_sent_total",
+				Help: "Total number of gRPC stream messages sent by the server.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+		serverHandledHistogramEnabled: false,
+		serverHandledHistogramOpts: prom.HistogramOpts{
+			Name:    "grpc_server_handling_seconds",
+			Help:    "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.",
+			Buckets: prom.DefBuckets,
+		},
+		serverHandledHistogram: nil,
+	}
+}
+
+// EnableHandlingTimeHistogram enables histograms being registered when
+// registering the ServerMetrics on a Prometheus registry. Histograms can be
+// expensive on Prometheus servers. It takes options to configure histogram
+// options such as the defined buckets.
+func (m *ServerMetrics) EnableHandlingTimeHistogram(opts ...HistogramOption) {
+	for _, o := range opts {
+		o(&m.serverHandledHistogramOpts)
+	}
+	if !m.serverHandledHistogramEnabled {
+		m.serverHandledHistogram = prom.NewHistogramVec(
+			m.serverHandledHistogramOpts,
+			[]string{"grpc_type", "grpc_service", "grpc_method"},
+		)
+	}
+	m.serverHandledHistogramEnabled = true
+}
+
+// Describe sends the super-set of all possible descriptors of metrics
+// collected by this Collector to the provided channel and returns once
+// the last descriptor has been sent.
+func (m *ServerMetrics) Describe(ch chan<- *prom.Desc) {
+	m.serverStartedCounter.Describe(ch)
+	m.serverHandledCounter.Describe(ch)
+	m.serverStreamMsgReceived.Describe(ch)
+	m.serverStreamMsgSent.Describe(ch)
+	if m.serverHandledHistogramEnabled {
+		m.serverHandledHistogram.Describe(ch)
+	}
+}
+
+// Collect is called by the Prometheus registry when collecting
+// metrics. The implementation sends each collected metric via the
+// provided channel and returns once the last metric has been sent.
+func (m *ServerMetrics) Collect(ch chan<- prom.Metric) {
+	m.serverStartedCounter.Collect(ch)
+	m.serverHandledCounter.Collect(ch)
+	m.serverStreamMsgReceived.Collect(ch)
+	m.serverStreamMsgSent.Collect(ch)
+	if m.serverHandledHistogramEnabled {
+		m.serverHandledHistogram.Collect(ch)
+	}
+}
+
+// UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs.
+func (m *ServerMetrics) UnaryServerInterceptor() func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+		monitor := newServerReporter(m, Unary, info.FullMethod)
+		monitor.ReceivedMessage()
+		resp, err := handler(ctx, req)
+		st, _ := status.FromError(err)
+		monitor.Handled(st.Code())
+		if err == nil {
+			monitor.SentMessage()
+		}
+		return resp, err
+	}
+}
+
+// StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs.
+func (m *ServerMetrics) StreamServerInterceptor() func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+	return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+		monitor := newServerReporter(m, streamRPCType(info), info.FullMethod)
+		err := handler(srv, &monitoredServerStream{ss, monitor})
+		st, _ := status.FromError(err)
+		monitor.Handled(st.Code())
+		return err
+	}
+}
+
+// InitializeMetrics initializes all metrics, with their appropriate null
+// value, for all gRPC methods registered on a gRPC server. This is useful, to
+// ensure that all metrics exist when collecting and querying.
+func (m *ServerMetrics) InitializeMetrics(server *grpc.Server) {
+	serviceInfo := server.GetServiceInfo()
+	for serviceName, info := range serviceInfo {
+		for _, mInfo := range info.Methods {
+			preRegisterMethod(m, serviceName, &mInfo)
+		}
+	}
+}
+
+func streamRPCType(info *grpc.StreamServerInfo) grpcType {
+	if info.IsClientStream && !info.IsServerStream {
+		return ClientStream
+	} else if !info.IsClientStream && info.IsServerStream {
+		return ServerStream
+	}
+	return BidiStream
+}
+
+// monitoredStream wraps grpc.ServerStream allowing each Sent/Recv of message to increment counters.
+type monitoredServerStream struct {
+	grpc.ServerStream
+	monitor *serverReporter
+}
+
+func (s *monitoredServerStream) SendMsg(m interface{}) error {
+	err := s.ServerStream.SendMsg(m)
+	if err == nil {
+		s.monitor.SentMessage()
+	}
+	return err
+}
+
+func (s *monitoredServerStream) RecvMsg(m interface{}) error {
+	err := s.ServerStream.RecvMsg(m)
+	if err == nil {
+		s.monitor.ReceivedMessage()
+	}
+	return err
+}
+
+// preRegisterMethod is invoked on Register of a Server, allowing all gRPC services labels to be pre-populated.
+func preRegisterMethod(metrics *ServerMetrics, serviceName string, mInfo *grpc.MethodInfo) {
+	methodName := mInfo.Name
+	methodType := string(typeFromMethodInfo(mInfo))
+	// These are just references (no increments), as just referencing will create the labels but not set values.
+	metrics.serverStartedCounter.GetMetricWithLabelValues(methodType, serviceName, methodName)
+	metrics.serverStreamMsgReceived.GetMetricWithLabelValues(methodType, serviceName, methodName)
+	metrics.serverStreamMsgSent.GetMetricWithLabelValues(methodType, serviceName, methodName)
+	if metrics.serverHandledHistogramEnabled {
+		metrics.serverHandledHistogram.GetMetricWithLabelValues(methodType, serviceName, methodName)
+	}
+	for _, code := range allCodes {
+		metrics.serverHandledCounter.GetMetricWithLabelValues(methodType, serviceName, methodName, code.String())
+	}
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go
index 628a890..aa9db54 100644
--- a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go
@@ -7,151 +7,40 @@
 	"time"
 
 	"google.golang.org/grpc/codes"
-
-	prom "github.com/prometheus/client_golang/prometheus"
-	"google.golang.org/grpc"
 )
 
-type grpcType string
-
-const (
-	Unary        grpcType = "unary"
-	ClientStream grpcType = "client_stream"
-	ServerStream grpcType = "server_stream"
-	BidiStream   grpcType = "bidi_stream"
-)
-
-var (
-	serverStartedCounter = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "server",
-			Name:      "started_total",
-			Help:      "Total number of RPCs started on the server.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	serverHandledCounter = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "server",
-			Name:      "handled_total",
-			Help:      "Total number of RPCs completed on the server, regardless of success or failure.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"})
-
-	serverStreamMsgReceived = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "server",
-			Name:      "msg_received_total",
-			Help:      "Total number of RPC stream messages received on the server.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	serverStreamMsgSent = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "server",
-			Name:      "msg_sent_total",
-			Help:      "Total number of gRPC stream messages sent by the server.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	serverHandledHistogramEnabled = false
-	serverHandledHistogramOpts    = prom.HistogramOpts{
-		Namespace: "grpc",
-		Subsystem: "server",
-		Name:      "handling_seconds",
-		Help:      "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.",
-		Buckets:   prom.DefBuckets,
-	}
-	serverHandledHistogram *prom.HistogramVec
-)
-
-func init() {
-	prom.MustRegister(serverStartedCounter)
-	prom.MustRegister(serverHandledCounter)
-	prom.MustRegister(serverStreamMsgReceived)
-	prom.MustRegister(serverStreamMsgSent)
-}
-
-type HistogramOption func(*prom.HistogramOpts)
-
-// WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on.
-func WithHistogramBuckets(buckets []float64) HistogramOption {
-	return func(o *prom.HistogramOpts) { o.Buckets = buckets }
-}
-
-// EnableHandlingTimeHistogram turns on recording of handling time of RPCs for server-side interceptors.
-// Histogram metrics can be very expensive for Prometheus to retain and query.
-func EnableHandlingTimeHistogram(opts ...HistogramOption) {
-	for _, o := range opts {
-		o(&serverHandledHistogramOpts)
-	}
-	if !serverHandledHistogramEnabled {
-		serverHandledHistogram = prom.NewHistogramVec(
-			serverHandledHistogramOpts,
-			[]string{"grpc_type", "grpc_service", "grpc_method"},
-		)
-		prom.Register(serverHandledHistogram)
-	}
-	serverHandledHistogramEnabled = true
-}
-
 type serverReporter struct {
+	metrics     *ServerMetrics
 	rpcType     grpcType
 	serviceName string
 	methodName  string
 	startTime   time.Time
 }
 
-func newServerReporter(rpcType grpcType, fullMethod string) *serverReporter {
-	r := &serverReporter{rpcType: rpcType}
-	if serverHandledHistogramEnabled {
+func newServerReporter(m *ServerMetrics, rpcType grpcType, fullMethod string) *serverReporter {
+	r := &serverReporter{
+		metrics: m,
+		rpcType: rpcType,
+	}
+	if r.metrics.serverHandledHistogramEnabled {
 		r.startTime = time.Now()
 	}
 	r.serviceName, r.methodName = splitMethodName(fullMethod)
-	serverStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.serverStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 	return r
 }
 
 func (r *serverReporter) ReceivedMessage() {
-	serverStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.serverStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 }
 
 func (r *serverReporter) SentMessage() {
-	serverStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.serverStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 }
 
 func (r *serverReporter) Handled(code codes.Code) {
-	serverHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc()
-	if serverHandledHistogramEnabled {
-		serverHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds())
+	r.metrics.serverHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc()
+	if r.metrics.serverHandledHistogramEnabled {
+		r.metrics.serverHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds())
 	}
 }
-
-// preRegisterMethod is invoked on Register of a Server, allowing all gRPC services labels to be pre-populated.
-func preRegisterMethod(serviceName string, mInfo *grpc.MethodInfo) {
-	methodName := mInfo.Name
-	methodType := string(typeFromMethodInfo(mInfo))
-	// These are just references (no increments), as just referencing will create the labels but not set values.
-	serverStartedCounter.GetMetricWithLabelValues(methodType, serviceName, methodName)
-	serverStreamMsgReceived.GetMetricWithLabelValues(methodType, serviceName, methodName)
-	serverStreamMsgSent.GetMetricWithLabelValues(methodType, serviceName, methodName)
-	if serverHandledHistogramEnabled {
-		serverHandledHistogram.GetMetricWithLabelValues(methodType, serviceName, methodName)
-	}
-	for _, code := range allCodes {
-		serverHandledCounter.GetMetricWithLabelValues(methodType, serviceName, methodName, code.String())
-	}
-}
-
-func typeFromMethodInfo(mInfo *grpc.MethodInfo) grpcType {
-	if mInfo.IsClientStream == false && mInfo.IsServerStream == false {
-		return Unary
-	}
-	if mInfo.IsClientStream == true && mInfo.IsServerStream == false {
-		return ClientStream
-	}
-	if mInfo.IsClientStream == false && mInfo.IsServerStream == true {
-		return ServerStream
-	}
-	return BidiStream
-}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go
index 372460a..7987de3 100644
--- a/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go
@@ -6,9 +6,19 @@
 import (
 	"strings"
 
+	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 )
 
+type grpcType string
+
+const (
+	Unary        grpcType = "unary"
+	ClientStream grpcType = "client_stream"
+	ServerStream grpcType = "server_stream"
+	BidiStream   grpcType = "bidi_stream"
+)
+
 var (
 	allCodes = []codes.Code{
 		codes.OK, codes.Canceled, codes.Unknown, codes.InvalidArgument, codes.DeadlineExceeded, codes.NotFound,
@@ -25,3 +35,16 @@
 	}
 	return "unknown", "unknown"
 }
+
+func typeFromMethodInfo(mInfo *grpc.MethodInfo) grpcType {
+	if !mInfo.IsClientStream && !mInfo.IsServerStream {
+		return Unary
+	}
+	if mInfo.IsClientStream && !mInfo.IsServerStream {
+		return ClientStream
+	}
+	if !mInfo.IsClientStream && mInfo.IsServerStream {
+		return ServerStream
+	}
+	return BidiStream
+}
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
index 478901c..35199e0 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
@@ -19,6 +19,7 @@
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
 	"github.com/tonistiigi/fsutil"
+	fstypes "github.com/tonistiigi/fsutil/types"
 )
 
 var errNotFound = errors.Errorf("not found")
@@ -274,7 +275,7 @@
 		return
 	}
 
-	stat, ok := fi.Sys().(*fsutil.Stat)
+	stat, ok := fi.Sys().(*fstypes.Stat)
 	if !ok {
 		return errors.Errorf("%s invalid change without stat information", p)
 	}
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/filehash.go b/vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
index 46c15cc..84018e7 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
@@ -8,7 +8,7 @@
 	"path/filepath"
 	"time"
 
-	"github.com/tonistiigi/fsutil"
+	fstypes "github.com/tonistiigi/fsutil/types"
 )
 
 // NewFileHash returns new hash that is used for the builder cache keys
@@ -22,7 +22,7 @@
 		}
 	}
 
-	stat := &fsutil.Stat{
+	stat := &fstypes.Stat{
 		Mode:     uint32(fi.Mode()),
 		Size_:    fi.Size(),
 		ModTime:  fi.ModTime().UnixNano(),
@@ -39,7 +39,7 @@
 	return NewFromStat(stat)
 }
 
-func NewFromStat(stat *fsutil.Stat) (hash.Hash, error) {
+func NewFromStat(stat *fstypes.Stat) (hash.Hash, error) {
 	fi := &statInfo{stat}
 	hdr, err := tar.FileInfoHeader(fi, stat.Linkname)
 	if err != nil {
@@ -75,7 +75,7 @@
 }
 
 type statInfo struct {
-	*fsutil.Stat
+	*fstypes.Stat
 }
 
 func (s *statInfo) Name() string {
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go b/vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
index 0939112..4f610d7 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
@@ -7,7 +7,7 @@
 	"syscall"
 
 	"github.com/containerd/continuity/sysx"
-	"github.com/tonistiigi/fsutil"
+	fstypes "github.com/tonistiigi/fsutil/types"
 
 	"golang.org/x/sys/unix"
 )
@@ -16,7 +16,7 @@
 	return perm
 }
 
-func setUnixOpt(path string, fi os.FileInfo, stat *fsutil.Stat) error {
+func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
 	s := fi.Sys().(*syscall.Stat_t)
 
 	stat.Uid = s.Uid
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go b/vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
index 340954a..e15bf1e 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
@@ -5,7 +5,7 @@
 import (
 	"os"
 
-	"github.com/tonistiigi/fsutil"
+	fstypes "github.com/tonistiigi/fsutil/types"
 )
 
 // chmodWindowsTarEntry is used to adjust the file permissions used in tar
@@ -18,6 +18,6 @@
 	return perm
 }
 
-func setUnixOpt(path string, fi os.FileInfo, stat *fsutil.Stat) error {
+func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
 	return nil
 }
diff --git a/vendor/github.com/moby/buildkit/cache/fsutil.go b/vendor/github.com/moby/buildkit/cache/fsutil.go
deleted file mode 100644
index ec757d5..0000000
--- a/vendor/github.com/moby/buildkit/cache/fsutil.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package cache
-
-import (
-	"context"
-	"io"
-	"io/ioutil"
-	"os"
-
-	"github.com/containerd/continuity/fs"
-	"github.com/moby/buildkit/snapshot"
-)
-
-type ReadRequest struct {
-	Filename string
-	Range    *FileRange
-}
-
-type FileRange struct {
-	Offset int
-	Length int
-}
-
-func ReadFile(ctx context.Context, ref ImmutableRef, req ReadRequest) ([]byte, error) {
-	mount, err := ref.Mount(ctx, true)
-	if err != nil {
-		return nil, err
-	}
-
-	lm := snapshot.LocalMounter(mount)
-
-	root, err := lm.Mount()
-	if err != nil {
-		return nil, err
-	}
-
-	defer func() {
-		if lm != nil {
-			lm.Unmount()
-		}
-	}()
-
-	fp, err := fs.RootPath(root, req.Filename)
-	if err != nil {
-		return nil, err
-	}
-
-	var dt []byte
-
-	if req.Range == nil {
-		dt, err = ioutil.ReadFile(fp)
-		if err != nil {
-			return nil, err
-		}
-	} else {
-		f, err := os.Open(fp)
-		if err != nil {
-			return nil, err
-		}
-		dt, err = ioutil.ReadAll(io.NewSectionReader(f, int64(req.Range.Offset), int64(req.Range.Length)))
-		f.Close()
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	if err := lm.Unmount(); err != nil {
-		return nil, err
-	}
-	lm = nil
-	return dt, err
-}
diff --git a/vendor/github.com/moby/buildkit/cache/util/fsutil.go b/vendor/github.com/moby/buildkit/cache/util/fsutil.go
new file mode 100644
index 0000000..b7aa673
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/cache/util/fsutil.go
@@ -0,0 +1,139 @@
+package util
+
+import (
+	"context"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+
+	"github.com/containerd/continuity/fs"
+	"github.com/moby/buildkit/cache"
+	"github.com/moby/buildkit/snapshot"
+	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil"
+	fstypes "github.com/tonistiigi/fsutil/types"
+)
+
+type ReadRequest struct {
+	Filename string
+	Range    *FileRange
+}
+
+type FileRange struct {
+	Offset int
+	Length int
+}
+
+func withMount(ctx context.Context, ref cache.ImmutableRef, cb func(string) error) error {
+	mount, err := ref.Mount(ctx, true)
+	if err != nil {
+		return err
+	}
+
+	lm := snapshot.LocalMounter(mount)
+
+	root, err := lm.Mount()
+	if err != nil {
+		return err
+	}
+
+	defer func() {
+		if lm != nil {
+			lm.Unmount()
+		}
+	}()
+
+	if err := cb(root); err != nil {
+		return err
+	}
+
+	if err := lm.Unmount(); err != nil {
+		return err
+	}
+	lm = nil
+	return nil
+}
+
+func ReadFile(ctx context.Context, ref cache.ImmutableRef, req ReadRequest) ([]byte, error) {
+	var dt []byte
+
+	err := withMount(ctx, ref, func(root string) error {
+		fp, err := fs.RootPath(root, req.Filename)
+		if err != nil {
+			return err
+		}
+
+		if req.Range == nil {
+			dt, err = ioutil.ReadFile(fp)
+			if err != nil {
+				return err
+			}
+		} else {
+			f, err := os.Open(fp)
+			if err != nil {
+				return err
+			}
+			dt, err = ioutil.ReadAll(io.NewSectionReader(f, int64(req.Range.Offset), int64(req.Range.Length)))
+			f.Close()
+			if err != nil {
+				return err
+			}
+		}
+		return nil
+	})
+	return dt, err
+}
+
+type ReadDirRequest struct {
+	Path           string
+	IncludePattern string
+}
+
+func ReadDir(ctx context.Context, ref cache.ImmutableRef, req ReadDirRequest) ([]*fstypes.Stat, error) {
+	var (
+		rd []*fstypes.Stat
+		wo fsutil.WalkOpt
+	)
+	if req.IncludePattern != "" {
+		wo.IncludePatterns = append(wo.IncludePatterns, req.IncludePattern)
+	}
+	err := withMount(ctx, ref, func(root string) error {
+		fp, err := fs.RootPath(root, req.Path)
+		if err != nil {
+			return err
+		}
+		return fsutil.Walk(ctx, fp, &wo, func(path string, info os.FileInfo, err error) error {
+			if err != nil {
+				return errors.Wrapf(err, "walking %q", root)
+			}
+			stat, ok := info.Sys().(*fstypes.Stat)
+			if !ok {
+				// This "can't happen(tm)".
+				return errors.Errorf("expected a *fsutil.Stat but got %T", info.Sys())
+			}
+			rd = append(rd, stat)
+
+			if info.IsDir() {
+				return filepath.SkipDir
+			}
+			return nil
+		})
+	})
+	return rd, err
+}
+
+func StatFile(ctx context.Context, ref cache.ImmutableRef, path string) (*fstypes.Stat, error) {
+	var st *fstypes.Stat
+	err := withMount(ctx, ref, func(root string) error {
+		fp, err := fs.RootPath(root, path)
+		if err != nil {
+			return err
+		}
+		if st, err = fsutil.Stat(fp); err != nil {
+			return err
+		}
+		return nil
+	})
+	return st, err
+}
diff --git a/vendor/github.com/moby/buildkit/client/build.go b/vendor/github.com/moby/buildkit/client/build.go
index 93059d1..f23df44 100644
--- a/vendor/github.com/moby/buildkit/client/build.go
+++ b/vendor/github.com/moby/buildkit/client/build.go
@@ -84,6 +84,16 @@
 	return g.gateway.ReadFile(ctx, in, opts...)
 }
 
+func (g *gatewayClientForBuild) ReadDir(ctx context.Context, in *gatewayapi.ReadDirRequest, opts ...grpc.CallOption) (*gatewayapi.ReadDirResponse, error) {
+	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
+	return g.gateway.ReadDir(ctx, in, opts...)
+}
+
+func (g *gatewayClientForBuild) StatFile(ctx context.Context, in *gatewayapi.StatFileRequest, opts ...grpc.CallOption) (*gatewayapi.StatFileResponse, error) {
+	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
+	return g.gateway.StatFile(ctx, in, opts...)
+}
+
 func (g *gatewayClientForBuild) Ping(ctx context.Context, in *gatewayapi.PingRequest, opts ...grpc.CallOption) (*gatewayapi.PongResponse, error) {
 	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
 	return g.gateway.Ping(ctx, in, opts...)
diff --git a/vendor/github.com/moby/buildkit/client/llb/exec.go b/vendor/github.com/moby/buildkit/client/llb/exec.go
index a34e75e..8233b07 100644
--- a/vendor/github.com/moby/buildkit/client/llb/exec.go
+++ b/vendor/github.com/moby/buildkit/client/llb/exec.go
@@ -7,6 +7,7 @@
 	"sort"
 
 	"github.com/moby/buildkit/solver/pb"
+	"github.com/moby/buildkit/util/system"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
 )
@@ -142,6 +143,13 @@
 			e.meta.Env = e.meta.Env.AddOrReplace("SSH_AUTH_SOCK", e.ssh[0].Target)
 		}
 	}
+	if c.Caps != nil {
+		if err := c.Caps.Supports(pb.CapExecMetaSetsDefaultPath); err != nil {
+			e.meta.Env = e.meta.Env.SetDefault("PATH", system.DefaultPathEnv)
+		} else {
+			addCap(&e.constraints, pb.CapExecMetaSetsDefaultPath)
+		}
+	}
 
 	meta := &pb.Meta{
 		Args: e.meta.Args,
@@ -191,6 +199,14 @@
 		}
 	}
 
+	if len(e.secrets) > 0 {
+		addCap(&e.constraints, pb.CapExecMountSecret)
+	}
+
+	if len(e.ssh) > 0 {
+		addCap(&e.constraints, pb.CapExecMountSSH)
+	}
+
 	pop, md := MarshalConstraints(c, &e.constraints)
 	pop.Op = &pb.Op_Exec{
 		Exec: peo,
@@ -258,10 +274,6 @@
 		peo.Mounts = append(peo.Mounts, pm)
 	}
 
-	if len(e.secrets) > 0 {
-		addCap(&e.constraints, pb.CapMountSecret)
-	}
-
 	for _, s := range e.secrets {
 		pm := &pb.Mount{
 			Dest:      s.Target,
@@ -488,6 +500,12 @@
 	})
 }
 
+func SSHSocketTarget(target string) SSHOption {
+	return sshOptionFunc(func(si *SSHInfo) {
+		si.Target = target
+	})
+}
+
 func SSHSocketOpt(target string, uid, gid, mode int) SSHOption {
 	return sshOptionFunc(func(si *SSHInfo) {
 		si.Target = target
diff --git a/vendor/github.com/moby/buildkit/client/llb/meta.go b/vendor/github.com/moby/buildkit/client/llb/meta.go
index 25b7885..702ea14 100644
--- a/vendor/github.com/moby/buildkit/client/llb/meta.go
+++ b/vendor/github.com/moby/buildkit/client/llb/meta.go
@@ -23,10 +23,6 @@
 	keyNetwork   = contextKeyT("llb.network")
 )
 
-func addEnv(key, value string) StateOption {
-	return addEnvf(key, value)
-}
-
 func addEnvf(key, value string, v ...interface{}) StateOption {
 	return func(s State) State {
 		return s.WithValue(keyEnv, getEnv(s).AddOrReplace(key, fmt.Sprintf(value, v...)))
@@ -175,6 +171,13 @@
 	return e
 }
 
+func (e EnvList) SetDefault(k, v string) EnvList {
+	if _, ok := e.Get(k); !ok {
+		e = append(e, KeyValue{key: k, value: v})
+	}
+	return e
+}
+
 func (e EnvList) Delete(k string) EnvList {
 	e = append([]KeyValue(nil), e...)
 	if i, ok := e.Index(k); ok {
diff --git a/vendor/github.com/moby/buildkit/client/llb/state.go b/vendor/github.com/moby/buildkit/client/llb/state.go
index 12ee97a..15639fd 100644
--- a/vendor/github.com/moby/buildkit/client/llb/state.go
+++ b/vendor/github.com/moby/buildkit/client/llb/state.go
@@ -9,7 +9,6 @@
 	"github.com/moby/buildkit/identity"
 	"github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/apicaps"
-	"github.com/moby/buildkit/util/system"
 	digest "github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 )
@@ -34,7 +33,6 @@
 		ctx: context.Background(),
 	}
 	s = dir("/")(s)
-	s = addEnv("PATH", system.DefaultPathEnv)(s)
 	s = s.ensurePlatform()
 	return s
 }
diff --git a/vendor/github.com/moby/buildkit/client/solve.go b/vendor/github.com/moby/buildkit/client/solve.go
index a4267c0..b8da069 100644
--- a/vendor/github.com/moby/buildkit/client/solve.go
+++ b/vendor/github.com/moby/buildkit/client/solve.go
@@ -19,7 +19,7 @@
 	opentracing "github.com/opentracing/opentracing-go"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"github.com/tonistiigi/fsutil"
+	fstypes "github.com/tonistiigi/fsutil/types"
 	"golang.org/x/sync/errgroup"
 )
 
@@ -256,7 +256,7 @@
 			return nil, errors.Errorf("%s not a directory", d)
 		}
 	}
-	resetUIDAndGID := func(st *fsutil.Stat) bool {
+	resetUIDAndGID := func(st *fstypes.Stat) bool {
 		st.Uid = 0
 		st.Gid = 0
 		return true
diff --git a/vendor/github.com/moby/buildkit/control/gateway/gateway.go b/vendor/github.com/moby/buildkit/control/gateway/gateway.go
index 475d18b..074e739 100644
--- a/vendor/github.com/moby/buildkit/control/gateway/gateway.go
+++ b/vendor/github.com/moby/buildkit/control/gateway/gateway.go
@@ -125,3 +125,19 @@
 	res, err := fwd.Return(ctx, req)
 	return res, err
 }
+
+func (gwf *GatewayForwarder) ReadDir(ctx context.Context, req *gwapi.ReadDirRequest) (*gwapi.ReadDirResponse, error) {
+	fwd, err := gwf.lookupForwarder(ctx)
+	if err != nil {
+		return nil, errors.Wrap(err, "forwarding ReadDir")
+	}
+	return fwd.ReadDir(ctx, req)
+}
+
+func (gwf *GatewayForwarder) StatFile(ctx context.Context, req *gwapi.StatFileRequest) (*gwapi.StatFileResponse, error) {
+	fwd, err := gwf.lookupForwarder(ctx)
+	if err != nil {
+		return nil, errors.Wrap(err, "forwarding StatFile")
+	}
+	return fwd.StatFile(ctx, req)
+}
diff --git a/vendor/github.com/moby/buildkit/executor/oci/hosts.go b/vendor/github.com/moby/buildkit/executor/oci/hosts.go
index 405d758..c350a6d 100644
--- a/vendor/github.com/moby/buildkit/executor/oci/hosts.go
+++ b/vendor/github.com/moby/buildkit/executor/oci/hosts.go
@@ -13,7 +13,7 @@
 )
 
 const hostsContent = `
-127.0.0.1	localhost
+127.0.0.1	localhost buildkitsandbox
 ::1	localhost ip6-localhost ip6-loopback
 `
 
diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_unix.go b/vendor/github.com/moby/buildkit/executor/oci/spec_unix.go
index 8a0610e..3e1976a 100644
--- a/vendor/github.com/moby/buildkit/executor/oci/spec_unix.go
+++ b/vendor/github.com/moby/buildkit/executor/oci/spec_unix.go
@@ -44,11 +44,21 @@
 	s.Process.Args = meta.Args
 	s.Process.Env = meta.Env
 	s.Process.Cwd = meta.Cwd
+	s.Process.Rlimits = nil // reset open files limit
+	s.Hostname = "buildkitsandbox"
 
 	s.Mounts = GetMounts(ctx,
 		withROBind(resolvConf, "/etc/resolv.conf"),
 		withROBind(hostsFile, "/etc/hosts"),
 	)
+
+	s.Mounts = append(s.Mounts, specs.Mount{
+		Destination: "/sys/fs/cgroup",
+		Type:        "cgroup",
+		Source:      "cgroup",
+		Options:     []string{"ro", "nosuid", "noexec", "nodev"},
+	})
+
 	// TODO: User
 
 	sm := &submounts{}
diff --git a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go
index dca82ff..8080f57 100644
--- a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go
+++ b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go
@@ -85,6 +85,10 @@
 		return nil, err
 	}
 
+	// clean up old hosts/resolv.conf file. ignore errors
+	os.RemoveAll(filepath.Join(root, "hosts"))
+	os.RemoveAll(filepath.Join(root, "resolv.conf"))
+
 	runtime := &runc.Runc{
 		Command:      cmd,
 		Log:          filepath.Join(root, "runc-log.json"),
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go
index 3a7c624..7e082df 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go
@@ -96,10 +96,7 @@
 		}
 	}
 
-	name := "load Dockerfile"
-	if filename != "Dockerfile" {
-		name += " from " + filename
-	}
+	name := "load build definition from " + filename
 
 	src := llb.Local(LocalNameDockerfile,
 		llb.IncludePatterns([]string{filename}),
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
index f32316b..5342046 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
@@ -35,7 +35,7 @@
 	localNameContext = "context"
 	historyComment   = "buildkit.dockerfile.v0"
 
-	DefaultCopyImage = "tonistiigi/copy:v0.1.5@sha256:eab89b76ffbb3c807663a67a41e8be31b8a0e362d7fb074a55bddace563a28bb"
+	DefaultCopyImage = "tonistiigi/copy:v0.1.7@sha256:9aab7d9ab369c6daf4831bf0653f7592110ab4b7e8a33fee2b9dca546e9d3089"
 )
 
 type ConvertOpt struct {
@@ -212,7 +212,7 @@
 				eg.Go(func() error {
 					ref, err := reference.ParseNormalizedNamed(d.stage.BaseName)
 					if err != nil {
-						return err
+						return errors.Wrapf(err, "failed to parse stage name %q", d.stage.BaseName)
 					}
 					platform := d.platform
 					if platform == nil {
@@ -608,8 +608,10 @@
 	if c.PrependShell {
 		args = withShell(d.image, args)
 	}
+	env := d.state.Env()
 	opt := []llb.RunOption{llb.Args(args)}
 	for _, arg := range d.buildArgs {
+		env = append(env, fmt.Sprintf("%s=%s", arg.Key, arg.ValueString()))
 		opt = append(opt, llb.AddEnv(arg.Key, arg.ValueString()))
 	}
 	opt = append(opt, dfCmd(c))
@@ -625,7 +627,7 @@
 		return err
 	}
 	opt = append(opt, runMounts...)
-	opt = append(opt, llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(dopt.shlex, c.String(), d.state.Run(opt...).Env())), d.prefixPlatform, d.state.GetPlatform())))
+	opt = append(opt, llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(dopt.shlex, c.String(), env)), d.prefixPlatform, d.state.GetPlatform())))
 	for _, h := range dopt.extraHosts {
 		opt = append(opt, llb.AddExtraHost(h.Host, h.IP))
 	}
@@ -651,7 +653,7 @@
 	img := llb.Image(opt.copyImage, llb.MarkImageInternal, llb.Platform(opt.buildPlatforms[0]), WithInternalName("helper image for file operations"))
 
 	dest := path.Join(".", pathRelativeToWorkingDir(d.state, c.Dest()))
-	if c.Dest() == "." || c.Dest()[len(c.Dest())-1] == filepath.Separator {
+	if c.Dest() == "." || c.Dest() == "" || c.Dest()[len(c.Dest())-1] == filepath.Separator {
 		dest += string(filepath.Separator)
 	}
 	args := []string{"copy"}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nossh.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nossh.go
new file mode 100644
index 0000000..8b8afdc
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nossh.go
@@ -0,0 +1,13 @@
+// +build dfrunmount,!dfssh
+
+package dockerfile2llb
+
+import (
+	"github.com/moby/buildkit/client/llb"
+	"github.com/moby/buildkit/frontend/dockerfile/instructions"
+	"github.com/pkg/errors"
+)
+
+func dispatchSSH(m *instructions.Mount) (llb.RunOption, error) {
+	return nil, errors.Errorf("ssh mounts not allowed")
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go
index e42c861..a06ab9a 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go
@@ -65,6 +65,14 @@
 			out = append(out, secret)
 			continue
 		}
+		if mount.Type == instructions.MountTypeSSH {
+			ssh, err := dispatchSSH(mount)
+			if err != nil {
+				return nil, err
+			}
+			out = append(out, ssh)
+			continue
+		}
 		if mount.ReadOnly {
 			mountOpts = append(mountOpts, llb.Readonly)
 		}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_ssh.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_ssh.go
new file mode 100644
index 0000000..b651ad6
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_ssh.go
@@ -0,0 +1,27 @@
+// +build dfssh dfextall
+
+package dockerfile2llb
+
+import (
+	"github.com/moby/buildkit/client/llb"
+	"github.com/moby/buildkit/frontend/dockerfile/instructions"
+	"github.com/pkg/errors"
+)
+
+func dispatchSSH(m *instructions.Mount) (llb.RunOption, error) {
+	if m.Source != "" {
+		return nil, errors.Errorf("ssh does not support source")
+	}
+	opts := []llb.SSHOption{llb.SSHID(m.CacheID)}
+
+	if m.Target != "" {
+		// TODO(AkihiroSuda): support specifying permission bits
+		opts = append(opts, llb.SSHSocketTarget(m.Target))
+	}
+
+	if !m.Required {
+		opts = append(opts, llb.SSHOptional)
+	}
+
+	return llb.AddSSHSocket(opts...), nil
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nosecrets.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nosecrets.go
index 5878064..b0989b2 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nosecrets.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nosecrets.go
@@ -1,4 +1,4 @@
-// +build !dfsecrets
+// +build !dfsecrets,!dfextall
 
 package instructions
 
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nossh.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nossh.go
new file mode 100644
index 0000000..de80958
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nossh.go
@@ -0,0 +1,7 @@
+// +build !dfssh,!dfextall
+
+package instructions
+
+func isSSHMountsSupported() bool {
+	return false
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_runmount.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_runmount.go
index 8cccb76..2540a7e 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_runmount.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_runmount.go
@@ -14,12 +14,14 @@
 const MountTypeCache = "cache"
 const MountTypeTmpfs = "tmpfs"
 const MountTypeSecret = "secret"
+const MountTypeSSH = "ssh"
 
 var allowedMountTypes = map[string]struct{}{
 	MountTypeBind:   {},
 	MountTypeCache:  {},
 	MountTypeTmpfs:  {},
 	MountTypeSecret: {},
+	MountTypeSSH:    {},
 }
 
 const MountSharingShared = "shared"
@@ -47,6 +49,11 @@
 			return false
 		}
 	}
+	if s == "ssh" {
+		if !isSSHMountsSupported() {
+			return false
+		}
+	}
 	_, ok := allowedMountTypes[s]
 	return ok
 }
@@ -129,7 +136,7 @@
 				roAuto = false
 				continue
 			case "required":
-				if m.Type == "secret" {
+				if m.Type == "secret" || m.Type == "ssh" {
 					m.Required = true
 					continue
 				}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_ssh.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_ssh.go
new file mode 100644
index 0000000..8e591d3
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_ssh.go
@@ -0,0 +1,7 @@
+// +build dfssh dfextall
+
+package instructions
+
+func isSSHMountsSupported() bool {
+	return true
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/client/client.go b/vendor/github.com/moby/buildkit/frontend/gateway/client/client.go
index 18a26c1..3723538 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/client/client.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/client/client.go
@@ -7,6 +7,7 @@
 	"github.com/moby/buildkit/util/apicaps"
 	digest "github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
+	fstypes "github.com/tonistiigi/fsutil/types"
 )
 
 type Client interface {
@@ -17,8 +18,8 @@
 
 type Reference interface {
 	ReadFile(ctx context.Context, req ReadRequest) ([]byte, error)
-	// StatFile(ctx context.Context, req StatRequest) (*StatResponse, error)
-	// ReadDir(ctx context.Context, req ReadDirRequest) ([]*StatResponse, error)
+	StatFile(ctx context.Context, req StatRequest) (*fstypes.Stat, error)
+	ReadDir(ctx context.Context, req ReadDirRequest) ([]*fstypes.Stat, error)
 }
 
 type ReadRequest struct {
@@ -31,6 +32,15 @@
 	Length int
 }
 
+type ReadDirRequest struct {
+	Path           string
+	IncludePattern string
+}
+
+type StatRequest struct {
+	Path string
+}
+
 // SolveRequest is same as frontend.SolveRequest but avoiding dependency
 type SolveRequest struct {
 	Definition      *pb.Definition
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go
index d270aed..23eb227 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go
@@ -5,6 +5,7 @@
 	"sync"
 
 	"github.com/moby/buildkit/cache"
+	cacheutil "github.com/moby/buildkit/cache/util"
 	clienttypes "github.com/moby/buildkit/client"
 	"github.com/moby/buildkit/frontend"
 	"github.com/moby/buildkit/frontend/gateway/client"
@@ -15,6 +16,7 @@
 	"github.com/moby/buildkit/util/apicaps"
 	"github.com/moby/buildkit/worker"
 	"github.com/pkg/errors"
+	fstypes "github.com/tonistiigi/fsutil/types"
 )
 
 func llbBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, workerInfos []clienttypes.WorkerInfo) (*bridgeClient, error) {
@@ -136,16 +138,36 @@
 	if err != nil {
 		return nil, err
 	}
-	newReq := cache.ReadRequest{
+	newReq := cacheutil.ReadRequest{
 		Filename: req.Filename,
 	}
 	if r := req.Range; r != nil {
-		newReq.Range = &cache.FileRange{
+		newReq.Range = &cacheutil.FileRange{
 			Offset: r.Offset,
 			Length: r.Length,
 		}
 	}
-	return cache.ReadFile(ctx, ref, newReq)
+	return cacheutil.ReadFile(ctx, ref, newReq)
+}
+
+func (r *ref) ReadDir(ctx context.Context, req client.ReadDirRequest) ([]*fstypes.Stat, error) {
+	ref, err := r.getImmutableRef()
+	if err != nil {
+		return nil, err
+	}
+	newReq := cacheutil.ReadDirRequest{
+		Path:           req.Path,
+		IncludePattern: req.IncludePattern,
+	}
+	return cacheutil.ReadDir(ctx, ref, newReq)
+}
+
+func (r *ref) StatFile(ctx context.Context, req client.StatRequest) (*fstypes.Stat, error) {
+	ref, err := r.getImmutableRef()
+	if err != nil {
+		return nil, err
+	}
+	return cacheutil.StatFile(ctx, ref, req.Path)
 }
 
 func (r *ref) getImmutableRef() (cache.ImmutableRef, error) {
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go b/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go
index f5cceeb..18a28b0 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go
@@ -14,6 +14,7 @@
 	"github.com/docker/distribution/reference"
 	apitypes "github.com/moby/buildkit/api/types"
 	"github.com/moby/buildkit/cache"
+	cacheutil "github.com/moby/buildkit/cache/util"
 	"github.com/moby/buildkit/client"
 	"github.com/moby/buildkit/client/llb"
 	"github.com/moby/buildkit/executor"
@@ -479,24 +480,24 @@
 		return nil, errors.Errorf("no such ref: %v", req.Ref)
 	}
 	if ref == nil {
-		return nil, errors.Wrapf(os.ErrNotExist, "%s no found", req.FilePath)
+		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", req.FilePath)
 	}
 	workerRef, ok := ref.Sys().(*worker.WorkerRef)
 	if !ok {
 		return nil, errors.Errorf("invalid ref: %T", ref.Sys())
 	}
 
-	newReq := cache.ReadRequest{
+	newReq := cacheutil.ReadRequest{
 		Filename: req.FilePath,
 	}
 	if r := req.Range; r != nil {
-		newReq.Range = &cache.FileRange{
+		newReq.Range = &cacheutil.FileRange{
 			Offset: int(r.Offset),
 			Length: int(r.Length),
 		}
 	}
 
-	dt, err := cache.ReadFile(ctx, workerRef.ImmutableRef, newReq)
+	dt, err := cacheutil.ReadFile(ctx, workerRef.ImmutableRef, newReq)
 	if err != nil {
 		return nil, err
 	}
@@ -504,6 +505,58 @@
 	return &pb.ReadFileResponse{Data: dt}, nil
 }
 
+func (lbf *llbBridgeForwarder) ReadDir(ctx context.Context, req *pb.ReadDirRequest) (*pb.ReadDirResponse, error) {
+	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
+	lbf.mu.Lock()
+	ref, ok := lbf.refs[req.Ref]
+	lbf.mu.Unlock()
+	if !ok {
+		return nil, errors.Errorf("no such ref: %v", req.Ref)
+	}
+	if ref == nil {
+		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", req.DirPath)
+	}
+	workerRef, ok := ref.Sys().(*worker.WorkerRef)
+	if !ok {
+		return nil, errors.Errorf("invalid ref: %T", ref.Sys())
+	}
+
+	newReq := cacheutil.ReadDirRequest{
+		Path:           req.DirPath,
+		IncludePattern: req.IncludePattern,
+	}
+	entries, err := cacheutil.ReadDir(ctx, workerRef.ImmutableRef, newReq)
+	if err != nil {
+		return nil, err
+	}
+
+	return &pb.ReadDirResponse{Entries: entries}, nil
+}
+
+func (lbf *llbBridgeForwarder) StatFile(ctx context.Context, req *pb.StatFileRequest) (*pb.StatFileResponse, error) {
+	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
+	lbf.mu.Lock()
+	ref, ok := lbf.refs[req.Ref]
+	lbf.mu.Unlock()
+	if !ok {
+		return nil, errors.Errorf("no such ref: %v", req.Ref)
+	}
+	if ref == nil {
+		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", req.Path)
+	}
+	workerRef, ok := ref.Sys().(*worker.WorkerRef)
+	if !ok {
+		return nil, errors.Errorf("invalid ref: %T", ref.Sys())
+	}
+
+	st, err := cacheutil.StatFile(ctx, workerRef.ImmutableRef, req.Path)
+	if err != nil {
+		return nil, err
+	}
+
+	return &pb.StatFileResponse{Stat: st}, nil
+}
+
 func (lbf *llbBridgeForwarder) Ping(context.Context, *pb.PingRequest) (*pb.PongResponse, error) {
 
 	workers := lbf.workers.WorkerInfos()
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go b/vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go
index e30c259..d4e0525 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go
@@ -16,6 +16,7 @@
 	"github.com/moby/buildkit/util/apicaps"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
+	fstypes "github.com/tonistiigi/fsutil/types"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/status"
 )
@@ -207,7 +208,7 @@
 		{ID: string(opspb.CapExecMountCacheSharing), Enabled: true},
 		{ID: string(opspb.CapExecMountSelector), Enabled: true},
 		{ID: string(opspb.CapExecMountTmpfs), Enabled: true},
-		{ID: string(opspb.CapMountSecret), Enabled: true},
+		{ID: string(opspb.CapExecMountSecret), Enabled: true},
 		{ID: string(opspb.CapConstraints), Enabled: true},
 		{ID: string(opspb.CapPlatform), Enabled: true},
 		{ID: string(opspb.CapMetaIgnoreCache), Enabled: true},
@@ -354,6 +355,37 @@
 	return resp.Data, nil
 }
 
+func (r *reference) ReadDir(ctx context.Context, req client.ReadDirRequest) ([]*fstypes.Stat, error) {
+	if err := r.c.caps.Supports(pb.CapReadDir); err != nil {
+		return nil, err
+	}
+	rdr := &pb.ReadDirRequest{
+		DirPath:        req.Path,
+		IncludePattern: req.IncludePattern,
+		Ref:            r.id,
+	}
+	resp, err := r.c.client.ReadDir(ctx, rdr)
+	if err != nil {
+		return nil, err
+	}
+	return resp.Entries, nil
+}
+
+func (r *reference) StatFile(ctx context.Context, req client.StatRequest) (*fstypes.Stat, error) {
+	if err := r.c.caps.Supports(pb.CapStatFile); err != nil {
+		return nil, err
+	}
+	rdr := &pb.StatFileRequest{
+		Path: req.Path,
+		Ref:  r.id,
+	}
+	resp, err := r.c.client.StatFile(ctx, rdr)
+	if err != nil {
+		return nil, err
+	}
+	return resp.Stat, nil
+}
+
 func grpcClientConn(ctx context.Context) (context.Context, *grpc.ClientConn, error) {
 	dialOpt := grpc.WithDialer(func(addr string, d time.Duration) (net.Conn, error) {
 		return stdioConn(), nil
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/pb/caps.go b/vendor/github.com/moby/buildkit/frontend/gateway/pb/caps.go
index f440768..fd05e4c 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/pb/caps.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/pb/caps.go
@@ -16,6 +16,8 @@
 	CapReadFile                apicaps.CapID = "readfile"
 	CapReturnResult            apicaps.CapID = "return"
 	CapReturnMap               apicaps.CapID = "returnmap"
+	CapReadDir                 apicaps.CapID = "readdir"
+	CapStatFile                apicaps.CapID = "statfile"
 )
 
 func init() {
@@ -69,4 +71,17 @@
 		Status:  apicaps.CapStatusExperimental,
 	})
 
+	Caps.Init(apicaps.Cap{
+		ID:      CapReadDir,
+		Name:    "read static directory",
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
+
+	Caps.Init(apicaps.Cap{
+		ID:      CapStatFile,
+		Name:    "stat a file",
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
 }
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go
index 2895a4b..cf90c8a 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go
@@ -19,6 +19,10 @@
 		ReadFileRequest
 		FileRange
 		ReadFileResponse
+		ReadDirRequest
+		ReadDirResponse
+		StatFileRequest
+		StatFileResponse
 		PingRequest
 		PongResponse
 */
@@ -32,6 +36,7 @@
 import pb "github.com/moby/buildkit/solver/pb"
 import moby_buildkit_v1_types "github.com/moby/buildkit/api/types"
 import moby_buildkit_v1_apicaps "github.com/moby/buildkit/util/apicaps/pb"
+import fsutil_types "github.com/tonistiigi/fsutil/types"
 
 import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
 
@@ -448,13 +453,101 @@
 	return nil
 }
 
+type ReadDirRequest struct {
+	Ref            string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
+	DirPath        string `protobuf:"bytes,2,opt,name=DirPath,proto3" json:"DirPath,omitempty"`
+	IncludePattern string `protobuf:"bytes,3,opt,name=IncludePattern,proto3" json:"IncludePattern,omitempty"`
+}
+
+func (m *ReadDirRequest) Reset()                    { *m = ReadDirRequest{} }
+func (m *ReadDirRequest) String() string            { return proto.CompactTextString(m) }
+func (*ReadDirRequest) ProtoMessage()               {}
+func (*ReadDirRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{11} }
+
+func (m *ReadDirRequest) GetRef() string {
+	if m != nil {
+		return m.Ref
+	}
+	return ""
+}
+
+func (m *ReadDirRequest) GetDirPath() string {
+	if m != nil {
+		return m.DirPath
+	}
+	return ""
+}
+
+func (m *ReadDirRequest) GetIncludePattern() string {
+	if m != nil {
+		return m.IncludePattern
+	}
+	return ""
+}
+
+type ReadDirResponse struct {
+	Entries []*fsutil_types.Stat `protobuf:"bytes,1,rep,name=entries" json:"entries,omitempty"`
+}
+
+func (m *ReadDirResponse) Reset()                    { *m = ReadDirResponse{} }
+func (m *ReadDirResponse) String() string            { return proto.CompactTextString(m) }
+func (*ReadDirResponse) ProtoMessage()               {}
+func (*ReadDirResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{12} }
+
+func (m *ReadDirResponse) GetEntries() []*fsutil_types.Stat {
+	if m != nil {
+		return m.Entries
+	}
+	return nil
+}
+
+type StatFileRequest struct {
+	Ref  string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
+	Path string `protobuf:"bytes,2,opt,name=Path,proto3" json:"Path,omitempty"`
+}
+
+func (m *StatFileRequest) Reset()                    { *m = StatFileRequest{} }
+func (m *StatFileRequest) String() string            { return proto.CompactTextString(m) }
+func (*StatFileRequest) ProtoMessage()               {}
+func (*StatFileRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{13} }
+
+func (m *StatFileRequest) GetRef() string {
+	if m != nil {
+		return m.Ref
+	}
+	return ""
+}
+
+func (m *StatFileRequest) GetPath() string {
+	if m != nil {
+		return m.Path
+	}
+	return ""
+}
+
+type StatFileResponse struct {
+	Stat *fsutil_types.Stat `protobuf:"bytes,1,opt,name=stat" json:"stat,omitempty"`
+}
+
+func (m *StatFileResponse) Reset()                    { *m = StatFileResponse{} }
+func (m *StatFileResponse) String() string            { return proto.CompactTextString(m) }
+func (*StatFileResponse) ProtoMessage()               {}
+func (*StatFileResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{14} }
+
+func (m *StatFileResponse) GetStat() *fsutil_types.Stat {
+	if m != nil {
+		return m.Stat
+	}
+	return nil
+}
+
 type PingRequest struct {
 }
 
 func (m *PingRequest) Reset()                    { *m = PingRequest{} }
 func (m *PingRequest) String() string            { return proto.CompactTextString(m) }
 func (*PingRequest) ProtoMessage()               {}
-func (*PingRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{11} }
+func (*PingRequest) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{15} }
 
 type PongResponse struct {
 	FrontendAPICaps []moby_buildkit_v1_apicaps.APICap      `protobuf:"bytes,1,rep,name=FrontendAPICaps" json:"FrontendAPICaps"`
@@ -465,7 +558,7 @@
 func (m *PongResponse) Reset()                    { *m = PongResponse{} }
 func (m *PongResponse) String() string            { return proto.CompactTextString(m) }
 func (*PongResponse) ProtoMessage()               {}
-func (*PongResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{12} }
+func (*PongResponse) Descriptor() ([]byte, []int) { return fileDescriptorGateway, []int{16} }
 
 func (m *PongResponse) GetFrontendAPICaps() []moby_buildkit_v1_apicaps.APICap {
 	if m != nil {
@@ -500,6 +593,10 @@
 	proto.RegisterType((*ReadFileRequest)(nil), "moby.buildkit.v1.frontend.ReadFileRequest")
 	proto.RegisterType((*FileRange)(nil), "moby.buildkit.v1.frontend.FileRange")
 	proto.RegisterType((*ReadFileResponse)(nil), "moby.buildkit.v1.frontend.ReadFileResponse")
+	proto.RegisterType((*ReadDirRequest)(nil), "moby.buildkit.v1.frontend.ReadDirRequest")
+	proto.RegisterType((*ReadDirResponse)(nil), "moby.buildkit.v1.frontend.ReadDirResponse")
+	proto.RegisterType((*StatFileRequest)(nil), "moby.buildkit.v1.frontend.StatFileRequest")
+	proto.RegisterType((*StatFileResponse)(nil), "moby.buildkit.v1.frontend.StatFileResponse")
 	proto.RegisterType((*PingRequest)(nil), "moby.buildkit.v1.frontend.PingRequest")
 	proto.RegisterType((*PongResponse)(nil), "moby.buildkit.v1.frontend.PongResponse")
 }
@@ -521,6 +618,10 @@
 	Solve(ctx context.Context, in *SolveRequest, opts ...grpc.CallOption) (*SolveResponse, error)
 	// apicaps:CapReadFile
 	ReadFile(ctx context.Context, in *ReadFileRequest, opts ...grpc.CallOption) (*ReadFileResponse, error)
+	// apicaps:CapReadDir
+	ReadDir(ctx context.Context, in *ReadDirRequest, opts ...grpc.CallOption) (*ReadDirResponse, error)
+	// apicaps:CapStatFile
+	StatFile(ctx context.Context, in *StatFileRequest, opts ...grpc.CallOption) (*StatFileResponse, error)
 	Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error)
 	Return(ctx context.Context, in *ReturnRequest, opts ...grpc.CallOption) (*ReturnResponse, error)
 }
@@ -560,6 +661,24 @@
 	return out, nil
 }
 
+func (c *lLBBridgeClient) ReadDir(ctx context.Context, in *ReadDirRequest, opts ...grpc.CallOption) (*ReadDirResponse, error) {
+	out := new(ReadDirResponse)
+	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/ReadDir", in, out, c.cc, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *lLBBridgeClient) StatFile(ctx context.Context, in *StatFileRequest, opts ...grpc.CallOption) (*StatFileResponse, error) {
+	out := new(StatFileResponse)
+	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/StatFile", in, out, c.cc, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 func (c *lLBBridgeClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PongResponse, error) {
 	out := new(PongResponse)
 	err := grpc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/Ping", in, out, c.cc, opts...)
@@ -587,6 +706,10 @@
 	Solve(context.Context, *SolveRequest) (*SolveResponse, error)
 	// apicaps:CapReadFile
 	ReadFile(context.Context, *ReadFileRequest) (*ReadFileResponse, error)
+	// apicaps:CapReadDir
+	ReadDir(context.Context, *ReadDirRequest) (*ReadDirResponse, error)
+	// apicaps:CapStatFile
+	StatFile(context.Context, *StatFileRequest) (*StatFileResponse, error)
 	Ping(context.Context, *PingRequest) (*PongResponse, error)
 	Return(context.Context, *ReturnRequest) (*ReturnResponse, error)
 }
@@ -649,6 +772,42 @@
 	return interceptor(ctx, in, info, handler)
 }
 
+func _LLBBridge_ReadDir_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ReadDirRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(LLBBridgeServer).ReadDir(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/moby.buildkit.v1.frontend.LLBBridge/ReadDir",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(LLBBridgeServer).ReadDir(ctx, req.(*ReadDirRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _LLBBridge_StatFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(StatFileRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(LLBBridgeServer).StatFile(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/moby.buildkit.v1.frontend.LLBBridge/StatFile",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(LLBBridgeServer).StatFile(ctx, req.(*StatFileRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 func _LLBBridge_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(PingRequest)
 	if err := dec(in); err != nil {
@@ -702,6 +861,14 @@
 			Handler:    _LLBBridge_ReadFile_Handler,
 		},
 		{
+			MethodName: "ReadDir",
+			Handler:    _LLBBridge_ReadDir_Handler,
+		},
+		{
+			MethodName: "StatFile",
+			Handler:    _LLBBridge_StatFile_Handler,
+		},
+		{
 			MethodName: "Ping",
 			Handler:    _LLBBridge_Ping_Handler,
 		},
@@ -1169,6 +1336,130 @@
 	return i, nil
 }
 
+func (m *ReadDirRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ReadDirRequest) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.Ref) > 0 {
+		dAtA[i] = 0xa
+		i++
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.Ref)))
+		i += copy(dAtA[i:], m.Ref)
+	}
+	if len(m.DirPath) > 0 {
+		dAtA[i] = 0x12
+		i++
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.DirPath)))
+		i += copy(dAtA[i:], m.DirPath)
+	}
+	if len(m.IncludePattern) > 0 {
+		dAtA[i] = 0x1a
+		i++
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.IncludePattern)))
+		i += copy(dAtA[i:], m.IncludePattern)
+	}
+	return i, nil
+}
+
+func (m *ReadDirResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ReadDirResponse) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.Entries) > 0 {
+		for _, msg := range m.Entries {
+			dAtA[i] = 0xa
+			i++
+			i = encodeVarintGateway(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
+	}
+	return i, nil
+}
+
+func (m *StatFileRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *StatFileRequest) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.Ref) > 0 {
+		dAtA[i] = 0xa
+		i++
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.Ref)))
+		i += copy(dAtA[i:], m.Ref)
+	}
+	if len(m.Path) > 0 {
+		dAtA[i] = 0x12
+		i++
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.Path)))
+		i += copy(dAtA[i:], m.Path)
+	}
+	return i, nil
+}
+
+func (m *StatFileResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *StatFileResponse) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.Stat != nil {
+		dAtA[i] = 0xa
+		i++
+		i = encodeVarintGateway(dAtA, i, uint64(m.Stat.Size()))
+		n9, err := m.Stat.MarshalTo(dAtA[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n9
+	}
+	return i, nil
+}
+
 func (m *PingRequest) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -1449,6 +1740,60 @@
 	return n
 }
 
+func (m *ReadDirRequest) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.Ref)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	l = len(m.DirPath)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	l = len(m.IncludePattern)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	return n
+}
+
+func (m *ReadDirResponse) Size() (n int) {
+	var l int
+	_ = l
+	if len(m.Entries) > 0 {
+		for _, e := range m.Entries {
+			l = e.Size()
+			n += 1 + l + sovGateway(uint64(l))
+		}
+	}
+	return n
+}
+
+func (m *StatFileRequest) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.Ref)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	l = len(m.Path)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	return n
+}
+
+func (m *StatFileResponse) Size() (n int) {
+	var l int
+	_ = l
+	if m.Stat != nil {
+		l = m.Stat.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	return n
+}
+
 func (m *PingRequest) Size() (n int) {
 	var l int
 	_ = l
@@ -3088,6 +3433,415 @@
 	}
 	return nil
 }
+func (m *ReadDirRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ReadDirRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ReadDirRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Ref = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field DirPath", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.DirPath = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field IncludePattern", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.IncludePattern = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ReadDirResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ReadDirResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ReadDirResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Entries", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Entries = append(m.Entries, &fsutil_types.Stat{})
+			if err := m.Entries[len(m.Entries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *StatFileRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: StatFileRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: StatFileRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Ref = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Path = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *StatFileResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: StatFileResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: StatFileResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Stat", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Stat == nil {
+				m.Stat = &fsutil_types.Stat{}
+			}
+			if err := m.Stat.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *PingRequest) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
@@ -3389,68 +4143,77 @@
 func init() { proto.RegisterFile("gateway.proto", fileDescriptorGateway) }
 
 var fileDescriptorGateway = []byte{
-	// 999 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xcf, 0x6f, 0xdb, 0x36,
-	0x14, 0x8e, 0x22, 0xdb, 0xb1, 0x9f, 0xed, 0xc6, 0x23, 0x86, 0x41, 0xd5, 0x21, 0xf5, 0x84, 0xa1,
-	0xd3, 0xfa, 0x43, 0xc2, 0xdc, 0x0d, 0xed, 0x5a, 0xa0, 0x5b, 0x9d, 0x34, 0x68, 0x36, 0x67, 0x35,
-	0xd8, 0x43, 0x81, 0x62, 0x3b, 0xd0, 0x36, 0xa5, 0x08, 0x91, 0x45, 0x8d, 0xa2, 0x93, 0x19, 0xbb,
-	0x6c, 0x3b, 0xf5, 0xbe, 0x7f, 0xaa, 0xc7, 0x9d, 0x77, 0x08, 0x86, 0xdc, 0xf6, 0x5f, 0x0c, 0xa4,
-	0x28, 0x47, 0xf9, 0xe5, 0x24, 0x27, 0xf3, 0x51, 0xef, 0x7b, 0xef, 0xe3, 0x7b, 0xdf, 0x23, 0x0d,
-	0xed, 0x90, 0x08, 0x7a, 0x48, 0xe6, 0x5e, 0xca, 0x99, 0x60, 0xe8, 0xf6, 0x94, 0x8d, 0xe6, 0xde,
-	0x68, 0x16, 0xc5, 0x93, 0xfd, 0x48, 0x78, 0x07, 0x5f, 0x7a, 0x01, 0x67, 0x89, 0xa0, 0xc9, 0xc4,
-	0x7e, 0x18, 0x46, 0x62, 0x6f, 0x36, 0xf2, 0xc6, 0x6c, 0xea, 0x87, 0x2c, 0x64, 0xbe, 0x42, 0x8c,
-	0x66, 0x81, 0xb2, 0x94, 0xa1, 0x56, 0x79, 0x24, 0xbb, 0x77, 0xd6, 0x3d, 0x64, 0x2c, 0x8c, 0x29,
-	0x49, 0xa3, 0x4c, 0x2f, 0x7d, 0x9e, 0x8e, 0xfd, 0x4c, 0x10, 0x31, 0xcb, 0x34, 0xe6, 0x41, 0x09,
-	0x23, 0x89, 0xf8, 0x05, 0x11, 0x3f, 0x63, 0xf1, 0x01, 0xe5, 0x7e, 0x3a, 0xf2, 0x59, 0x5a, 0x78,
-	0xfb, 0x97, 0x7a, 0x93, 0x34, 0xf2, 0xc5, 0x3c, 0xa5, 0x99, 0x7f, 0xc8, 0xf8, 0x3e, 0xe5, 0x1a,
-	0xf0, 0xe8, 0x52, 0xc0, 0x4c, 0x44, 0xb1, 0x44, 0x8d, 0x49, 0x9a, 0xc9, 0x24, 0xf2, 0x37, 0x07,
-	0x39, 0xff, 0x19, 0x50, 0xc3, 0x34, 0x9b, 0xc5, 0x02, 0x21, 0x30, 0x39, 0x0d, 0x2c, 0xa3, 0x6b,
-	0xb8, 0x8d, 0x57, 0x2b, 0x58, 0x1a, 0xe8, 0x31, 0x54, 0x38, 0x0d, 0x32, 0x6b, 0xb5, 0x6b, 0xb8,
-	0xcd, 0xde, 0xa7, 0xde, 0xa5, 0xf5, 0xf3, 0x30, 0x0d, 0x76, 0x49, 0xfa, 0x6a, 0x05, 0x2b, 0x00,
-	0xfa, 0x01, 0xea, 0x53, 0x2a, 0xc8, 0x84, 0x08, 0x62, 0x41, 0xd7, 0x74, 0x9b, 0x3d, 0x7f, 0x29,
-	0x58, 0x32, 0xf0, 0x76, 0x35, 0xe2, 0x65, 0x22, 0xf8, 0x1c, 0x2f, 0x02, 0xd8, 0xcf, 0xa0, 0x7d,
-	0xea, 0x13, 0xea, 0x80, 0xb9, 0x4f, 0xe7, 0x39, 0x55, 0x2c, 0x97, 0xe8, 0x63, 0xa8, 0x1e, 0x90,
-	0x78, 0x46, 0x15, 0xd3, 0x16, 0xce, 0x8d, 0xa7, 0xab, 0x4f, 0x8c, 0x7e, 0x1d, 0x6a, 0x5c, 0x85,
-	0x77, 0xfe, 0x54, 0x67, 0x95, 0x34, 0xd1, 0xb7, 0xfa, 0x5c, 0x86, 0xa2, 0x76, 0xff, 0xca, 0x73,
-	0xc9, 0x9f, 0x2c, 0xa7, 0xa5, 0x80, 0xf6, 0x63, 0x68, 0x2c, 0xb6, 0xae, 0xa2, 0xd3, 0x28, 0xd1,
-	0x71, 0x04, 0xb4, 0x31, 0x15, 0x33, 0x9e, 0x60, 0xfa, 0xcb, 0x8c, 0x66, 0x02, 0x7d, 0x53, 0xf0,
-	0x53, 0xf8, 0xab, 0x8a, 0x2c, 0x1d, 0xb1, 0x06, 0x20, 0x17, 0xaa, 0x94, 0x73, 0xc6, 0x75, 0x7b,
-	0x90, 0x97, 0x2b, 0xcf, 0xe3, 0xe9, 0xd8, 0x7b, 0xa3, 0x94, 0x87, 0x73, 0x07, 0xa7, 0x03, 0xb7,
-	0x8a, 0xac, 0x59, 0xca, 0x92, 0x8c, 0x3a, 0x7f, 0x19, 0x70, 0x1b, 0x53, 0x25, 0xbc, 0x9d, 0x29,
-	0x09, 0xe9, 0x26, 0x4b, 0x82, 0x28, 0x2c, 0x48, 0x75, 0xc0, 0xc4, 0x85, 0x16, 0xb0, 0x5c, 0x22,
-	0x17, 0xea, 0xc3, 0x98, 0x88, 0x80, 0xf1, 0xa9, 0x4e, 0xd7, 0xf2, 0xd2, 0x91, 0x57, 0xec, 0xe1,
-	0xc5, 0x57, 0xd4, 0x85, 0xa6, 0x0e, 0xbc, 0xcb, 0x26, 0xd4, 0x32, 0x55, 0x8c, 0xf2, 0x16, 0xb2,
-	0x60, 0x6d, 0xc0, 0xc2, 0x1f, 0xc9, 0x94, 0x5a, 0x15, 0xf5, 0xb5, 0x30, 0x9d, 0xdf, 0x0d, 0xb0,
-	0x2f, 0x62, 0x95, 0x93, 0x46, 0xdf, 0x43, 0x6d, 0x2b, 0x0a, 0x69, 0x96, 0xd7, 0xaa, 0xd1, 0xef,
-	0x7d, 0x38, 0xba, 0xb3, 0xf2, 0xcf, 0xd1, 0x9d, 0x7b, 0x25, 0xe9, 0xb3, 0x94, 0x26, 0x63, 0x96,
-	0x08, 0x12, 0x25, 0x94, 0xcb, 0x61, 0x7c, 0x38, 0x51, 0x10, 0x2f, 0x47, 0x62, 0x1d, 0x01, 0x7d,
-	0x02, 0xb5, 0x3c, 0xba, 0x96, 0x8c, 0xb6, 0x9c, 0xf7, 0x26, 0xb4, 0xde, 0x48, 0x02, 0x45, 0x2d,
-	0x3c, 0x80, 0x2d, 0x1a, 0x44, 0x49, 0x24, 0x22, 0x96, 0xe8, 0x26, 0xdd, 0x92, 0x67, 0x3f, 0xd9,
-	0xc5, 0x25, 0x0f, 0x64, 0x43, 0x7d, 0x5b, 0x37, 0x4c, 0xb7, 0x7f, 0x61, 0xa3, 0x77, 0xd0, 0x2c,
-	0xd6, 0xaf, 0x53, 0x61, 0x99, 0x4a, 0x7e, 0x4f, 0x96, 0x74, 0xbc, 0xcc, 0xc4, 0x2b, 0x41, 0x73,
-	0x2d, 0x96, 0x83, 0x21, 0x17, 0xd6, 0x77, 0xa6, 0x29, 0xe3, 0x62, 0x93, 0x8c, 0xf7, 0xa8, 0x54,
-	0xa7, 0x55, 0xe9, 0x9a, 0x6e, 0x03, 0x9f, 0xdd, 0x46, 0x0f, 0xe0, 0x23, 0x12, 0xc7, 0xec, 0x50,
-	0xcb, 0x49, 0x09, 0xc3, 0xaa, 0x76, 0x0d, 0xb7, 0x8e, 0xcf, 0x7f, 0x90, 0x5a, 0xde, 0x8e, 0x12,
-	0x12, 0x5b, 0xa0, 0x3c, 0x72, 0x03, 0x39, 0xd0, 0x7a, 0xf9, 0xab, 0x0c, 0x4b, 0xf9, 0x0b, 0x21,
-	0xb8, 0xd5, 0x54, 0x45, 0x3c, 0xb5, 0x67, 0x3f, 0x87, 0xce, 0x59, 0xca, 0x37, 0x9a, 0x95, 0x9f,
-	0xa0, 0xad, 0xcf, 0xaf, 0xfb, 0xdf, 0x29, 0x5d, 0x51, 0xf9, 0x05, 0x75, 0x32, 0x3d, 0xe6, 0x0d,
-	0xa7, 0xc7, 0xf9, 0x0d, 0xd6, 0x31, 0x25, 0x93, 0xed, 0x28, 0xa6, 0x97, 0xcb, 0x5e, 0x36, 0x33,
-	0x8a, 0xe9, 0x90, 0x88, 0xbd, 0x45, 0x33, 0xb5, 0x8d, 0x9e, 0x42, 0x15, 0x93, 0x24, 0xa4, 0x3a,
-	0xf5, 0x67, 0x4b, 0x52, 0xab, 0x24, 0xd2, 0x17, 0xe7, 0x10, 0xe7, 0x19, 0x34, 0x16, 0x7b, 0x52,
-	0x8a, 0xaf, 0x83, 0x20, 0xa3, 0xb9, 0xac, 0x4d, 0xac, 0x2d, 0xb9, 0x3f, 0xa0, 0x49, 0xa8, 0x53,
-	0x9b, 0x58, 0x5b, 0xce, 0x5d, 0xe8, 0x9c, 0x30, 0xd7, 0xa5, 0x41, 0x50, 0xd9, 0x92, 0x97, 0xad,
-	0xa1, 0xfa, 0xa0, 0xd6, 0x4e, 0x1b, 0x9a, 0xc3, 0x28, 0x29, 0x86, 0xda, 0x39, 0x36, 0xa0, 0x35,
-	0x64, 0xc9, 0xc9, 0x38, 0x0d, 0x61, 0xbd, 0xe8, 0xcf, 0x8b, 0xe1, 0xce, 0x26, 0x49, 0x8b, 0x0b,
-	0xb1, 0x7b, 0xfe, 0x28, 0xfa, 0xf9, 0xf0, 0x72, 0xc7, 0x7e, 0x45, 0x4e, 0x1e, 0x3e, 0x0b, 0x47,
-	0xdf, 0xc1, 0xda, 0x60, 0xd0, 0x57, 0x91, 0x56, 0x6f, 0x14, 0xa9, 0x80, 0xa1, 0xe7, 0xb0, 0xf6,
-	0x56, 0xbd, 0x6a, 0x99, 0x9e, 0x8e, 0x0b, 0xca, 0xaa, 0x1e, 0x3f, 0x2f, 0x77, 0xc3, 0x74, 0xcc,
-	0xf8, 0x04, 0x17, 0xa0, 0xde, 0xfb, 0x0a, 0x34, 0x06, 0x83, 0x7e, 0x9f, 0x47, 0x93, 0x90, 0xa2,
-	0x3f, 0x0c, 0x40, 0xe7, 0xef, 0x13, 0xf4, 0xd5, 0x72, 0x95, 0x5c, 0x7c, 0x29, 0xda, 0x5f, 0xdf,
-	0x10, 0xa5, 0xab, 0xfc, 0x0e, 0xaa, 0x4a, 0xc5, 0xe8, 0xf3, 0x6b, 0xce, 0xb9, 0xed, 0x5e, 0xed,
-	0xa8, 0x63, 0x8f, 0xa1, 0x5e, 0x28, 0x01, 0xdd, 0x5b, 0x4a, 0xef, 0x94, 0xd0, 0xed, 0xfb, 0xd7,
-	0xf2, 0xd5, 0x49, 0xde, 0x42, 0x45, 0xca, 0x08, 0xdd, 0x5d, 0x02, 0x2a, 0xe9, 0xcc, 0x5e, 0x76,
-	0xce, 0x53, 0xfa, 0xfb, 0x59, 0xbe, 0xc7, 0xea, 0x8e, 0x71, 0x97, 0xf2, 0x29, 0x3d, 0x97, 0xf6,
-	0x17, 0xd7, 0xf0, 0xcc, 0xc3, 0xf7, 0x5b, 0x1f, 0x8e, 0x37, 0x8c, 0xbf, 0x8f, 0x37, 0x8c, 0x7f,
-	0x8f, 0x37, 0x8c, 0x51, 0x4d, 0xfd, 0xe1, 0x79, 0xf4, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f,
-	0xfd, 0x24, 0x08, 0x13, 0x0a, 0x00, 0x00,
+	// 1144 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xcf, 0x4f, 0x1b, 0xc7,
+	0x17, 0x67, 0xb1, 0x8d, 0xed, 0x67, 0x03, 0xfe, 0x8e, 0xbe, 0xaa, 0x36, 0x7b, 0x20, 0xee, 0xaa,
+	0xa2, 0x0e, 0x21, 0xbb, 0x2a, 0x69, 0x45, 0x4a, 0xa4, 0xa4, 0x31, 0x04, 0x85, 0xd6, 0x34, 0xd6,
+	0xe4, 0x10, 0x29, 0x6a, 0xa5, 0xae, 0xed, 0xf1, 0x32, 0x62, 0xbd, 0xb3, 0x9d, 0x1d, 0x43, 0x51,
+	0x2f, 0x6d, 0x4f, 0xbd, 0xf7, 0x9f, 0xca, 0xad, 0x3d, 0xf7, 0x10, 0x55, 0xdc, 0xfa, 0x5f, 0x54,
+	0xf3, 0x63, 0xed, 0xc5, 0x80, 0x81, 0xd3, 0xce, 0x9b, 0x79, 0x9f, 0xf7, 0x3e, 0x6f, 0xde, 0x8f,
+	0x59, 0x58, 0x0e, 0x03, 0x41, 0x4e, 0x83, 0x33, 0x2f, 0xe1, 0x4c, 0x30, 0x74, 0x6f, 0xc4, 0x7a,
+	0x67, 0x5e, 0x6f, 0x4c, 0xa3, 0xc1, 0x31, 0x15, 0xde, 0xc9, 0x67, 0xde, 0x90, 0xb3, 0x58, 0x90,
+	0x78, 0xe0, 0x3c, 0x0a, 0xa9, 0x38, 0x1a, 0xf7, 0xbc, 0x3e, 0x1b, 0xf9, 0x21, 0x0b, 0x99, 0xaf,
+	0x10, 0xbd, 0xf1, 0x50, 0x49, 0x4a, 0x50, 0x2b, 0x6d, 0xc9, 0xd9, 0x9a, 0x55, 0x0f, 0x19, 0x0b,
+	0x23, 0x12, 0x24, 0x34, 0x35, 0x4b, 0x9f, 0x27, 0x7d, 0x3f, 0x15, 0x81, 0x18, 0xa7, 0x06, 0xb3,
+	0x99, 0xc3, 0x48, 0x22, 0x7e, 0x46, 0xc4, 0x4f, 0x59, 0x74, 0x42, 0xb8, 0x9f, 0xf4, 0x7c, 0x96,
+	0x64, 0xda, 0xfe, 0xb5, 0xda, 0x41, 0x42, 0x7d, 0x71, 0x96, 0x90, 0xd4, 0x3f, 0x65, 0xfc, 0x98,
+	0x70, 0x03, 0x78, 0x7c, 0x2d, 0x60, 0x2c, 0x68, 0x24, 0x51, 0xfd, 0x20, 0x49, 0xa5, 0x13, 0xf9,
+	0x35, 0xa0, 0x7c, 0xd8, 0x82, 0xc5, 0x34, 0x15, 0x94, 0x86, 0xd4, 0x1f, 0xa6, 0x0a, 0xa3, 0xbd,
+	0xc8, 0x20, 0xb4, 0xba, 0xfb, 0xaf, 0x05, 0x4b, 0x98, 0xa4, 0xe3, 0x48, 0x20, 0x04, 0x05, 0x4e,
+	0x86, 0xb6, 0xd5, 0xb4, 0x5a, 0xd5, 0x57, 0x0b, 0x58, 0x0a, 0x68, 0x1b, 0x8a, 0x9c, 0x0c, 0x53,
+	0x7b, 0xb1, 0x69, 0xb5, 0x6a, 0x5b, 0x1f, 0x7b, 0xd7, 0x5e, 0xb7, 0x87, 0xc9, 0xf0, 0x30, 0x48,
+	0x5e, 0x2d, 0x60, 0x05, 0x40, 0xdf, 0x40, 0x65, 0x44, 0x44, 0x30, 0x08, 0x44, 0x60, 0x43, 0xb3,
+	0xd0, 0xaa, 0x6d, 0xf9, 0x73, 0xc1, 0x92, 0x81, 0x77, 0x68, 0x10, 0x2f, 0x63, 0xc1, 0xcf, 0xf0,
+	0xc4, 0x80, 0xf3, 0x14, 0x96, 0x2f, 0x1c, 0xa1, 0x06, 0x14, 0x8e, 0xc9, 0x99, 0xa6, 0x8a, 0xe5,
+	0x12, 0xfd, 0x1f, 0x4a, 0x27, 0x41, 0x34, 0x26, 0x8a, 0x69, 0x1d, 0x6b, 0x61, 0x67, 0xf1, 0x89,
+	0xd5, 0xae, 0xc0, 0x12, 0x57, 0xe6, 0xdd, 0xdf, 0x54, 0xac, 0x92, 0x26, 0x7a, 0x6e, 0xe2, 0xb2,
+	0x14, 0xb5, 0x87, 0x37, 0xc6, 0x25, 0x3f, 0xa9, 0xa6, 0xa5, 0x80, 0xce, 0x36, 0x54, 0x27, 0x5b,
+	0x37, 0xd1, 0xa9, 0xe6, 0xe8, 0xb8, 0x02, 0x96, 0x31, 0x11, 0x63, 0x1e, 0x63, 0xf2, 0xe3, 0x98,
+	0xa4, 0x02, 0x7d, 0x99, 0xf1, 0x53, 0xf8, 0x9b, 0x2e, 0x59, 0x2a, 0x62, 0x03, 0x40, 0x2d, 0x28,
+	0x11, 0xce, 0x19, 0x37, 0xe9, 0x41, 0x9e, 0x2e, 0x54, 0x8f, 0x27, 0x7d, 0xef, 0x8d, 0x2a, 0x54,
+	0xac, 0x15, 0xdc, 0x06, 0xac, 0x64, 0x5e, 0xd3, 0x84, 0xc5, 0x29, 0x71, 0xff, 0xb0, 0xe0, 0x1e,
+	0x26, 0xaa, 0x4e, 0x0f, 0x46, 0x41, 0x48, 0x76, 0x59, 0x3c, 0xa4, 0x61, 0x46, 0xaa, 0x01, 0x05,
+	0x9c, 0xd5, 0x02, 0x96, 0x4b, 0xd4, 0x82, 0x4a, 0x37, 0x0a, 0xc4, 0x90, 0xf1, 0x91, 0x71, 0x57,
+	0xf7, 0x92, 0x9e, 0x97, 0xed, 0xe1, 0xc9, 0x29, 0x6a, 0x42, 0xcd, 0x18, 0x3e, 0x64, 0x03, 0x62,
+	0x17, 0x94, 0x8d, 0xfc, 0x16, 0xb2, 0xa1, 0xdc, 0x61, 0xe1, 0xb7, 0xc1, 0x88, 0xd8, 0x45, 0x75,
+	0x9a, 0x89, 0xee, 0x2f, 0x16, 0x38, 0x57, 0xb1, 0xd2, 0xa4, 0xd1, 0xd7, 0xb0, 0xb4, 0x47, 0x43,
+	0x92, 0xea, 0xbb, 0xaa, 0xb6, 0xb7, 0xde, 0x7f, 0xb8, 0xbf, 0xf0, 0xf7, 0x87, 0xfb, 0x1b, 0xb9,
+	0xa2, 0x67, 0x09, 0x89, 0xfb, 0x2c, 0x16, 0x01, 0x8d, 0x09, 0x97, 0xbd, 0xfb, 0x68, 0xa0, 0x20,
+	0x9e, 0x46, 0x62, 0x63, 0x01, 0x7d, 0x04, 0x4b, 0xda, 0xba, 0x29, 0x19, 0x23, 0xb9, 0xbf, 0x17,
+	0xa0, 0xfe, 0x46, 0x12, 0xc8, 0xee, 0xc2, 0x03, 0xd8, 0x23, 0x43, 0x1a, 0x53, 0x41, 0x59, 0x6c,
+	0x92, 0xb4, 0x22, 0x63, 0x9f, 0xee, 0xe2, 0x9c, 0x06, 0x72, 0xa0, 0xb2, 0x6f, 0x12, 0x66, 0xd2,
+	0x3f, 0x91, 0xd1, 0x3b, 0xa8, 0x65, 0xeb, 0xd7, 0x89, 0xb0, 0x0b, 0xaa, 0xfc, 0x9e, 0xcc, 0xc9,
+	0x78, 0x9e, 0x89, 0x97, 0x83, 0xea, 0x5a, 0xcc, 0x1b, 0x43, 0x2d, 0x58, 0x3d, 0x18, 0x25, 0x8c,
+	0x8b, 0xdd, 0xa0, 0x7f, 0x44, 0x64, 0x75, 0xda, 0xc5, 0x66, 0xa1, 0x55, 0xc5, 0xb3, 0xdb, 0x68,
+	0x13, 0xfe, 0x17, 0x44, 0x11, 0x3b, 0x35, 0xe5, 0xa4, 0x0a, 0xc3, 0x2e, 0x35, 0xad, 0x56, 0x05,
+	0x5f, 0x3e, 0x90, 0xb5, 0xbc, 0x4f, 0xe3, 0x20, 0xb2, 0x41, 0x69, 0x68, 0x01, 0xb9, 0x50, 0x7f,
+	0xf9, 0x93, 0x34, 0x4b, 0xf8, 0x0b, 0x21, 0xb8, 0x5d, 0x53, 0x97, 0x78, 0x61, 0xcf, 0x79, 0x06,
+	0x8d, 0x59, 0xca, 0x77, 0xea, 0x95, 0xef, 0x60, 0xd9, 0xc4, 0x6f, 0xf2, 0xdf, 0xc8, 0x8d, 0x28,
+	0x3d, 0xa0, 0xa6, 0xdd, 0x53, 0xb8, 0x63, 0xf7, 0xb8, 0x3f, 0xc3, 0x2a, 0x26, 0xc1, 0x60, 0x9f,
+	0x46, 0xe4, 0xfa, 0xb2, 0x97, 0xc9, 0xa4, 0x11, 0xe9, 0x06, 0xe2, 0x68, 0x92, 0x4c, 0x23, 0xa3,
+	0x1d, 0x28, 0xe1, 0x20, 0x0e, 0x89, 0x71, 0xfd, 0xc9, 0x1c, 0xd7, 0xca, 0x89, 0xd4, 0xc5, 0x1a,
+	0xe2, 0x3e, 0x85, 0xea, 0x64, 0x4f, 0x96, 0xe2, 0xeb, 0xe1, 0x30, 0x25, 0xba, 0xac, 0x0b, 0xd8,
+	0x48, 0x72, 0xbf, 0x43, 0xe2, 0xd0, 0xb8, 0x2e, 0x60, 0x23, 0xb9, 0xeb, 0xd0, 0x98, 0x32, 0x37,
+	0x57, 0x83, 0xa0, 0xb8, 0x27, 0x87, 0xad, 0xa5, 0xf2, 0xa0, 0xd6, 0xee, 0x40, 0x76, 0x7d, 0x30,
+	0xd8, 0xa3, 0xfc, 0xfa, 0x00, 0x6d, 0x28, 0xef, 0x51, 0x9e, 0x8b, 0x2f, 0x13, 0xd1, 0x3a, 0xac,
+	0x1c, 0xc4, 0xfd, 0x68, 0x3c, 0x90, 0xd1, 0x0a, 0xc2, 0x63, 0xd3, 0xca, 0x33, 0xbb, 0xee, 0x73,
+	0x7d, 0x8f, 0xca, 0x8b, 0x21, 0xb3, 0x09, 0x65, 0x12, 0x0b, 0x4e, 0x49, 0x36, 0x61, 0x91, 0xa7,
+	0x1f, 0x20, 0x4f, 0x3d, 0x40, 0x6a, 0x38, 0xe1, 0x4c, 0xc5, 0xdd, 0x86, 0x55, 0xb9, 0x31, 0x3f,
+	0x11, 0x08, 0x8a, 0x39, 0x92, 0x6a, 0xed, 0xee, 0x40, 0x63, 0x0a, 0x34, 0xae, 0xd7, 0xa1, 0x28,
+	0x9f, 0x37, 0xd3, 0xa7, 0x57, 0xf9, 0x55, 0xe7, 0xee, 0x32, 0xd4, 0xba, 0x34, 0xce, 0x06, 0x9e,
+	0x7b, 0x6e, 0x41, 0xbd, 0xcb, 0xe2, 0xe9, 0xa8, 0xe9, 0xc2, 0x6a, 0x56, 0xbb, 0x2f, 0xba, 0x07,
+	0xbb, 0x41, 0x92, 0x85, 0xd2, 0xbc, 0x9c, 0x66, 0xf3, 0x12, 0x7b, 0x5a, 0xb1, 0x5d, 0x94, 0x53,
+	0x09, 0xcf, 0xc2, 0xd1, 0x57, 0x50, 0xee, 0x74, 0xda, 0xca, 0xd2, 0xe2, 0x9d, 0x2c, 0x65, 0x30,
+	0xf4, 0x0c, 0xca, 0x6f, 0xd5, 0x0f, 0x42, 0x6a, 0x26, 0xc7, 0x15, 0x25, 0xa7, 0x03, 0xd5, 0x6a,
+	0x98, 0xf4, 0x19, 0x1f, 0xe0, 0x0c, 0xb4, 0xf5, 0x67, 0x09, 0xaa, 0x9d, 0x4e, 0xbb, 0xcd, 0xe9,
+	0x20, 0x24, 0xe8, 0x57, 0x0b, 0xd0, 0xe5, 0x59, 0x8b, 0x3e, 0x9f, 0xdf, 0x41, 0x57, 0x3f, 0x18,
+	0xce, 0x17, 0x77, 0x44, 0x99, 0x5b, 0x7e, 0x07, 0x25, 0xd5, 0xe1, 0xe8, 0xd3, 0x5b, 0xce, 0x40,
+	0xa7, 0x75, 0xb3, 0xa2, 0xb1, 0xdd, 0x87, 0x4a, 0xd6, 0x25, 0x68, 0x63, 0x2e, 0xbd, 0x0b, 0x43,
+	0xc0, 0x79, 0x78, 0x2b, 0x5d, 0xe3, 0xe4, 0x07, 0x28, 0x9b, 0xe2, 0x47, 0x0f, 0x6e, 0xc0, 0x4d,
+	0xdb, 0xd0, 0xd9, 0xb8, 0x8d, 0xea, 0x34, 0x8c, 0xac, 0xc8, 0xe7, 0x86, 0x31, 0xd3, 0x42, 0x73,
+	0xc3, 0xb8, 0xd4, 0x35, 0x6f, 0xa1, 0x28, 0xbb, 0x01, 0xad, 0xcf, 0x01, 0xe5, 0xda, 0xc5, 0x99,
+	0x97, 0xae, 0x0b, 0x6d, 0xf4, 0xbd, 0xfc, 0xe5, 0x52, 0xcf, 0x48, 0x6b, 0x6e, 0xcc, 0xb9, 0x3f,
+	0x22, 0xe7, 0xc1, 0x2d, 0x34, 0xb5, 0xf9, 0x76, 0xfd, 0xfd, 0xf9, 0x9a, 0xf5, 0xd7, 0xf9, 0x9a,
+	0xf5, 0xcf, 0xf9, 0x9a, 0xd5, 0x5b, 0x52, 0xff, 0xb4, 0x8f, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff,
+	0x80, 0x7e, 0xd2, 0xb5, 0x25, 0x0c, 0x00, 0x00,
 }
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.proto b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.proto
index ff1856c..7699959 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.proto
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.proto
@@ -7,6 +7,7 @@
 import "github.com/moby/buildkit/solver/pb/ops.proto";
 import "github.com/moby/buildkit/api/types/worker.proto";
 import "github.com/moby/buildkit/util/apicaps/pb/caps.proto";
+import "github.com/tonistiigi/fsutil/types/stat.proto";
 
 option (gogoproto.sizer_all) = true;
 option (gogoproto.marshaler_all) = true;
@@ -19,6 +20,10 @@
 	rpc Solve(SolveRequest) returns (SolveResponse);
 	// apicaps:CapReadFile
 	rpc ReadFile(ReadFileRequest) returns (ReadFileResponse);
+	// apicaps:CapReadDir
+	rpc ReadDir(ReadDirRequest) returns (ReadDirResponse);
+	// apicaps:CapStatFile
+	rpc StatFile(StatFileRequest) returns (StatFileResponse);
 	rpc Ping(PingRequest) returns (PongResponse);
 	rpc Return(ReturnRequest) returns (ReturnResponse);
 }
@@ -92,6 +97,25 @@
 	bytes Data = 1;
 }
 
+message ReadDirRequest {
+	string Ref = 1;
+	string DirPath = 2;
+	string IncludePattern = 3;
+}
+
+message ReadDirResponse {
+	repeated fsutil.types.Stat entries = 1;
+}
+
+message StatFileRequest {
+	string Ref = 1;
+	string Path = 2;
+}
+
+message StatFileResponse {
+	fsutil.types.Stat stat = 1;
+}
+
 message PingRequest{
 }
 message PongResponse{
diff --git a/vendor/github.com/moby/buildkit/session/filesync/diffcopy.go b/vendor/github.com/moby/buildkit/session/filesync/diffcopy.go
index b50da2b..8334ab6 100644
--- a/vendor/github.com/moby/buildkit/session/filesync/diffcopy.go
+++ b/vendor/github.com/moby/buildkit/session/filesync/diffcopy.go
@@ -9,6 +9,7 @@
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"github.com/tonistiigi/fsutil"
+	fstypes "github.com/tonistiigi/fsutil/types"
 	"google.golang.org/grpc"
 )
 
@@ -81,10 +82,10 @@
 	}
 	return fsutil.Receive(ds.Context(), ds, dest, fsutil.ReceiveOpt{
 		Merge: true,
-		Filter: func() func(*fsutil.Stat) bool {
+		Filter: func() func(*fstypes.Stat) bool {
 			uid := os.Getuid()
 			gid := os.Getgid()
-			return func(st *fsutil.Stat) bool {
+			return func(st *fstypes.Stat) bool {
 				st.Uid = uint32(uid)
 				st.Gid = uint32(gid)
 				return true
diff --git a/vendor/github.com/moby/buildkit/session/filesync/filesync.go b/vendor/github.com/moby/buildkit/session/filesync/filesync.go
index 8f0a7c1..ae6775f 100644
--- a/vendor/github.com/moby/buildkit/session/filesync/filesync.go
+++ b/vendor/github.com/moby/buildkit/session/filesync/filesync.go
@@ -10,6 +10,7 @@
 	"github.com/moby/buildkit/session"
 	"github.com/pkg/errors"
 	"github.com/tonistiigi/fsutil"
+	fstypes "github.com/tonistiigi/fsutil/types"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/metadata"
@@ -34,7 +35,7 @@
 	Name     string
 	Dir      string
 	Excludes []string
-	Map      func(*fsutil.Stat) bool
+	Map      func(*fstypes.Stat) bool
 }
 
 // NewFSSyncProvider creates a new provider for sending files from client
diff --git a/vendor/github.com/moby/buildkit/snapshot/blobmapping/snapshotter.go b/vendor/github.com/moby/buildkit/snapshot/blobmapping/snapshotter.go
index d6861ae..e145235 100644
--- a/vendor/github.com/moby/buildkit/snapshot/blobmapping/snapshotter.go
+++ b/vendor/github.com/moby/buildkit/snapshot/blobmapping/snapshotter.go
@@ -107,10 +107,21 @@
 // Checks that there is a blob in the content store.
 // If same blob has already been set then this is a noop.
 func (s *Snapshotter) SetBlob(ctx context.Context, key string, diffID, blobsum digest.Digest) error {
-	_, err := s.opt.Content.Info(ctx, blobsum)
+	info, err := s.opt.Content.Info(ctx, blobsum)
 	if err != nil {
 		return err
 	}
+	if _, ok := info.Labels["containerd.io/uncompressed"]; !ok {
+		labels := map[string]string{
+			"containerd.io/uncompressed": diffID.String(),
+		}
+		if _, err := s.opt.Content.Update(ctx, content.Info{
+			Digest: blobsum,
+			Labels: labels,
+		}, "labels.containerd.io/uncompressed"); err != nil {
+			return err
+		}
+	}
 	md, _ := s.opt.MetadataStore.Get(key)
 
 	v, err := metadata.NewValue(DiffPair{DiffID: diffID, Blobsum: blobsum})
diff --git a/vendor/github.com/moby/buildkit/solver/index.go b/vendor/github.com/moby/buildkit/solver/index.go
index 1bb17d8..78a2cca 100644
--- a/vendor/github.com/moby/buildkit/solver/index.go
+++ b/vendor/github.com/moby/buildkit/solver/index.go
@@ -211,10 +211,12 @@
 			for _, d := range dd {
 				ll := CacheInfoLink{Input: Index(i), Digest: k.Digest(), Output: k.Output(), Selector: d.Selector}
 				for _, ckID := range d.CacheKey.CacheKey.indexIDs {
-					if l, ok := ei.items[ckID].links[ll]; ok {
-						if _, ok := l[m]; ok {
-							found = true
-							break
+					if item, ok := ei.items[ckID]; ok {
+						if l, ok := item.links[ll]; ok {
+							if _, ok := l[m]; ok {
+								found = true
+								break
+							}
 						}
 					}
 				}
diff --git a/vendor/github.com/moby/buildkit/solver/jobs.go b/vendor/github.com/moby/buildkit/solver/jobs.go
index 6b2ef61..371f431 100644
--- a/vendor/github.com/moby/buildkit/solver/jobs.go
+++ b/vendor/github.com/moby/buildkit/solver/jobs.go
@@ -13,6 +13,7 @@
 	"github.com/moby/buildkit/util/progress"
 	"github.com/moby/buildkit/util/tracing"
 	digest "github.com/opencontainers/go-digest"
+	opentracing "github.com/opentracing/opentracing-go"
 	"github.com/pkg/errors"
 )
 
@@ -45,8 +46,10 @@
 	parents  map[digest.Digest]struct{}
 	childVtx map[digest.Digest]struct{}
 
-	mpw   *progress.MultiWriter
-	allPw map[progress.Writer]struct{}
+	mpw     *progress.MultiWriter
+	allPw   map[progress.Writer]struct{}
+	mspan   *tracing.MultiSpan
+	allSpan map[opentracing.Span]struct{}
 
 	vtx          Vertex
 	clientVertex client.Vertex
@@ -168,7 +171,7 @@
 }
 
 func (sb *subBuilder) Context(ctx context.Context) context.Context {
-	return progress.WithProgress(ctx, sb.mpw)
+	return opentracing.ContextWithSpan(progress.WithProgress(ctx, sb.mpw), sb.mspan)
 }
 
 func (sb *subBuilder) EachValue(ctx context.Context, key string, fn func(interface{}) error) error {
@@ -186,6 +189,7 @@
 	list   *Solver
 	pr     *progress.MultiReader
 	pw     progress.Writer
+	span   opentracing.Span
 	values sync.Map
 
 	progressCloser func()
@@ -303,7 +307,9 @@
 			parents:      map[digest.Digest]struct{}{},
 			childVtx:     map[digest.Digest]struct{}{},
 			allPw:        map[progress.Writer]struct{}{},
+			allSpan:      map[opentracing.Span]struct{}{},
 			mpw:          progress.NewMultiWriter(progress.WithMetadata("vertex", dgst)),
+			mspan:        tracing.NewMultiSpan(),
 			vtx:          v,
 			clientVertex: initClientVertex(v),
 			edges:        map[Index]*edge{},
@@ -357,6 +363,8 @@
 			target.mpw.Add(j.pw)
 			target.allPw[j.pw] = struct{}{}
 			j.pw.Write(target.clientVertex.Digest.String(), target.clientVertex)
+			target.mspan.Add(j.span)
+			target.allSpan[j.span] = struct{}{}
 		}
 	}
 	for p := range src.parents {
@@ -380,6 +388,7 @@
 		pr:             progress.NewMultiReader(pr),
 		pw:             pw,
 		progressCloser: progressCloser,
+		span:           (&opentracing.NoopTracer{}).StartSpan(""),
 	}
 	jl.jobs[id] = j
 
@@ -428,6 +437,10 @@
 }
 
 func (j *Job) Build(ctx context.Context, e Edge) (CachedResult, error) {
+	if span := opentracing.SpanFromContext(ctx); span != nil {
+		j.span = span
+	}
+
 	v, err := j.list.load(e.Vertex, nil, j)
 	if err != nil {
 		return nil, err
@@ -453,6 +466,9 @@
 		if _, ok := st.allPw[j.pw]; ok {
 			delete(st.allPw, j.pw)
 		}
+		if _, ok := st.allSpan[j.span]; ok {
+			delete(st.allSpan, j.span)
+		}
 		st.mu.Unlock()
 	}
 	return nil
@@ -534,7 +550,7 @@
 }
 
 func (s *sharedOp) LoadCache(ctx context.Context, rec *CacheRecord) (Result, error) {
-	ctx = progress.WithProgress(ctx, s.st.mpw)
+	ctx = opentracing.ContextWithSpan(progress.WithProgress(ctx, s.st.mpw), s.st.mspan)
 	// no cache hit. start evaluating the node
 	span, ctx := tracing.StartSpan(ctx, "load cache: "+s.st.vtx.Name())
 	notifyStarted(ctx, &s.st.clientVertex, true)
@@ -557,7 +573,7 @@
 			return err, nil
 		}
 		s.slowMu.Unlock()
-		ctx = progress.WithProgress(ctx, s.st.mpw)
+		ctx = opentracing.ContextWithSpan(progress.WithProgress(ctx, s.st.mpw), s.st.mspan)
 		key, err := f(ctx, res)
 		complete := true
 		if err != nil {
@@ -581,7 +597,7 @@
 		return key, err
 	})
 	if err != nil {
-		ctx = progress.WithProgress(ctx, s.st.mpw)
+		ctx = opentracing.ContextWithSpan(progress.WithProgress(ctx, s.st.mpw), s.st.mspan)
 		notifyStarted(ctx, &s.st.clientVertex, false)
 		notifyCompleted(ctx, &s.st.clientVertex, err, false)
 		return "", err
@@ -601,7 +617,7 @@
 		if s.cacheErr != nil {
 			return nil, s.cacheErr
 		}
-		ctx = progress.WithProgress(ctx, s.st.mpw)
+		ctx = opentracing.ContextWithSpan(progress.WithProgress(ctx, s.st.mpw), s.st.mspan)
 		ctx = session.NewContext(ctx, s.st.getSessionID())
 		if len(s.st.vtx.Inputs()) == 0 {
 			// no cache hit. start evaluating the node
@@ -654,7 +670,7 @@
 			return s.execRes, s.execErr
 		}
 
-		ctx = progress.WithProgress(ctx, s.st.mpw)
+		ctx = opentracing.ContextWithSpan(progress.WithProgress(ctx, s.st.mpw), s.st.mspan)
 		ctx = session.NewContext(ctx, s.st.getSessionID())
 
 		// no cache hit. start evaluating the node
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go
index ee9c3af..9eb9968 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go
@@ -31,6 +31,7 @@
 	"github.com/moby/buildkit/solver/llbsolver"
 	"github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/progress/logs"
+	utilsystem "github.com/moby/buildkit/util/system"
 	"github.com/moby/buildkit/worker"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/opencontainers/runc/libcontainer/system"
@@ -301,7 +302,7 @@
 			return nil, nil
 		}
 		if st, ok := status.FromError(err); ok && st.Code() == codes.Unimplemented {
-			return nil, errors.Errorf("no ssh forwarded from the client")
+			return nil, errors.Errorf("no SSH key %q forwarded from the client", m.SSHOpt.ID)
 		}
 		return nil, err
 	}
@@ -467,6 +468,15 @@
 	return nil
 }
 
+func addDefaultEnvvar(env []string, k, v string) []string {
+	for _, e := range env {
+		if strings.HasPrefix(e, k+"=") {
+			return env
+		}
+	}
+	return append(env, k+"="+v)
+}
+
 func (e *execOp) Exec(ctx context.Context, inputs []solver.Result) ([]solver.Result, error) {
 	var mounts []executor.Mount
 	var root cache.Mountable
@@ -626,6 +636,7 @@
 	if e.op.Meta.ProxyEnv != nil {
 		meta.Env = append(meta.Env, proxyEnvList(e.op.Meta.ProxyEnv)...)
 	}
+	meta.Env = addDefaultEnvvar(meta.Env, "PATH", utilsystem.DefaultPathEnv)
 
 	stdout, stderr := logs.NewLogStreams(ctx, os.Getenv("BUILDKIT_DEBUG_EXEC_OUTPUT") == "1")
 	defer stdout.Close()
diff --git a/vendor/github.com/moby/buildkit/solver/pb/caps.go b/vendor/github.com/moby/buildkit/solver/pb/caps.go
index 2fa1615..b81ec62 100644
--- a/vendor/github.com/moby/buildkit/solver/pb/caps.go
+++ b/vendor/github.com/moby/buildkit/solver/pb/caps.go
@@ -30,15 +30,18 @@
 
 	CapBuildOpLLBFileName apicaps.CapID = "source.buildop.llbfilename"
 
-	CapExecMetaBase          apicaps.CapID = "exec.meta.base"
-	CapExecMetaProxy         apicaps.CapID = "exec.meta.proxyenv"
-	CapExecMetaNetwork       apicaps.CapID = "exec.meta.network"
-	CapExecMountBind         apicaps.CapID = "exec.mount.bind"
-	CapExecMountCache        apicaps.CapID = "exec.mount.cache"
-	CapExecMountCacheSharing apicaps.CapID = "exec.mount.cache.sharing"
-	CapExecMountSelector     apicaps.CapID = "exec.mount.selector"
-	CapExecMountTmpfs        apicaps.CapID = "exec.mount.tmpfs"
-	CapMountSecret           apicaps.CapID = "exec.mount.secret"
+	CapExecMetaBase            apicaps.CapID = "exec.meta.base"
+	CapExecMetaProxy           apicaps.CapID = "exec.meta.proxyenv"
+	CapExecMetaNetwork         apicaps.CapID = "exec.meta.network"
+	CapExecMetaSetsDefaultPath apicaps.CapID = "exec.meta.setsdefaultpath"
+	CapExecMountBind           apicaps.CapID = "exec.mount.bind"
+	CapExecMountCache          apicaps.CapID = "exec.mount.cache"
+	CapExecMountCacheSharing   apicaps.CapID = "exec.mount.cache.sharing"
+	CapExecMountSelector       apicaps.CapID = "exec.mount.selector"
+	CapExecMountTmpfs          apicaps.CapID = "exec.mount.tmpfs"
+	CapExecMountSecret         apicaps.CapID = "exec.mount.secret"
+	CapExecMountSSH            apicaps.CapID = "exec.mount.ssh"
+	CapExecCgroupsMounted      apicaps.CapID = "exec.cgroup"
 
 	CapConstraints apicaps.CapID = "constraints"
 	CapPlatform    apicaps.CapID = "platform"
@@ -170,6 +173,12 @@
 	})
 
 	Caps.Init(apicaps.Cap{
+		ID:      CapExecMetaSetsDefaultPath,
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
+
+	Caps.Init(apicaps.Cap{
 		ID:      CapExecMountBind,
 		Enabled: true,
 		Status:  apicaps.CapStatusExperimental,
@@ -200,7 +209,19 @@
 	})
 
 	Caps.Init(apicaps.Cap{
-		ID:      CapMountSecret,
+		ID:      CapExecMountSecret,
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
+
+	Caps.Init(apicaps.Cap{
+		ID:      CapExecMountSSH,
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
+
+	Caps.Init(apicaps.Cap{
+		ID:      CapExecCgroupsMounted,
 		Enabled: true,
 		Status:  apicaps.CapStatusExperimental,
 	})
diff --git a/vendor/github.com/moby/buildkit/util/contentutil/refs.go b/vendor/github.com/moby/buildkit/util/contentutil/refs.go
index b3a10d1..9df8406 100644
--- a/vendor/github.com/moby/buildkit/util/contentutil/refs.go
+++ b/vendor/github.com/moby/buildkit/util/contentutil/refs.go
@@ -3,11 +3,16 @@
 import (
 	"context"
 	"net/http"
+	"sync"
 
 	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes/docker"
+	"github.com/docker/docker/pkg/locker"
+	digest "github.com/opencontainers/go-digest"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
 )
 
 func ProviderFromRef(ref string) (ocispec.Descriptor, content.Provider, error) {
@@ -38,11 +43,13 @@
 	}
 
 	return &ingester{
+		locker: locker.New(),
 		pusher: pusher,
 	}, nil
 }
 
 type ingester struct {
+	locker *locker.Locker
 	pusher remotes.Pusher
 }
 
@@ -53,5 +60,38 @@
 			return nil, err
 		}
 	}
-	return w.pusher.Push(ctx, wo.Desc)
+	if wo.Ref == "" {
+		return nil, errors.Wrap(errdefs.ErrInvalidArgument, "ref must not be empty")
+	}
+	w.locker.Lock(wo.Ref)
+	var once sync.Once
+	unlock := func() {
+		once.Do(func() {
+			w.locker.Unlock(wo.Ref)
+		})
+	}
+	writer, err := w.pusher.Push(ctx, wo.Desc)
+	if err != nil {
+		return nil, err
+	}
+	return &lockedWriter{unlock: unlock, Writer: writer}, nil
+}
+
+type lockedWriter struct {
+	unlock func()
+	content.Writer
+}
+
+func (w *lockedWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
+	err := w.Writer.Commit(ctx, size, expected, opts...)
+	if err == nil {
+		w.unlock()
+	}
+	return err
+}
+
+func (w *lockedWriter) Close() error {
+	err := w.Writer.Close()
+	w.unlock()
+	return err
 }
diff --git a/vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go b/vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go
index d792311..89866b7 100644
--- a/vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go
+++ b/vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go
@@ -15,7 +15,10 @@
 // flightcontrol is like singleflight but with support for cancellation and
 // nested progress reporting
 
-var errRetry = errors.Errorf("retry")
+var (
+	errRetry        = errors.Errorf("retry")
+	errRetryTimeout = errors.Errorf("exceeded retry timeout")
+)
 
 type contextKeyT string
 
@@ -29,12 +32,28 @@
 
 // Do executes a context function syncronized by the key
 func (g *Group) Do(ctx context.Context, key string, fn func(ctx context.Context) (interface{}, error)) (v interface{}, err error) {
-	defer func() {
-		if errors.Cause(err) == errRetry {
-			runtime.Gosched()
-			v, err = g.Do(ctx, key, fn)
+	var backoff time.Duration
+	for {
+		v, err = g.do(ctx, key, fn)
+		if err == nil || errors.Cause(err) != errRetry {
+			return v, err
 		}
-	}()
+		// backoff logic
+		if backoff >= 3*time.Second {
+			err = errors.Wrapf(errRetryTimeout, "flightcontrol")
+			return v, err
+		}
+		runtime.Gosched()
+		if backoff > 0 {
+			time.Sleep(backoff)
+			backoff *= 2
+		} else {
+			backoff = time.Millisecond
+		}
+	}
+}
+
+func (g *Group) do(ctx context.Context, key string, fn func(ctx context.Context) (interface{}, error)) (interface{}, error) {
 	g.mu.Lock()
 	if g.m == nil {
 		g.m = make(map[string]*call)
diff --git a/vendor/github.com/moby/buildkit/util/tracing/multispan.go b/vendor/github.com/moby/buildkit/util/tracing/multispan.go
new file mode 100644
index 0000000..2b157a1
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/tracing/multispan.go
@@ -0,0 +1,22 @@
+package tracing
+
+import (
+	opentracing "github.com/opentracing/opentracing-go"
+)
+
+// MultiSpan allows shared tracing to multiple spans.
+// TODO: This is a temporary solution and doesn't really support shared tracing yet. Instead the first always wins.
+
+type MultiSpan struct {
+	opentracing.Span
+}
+
+func NewMultiSpan() *MultiSpan {
+	return &MultiSpan{}
+}
+
+func (ms *MultiSpan) Add(s opentracing.Span) {
+	if ms.Span == nil {
+		ms.Span = s
+	}
+}
diff --git a/vendor/github.com/moby/buildkit/vendor.conf b/vendor/github.com/moby/buildkit/vendor.conf
index 00f8c83..ba9a01e 100644
--- a/vendor/github.com/moby/buildkit/vendor.conf
+++ b/vendor/github.com/moby/buildkit/vendor.conf
@@ -40,7 +40,7 @@
 github.com/docker/docker 71cd53e4a197b303c6ba086bd584ffd67a884281
 github.com/pkg/profile 5b67d428864e92711fcbd2f8629456121a56d91f
 
-github.com/tonistiigi/fsutil 7e391b0e788f9b925f22bd3cf88e0210d1643673
+github.com/tonistiigi/fsutil f567071bed2416e4d87d260d3162722651182317
 github.com/hashicorp/go-immutable-radix 826af9ccf0feeee615d546d69b11f8e98da8c8f1 git://github.com/tonistiigi/go-immutable-radix.git
 github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
 github.com/mitchellh/hashstructure 2bca23e0e452137f789efbc8610126fd8b94f73b
diff --git a/vendor/github.com/opencontainers/runc/README.md b/vendor/github.com/opencontainers/runc/README.md
index 5215e32..83379d9 100644
--- a/vendor/github.com/opencontainers/runc/README.md
+++ b/vendor/github.com/opencontainers/runc/README.md
@@ -87,6 +87,18 @@
 # make test TESTFLAGS="-run=SomeTestFunction"
 ```
 
+You can run a specific integration test by setting the `TESTPATH` variable.
+
+```bash
+# make test TESTPATH="/checkpoint.bats"
+```
+
+You can run a test in your proxy environment by setting `DOCKER_BUILD_PROXY` and `DOCKER_RUN_PROXY` variables.
+
+```bash
+# make test DOCKER_BUILD_PROXY="--build-arg HTTP_PROXY=http://yourproxy/" DOCKER_RUN_PROXY="-e HTTP_PROXY=http://yourproxy/"
+```
+
 ### Dependencies Management
 
 `runc` uses [vndr](https://github.com/LK4D4/vndr) for dependencies management.
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
index 7c995ef..7c61ff1 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
@@ -13,7 +13,7 @@
 	"strings"
 	"time"
 
-	"github.com/docker/go-units"
+	units "github.com/docker/go-units"
 )
 
 const (
@@ -103,7 +103,7 @@
 		}
 
 		if postSeparatorFields[0] == "cgroup" {
-			// Check that the mount is properly formated.
+			// Check that the mount is properly formatted.
 			if numPostFields < 3 {
 				return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
 			}
@@ -151,19 +151,20 @@
 			Root:       fields[3],
 		}
 		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
-			if !ss[opt] {
+			seen, known := ss[opt]
+			if !known || (!all && seen) {
 				continue
 			}
+			ss[opt] = true
 			if strings.HasPrefix(opt, cgroupNamePrefix) {
-				m.Subsystems = append(m.Subsystems, opt[len(cgroupNamePrefix):])
-			} else {
-				m.Subsystems = append(m.Subsystems, opt)
+				opt = opt[len(cgroupNamePrefix):]
 			}
-			if !all {
-				numFound++
-			}
+			m.Subsystems = append(m.Subsystems, opt)
+			numFound++
 		}
-		res = append(res, m)
+		if len(m.Subsystems) > 0 || all {
+			res = append(res, m)
+		}
 	}
 	if err := scanner.Err(); err != nil {
 		return nil, err
@@ -187,7 +188,7 @@
 
 	allMap := make(map[string]bool)
 	for s := range allSubsystems {
-		allMap[s] = true
+		allMap[s] = false
 	}
 	return getCgroupMountsHelper(allMap, f, all)
 }
@@ -262,7 +263,7 @@
 	}
 
 	// This is needed for nested containers, because in /proc/self/cgroup we
-	// see pathes from host, which don't exist in container.
+	// see paths from host, which don't exist in container.
 	relCgroup, err := filepath.Rel(root, cgroup)
 	if err != nil {
 		return "", err
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/nsenter/README.md b/vendor/github.com/opencontainers/runc/libcontainer/nsenter/README.md
index 5757013..9ec6c39 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/nsenter/README.md
+++ b/vendor/github.com/opencontainers/runc/libcontainer/nsenter/README.md
@@ -10,8 +10,8 @@
 package. In cgo, if the import of "C" is immediately preceded by a comment, that comment, 
 called the preamble, is used as a header when compiling the C parts of the package.
 So every time we  import package `nsenter`, the C code function `nsexec()` would be 
-called. And package `nsenter` is now only imported in `main_unix.go`, so every time
-before we call `cmd.Start` on linux, that C code would run.
+called. And package `nsenter` is only imported in `init.go`, so every time the runc
+`init` command is invoked, that C code is run.
 
 Because `nsexec()` must be run before the Go runtime in order to use the
 Linux kernel namespace, you must `import` this library into a package if
@@ -37,7 +37,7 @@
 return to allow the Go runtime take over.
 
 NOTE: We do both `setns(2)` and `clone(2)` even if we don't have any
-CLONE_NEW* clone flags because we must fork a new process in order to
+`CLONE_NEW*` clone flags because we must fork a new process in order to
 enter the PID namespace.
 
 
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c b/vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
index a4cd139..cb22431 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
+++ b/vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
@@ -211,7 +211,7 @@
 
 	/*
 	 * If @app is NULL, execve will segfault. Just check it here and bail (if
-	 * we're in this path, the caller is already getting desparate and there
+	 * we're in this path, the caller is already getting desperate and there
 	 * isn't a backup to this failing). This usually would be a configuration
 	 * or programming issue.
 	 */
diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
index 7781c53..f32698c 100644
--- a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
+++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
@@ -503,6 +503,8 @@
 	DNSSearchList []string `json:"DNSSearchList,omitempty"`
 	// Name (ID) of the container that we will share with the network stack.
 	NetworkSharedContainerName string `json:"networkSharedContainerName,omitempty"`
+	// name (ID) of the network namespace that will be used for the container.
+	NetworkNamespace string `json:"networkNamespace,omitempty"`
 }
 
 // WindowsHyperV contains information for configuring a container to run with Hyper-V isolation.
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
index c008a38..f0a055b 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
@@ -87,9 +87,6 @@
 // SetProcessLabel takes a process label and tells the kernel to assign the
 // label to the next program executed by the current process.
 func SetProcessLabel(processLabel string) error {
-	if processLabel == "" {
-		return nil
-	}
 	return selinux.SetExecLabel(processLabel)
 }
 
@@ -133,7 +130,7 @@
 		return nil
 	}
 
-	exclude_paths := map[string]bool{"/": true, "/usr": true, "/etc": true}
+	exclude_paths := map[string]bool{"/": true, "/usr": true, "/etc": true, "/tmp": true, "/home": true, "/run": true, "/var": true, "/root": true}
 	if exclude_paths[path] {
 		return fmt.Errorf("SELinux relabeling of %s is not allowed", path)
 	}
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
similarity index 69%
rename from vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
rename to vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
index de9316c..5dc09a5 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
@@ -1,13 +1,16 @@
-// +build linux
+// +build selinux,linux
 
 package selinux
 
 import (
 	"bufio"
+	"bytes"
 	"crypto/rand"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"regexp"
@@ -23,14 +26,16 @@
 	// Permissive constant to indicate SELinux is in permissive mode
 	Permissive = 0
 	// Disabled constant to indicate SELinux is disabled
-	Disabled         = -1
+	Disabled = -1
+
 	selinuxDir       = "/etc/selinux/"
 	selinuxConfig    = selinuxDir + "config"
+	selinuxfsMount   = "/sys/fs/selinux"
 	selinuxTypeTag   = "SELINUXTYPE"
 	selinuxTag       = "SELINUX"
-	selinuxPath      = "/sys/fs/selinux"
 	xattrNameSelinux = "security.selinux"
 	stRdOnly         = 0x01
+	selinuxfsMagic   = 0xf97cff8c
 )
 
 type selinuxState struct {
@@ -43,7 +48,13 @@
 }
 
 var (
+	// ErrMCSAlreadyExists is returned when trying to allocate a duplicate MCS.
+	ErrMCSAlreadyExists = errors.New("MCS label already exists")
+	// ErrEmptyPath is returned when an empty path has been specified.
+	ErrEmptyPath = errors.New("empty path")
+
 	assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`)
+	roFileLabel string
 	state       = selinuxState{
 		mcsList: make(map[string]bool),
 	}
@@ -91,6 +102,83 @@
 	return s.selinuxfs
 }
 
+func verifySELinuxfsMount(mnt string) bool {
+	var buf syscall.Statfs_t
+	for {
+		err := syscall.Statfs(mnt, &buf)
+		if err == nil {
+			break
+		}
+		if err == syscall.EAGAIN {
+			continue
+		}
+		return false
+	}
+	if uint32(buf.Type) != uint32(selinuxfsMagic) {
+		return false
+	}
+	if (buf.Flags & stRdOnly) != 0 {
+		return false
+	}
+
+	return true
+}
+
+func findSELinuxfs() string {
+	// fast path: check the default mount first
+	if verifySELinuxfsMount(selinuxfsMount) {
+		return selinuxfsMount
+	}
+
+	// check if selinuxfs is available before going the slow path
+	fs, err := ioutil.ReadFile("/proc/filesystems")
+	if err != nil {
+		return ""
+	}
+	if !bytes.Contains(fs, []byte("\tselinuxfs\n")) {
+		return ""
+	}
+
+	// slow path: try to find among the mounts
+	f, err := os.Open("/proc/self/mountinfo")
+	if err != nil {
+		return ""
+	}
+	defer f.Close()
+
+	scanner := bufio.NewScanner(f)
+	for {
+		mnt := findSELinuxfsMount(scanner)
+		if mnt == "" { // error or not found
+			return ""
+		}
+		if verifySELinuxfsMount(mnt) {
+			return mnt
+		}
+	}
+}
+
+// findSELinuxfsMount returns a next selinuxfs mount point found,
+// if there is one, or an empty string in case of EOF or error.
+func findSELinuxfsMount(s *bufio.Scanner) string {
+	for s.Scan() {
+		txt := s.Text()
+		// The first field after - is fs type.
+		// Safe as spaces in mountpoints are encoded as \040
+		if !strings.Contains(txt, " - selinuxfs ") {
+			continue
+		}
+		const mPos = 5 // mount point is 5th field
+		fields := strings.SplitN(txt, " ", mPos+1)
+		if len(fields) < mPos+1 {
+			continue
+		}
+		return fields[mPos-1]
+	}
+
+	return ""
+}
+
 func (s *selinuxState) getSELinuxfs() string {
 	s.Lock()
 	selinuxfs := s.selinuxfs
@@ -100,40 +188,7 @@
 		return selinuxfs
 	}
 
-	selinuxfs = ""
-	f, err := os.Open("/proc/self/mountinfo")
-	if err != nil {
-		return selinuxfs
-	}
-	defer f.Close()
-
-	scanner := bufio.NewScanner(f)
-	for scanner.Scan() {
-		txt := scanner.Text()
-		// Safe as mountinfo encodes mountpoints with spaces as \040.
-		sepIdx := strings.Index(txt, " - ")
-		if sepIdx == -1 {
-			continue
-		}
-		if !strings.Contains(txt[sepIdx:], "selinuxfs") {
-			continue
-		}
-		fields := strings.Split(txt, " ")
-		if len(fields) < 5 {
-			continue
-		}
-		selinuxfs = fields[4]
-		break
-	}
-
-	if selinuxfs != "" {
-		var buf syscall.Statfs_t
-		syscall.Statfs(selinuxfs, &buf)
-		if (buf.Flags & stRdOnly) == 1 {
-			selinuxfs = ""
-		}
-	}
-	return s.setSELinuxfs(selinuxfs)
+	return s.setSELinuxfs(findSELinuxfs())
 }
 
 // getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs
@@ -150,7 +205,7 @@
 	return state.getEnabled()
 }
 
-func readConfig(target string) (value string) {
+func readConfig(target string) string {
 	var (
 		val, key string
 		bufin    *bufio.Reader
@@ -192,30 +247,42 @@
 }
 
 func getSELinuxPolicyRoot() string {
-	return selinuxDir + readConfig(selinuxTypeTag)
+	return filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
 }
 
-func readCon(name string) (string, error) {
-	var val string
+func readCon(fpath string) (string, error) {
+	if fpath == "" {
+		return "", ErrEmptyPath
+	}
 
-	in, err := os.Open(name)
+	in, err := os.Open(fpath)
 	if err != nil {
 		return "", err
 	}
 	defer in.Close()
 
-	_, err = fmt.Fscanf(in, "%s", &val)
-	return val, err
+	var retval string
+	if _, err := fmt.Fscanf(in, "%s", &retval); err != nil {
+		return "", err
+	}
+	return strings.Trim(retval, "\x00"), nil
 }
 
 // SetFileLabel sets the SELinux label for this path or returns an error.
-func SetFileLabel(path string, label string) error {
-	return lsetxattr(path, xattrNameSelinux, []byte(label), 0)
+func SetFileLabel(fpath string, label string) error {
+	if fpath == "" {
+		return ErrEmptyPath
+	}
+	return lsetxattr(fpath, xattrNameSelinux, []byte(label), 0)
 }
 
 // FileLabel returns the SELinux label for this path or returns an error.
-func FileLabel(path string) (string, error) {
-	label, err := lgetxattr(path, xattrNameSelinux)
+func FileLabel(fpath string) (string, error) {
+	if fpath == "" {
+		return "", ErrEmptyPath
+	}
+
+	label, err := lgetxattr(fpath, xattrNameSelinux)
 	if err != nil {
 		return "", err
 	}
@@ -260,8 +327,12 @@
 	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()))
 }
 
-func writeCon(name string, val string) error {
-	out, err := os.OpenFile(name, os.O_WRONLY, 0)
+func writeCon(fpath string, val string) error {
+	if fpath == "" {
+		return ErrEmptyPath
+	}
+
+	out, err := os.OpenFile(fpath, os.O_WRONLY, 0)
 	if err != nil {
 		return err
 	}
@@ -276,6 +347,37 @@
 }
 
 /*
+CanonicalizeContext takes a context string and writes it to the kernel
+the function then returns the context that the kernel will use.  This function
+can be used to see if two contexts are equivalent
+*/
+func CanonicalizeContext(val string) (string, error) {
+	return readWriteCon(filepath.Join(getSelinuxMountPoint(), "context"), val)
+}
+
+func readWriteCon(fpath string, val string) (string, error) {
+	if fpath == "" {
+		return "", ErrEmptyPath
+	}
+	f, err := os.OpenFile(fpath, os.O_RDWR, 0)
+	if err != nil {
+		return "", err
+	}
+	defer f.Close()
+
+	_, err = f.Write([]byte(val))
+	if err != nil {
+		return "", err
+	}
+
+	var retval string
+	if _, err := fmt.Fscanf(f, "%s", &retval); err != nil {
+		return "", err
+	}
+	return strings.Trim(retval, "\x00"), nil
+}
+
+/*
 SetExecLabel sets the SELinux label that the kernel will use for any programs
 that are executed by the current process thread, or an error.
 */
@@ -285,7 +387,10 @@
 
 // Get returns the Context as a string
 func (c Context) Get() string {
-	return fmt.Sprintf("%s:%s:%s:%s", c["user"], c["role"], c["type"], c["level"])
+	if c["level"] != "" {
+		return fmt.Sprintf("%s:%s:%s:%s", c["user"], c["role"], c["type"], c["level"])
+	}
+	return fmt.Sprintf("%s:%s:%s", c["user"], c["role"], c["type"])
 }
 
 // NewContext creates a new Context struct from the specified label
@@ -297,7 +402,9 @@
 		c["user"] = con[0]
 		c["role"] = con[1]
 		c["type"] = con[2]
-		c["level"] = con[3]
+		if len(con) > 3 {
+			c["level"] = con[3]
+		}
 	}
 	return c
 }
@@ -306,12 +413,14 @@
 func ReserveLabel(label string) {
 	if len(label) != 0 {
 		con := strings.SplitN(label, ":", 4)
-		mcsAdd(con[3])
+		if len(con) > 3 {
+			mcsAdd(con[3])
+		}
 	}
 }
 
 func selinuxEnforcePath() string {
-	return fmt.Sprintf("%s/enforce", selinuxPath)
+	return fmt.Sprintf("%s/enforce", getSelinuxMountPoint())
 }
 
 // EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
@@ -354,16 +463,22 @@
 }
 
 func mcsAdd(mcs string) error {
+	if mcs == "" {
+		return nil
+	}
 	state.Lock()
 	defer state.Unlock()
 	if state.mcsList[mcs] {
-		return fmt.Errorf("MCS Label already exists")
+		return ErrMCSAlreadyExists
 	}
 	state.mcsList[mcs] = true
 	return nil
 }
 
 func mcsDelete(mcs string) {
+	if mcs == "" {
+		return
+	}
 	state.Lock()
 	defer state.Unlock()
 	state.mcsList[mcs] = false
@@ -424,14 +539,14 @@
 func ReleaseLabel(label string) {
 	if len(label) != 0 {
 		con := strings.SplitN(label, ":", 4)
-		mcsDelete(con[3])
+		if len(con) > 3 {
+			mcsDelete(con[3])
+		}
 	}
 }
 
-var roFileLabel string
-
 // ROFileLabel returns the specified SELinux readonly file label
-func ROFileLabel() (fileLabel string) {
+func ROFileLabel() string {
 	return roFileLabel
 }
 
@@ -497,23 +612,25 @@
 		roFileLabel = fileLabel
 	}
 exit:
-	mcs := uniqMcs(1024)
 	scon := NewContext(processLabel)
-	scon["level"] = mcs
-	processLabel = scon.Get()
-	scon = NewContext(fileLabel)
-	scon["level"] = mcs
-	fileLabel = scon.Get()
+	if scon["level"] != "" {
+		mcs := uniqMcs(1024)
+		scon["level"] = mcs
+		processLabel = scon.Get()
+		scon = NewContext(fileLabel)
+		scon["level"] = mcs
+		fileLabel = scon.Get()
+	}
 	return processLabel, fileLabel
 }
 
 // SecurityCheckContext validates that the SELinux label is understood by the kernel
 func SecurityCheckContext(val string) error {
-	return writeCon(fmt.Sprintf("%s.context", selinuxPath), val)
+	return writeCon(fmt.Sprintf("%s/context", getSelinuxMountPoint()), val)
 }
 
 /*
-CopyLevel returns a label with the MLS/MCS level from src label replaces on
+CopyLevel returns a label with the MLS/MCS level from src label replaced on
 the dest label.
 */
 func CopyLevel(src, dest string) (string, error) {
@@ -536,20 +653,26 @@
 
 // Prevent users from relabing system files
 func badPrefix(fpath string) error {
-	var badprefixes = []string{"/usr"}
+	if fpath == "" {
+		return ErrEmptyPath
+	}
 
-	for _, prefix := range badprefixes {
-		if fpath == prefix || strings.HasPrefix(fpath, fmt.Sprintf("%s/", prefix)) {
+	badPrefixes := []string{"/usr"}
+	for _, prefix := range badPrefixes {
+		if strings.HasPrefix(fpath, prefix) {
 			return fmt.Errorf("relabeling content in %s is not allowed", prefix)
 		}
 	}
 	return nil
 }
 
-// Chcon changes the fpath file object to the SELinux label label.
-// If the fpath is a directory and recurse is true Chcon will walk the
-// directory tree setting the label
+// Chcon changes the `fpath` file object to the SELinux label `label`.
+// If `fpath` is a directory and `recurse`` is true, Chcon will walk the
+// directory tree setting the label.
 func Chcon(fpath string, label string, recurse bool) error {
+	if fpath == "" {
+		return ErrEmptyPath
+	}
 	if label == "" {
 		return nil
 	}
@@ -568,7 +691,7 @@
 }
 
 // DupSecOpt takes an SELinux process label and returns security options that
-// can will set the SELinux Type and Level for future container processes
+// can be used to set the SELinux Type and Level for future container processes.
 func DupSecOpt(src string) []string {
 	if src == "" {
 		return nil
@@ -576,18 +699,23 @@
 	con := NewContext(src)
 	if con["user"] == "" ||
 		con["role"] == "" ||
-		con["type"] == "" ||
-		con["level"] == "" {
+		con["type"] == "" {
 		return nil
 	}
-	return []string{"user:" + con["user"],
+	dup := []string{"user:" + con["user"],
 		"role:" + con["role"],
 		"type:" + con["type"],
-		"level:" + con["level"]}
+	}
+
+	if con["level"] != "" {
+		dup = append(dup, "level:"+con["level"])
+	}
+
+	return dup
 }
 
-// DisableSecOpt returns a security opt that can be used to disabling SELinux
-// labeling support for future container processes
+// DisableSecOpt returns a security opt that can be used to disable SELinux
+// labeling support for future container processes.
 func DisableSecOpt() []string {
 	return []string{"disable"}
 }
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
new file mode 100644
index 0000000..4dbfd83
--- /dev/null
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
@@ -0,0 +1,188 @@
+// +build !selinux
+
+package selinux
+
+import (
+	"errors"
+)
+
+const (
+	// Enforcing constant indicate SELinux is in enforcing mode
+	Enforcing = 1
+	// Permissive constant to indicate SELinux is in permissive mode
+	Permissive = 0
+	// Disabled constant to indicate SELinux is disabled
+	Disabled = -1
+)
+
+var (
+	// ErrMCSAlreadyExists is returned when trying to allocate a duplicate MCS.
+	ErrMCSAlreadyExists = errors.New("MCS label already exists")
+	// ErrEmptyPath is returned when an empty path has been specified.
+	ErrEmptyPath = errors.New("empty path")
+)
+
+// Context is a representation of the SELinux label broken into 4 parts
+type Context map[string]string
+
+// SetDisabled disables selinux support for the package
+func SetDisabled() {
+	return
+}
+
+// GetEnabled returns whether selinux is currently enabled.
+func GetEnabled() bool {
+	return false
+}
+
+// SetFileLabel sets the SELinux label for this path or returns an error.
+func SetFileLabel(fpath string, label string) error {
+	return nil
+}
+
+// FileLabel returns the SELinux label for this path or returns an error.
+func FileLabel(fpath string) (string, error) {
+	return "", nil
+}
+
+/*
+SetFSCreateLabel tells kernel the label to create all file system objects
+created by this task. Setting label="" to return to default.
+*/
+func SetFSCreateLabel(label string) error {
+	return nil
+}
+
+/*
+FSCreateLabel returns the default label the kernel which the kernel is using
+for file system objects created by this task. "" indicates default.
+*/
+func FSCreateLabel() (string, error) {
+	return "", nil
+}
+
+// CurrentLabel returns the SELinux label of the current process thread, or an error.
+func CurrentLabel() (string, error) {
+	return "", nil
+}
+
+// PidLabel returns the SELinux label of the given pid, or an error.
+func PidLabel(pid int) (string, error) {
+	return "", nil
+}
+
+/*
+ExecLabel returns the SELinux label that the kernel will use for any programs
+that are executed by the current process thread, or an error.
+*/
+func ExecLabel() (string, error) {
+	return "", nil
+}
+
+/*
+CanonicalizeContext takes a context string and writes it to the kernel
+the function then returns the context that the kernel will use.  This function
+can be used to see if two contexts are equivalent
+*/
+func CanonicalizeContext(val string) (string, error) {
+	return "", nil
+}
+
+/*
+SetExecLabel sets the SELinux label that the kernel will use for any programs
+that are executed by the current process thread, or an error.
+*/
+func SetExecLabel(label string) error {
+	return nil
+}
+
+// Get returns the Context as a string
+func (c Context) Get() string {
+	return ""
+}
+
+// NewContext creates a new Context struct from the specified label
+func NewContext(label string) Context {
+	c := make(Context)
+	return c
+}
+
+// ReserveLabel reserves the MLS/MCS level component of the specified label
+func ReserveLabel(label string) {
+	return
+}
+
+// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
+func EnforceMode() int {
+	return Disabled
+}
+
+/*
+SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
+Disabled is not valid, since this needs to be set at boot time.
+*/
+func SetEnforceMode(mode int) error {
+	return nil
+}
+
+/*
+DefaultEnforceMode returns the systems default SELinux mode Enforcing,
+Permissive or Disabled. Note this is is just the default at boot time.
+EnforceMode tells you the systems current mode.
+*/
+func DefaultEnforceMode() int {
+	return Disabled
+}
+
+/*
+ReleaseLabel will unreserve the MLS/MCS Level field of the specified label.
+Allowing it to be used by another process.
+*/
+func ReleaseLabel(label string) {
+	return
+}
+
+// ROFileLabel returns the specified SELinux readonly file label
+func ROFileLabel() string {
+	return ""
+}
+
+/*
+ContainerLabels returns an allocated processLabel and fileLabel to be used for
+container labeling by the calling process.
+*/
+func ContainerLabels() (processLabel string, fileLabel string) {
+	return "", ""
+}
+
+// SecurityCheckContext validates that the SELinux label is understood by the kernel
+func SecurityCheckContext(val string) error {
+	return nil
+}
+
+/*
+CopyLevel returns a label with the MLS/MCS level from src label replaced on
+the dest label.
+*/
+func CopyLevel(src, dest string) (string, error) {
+	return "", nil
+}
+
+// Chcon changes the `fpath` file object to the SELinux label `label`.
+// If `fpath` is a directory and `recurse`` is true, Chcon will walk the
+// directory tree setting the label.
+func Chcon(fpath string, label string, recurse bool) error {
+	return nil
+}
+
+// DupSecOpt takes an SELinux process label and returns security options that
+// can be used to set the SELinux Type and Level for future container processes.
+func DupSecOpt(src string) []string {
+	return nil
+}
+
+// DisableSecOpt returns a security opt that can be used to disable SELinux
+// labeling support for future container processes.
+func DisableSecOpt() []string {
+	return []string{"disable"}
+}
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go b/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
index 7f2ef85..67a9d8e 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
@@ -1,4 +1,4 @@
-// +build linux
+// +build selinux,linux
 
 package selinux
 
diff --git a/vendor/github.com/tonistiigi/fsutil/diff.go b/vendor/github.com/tonistiigi/fsutil/diff.go
index 340a0e4..acad9f4 100644
--- a/vendor/github.com/tonistiigi/fsutil/diff.go
+++ b/vendor/github.com/tonistiigi/fsutil/diff.go
@@ -4,6 +4,8 @@
 	"context"
 	"hash"
 	"os"
+
+	"github.com/tonistiigi/fsutil/types"
 )
 
 type walkerFn func(ctx context.Context, pathC chan<- *currentPath) error
@@ -14,7 +16,7 @@
 
 type HandleChangeFn func(ChangeKind, string, os.FileInfo, error) error
 
-type ContentHasher func(*Stat) (hash.Hash, error)
+type ContentHasher func(*types.Stat) (hash.Hash, error)
 
 func GetWalkerFn(root string) walkerFn {
 	return func(ctx context.Context, pathC chan<- *currentPath) error {
diff --git a/vendor/github.com/tonistiigi/fsutil/diff_containerd.go b/vendor/github.com/tonistiigi/fsutil/diff_containerd.go
index 73c0005..e63ee91 100644
--- a/vendor/github.com/tonistiigi/fsutil/diff_containerd.go
+++ b/vendor/github.com/tonistiigi/fsutil/diff_containerd.go
@@ -5,6 +5,7 @@
 	"os"
 	"strings"
 
+	"github.com/tonistiigi/fsutil/types"
 	"golang.org/x/sync/errgroup"
 )
 
@@ -170,11 +171,11 @@
 		}
 	}
 
-	ls1, ok := f1.f.Sys().(*Stat)
+	ls1, ok := f1.f.Sys().(*types.Stat)
 	if !ok {
 		return false, nil
 	}
-	ls2, ok := f2.f.Sys().(*Stat)
+	ls2, ok := f2.f.Sys().(*types.Stat)
 	if !ok {
 		return false, nil
 	}
@@ -185,7 +186,7 @@
 // compareStat returns whether the stats are equivalent,
 // whether the files are considered the same file, and
 // an error
-func compareStat(ls1, ls2 *Stat) (bool, error) {
+func compareStat(ls1, ls2 *types.Stat) (bool, error) {
 	return ls1.Mode == ls2.Mode && ls1.Uid == ls2.Uid && ls1.Gid == ls2.Gid && ls1.Devmajor == ls2.Devmajor && ls1.Devminor == ls2.Devminor && ls1.Linkname == ls2.Linkname, nil
 }
 
diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter.go b/vendor/github.com/tonistiigi/fsutil/diskwriter.go
index 4b727ed..3213113 100644
--- a/vendor/github.com/tonistiigi/fsutil/diskwriter.go
+++ b/vendor/github.com/tonistiigi/fsutil/diskwriter.go
@@ -12,6 +12,7 @@
 
 	"github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
 	"golang.org/x/sync/errgroup"
 )
 
@@ -25,7 +26,7 @@
 	Filter        FilterFunc
 }
 
-type FilterFunc func(*Stat) bool
+type FilterFunc func(*types.Stat) bool
 
 type DiskWriter struct {
 	opt  DiskWriterOpt
@@ -95,7 +96,7 @@
 		return nil
 	}
 
-	stat, ok := fi.Sys().(*Stat)
+	stat, ok := fi.Sys().(*types.Stat)
 	if !ok {
 		return errors.Errorf("%s invalid change without stat information", p)
 	}
@@ -246,7 +247,7 @@
 }
 
 func newHashWriter(ch ContentHasher, fi os.FileInfo, w io.WriteCloser) (*hashedWriter, error) {
-	stat, ok := fi.Sys().(*Stat)
+	stat, ok := fi.Sys().(*types.Stat)
 	if !ok {
 		return nil, errors.Errorf("invalid change without stat information")
 	}
diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go b/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go
index 19dffab..ff0a22e 100644
--- a/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go
+++ b/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go
@@ -8,9 +8,10 @@
 
 	"github.com/containerd/continuity/sysx"
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
 )
 
-func rewriteMetadata(p string, stat *Stat) error {
+func rewriteMetadata(p string, stat *types.Stat) error {
 	for key, value := range stat.Xattrs {
 		sysx.Setxattr(p, key, value, 0)
 	}
@@ -34,7 +35,7 @@
 
 // handleTarTypeBlockCharFifo is an OS-specific helper function used by
 // createTarFile to handle the following types of header: Block; Char; Fifo
-func handleTarTypeBlockCharFifo(path string, stat *Stat) error {
+func handleTarTypeBlockCharFifo(path string, stat *types.Stat) error {
 	mode := uint32(stat.Mode & 07777)
 	if os.FileMode(stat.Mode)&os.ModeCharDevice != 0 {
 		mode |= syscall.S_IFCHR
diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter_windows.go b/vendor/github.com/tonistiigi/fsutil/diskwriter_windows.go
index c6d0d7b..036544f 100644
--- a/vendor/github.com/tonistiigi/fsutil/diskwriter_windows.go
+++ b/vendor/github.com/tonistiigi/fsutil/diskwriter_windows.go
@@ -4,14 +4,15 @@
 
 import (
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
 )
 
-func rewriteMetadata(p string, stat *Stat) error {
+func rewriteMetadata(p string, stat *types.Stat) error {
 	return chtimes(p, stat.ModTime)
 }
 
 // handleTarTypeBlockCharFifo is an OS-specific helper function used by
 // createTarFile to handle the following types of header: Block; Char; Fifo
-func handleTarTypeBlockCharFifo(path string, stat *Stat) error {
+func handleTarTypeBlockCharFifo(path string, stat *types.Stat) error {
 	return errors.New("Not implemented on windows")
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/fs.go b/vendor/github.com/tonistiigi/fsutil/fs.go
index 996f4e4..132850c 100644
--- a/vendor/github.com/tonistiigi/fsutil/fs.go
+++ b/vendor/github.com/tonistiigi/fsutil/fs.go
@@ -9,6 +9,7 @@
 	"strings"
 
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
 )
 
 type FS interface {
@@ -36,13 +37,13 @@
 	return os.Open(filepath.Join(fs.root, p))
 }
 
-func SubDirFS(fs FS, stat Stat) FS {
+func SubDirFS(fs FS, stat types.Stat) FS {
 	return &subDirFS{fs: fs, stat: stat}
 }
 
 type subDirFS struct {
 	fs   FS
-	stat Stat
+	stat types.Stat
 }
 
 func (fs *subDirFS) Walk(ctx context.Context, fn filepath.WalkFunc) error {
@@ -57,7 +58,7 @@
 		return err
 	}
 	return fs.fs.Walk(ctx, func(p string, fi os.FileInfo, err error) error {
-		stat, ok := fi.Sys().(*Stat)
+		stat, ok := fi.Sys().(*types.Stat)
 		if !ok {
 			return errors.Wrapf(err, "invalid fileinfo without stat info: %s", p)
 		}
diff --git a/vendor/github.com/tonistiigi/fsutil/hardlinks.go b/vendor/github.com/tonistiigi/fsutil/hardlinks.go
index e598ead..d977f0d 100644
--- a/vendor/github.com/tonistiigi/fsutil/hardlinks.go
+++ b/vendor/github.com/tonistiigi/fsutil/hardlinks.go
@@ -4,6 +4,7 @@
 	"os"
 
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
 )
 
 // Hardlinks validates that all targets for links were part of the changes
@@ -25,7 +26,7 @@
 		return nil
 	}
 
-	stat, ok := fi.Sys().(*Stat)
+	stat, ok := fi.Sys().(*types.Stat)
 	if !ok {
 		return errors.Errorf("invalid change without stat info: %s", p)
 	}
diff --git a/vendor/github.com/tonistiigi/fsutil/receive.go b/vendor/github.com/tonistiigi/fsutil/receive.go
index 14ccb6c..fd9ef9a 100644
--- a/vendor/github.com/tonistiigi/fsutil/receive.go
+++ b/vendor/github.com/tonistiigi/fsutil/receive.go
@@ -7,6 +7,7 @@
 	"sync"
 
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
 	"golang.org/x/sync/errgroup"
 )
 
@@ -119,7 +120,7 @@
 	g.Go(func() (retErr error) {
 		defer func() {
 			if retErr != nil {
-				r.conn.SendMsg(&Packet{Type: PACKET_ERR, Data: []byte(retErr.Error())})
+				r.conn.SendMsg(&types.Packet{Type: types.PACKET_ERR, Data: []byte(retErr.Error())})
 			}
 		}()
 		destWalker := emptyWalker
@@ -133,7 +134,7 @@
 		if err := dw.Wait(ctx); err != nil {
 			return err
 		}
-		r.conn.SendMsg(&Packet{Type: PACKET_FIN})
+		r.conn.SendMsg(&types.Packet{Type: types.PACKET_FIN})
 		return nil
 	})
 
@@ -146,9 +147,9 @@
 				r.progressCb(size, true)
 			}()
 		}
-		var p Packet
+		var p types.Packet
 		for {
-			p = Packet{Data: p.Data[:0]}
+			p = types.Packet{Data: p.Data[:0]}
 			if err := r.conn.RecvMsg(&p); err != nil {
 				return err
 			}
@@ -158,9 +159,9 @@
 			}
 
 			switch p.Type {
-			case PACKET_ERR:
+			case types.PACKET_ERR:
 				return errors.Errorf("error from sender: %s", p.Data)
-			case PACKET_STAT:
+			case types.PACKET_STAT:
 				if p.Stat == nil {
 					if err := w.update(nil); err != nil {
 						return err
@@ -183,12 +184,12 @@
 				if err := w.update(cp); err != nil {
 					return err
 				}
-			case PACKET_DATA:
+			case types.PACKET_DATA:
 				r.muPipes.Lock()
 				pw, ok := r.pipes[p.ID]
 				r.muPipes.Unlock()
 				if !ok {
-					return errors.Errorf("invalid file request %s", p.ID)
+					return errors.Errorf("invalid file request %d", p.ID)
 				}
 				if len(p.Data) == 0 {
 					if err := pw.Close(); err != nil {
@@ -199,9 +200,9 @@
 						return err
 					}
 				}
-			case PACKET_FIN:
+			case types.PACKET_FIN:
 				for {
-					var p Packet
+					var p types.Packet
 					if err := r.conn.RecvMsg(&p); err != nil {
 						if err == io.EOF {
 							return nil
@@ -229,7 +230,7 @@
 	r.muPipes.Lock()
 	r.pipes[id] = wwc
 	r.muPipes.Unlock()
-	if err := r.conn.SendMsg(&Packet{Type: PACKET_REQ, ID: id}); err != nil {
+	if err := r.conn.SendMsg(&types.Packet{Type: types.PACKET_REQ, ID: id}); err != nil {
 		return err
 	}
 	err := wwc.Wait(ctx)
diff --git a/vendor/github.com/tonistiigi/fsutil/send.go b/vendor/github.com/tonistiigi/fsutil/send.go
index e32f682..e7c5a37 100644
--- a/vendor/github.com/tonistiigi/fsutil/send.go
+++ b/vendor/github.com/tonistiigi/fsutil/send.go
@@ -7,6 +7,7 @@
 	"sync"
 
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
 	"golang.org/x/sync/errgroup"
 )
 
@@ -56,7 +57,7 @@
 	g.Go(func() error {
 		err := s.walk(ctx)
 		if err != nil {
-			s.conn.SendMsg(&Packet{Type: PACKET_ERR, Data: []byte(err.Error())})
+			s.conn.SendMsg(&types.Packet{Type: types.PACKET_ERR, Data: []byte(err.Error())})
 		}
 		return err
 	})
@@ -86,19 +87,19 @@
 				return ctx.Err()
 			default:
 			}
-			var p Packet
+			var p types.Packet
 			if err := s.conn.RecvMsg(&p); err != nil {
 				return err
 			}
 			switch p.Type {
-			case PACKET_ERR:
+			case types.PACKET_ERR:
 				return errors.Errorf("error from receiver: %s", p.Data)
-			case PACKET_REQ:
+			case types.PACKET_REQ:
 				if err := s.queue(p.ID); err != nil {
 					return err
 				}
-			case PACKET_FIN:
-				return s.conn.SendMsg(&Packet{Type: PACKET_FIN})
+			case types.PACKET_FIN:
+				return s.conn.SendMsg(&types.Packet{Type: types.PACKET_FIN})
 			}
 		}
 	})
@@ -136,7 +137,7 @@
 			return err
 		}
 	}
-	return s.conn.SendMsg(&Packet{ID: h.id, Type: PACKET_DATA})
+	return s.conn.SendMsg(&types.Packet{ID: h.id, Type: types.PACKET_DATA})
 }
 
 func (s *sender) walk(ctx context.Context) error {
@@ -145,13 +146,13 @@
 		if err != nil {
 			return err
 		}
-		stat, ok := fi.Sys().(*Stat)
+		stat, ok := fi.Sys().(*types.Stat)
 		if !ok {
 			return errors.Wrapf(err, "invalid fileinfo without stat info: %s", path)
 		}
 
-		p := &Packet{
-			Type: PACKET_STAT,
+		p := &types.Packet{
+			Type: types.PACKET_STAT,
 			Stat: stat,
 		}
 		if fileCanRequestData(os.FileMode(stat.Mode)) {
@@ -166,7 +167,7 @@
 	if err != nil {
 		return err
 	}
-	return errors.Wrapf(s.conn.SendMsg(&Packet{Type: PACKET_STAT}), "failed to send last stat")
+	return errors.Wrapf(s.conn.SendMsg(&types.Packet{Type: types.PACKET_STAT}), "failed to send last stat")
 }
 
 func fileCanRequestData(m os.FileMode) bool {
@@ -184,7 +185,7 @@
 	if len(dt) == 0 {
 		return 0, nil
 	}
-	p := &Packet{Type: PACKET_DATA, ID: fs.id, Data: dt}
+	p := &types.Packet{Type: types.PACKET_DATA, ID: fs.id, Data: dt}
 	if err := fs.sender.conn.SendMsg(p); err != nil {
 		return 0, err
 	}
diff --git a/vendor/github.com/tonistiigi/fsutil/stat.go b/vendor/github.com/tonistiigi/fsutil/stat.go
new file mode 100644
index 0000000..573894d
--- /dev/null
+++ b/vendor/github.com/tonistiigi/fsutil/stat.go
@@ -0,0 +1,61 @@
+package fsutil
+
+import (
+	"os"
+	"path/filepath"
+	"runtime"
+
+	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
+)
+
+// constructs a Stat object. path is where the path can be found right
+// now, relpath is the desired path to be recorded in the stat (so
+// relative to whatever base dir is relevant). fi is the os.Stat
+// info. inodemap is used to calculate hardlinks over a series of
+// mkstat calls and maps inode to the canonical (aka "first") path for
+// a set of hardlinks to that inode.
+func mkstat(path, relpath string, fi os.FileInfo, inodemap map[uint64]string) (*types.Stat, error) {
+	relpath = filepath.ToSlash(relpath)
+
+	stat := &types.Stat{
+		Path:    relpath,
+		Mode:    uint32(fi.Mode()),
+		ModTime: fi.ModTime().UnixNano(),
+	}
+
+	setUnixOpt(fi, stat, relpath, inodemap)
+
+	if !fi.IsDir() {
+		stat.Size_ = fi.Size()
+		if fi.Mode()&os.ModeSymlink != 0 {
+			link, err := os.Readlink(path)
+			if err != nil {
+				return nil, errors.Wrapf(err, "failed to readlink %s", path)
+			}
+			stat.Linkname = link
+		}
+	}
+	if err := loadXattr(path, stat); err != nil {
+		return nil, errors.Wrapf(err, "failed to xattr %s", relpath)
+	}
+
+	if runtime.GOOS == "windows" {
+		permPart := stat.Mode & uint32(os.ModePerm)
+		noPermPart := stat.Mode &^ uint32(os.ModePerm)
+		// Add the x bit: make everything +x from windows
+		permPart |= 0111
+		permPart &= 0755
+		stat.Mode = noPermPart | permPart
+	}
+
+	return stat, nil
+}
+
+func Stat(path string) (*types.Stat, error) {
+	fi, err := os.Lstat(path)
+	if err != nil {
+		return nil, errors.Wrap(err, "os stat")
+	}
+	return mkstat(path, filepath.Base(path), fi, nil)
+}
diff --git a/vendor/github.com/tonistiigi/fsutil/walker_unix.go b/vendor/github.com/tonistiigi/fsutil/stat_unix.go
similarity index 68%
rename from vendor/github.com/tonistiigi/fsutil/walker_unix.go
rename to vendor/github.com/tonistiigi/fsutil/stat_unix.go
index 7e8ee80..b2e8fea 100644
--- a/vendor/github.com/tonistiigi/fsutil/walker_unix.go
+++ b/vendor/github.com/tonistiigi/fsutil/stat_unix.go
@@ -8,11 +8,15 @@
 
 	"github.com/containerd/continuity/sysx"
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
 )
 
-func loadXattr(origpath string, stat *Stat) error {
+func loadXattr(origpath string, stat *types.Stat) error {
 	xattrs, err := sysx.LListxattr(origpath)
 	if err != nil {
+		if errors.Cause(err) == syscall.ENOTSUP {
+			return nil
+		}
 		return errors.Wrapf(err, "failed to xattr %s", origpath)
 	}
 	if len(xattrs) > 0 {
@@ -28,7 +32,7 @@
 	return nil
 }
 
-func setUnixOpt(fi os.FileInfo, stat *Stat, path string, seenFiles map[uint64]string) {
+func setUnixOpt(fi os.FileInfo, stat *types.Stat, path string, seenFiles map[uint64]string) {
 	s := fi.Sys().(*syscall.Stat_t)
 
 	stat.Uid = s.Uid
@@ -42,13 +46,15 @@
 		}
 
 		ino := s.Ino
-		if s.Nlink > 1 {
-			if oldpath, ok := seenFiles[ino]; ok {
-				stat.Linkname = oldpath
-				stat.Size_ = 0
+		if seenFiles != nil {
+			if s.Nlink > 1 {
+				if oldpath, ok := seenFiles[ino]; ok {
+					stat.Linkname = oldpath
+					stat.Size_ = 0
+				}
 			}
+			seenFiles[ino] = path
 		}
-		seenFiles[ino] = path
 	}
 }
 
diff --git a/vendor/github.com/tonistiigi/fsutil/stat_windows.go b/vendor/github.com/tonistiigi/fsutil/stat_windows.go
new file mode 100644
index 0000000..66379bd
--- /dev/null
+++ b/vendor/github.com/tonistiigi/fsutil/stat_windows.go
@@ -0,0 +1,16 @@
+// +build windows
+
+package fsutil
+
+import (
+	"os"
+
+	"github.com/tonistiigi/fsutil/types"
+)
+
+func loadXattr(_ string, _ *types.Stat) error {
+	return nil
+}
+
+func setUnixOpt(_ os.FileInfo, _ *types.Stat, _ string, _ map[uint64]string) {
+}
diff --git a/vendor/github.com/tonistiigi/fsutil/generate.go b/vendor/github.com/tonistiigi/fsutil/types/generate.go
similarity index 80%
rename from vendor/github.com/tonistiigi/fsutil/generate.go
rename to vendor/github.com/tonistiigi/fsutil/types/generate.go
index e433195..5c03178 100644
--- a/vendor/github.com/tonistiigi/fsutil/generate.go
+++ b/vendor/github.com/tonistiigi/fsutil/types/generate.go
@@ -1,3 +1,3 @@
-package fsutil
+package types
 
 //go:generate protoc --gogoslick_out=. stat.proto wire.proto
diff --git a/vendor/github.com/tonistiigi/fsutil/stat.pb.go b/vendor/github.com/tonistiigi/fsutil/types/stat.pb.go
similarity index 78%
rename from vendor/github.com/tonistiigi/fsutil/stat.pb.go
rename to vendor/github.com/tonistiigi/fsutil/types/stat.pb.go
index 3f6925e..d8b984e 100644
--- a/vendor/github.com/tonistiigi/fsutil/stat.pb.go
+++ b/vendor/github.com/tonistiigi/fsutil/types/stat.pb.go
@@ -1,9 +1,8 @@
-// Code generated by protoc-gen-gogo.
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
 // source: stat.proto
-// DO NOT EDIT!
 
 /*
-	Package fsutil is a generated protocol buffer package.
+	Package types is a generated protocol buffer package.
 
 	It is generated from these files:
 		stat.proto
@@ -13,7 +12,7 @@
 		Stat
 		Packet
 */
-package fsutil
+package types
 
 import proto "github.com/gogo/protobuf/proto"
 import fmt "fmt"
@@ -23,7 +22,7 @@
 
 import strings "strings"
 import reflect "reflect"
-import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
+import sortkeys "github.com/gogo/protobuf/sortkeys"
 
 import io "io"
 
@@ -127,14 +126,11 @@
 }
 
 func init() {
-	proto.RegisterType((*Stat)(nil), "fsutil.Stat")
+	proto.RegisterType((*Stat)(nil), "fsutil.types.Stat")
 }
 func (this *Stat) Equal(that interface{}) bool {
 	if that == nil {
-		if this == nil {
-			return true
-		}
-		return false
+		return this == nil
 	}
 
 	that1, ok := that.(*Stat)
@@ -147,10 +143,7 @@
 		}
 	}
 	if that1 == nil {
-		if this == nil {
-			return true
-		}
-		return false
+		return this == nil
 	} else if this == nil {
 		return false
 	}
@@ -196,7 +189,7 @@
 		return "nil"
 	}
 	s := make([]string, 0, 14)
-	s = append(s, "&fsutil.Stat{")
+	s = append(s, "&types.Stat{")
 	s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
 	s = append(s, "Mode: "+fmt.Sprintf("%#v", this.Mode)+",\n")
 	s = append(s, "Uid: "+fmt.Sprintf("%#v", this.Uid)+",\n")
@@ -210,7 +203,7 @@
 	for k, _ := range this.Xattrs {
 		keysForXattrs = append(keysForXattrs, k)
 	}
-	github_com_gogo_protobuf_sortkeys.Strings(keysForXattrs)
+	sortkeys.Strings(keysForXattrs)
 	mapStringForXattrs := "map[string][]byte{"
 	for _, k := range keysForXattrs {
 		mapStringForXattrs += fmt.Sprintf("%#v: %#v,", k, this.Xattrs[k])
@@ -318,24 +311,6 @@
 	return i, nil
 }
 
-func encodeFixed64Stat(dAtA []byte, offset int, v uint64) int {
-	dAtA[offset] = uint8(v)
-	dAtA[offset+1] = uint8(v >> 8)
-	dAtA[offset+2] = uint8(v >> 16)
-	dAtA[offset+3] = uint8(v >> 24)
-	dAtA[offset+4] = uint8(v >> 32)
-	dAtA[offset+5] = uint8(v >> 40)
-	dAtA[offset+6] = uint8(v >> 48)
-	dAtA[offset+7] = uint8(v >> 56)
-	return offset + 8
-}
-func encodeFixed32Stat(dAtA []byte, offset int, v uint32) int {
-	dAtA[offset] = uint8(v)
-	dAtA[offset+1] = uint8(v >> 8)
-	dAtA[offset+2] = uint8(v >> 16)
-	dAtA[offset+3] = uint8(v >> 24)
-	return offset + 4
-}
 func encodeVarintStat(dAtA []byte, offset int, v uint64) int {
 	for v >= 1<<7 {
 		dAtA[offset] = uint8(v&0x7f | 0x80)
@@ -413,7 +388,7 @@
 	for k, _ := range this.Xattrs {
 		keysForXattrs = append(keysForXattrs, k)
 	}
-	github_com_gogo_protobuf_sortkeys.Strings(keysForXattrs)
+	sortkeys.Strings(keysForXattrs)
 	mapStringForXattrs := "map[string][]byte{"
 	for _, k := range keysForXattrs {
 		mapStringForXattrs += fmt.Sprintf("%v: %v,", k, this.Xattrs[k])
@@ -688,51 +663,14 @@
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			var keykey uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowStat
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				keykey |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			var stringLenmapkey uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowStat
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLenmapkey |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLenmapkey := int(stringLenmapkey)
-			if intStringLenmapkey < 0 {
-				return ErrInvalidLengthStat
-			}
-			postStringIndexmapkey := iNdEx + intStringLenmapkey
-			if postStringIndexmapkey > l {
-				return io.ErrUnexpectedEOF
-			}
-			mapkey := string(dAtA[iNdEx:postStringIndexmapkey])
-			iNdEx = postStringIndexmapkey
 			if m.Xattrs == nil {
 				m.Xattrs = make(map[string][]byte)
 			}
-			if iNdEx < postIndex {
-				var valuekey uint64
+			var mapkey string
+			mapvalue := []byte{}
+			for iNdEx < postIndex {
+				entryPreIndex := iNdEx
+				var wire uint64
 				for shift := uint(0); ; shift += 7 {
 					if shift >= 64 {
 						return ErrIntOverflowStat
@@ -742,42 +680,81 @@
 					}
 					b := dAtA[iNdEx]
 					iNdEx++
-					valuekey |= (uint64(b) & 0x7F) << shift
+					wire |= (uint64(b) & 0x7F) << shift
 					if b < 0x80 {
 						break
 					}
 				}
-				var mapbyteLen uint64
-				for shift := uint(0); ; shift += 7 {
-					if shift >= 64 {
-						return ErrIntOverflowStat
+				fieldNum := int32(wire >> 3)
+				if fieldNum == 1 {
+					var stringLenmapkey uint64
+					for shift := uint(0); ; shift += 7 {
+						if shift >= 64 {
+							return ErrIntOverflowStat
+						}
+						if iNdEx >= l {
+							return io.ErrUnexpectedEOF
+						}
+						b := dAtA[iNdEx]
+						iNdEx++
+						stringLenmapkey |= (uint64(b) & 0x7F) << shift
+						if b < 0x80 {
+							break
+						}
 					}
-					if iNdEx >= l {
+					intStringLenmapkey := int(stringLenmapkey)
+					if intStringLenmapkey < 0 {
+						return ErrInvalidLengthStat
+					}
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
+					if postStringIndexmapkey > l {
 						return io.ErrUnexpectedEOF
 					}
-					b := dAtA[iNdEx]
-					iNdEx++
-					mapbyteLen |= (uint64(b) & 0x7F) << shift
-					if b < 0x80 {
-						break
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
+					iNdEx = postStringIndexmapkey
+				} else if fieldNum == 2 {
+					var mapbyteLen uint64
+					for shift := uint(0); ; shift += 7 {
+						if shift >= 64 {
+							return ErrIntOverflowStat
+						}
+						if iNdEx >= l {
+							return io.ErrUnexpectedEOF
+						}
+						b := dAtA[iNdEx]
+						iNdEx++
+						mapbyteLen |= (uint64(b) & 0x7F) << shift
+						if b < 0x80 {
+							break
+						}
 					}
+					intMapbyteLen := int(mapbyteLen)
+					if intMapbyteLen < 0 {
+						return ErrInvalidLengthStat
+					}
+					postbytesIndex := iNdEx + intMapbyteLen
+					if postbytesIndex > l {
+						return io.ErrUnexpectedEOF
+					}
+					mapvalue = make([]byte, mapbyteLen)
+					copy(mapvalue, dAtA[iNdEx:postbytesIndex])
+					iNdEx = postbytesIndex
+				} else {
+					iNdEx = entryPreIndex
+					skippy, err := skipStat(dAtA[iNdEx:])
+					if err != nil {
+						return err
+					}
+					if skippy < 0 {
+						return ErrInvalidLengthStat
+					}
+					if (iNdEx + skippy) > postIndex {
+						return io.ErrUnexpectedEOF
+					}
+					iNdEx += skippy
 				}
-				intMapbyteLen := int(mapbyteLen)
-				if intMapbyteLen < 0 {
-					return ErrInvalidLengthStat
-				}
-				postbytesIndex := iNdEx + intMapbyteLen
-				if postbytesIndex > l {
-					return io.ErrUnexpectedEOF
-				}
-				mapvalue := make([]byte, mapbyteLen)
-				copy(mapvalue, dAtA[iNdEx:postbytesIndex])
-				iNdEx = postbytesIndex
-				m.Xattrs[mapkey] = mapvalue
-			} else {
-				var mapvalue []byte
-				m.Xattrs[mapkey] = mapvalue
 			}
+			m.Xattrs[mapkey] = mapvalue
 			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
@@ -908,24 +885,25 @@
 func init() { proto.RegisterFile("stat.proto", fileDescriptorStat) }
 
 var fileDescriptorStat = []byte{
-	// 303 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x4c, 0x91, 0xb1, 0x4e, 0xf3, 0x30,
-	0x14, 0x85, 0x73, 0x9b, 0x36, 0x6d, 0xdd, 0xff, 0x97, 0x90, 0xc5, 0x70, 0xd5, 0xc1, 0x8a, 0x98,
-	0x32, 0xa0, 0x08, 0xc1, 0x02, 0x8c, 0x48, 0xbc, 0x40, 0x60, 0x60, 0x35, 0xb2, 0x29, 0xa6, 0x4d,
-	0x5c, 0x25, 0x4e, 0x45, 0x99, 0x78, 0x04, 0x1e, 0x83, 0xd7, 0x60, 0x63, 0xec, 0xc8, 0x48, 0xcc,
-	0xc2, 0xd8, 0x47, 0x40, 0x76, 0xda, 0xc2, 0x76, 0xce, 0x77, 0x7c, 0x65, 0x9d, 0x7b, 0x09, 0xa9,
-	0x0c, 0x37, 0xe9, 0xbc, 0xd4, 0x46, 0xd3, 0xe8, 0xae, 0xaa, 0x8d, 0x9a, 0x1d, 0xbc, 0x75, 0x48,
-	0xf7, 0xca, 0x70, 0x43, 0x29, 0xe9, 0xce, 0xb9, 0xb9, 0x47, 0x88, 0x21, 0x19, 0x66, 0x5e, 0x3b,
-	0x96, 0x6b, 0x21, 0xb1, 0x13, 0x43, 0xf2, 0x3f, 0xf3, 0x9a, 0xee, 0x91, 0xb0, 0x56, 0x02, 0x43,
-	0x8f, 0x9c, 0x74, 0x64, 0xa2, 0x04, 0x76, 0x5b, 0x32, 0x51, 0xc2, 0xcd, 0x55, 0xea, 0x49, 0x62,
-	0x2f, 0x86, 0x24, 0xcc, 0xbc, 0xa6, 0x48, 0xfa, 0xb9, 0x16, 0xd7, 0x2a, 0x97, 0x18, 0x79, 0xbc,
-	0xb5, 0x74, 0x4c, 0x06, 0x33, 0x55, 0x4c, 0x0b, 0x9e, 0x4b, 0xec, 0xfb, 0xdf, 0x77, 0xde, 0x65,
-	0x42, 0x2e, 0x72, 0xfe, 0xa0, 0x4b, 0x1c, 0xf8, 0xb1, 0x9d, 0xdf, 0x66, 0xaa, 0xd0, 0x25, 0x0e,
-	0x7f, 0x33, 0xe7, 0xe9, 0x11, 0x89, 0x1e, 0xb9, 0x31, 0x65, 0x85, 0x24, 0x0e, 0x93, 0xd1, 0x31,
-	0xa6, 0x6d, 0xdf, 0xd4, 0x75, 0x4d, 0x6f, 0x7c, 0x74, 0x59, 0x98, 0x72, 0x99, 0x6d, 0xde, 0x8d,
-	0xcf, 0xc8, 0xe8, 0x0f, 0x76, 0xa5, 0xa6, 0x72, 0xb9, 0xd9, 0x86, 0x93, 0x74, 0x9f, 0xf4, 0x16,
-	0x7c, 0x56, 0xb7, 0xdb, 0xf8, 0x97, 0xb5, 0xe6, 0xbc, 0x73, 0x0a, 0x17, 0x87, 0xab, 0x86, 0x05,
-	0x1f, 0x0d, 0x0b, 0xd6, 0x0d, 0x83, 0x67, 0xcb, 0xe0, 0xd5, 0x32, 0x78, 0xb7, 0x0c, 0x56, 0x96,
-	0xc1, 0xa7, 0x65, 0xf0, 0x6d, 0x59, 0xb0, 0xb6, 0x0c, 0x5e, 0xbe, 0x58, 0x70, 0x1b, 0xf9, 0x03,
-	0x9c, 0xfc, 0x04, 0x00, 0x00, 0xff, 0xff, 0x19, 0x97, 0x14, 0xf4, 0x8e, 0x01, 0x00, 0x00,
+	// 310 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0xbd, 0x4e, 0xc3, 0x30,
+	0x14, 0x85, 0x73, 0x9b, 0xfe, 0xba, 0x45, 0x42, 0x16, 0x83, 0xd5, 0xe1, 0x2a, 0x62, 0xca, 0x94,
+	0x81, 0x4a, 0x08, 0x18, 0x91, 0x78, 0x81, 0xc0, 0x80, 0xd8, 0x8c, 0x6c, 0x8a, 0x69, 0x13, 0x57,
+	0x89, 0x5b, 0x51, 0x26, 0x1e, 0x81, 0xc7, 0xe0, 0x4d, 0x60, 0xec, 0xc8, 0x48, 0xcc, 0xc2, 0xd8,
+	0x47, 0x40, 0x76, 0xda, 0xd2, 0xed, 0x9c, 0xef, 0xdc, 0xab, 0xe4, 0x5c, 0x13, 0x52, 0x1a, 0x6e,
+	0x92, 0x59, 0xa1, 0x8d, 0xa6, 0x83, 0x87, 0x72, 0x6e, 0xd4, 0x34, 0x31, 0xcb, 0x99, 0x2c, 0x8f,
+	0x3f, 0x1a, 0xa4, 0x79, 0x6d, 0xb8, 0xa1, 0x94, 0x34, 0x67, 0xdc, 0x3c, 0x32, 0x88, 0x20, 0xee,
+	0xa5, 0x5e, 0x3b, 0x96, 0x69, 0x21, 0x59, 0x23, 0x82, 0xf8, 0x20, 0xf5, 0x9a, 0x1e, 0x92, 0x70,
+	0xae, 0x04, 0x0b, 0x3d, 0x72, 0xd2, 0x91, 0xb1, 0x12, 0xac, 0x59, 0x93, 0xb1, 0x12, 0x6e, 0xaf,
+	0x54, 0x2f, 0x92, 0xb5, 0x22, 0x88, 0xc3, 0xd4, 0x6b, 0xca, 0x48, 0x27, 0xd3, 0xe2, 0x46, 0x65,
+	0x92, 0xb5, 0x3d, 0xde, 0x5a, 0x3a, 0x24, 0xdd, 0xa9, 0xca, 0x27, 0x39, 0xcf, 0x24, 0xeb, 0xf8,
+	0xaf, 0xef, 0xbc, 0xcb, 0x84, 0x5c, 0x64, 0xfc, 0x49, 0x17, 0xac, 0xeb, 0xd7, 0x76, 0x7e, 0x9b,
+	0xa9, 0x5c, 0x17, 0xac, 0xf7, 0x9f, 0x39, 0x4f, 0x4f, 0x49, 0xfb, 0x99, 0x1b, 0x53, 0x94, 0x8c,
+	0x44, 0x61, 0xdc, 0x3f, 0xc1, 0x64, 0xbf, 0x75, 0xe2, 0x1a, 0x27, 0xb7, 0x7e, 0xe0, 0x2a, 0x37,
+	0xc5, 0x32, 0xdd, 0x4c, 0x0f, 0xcf, 0x49, 0x7f, 0x0f, 0xbb, 0x6a, 0x13, 0xb9, 0xdc, 0xdc, 0xc4,
+	0x49, 0x7a, 0x44, 0x5a, 0x0b, 0x3e, 0x9d, 0xd7, 0x37, 0x19, 0xa4, 0xb5, 0xb9, 0x68, 0x9c, 0xc1,
+	0xe5, 0x68, 0x55, 0x61, 0xf0, 0x55, 0x61, 0xb0, 0xae, 0x10, 0x5e, 0x2d, 0xc2, 0xbb, 0x45, 0xf8,
+	0xb4, 0x08, 0x2b, 0x8b, 0xf0, 0x6d, 0x11, 0x7e, 0x2d, 0x06, 0x6b, 0x8b, 0xf0, 0xf6, 0x83, 0xc1,
+	0x5d, 0xcb, 0xff, 0xc8, 0x7d, 0xdb, 0xbf, 0xc9, 0xe8, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x90, 0xc2,
+	0xcf, 0x79, 0xa1, 0x01, 0x00, 0x00,
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/stat.proto b/vendor/github.com/tonistiigi/fsutil/types/stat.proto
similarity index 84%
rename from vendor/github.com/tonistiigi/fsutil/stat.proto
rename to vendor/github.com/tonistiigi/fsutil/types/stat.proto
index e279413..4138be6 100644
--- a/vendor/github.com/tonistiigi/fsutil/stat.proto
+++ b/vendor/github.com/tonistiigi/fsutil/types/stat.proto
@@ -1,6 +1,8 @@
 syntax = "proto3";
 
-package fsutil;
+package fsutil.types;
+
+option go_package = "types";
 
 message Stat {
   string path = 1;
diff --git a/vendor/github.com/tonistiigi/fsutil/wire.pb.go b/vendor/github.com/tonistiigi/fsutil/types/wire.pb.go
similarity index 80%
rename from vendor/github.com/tonistiigi/fsutil/wire.pb.go
rename to vendor/github.com/tonistiigi/fsutil/types/wire.pb.go
index 9d334bb..47db094 100644
--- a/vendor/github.com/tonistiigi/fsutil/wire.pb.go
+++ b/vendor/github.com/tonistiigi/fsutil/types/wire.pb.go
@@ -1,8 +1,7 @@
-// Code generated by protoc-gen-gogo.
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
 // source: wire.proto
-// DO NOT EDIT!
 
-package fsutil
+package types
 
 import proto "github.com/gogo/protobuf/proto"
 import fmt "fmt"
@@ -50,7 +49,7 @@
 func (Packet_PacketType) EnumDescriptor() ([]byte, []int) { return fileDescriptorWire, []int{0, 0} }
 
 type Packet struct {
-	Type Packet_PacketType `protobuf:"varint,1,opt,name=type,proto3,enum=fsutil.Packet_PacketType" json:"type,omitempty"`
+	Type Packet_PacketType `protobuf:"varint,1,opt,name=type,proto3,enum=fsutil.types.Packet_PacketType" json:"type,omitempty"`
 	Stat *Stat             `protobuf:"bytes,2,opt,name=stat" json:"stat,omitempty"`
 	ID   uint32            `protobuf:"varint,3,opt,name=ID,proto3" json:"ID,omitempty"`
 	Data []byte            `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
@@ -89,8 +88,8 @@
 }
 
 func init() {
-	proto.RegisterType((*Packet)(nil), "fsutil.Packet")
-	proto.RegisterEnum("fsutil.Packet_PacketType", Packet_PacketType_name, Packet_PacketType_value)
+	proto.RegisterType((*Packet)(nil), "fsutil.types.Packet")
+	proto.RegisterEnum("fsutil.types.Packet_PacketType", Packet_PacketType_name, Packet_PacketType_value)
 }
 func (x Packet_PacketType) String() string {
 	s, ok := Packet_PacketType_name[int32(x)]
@@ -101,10 +100,7 @@
 }
 func (this *Packet) Equal(that interface{}) bool {
 	if that == nil {
-		if this == nil {
-			return true
-		}
-		return false
+		return this == nil
 	}
 
 	that1, ok := that.(*Packet)
@@ -117,10 +113,7 @@
 		}
 	}
 	if that1 == nil {
-		if this == nil {
-			return true
-		}
-		return false
+		return this == nil
 	} else if this == nil {
 		return false
 	}
@@ -143,7 +136,7 @@
 		return "nil"
 	}
 	s := make([]string, 0, 8)
-	s = append(s, "&fsutil.Packet{")
+	s = append(s, "&types.Packet{")
 	s = append(s, "Type: "+fmt.Sprintf("%#v", this.Type)+",\n")
 	if this.Stat != nil {
 		s = append(s, "Stat: "+fmt.Sprintf("%#v", this.Stat)+",\n")
@@ -205,24 +198,6 @@
 	return i, nil
 }
 
-func encodeFixed64Wire(dAtA []byte, offset int, v uint64) int {
-	dAtA[offset] = uint8(v)
-	dAtA[offset+1] = uint8(v >> 8)
-	dAtA[offset+2] = uint8(v >> 16)
-	dAtA[offset+3] = uint8(v >> 24)
-	dAtA[offset+4] = uint8(v >> 32)
-	dAtA[offset+5] = uint8(v >> 40)
-	dAtA[offset+6] = uint8(v >> 48)
-	dAtA[offset+7] = uint8(v >> 56)
-	return offset + 8
-}
-func encodeFixed32Wire(dAtA []byte, offset int, v uint32) int {
-	dAtA[offset] = uint8(v)
-	dAtA[offset+1] = uint8(v >> 8)
-	dAtA[offset+2] = uint8(v >> 16)
-	dAtA[offset+3] = uint8(v >> 24)
-	return offset + 4
-}
 func encodeVarintWire(dAtA []byte, offset int, v uint64) int {
 	for v >= 1<<7 {
 		dAtA[offset] = uint8(v&0x7f | 0x80)
@@ -546,22 +521,22 @@
 func init() { proto.RegisterFile("wire.proto", fileDescriptorWire) }
 
 var fileDescriptorWire = []byte{
-	// 259 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xcf, 0x2c, 0x4a,
-	0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4b, 0x2b, 0x2e, 0x2d, 0xc9, 0xcc, 0x91, 0xe2,
-	0x2a, 0x2e, 0x49, 0x2c, 0x81, 0x88, 0x29, 0xdd, 0x65, 0xe4, 0x62, 0x0b, 0x48, 0x4c, 0xce, 0x4e,
-	0x2d, 0x11, 0xd2, 0xe5, 0x62, 0x29, 0xa9, 0x2c, 0x48, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x33,
-	0x92, 0xd4, 0x83, 0xa8, 0xd6, 0x83, 0xc8, 0x42, 0xa9, 0x90, 0xca, 0x82, 0xd4, 0x20, 0xb0, 0x32,
-	0x21, 0x05, 0x2e, 0x16, 0x90, 0x39, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0x3c, 0x30, 0xe5,
-	0xc1, 0x25, 0x89, 0x25, 0x41, 0x60, 0x19, 0x21, 0x3e, 0x2e, 0x26, 0x4f, 0x17, 0x09, 0x66, 0x05,
-	0x46, 0x0d, 0xde, 0x20, 0x26, 0x4f, 0x17, 0x21, 0x21, 0x2e, 0x96, 0x94, 0xc4, 0x92, 0x44, 0x09,
-	0x16, 0x05, 0x46, 0x0d, 0x9e, 0x20, 0x30, 0x5b, 0x29, 0x8e, 0x8b, 0x0b, 0x61, 0xb2, 0x10, 0x3f,
-	0x17, 0x77, 0x80, 0xa3, 0xb3, 0xb7, 0x6b, 0x48, 0x7c, 0x70, 0x88, 0x63, 0x88, 0x00, 0x83, 0x10,
-	0x1f, 0x17, 0x17, 0x54, 0x20, 0xc8, 0x35, 0x50, 0x80, 0x11, 0x49, 0x81, 0x8b, 0x63, 0x88, 0xa3,
-	0x00, 0x13, 0x92, 0x02, 0x37, 0x4f, 0x3f, 0x01, 0x66, 0x24, 0xbe, 0x6b, 0x50, 0x90, 0x00, 0x8b,
-	0x93, 0xce, 0x85, 0x87, 0x72, 0x0c, 0x37, 0x1e, 0xca, 0x31, 0x7c, 0x78, 0x28, 0xc7, 0xd8, 0xf0,
-	0x48, 0x8e, 0x71, 0xc5, 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c,
-	0xf0, 0x48, 0x8e, 0xf1, 0xc5, 0x23, 0x39, 0x86, 0x0f, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63,
-	0x48, 0x62, 0x03, 0x07, 0x8a, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x8b, 0xce, 0x55, 0x3b, 0x36,
-	0x01, 0x00, 0x00,
+	// 268 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xcf, 0x2c, 0x4a,
+	0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x49, 0x2b, 0x2e, 0x2d, 0xc9, 0xcc, 0xd1, 0x2b,
+	0xa9, 0x2c, 0x48, 0x2d, 0x96, 0xe2, 0x2a, 0x2e, 0x49, 0x2c, 0x81, 0xc8, 0x28, 0xbd, 0x64, 0xe4,
+	0x62, 0x0b, 0x48, 0x4c, 0xce, 0x4e, 0x2d, 0x11, 0x32, 0xe6, 0x62, 0x01, 0xc9, 0x4b, 0x30, 0x2a,
+	0x30, 0x6a, 0xf0, 0x19, 0xc9, 0xeb, 0x21, 0xeb, 0xd1, 0x83, 0xa8, 0x81, 0x52, 0x21, 0x95, 0x05,
+	0xa9, 0x41, 0x60, 0xc5, 0x42, 0x6a, 0x5c, 0x2c, 0x20, 0xd3, 0x24, 0x98, 0x14, 0x18, 0x35, 0xb8,
+	0x8d, 0x84, 0x50, 0x35, 0x05, 0x97, 0x24, 0x96, 0x04, 0x81, 0xe5, 0x85, 0xf8, 0xb8, 0x98, 0x3c,
+	0x5d, 0x24, 0x98, 0x15, 0x18, 0x35, 0x78, 0x83, 0x98, 0x3c, 0x5d, 0x84, 0x84, 0xb8, 0x58, 0x52,
+	0x12, 0x4b, 0x12, 0x25, 0x58, 0x14, 0x18, 0x35, 0x78, 0x82, 0xc0, 0x6c, 0xa5, 0x38, 0x2e, 0x2e,
+	0x84, 0xf9, 0x42, 0xfc, 0x5c, 0xdc, 0x01, 0x8e, 0xce, 0xde, 0xae, 0x21, 0xf1, 0xc1, 0x21, 0x8e,
+	0x21, 0x02, 0x0c, 0x42, 0x7c, 0x5c, 0x5c, 0x50, 0x81, 0x20, 0xd7, 0x40, 0x01, 0x46, 0x24, 0x05,
+	0x2e, 0x8e, 0x21, 0x8e, 0x02, 0x4c, 0x48, 0x0a, 0xdc, 0x3c, 0xfd, 0x04, 0x98, 0x91, 0xf8, 0xae,
+	0x41, 0x41, 0x02, 0x2c, 0x4e, 0xc6, 0x17, 0x1e, 0xca, 0x31, 0xdc, 0x78, 0x28, 0xc7, 0xf0, 0xe1,
+	0xa1, 0x1c, 0x63, 0xc3, 0x23, 0x39, 0xc6, 0x15, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63, 0xbc,
+	0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x17, 0x8f, 0xe4, 0x18, 0x3e, 0x3c, 0x92, 0x63,
+	0x9c, 0xf0, 0x58, 0x8e, 0x21, 0x8a, 0x15, 0xec, 0x87, 0x24, 0x36, 0x70, 0x38, 0x19, 0x03, 0x02,
+	0x00, 0x00, 0xff, 0xff, 0xce, 0x0f, 0xe2, 0x94, 0x4f, 0x01, 0x00, 0x00,
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/wire.proto b/vendor/github.com/tonistiigi/fsutil/types/wire.proto
similarity index 83%
rename from vendor/github.com/tonistiigi/fsutil/wire.proto
rename to vendor/github.com/tonistiigi/fsutil/types/wire.proto
index f9b33f3..3e85000 100644
--- a/vendor/github.com/tonistiigi/fsutil/wire.proto
+++ b/vendor/github.com/tonistiigi/fsutil/types/wire.proto
@@ -1,6 +1,8 @@
 syntax = "proto3";
 
-package fsutil;
+package fsutil.types;
+
+option go_package = "types";
 
 import "stat.proto";
 
diff --git a/vendor/github.com/tonistiigi/fsutil/walker.go b/vendor/github.com/tonistiigi/fsutil/walker.go
index aa50991..39e6c94 100644
--- a/vendor/github.com/tonistiigi/fsutil/walker.go
+++ b/vendor/github.com/tonistiigi/fsutil/walker.go
@@ -4,12 +4,12 @@
 	"context"
 	"os"
 	"path/filepath"
-	"runtime"
 	"strings"
 	"time"
 
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/fsutil/types"
 )
 
 type WalkOpt struct {
@@ -18,7 +18,7 @@
 	// FollowPaths contains symlinks that are resolved into include patterns
 	// before performing the fs walk
 	FollowPaths []string
-	Map         func(*Stat) bool
+	Map         func(*types.Stat) bool
 }
 
 func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) error {
@@ -146,37 +146,9 @@
 		}
 
 	passedFilter:
-		path = filepath.ToSlash(path)
-
-		stat := &Stat{
-			Path:    path,
-			Mode:    uint32(fi.Mode()),
-			ModTime: fi.ModTime().UnixNano(),
-		}
-
-		setUnixOpt(fi, stat, path, seenFiles)
-
-		if !fi.IsDir() {
-			stat.Size_ = fi.Size()
-			if fi.Mode()&os.ModeSymlink != 0 {
-				link, err := os.Readlink(origpath)
-				if err != nil {
-					return errors.Wrapf(err, "failed to readlink %s", origpath)
-				}
-				stat.Linkname = link
-			}
-		}
-		if err := loadXattr(origpath, stat); err != nil {
-			return errors.Wrapf(err, "failed to xattr %s", path)
-		}
-
-		if runtime.GOOS == "windows" {
-			permPart := stat.Mode & uint32(os.ModePerm)
-			noPermPart := stat.Mode &^ uint32(os.ModePerm)
-			// Add the x bit: make everything +x from windows
-			permPart |= 0111
-			permPart &= 0755
-			stat.Mode = noPermPart | permPart
+		stat, err := mkstat(origpath, path, fi, seenFiles)
+		if err != nil {
+			return err
 		}
 
 		select {
@@ -197,7 +169,7 @@
 }
 
 type StatInfo struct {
-	*Stat
+	*types.Stat
 }
 
 func (s *StatInfo) Name() string {
diff --git a/vendor/github.com/tonistiigi/fsutil/walker_windows.go b/vendor/github.com/tonistiigi/fsutil/walker_windows.go
deleted file mode 100644
index a1a2b45..0000000
--- a/vendor/github.com/tonistiigi/fsutil/walker_windows.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// +build windows
-
-package fsutil
-
-import (
-	"os"
-)
-
-func loadXattr(_ string, _ *Stat) error {
-	return nil
-}
-
-func setUnixOpt(_ os.FileInfo, _ *Stat, _ string, _ map[uint64]string) {
-}