Repository: mesos
Updated Branches:
  refs/heads/master c2b595e1c -> f433cdd0c


Added support for opaque whiteout file `.wh..wh..opq`.

Review: https://reviews.apache.org/r/52118/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/f433cdd0
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/f433cdd0
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/f433cdd0

Branch: refs/heads/master
Commit: f433cdd0c5ccbe8f2750bd92b47688fe89951b1d
Parents: c2b595e
Author: Qian Zhang <zhang...@cn.ibm.com>
Authored: Thu Sep 22 10:36:17 2016 -0700
Committer: Jie Yu <yujie....@gmail.com>
Committed: Thu Sep 22 10:39:30 2016 -0700

----------------------------------------------------------------------
 include/mesos/docker/spec.hpp                   |  4 ++
 .../mesos/provisioner/provisioner.cpp           | 67 ++++++++++++++------
 2 files changed, 50 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/f433cdd0/include/mesos/docker/spec.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/docker/spec.hpp b/include/mesos/docker/spec.hpp
index 92367cf..b90f731 100644
--- a/include/mesos/docker/spec.hpp
+++ b/include/mesos/docker/spec.hpp
@@ -38,6 +38,10 @@ namespace spec {
 constexpr char WHITEOUT_PREFIX[] = ".wh.";
 
 
+// The prefix of opaque whiteout files in a docker image.
+constexpr char WHITEOUT_OPAQUE_PREFIX[] = ".wh..wh..opq";
+
+
 /**
  * Parse the docker image reference. Docker expects the image
  * reference to be in the following format:

http://git-wip-us.apache.org/repos/asf/mesos/blob/f433cdd0/src/slave/containerizer/mesos/provisioner/provisioner.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/provisioner/provisioner.cpp 
b/src/slave/containerizer/mesos/provisioner/provisioner.cpp
index f37c45c..2fa9bca 100644
--- a/src/slave/containerizer/mesos/provisioner/provisioner.cpp
+++ b/src/slave/containerizer/mesos/provisioner/provisioner.cpp
@@ -318,11 +318,16 @@ Future<ProvisionInfo> ProvisionerProcess::_provision(
 // This function is currently docker image specific. Depending
 // on docker v1 spec, a docker image may include filesystem
 // changeset, which may need to delete directories or files.
-// The file/dir to be deleted will be labeled by creating a
-// 'whiteout' file, which is at the same location and with the
-// basename of the deleted file or directory prefixed with
-// '.wh.'. Please see:
+// The file/directory to be deleted will be labeled by creating
+// a 'whiteout' file, which is at the same location and with the
+// basename of the deleted file or directory prefixed with '.wh.'.
+// For the directory which has an opaque whiteout file '.wh..wh..opq'
+// under it, we need to delete all the files/directories under it.
+// Please see:
 // https://github.com/docker/docker/blob/master/image/spec/v1.md
+// https://github.com/docker/docker/blob/master/pkg/archive/whiteouts.go
+// And OCI image spec also has the concepts 'whiteout' and 'opaque whiteout':
+// https://github.com/opencontainers/image-spec/blob/master/layer.md#whiteouts
 Future<ProvisionInfo> ProvisionerProcess::__provision(
     const string& rootfs,
     const Image& image,
@@ -353,21 +358,26 @@ Future<ProvisionInfo> ProvisionerProcess::__provision(
   }
 
   vector<string> whiteout;
+  vector<string> whiteoutOpaque;
 
   for (FTSENT *node = ::fts_read(tree);
        node != nullptr; node = ::fts_read(tree)) {
     if (node->fts_info == FTS_F &&
         strings::startsWith(node->fts_name, string(spec::WHITEOUT_PREFIX))) {
       Path path = Path(node->fts_path);
-
-      whiteout.push_back(path::join(path.dirname(), path.basename().substr(
-          strlen(spec::WHITEOUT_PREFIX))));
+      if (node->fts_name == string(spec::WHITEOUT_OPAQUE_PREFIX)) {
+        whiteoutOpaque.push_back(path.dirname());
+      } else {
+        whiteout.push_back(path::join(
+            path.dirname(),
+            path.basename().substr(strlen(spec::WHITEOUT_PREFIX))));
+      }
 
       Try<Nothing> rm = os::rm(path.string());
       if (rm.isError()) {
         ::fts_close(tree);
         return Failure(
-            "Failed to remove the whiteout '.wh.' file '" +
+            "Failed to remove whiteout file '" +
             path.string() + "': " + rm.error());
       }
     }
@@ -384,20 +394,35 @@ Future<ProvisionInfo> ProvisionerProcess::__provision(
         "Failed to stop traversing file system: " + os::strerror(errno));
   }
 
+  foreach (const string& path, whiteoutOpaque) {
+    Try<Nothing> rmdir = os::rmdir(path, true, false);
+    if (rmdir.isError()) {
+      return Failure(
+          "Failed to remove the entries under the directory labeled as"
+          " opaque whiteout '" + path + "': " + rmdir.error());
+    }
+  }
+
   foreach (const string& path, whiteout) {
-    if (os::stat::isdir(path)) {
-      Try<Nothing> rmdir = os::rmdir(path);
-      if (rmdir.isError()) {
-        return Failure(
-            "Failed to remove whiteout directory '" +
-            path + "': " + rmdir.error());
-      }
-    } else {
-      Try<Nothing> rm = os::rm(path);
-      if (rm.isError()) {
-        return Failure(
-            "Failed to remove whiteout file '" +
-            path + "': " + rm.error());
+    // The file/directory labeled as whiteout may have already been
+    // removed with the code above due to its parent directory labeled
+    // as opaque whiteout, so here we need to check if it still exists
+    // before trying to remove it.
+    if (os::exists(path)) {
+      if (os::stat::isdir(path)) {
+        Try<Nothing> rmdir = os::rmdir(path);
+        if (rmdir.isError()) {
+          return Failure(
+              "Failed to remove the directory labeled as whiteout '" +
+              path + "': " + rmdir.error());
+        }
+      } else {
+        Try<Nothing> rm = os::rm(path);
+        if (rm.isError()) {
+          return Failure(
+              "Failed to remove the file labeled as whiteout '" +
+              path + "': " + rm.error());
+        }
       }
     }
   }

Reply via email to