From f05a023760493dbd41fbfc1bb76ad334b579e94e Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Thu, 15 Jun 2017 10:27:06 -0400 Subject: [PATCH] Don't chown/chmod volumes if not needed. Doing a chown/chmod automatically can cause `EPERM` in some cases (e.g. with an NFS mount). Currently Docker will always call chown+chmod on a volume path unless `:nocopy` is passed in, but we don't need to make these calls if the perms and ownership already match and potentially avoid an uneccessary `EPERM`. Signed-off-by: Brian Goff --- container/container_unix.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/container/container_unix.go b/container/container_unix.go index 530343d5ca..4a26a94389 100644 --- a/container/container_unix.go +++ b/container/container_unix.go @@ -441,11 +441,26 @@ func copyOwnership(source, destination string) error { return err } - if err := os.Chown(destination, int(stat.UID()), int(stat.GID())); err != nil { + destStat, err := system.Stat(destination) + if err != nil { return err } - return os.Chmod(destination, os.FileMode(stat.Mode())) + // In some cases, even though UID/GID match and it would effectively be a no-op, + // this can return a permission denied error... for example if this is an NFS + // mount. + // Since it's not really an error that we can't chown to the same UID/GID, don't + // even bother trying in such cases. + if stat.UID() != destStat.UID() || stat.GID() != destStat.GID() { + if err := os.Chown(destination, int(stat.UID()), int(stat.GID())); err != nil { + return err + } + } + + if stat.Mode() != destStat.Mode() { + return os.Chmod(destination, os.FileMode(stat.Mode())) + } + return nil } // TmpfsMounts returns the list of tmpfs mounts