[buildd-tools-devel] Bug#808387: [schroot] Add support for overlay mounts.

Peter Pentchev roam at ringlet.net
Sat Dec 19 12:34:25 UTC 2015


Source: schroot
Version: 1.7.2-2
Severity: wishlist
Tags: patch

Hi,

First of all, thanks a lot for maintaining schroot and the rest of
the automatic build infrastructure!

A couple of months ago, aufs stopped working in the 4.x kernel for
a while.  It was fixed afterwards, but in the meantime I threw
together this simple thing that adds support for overlay mounts
(not quite the same as the existing overlayfs support).
One of the drawbacks is that overlay mounts need an additional directory
as scratch space, so there's a whole new directory/property/method
added to various classes and configuration objects, and there's
a little pain in transitioning from an aufs chroot to an overlay one,
since this directory needs to be created first.

Just let me know if you're interested in this, and I can see what
it will take to port the patch to schroot-1.7.3, and also document
the new additions properly.  If not, and/or if aufs works in a stable
manner now and it can be used again, well, yeah, feel free to close
this bug report, I'm just putting this out there as a proof of concept
or something :)

G'luck,
Peter

-- System Information:
Debian Release: stretch/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'oldoldstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.2.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=bg_BG.UTF-8, LC_CTYPE=bg_BG.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

-- no debconf information


-------------- next part --------------
Description: Add support for the 3.18+ kernel "overlay" mounts.
Author: Peter Pentchev <roam at ringlet.net>
Forwarded: not-yet
Last-Update: 2015-08-04

--- a/etc/setup.d/10mount
+++ b/etc/setup.d/10mount
@@ -107,6 +107,9 @@
             overlayfs)
                 CHROOT_UNION_MOUNT_OPTIONS="lowerdir=${CHROOT_UNION_UNDERLAY_DIRECTORY},upperdir=${CHROOT_UNION_OVERLAY_DIRECTORY}"
                 ;;
+            overlay)
+                CHROOT_UNION_MOUNT_OPTIONS="lowerdir=${CHROOT_UNION_UNDERLAY_DIRECTORY},upperdir=${CHROOT_UNION_OVERLAY_DIRECTORY},workdir=${CHROOT_UNION_WORK_DIRECTORY}"
+                ;;
         esac
     fi
 
@@ -211,6 +214,9 @@
         do_umount_all "$CHROOT_MOUNT_LOCATION"
         if [ "$CREATE_UNION" = "yes" ]; then
             do_umount_all "$CHROOT_UNION_UNDERLAY_DIRECTORY"
+            if [ -n "$CHROOT_UNION_WORK_DIRECTORY" ]; then
+                do_umount_all "$CHROOT_UNION_WORK_DIRECTORY"
+            fi
         fi
 
         # Purge mount location.
--- a/lib/sbuild/chroot/facet/fsunion.cc
+++ b/lib/sbuild/chroot/facet/fsunion.cc
@@ -62,14 +62,16 @@
           // TRANSLATORS: %1% = chroot fs type
           {chroot::facet::fsunion::FSUNION_TYPE_UNKNOWN, N_("Unknown filesystem union type ?%1%?")},
           {chroot::facet::fsunion::FSUNION_OVERLAY_ABS,  N_("Union overlay must have an absolute path")},
-          {chroot::facet::fsunion::FSUNION_UNDERLAY_ABS, N_("Union underlay must have an absolute path")}
+          {chroot::facet::fsunion::FSUNION_UNDERLAY_ABS, N_("Union underlay must have an absolute path")},
+          {chroot::facet::fsunion::FSUNION_WORK_ABS, N_("Union work must have an absolute path")}
         };
 
       fsunion::fsunion ():
         facet(),
         union_type("none"),
         union_overlay_directory(SCHROOT_OVERLAY_DIR),
-        union_underlay_directory(SCHROOT_UNDERLAY_DIR)
+        union_underlay_directory(SCHROOT_UNDERLAY_DIR),
+        union_work_directory(SCHROOT_WORK_DIR)
       {
       }
 
@@ -134,6 +136,22 @@
       }
 
       std::string const&
+      fsunion::get_union_work_directory () const
+      {
+        return this->union_work_directory;
+      }
+
+      void
+      fsunion::set_union_work_directory
+      (const std::string& directory)
+      {
+        if (!is_absname(directory))
+          throw error(directory, FSUNION_WORK_ABS);
+
+        this->union_work_directory = directory;
+      }
+
+      std::string const&
       fsunion::get_union_type () const
       {
         return this->union_type;
@@ -144,6 +162,7 @@
       {
         if (type == "aufs" ||
             type == "overlayfs" ||
+            type == "overlay" ||
             type == "unionfs" ||
             type == "none")
           this->union_type = type;
@@ -187,6 +206,8 @@
                     get_union_overlay_directory());
             env.add("CHROOT_UNION_UNDERLAY_DIRECTORY",
                     get_union_underlay_directory());
+            env.add("CHROOT_UNION_WORK_DIRECTORY",
+                    get_union_work_directory());
           }
       }
 
@@ -216,6 +237,9 @@
             if (!this->union_underlay_directory.empty())
               detail.add(_("Filesystem Union Underlay Directory"),
                          get_union_underlay_directory());
+            if (!this->union_work_directory.empty())
+              detail.add(_("Filesystem Union Work Directory"),
+                         get_union_work_directory());
           }
       }
 
@@ -226,6 +250,7 @@
         used_keys.push_back("union-mount-options");
         used_keys.push_back("union-overlay-directory");
         used_keys.push_back("union-underlay-directory");
+        used_keys.push_back("union-work-directory");
       }
 
       void
@@ -250,6 +275,11 @@
                                       &fsunion::get_union_underlay_directory,
                                       keyfile, owner->get_name(),
                                       "union-underlay-directory");
+
+            keyfile::set_object_value(*this,
+                                      &fsunion::get_union_work_directory,
+                                      keyfile, owner->get_name(),
+                                      "union-work-directory");
           }
       }
 
@@ -282,6 +312,14 @@
                                   (is_session && get_union_configured()) ?
                                   keyfile::PRIORITY_REQUIRED :
                                   keyfile::PRIORITY_OPTIONAL);
+
+        keyfile::get_object_value(*this,
+                                  &fsunion::set_union_work_directory,
+                                  keyfile, owner->get_name(),
+                                  "union-work-directory",
+                                  (is_session && get_union_configured()) ?
+                                  keyfile::PRIORITY_REQUIRED :
+                                  keyfile::PRIORITY_OPTIONAL);
       }
 
       void
@@ -307,6 +345,10 @@
         std::string underlay = get_union_underlay_directory();
         underlay += "/" + owner->get_name();
         set_union_underlay_directory(underlay);
+
+        std::string work = get_union_work_directory();
+        work += "/" + owner->get_name();
+        set_union_work_directory(work);
       }
 
       void
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -121,6 +121,8 @@
     CACHE PATH "Directory for union filesystem writable overlays")
 set(SCHROOT_UNDERLAY_DIR "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/${CMAKE_PROJECT_NAME}/union/underlay"
     CACHE PATH "Directory for union filesystem read-only underlays")
+set(SCHROOT_WORK_DIR "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/${CMAKE_PROJECT_NAME}/union/work"
+    CACHE PATH "Directory for union filesystem read-write overlay scratch space")
 set(SCHROOT_MODULE_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/${CMAKE_PROJECT_NAME}/${GIT_RELEASE_VERSION}/modules"
     CACHE PATH "Directory for loadable modules")
 set(SCHROOT_DATA_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${CMAKE_PROJECT_NAME}"
--- a/bin/schroot/CMakeLists.txt
+++ b/bin/schroot/CMakeLists.txt
@@ -40,7 +40,8 @@
     ${SCHROOT_SESSION_DIR}
     ${SCHROOT_FILE_UNPACK_DIR}
     ${SCHROOT_OVERLAY_DIR}
-    ${SCHROOT_UNDERLAY_DIR})
+    ${SCHROOT_UNDERLAY_DIR}
+    ${SCHROOT_WORK_DIR})
 
 foreach(dir ${installdirs})
   install(CODE "
--- a/etc/setup.d/05union
+++ b/etc/setup.d/05union
@@ -36,6 +36,13 @@
             fatal "$CHROOT_UNION_UNDERLAY_DIRECTORY does not exist, and could not be created"
         fi
 
+        if [ -n "${CHROOT_UNION_WORK_DIRECTORY}" ]; then
+            mkdir "${CHROOT_UNION_WORK_DIRECTORY}"
+            if [ ! -d "$CHROOT_UNION_WORK_DIRECTORY" ]; then
+                fatal "$CHROOT_UNION_WORK_DIRECTORY does not exist, and could not be created"
+            fi
+        fi
+
     elif [ $STAGE = "setup-recover" ]; then
         if [ ! -d "${CHROOT_UNION_OVERLAY_DIRECTORY}" ]; then
             fatal "Missing overlay directory for session: can't recover"
@@ -43,6 +50,10 @@
         if [ ! -d "${CHROOT_UNION_UNDERLAY_DIRECTORY}" ]; then
             fatal "Missing underlay directory for session: can't recover"
         fi
+        if [ -n "${CHROOT_UNION_WORK_DIRECTORY}" ] &&
+           [ ! -d "${CHROOT_UNION_WORK_DIRECTORY}" ]; then
+            fatal "Missing work directory for session: can't recover"
+        fi
 
     elif [ $STAGE = "setup-stop" ]; then
         if [ "$CHROOT_SESSION_PURGE" = "true" ]; then
@@ -60,6 +71,14 @@
                     fatal "Failed to remove $CHROOT_UNION_UNDERLAY_DIRECTORY (directory not empty)."
                 fi
             fi
+
+            if [ -n "$CHROOT_UNION_WORK_DIRECTORY" ]; then
+                info "Removing $CHROOT_UNION_WORK_DIRECTORY"
+                if [ -d "${CHROOT_UNION_WORK_DIRECTORY}" ]; then
+                    # The work directory may contain... whatever.  Just remove it.
+                    rm -rf "${CHROOT_UNION_WORK_DIRECTORY}"
+                fi
+            fi
         fi
     fi
 
--- a/lib/sbuild/chroot/facet/fsunion.h
+++ b/lib/sbuild/chroot/facet/fsunion.h
@@ -51,7 +51,8 @@
           {
             FSUNION_TYPE_UNKNOWN, ///< Unknown filesystem union type.
             FSUNION_OVERLAY_ABS,  ///< Union overlay must have an absolute path.
-            FSUNION_UNDERLAY_ABS  ///< Union underlay must have an absolute path.
+            FSUNION_UNDERLAY_ABS, ///< Union underlay must have an absolute path.
+            FSUNION_WORK_ABS      ///< Union work must have an absolute path.
           };
 
         /// Exception type.
@@ -168,6 +169,22 @@
         virtual void
         set_union_underlay_directory (const std::string& directory);
 
+        /**
+         * Get the union work directory.
+         *
+         * @returns the writeable work directory.
+         */
+        virtual std::string const&
+        get_union_work_directory () const;
+
+        /**
+         * Set the union work directory.
+         *
+         * @param directory the writeable work directory.
+         */
+        virtual void
+        set_union_work_directory (const std::string& directory);
+
         virtual void
         setup_env (environment& env) const;
 
@@ -205,6 +222,8 @@
         std::string union_overlay_directory;
         /// Union read-only underlay directory.
         std::string union_underlay_directory;
+        /// Union read-write work directory (for "overlay" unions).
+        std::string union_work_directory;
       };
 
     }
--- a/lib/sbuild/config.h.cmake
+++ b/lib/sbuild/config.h.cmake
@@ -73,6 +73,7 @@
 #cmakedefine SCHROOT_FILE_UNPACK_DIR "${SCHROOT_FILE_UNPACK_DIR}"
 #cmakedefine SCHROOT_OVERLAY_DIR "${SCHROOT_OVERLAY_DIR}"
 #cmakedefine SCHROOT_UNDERLAY_DIR "${SCHROOT_UNDERLAY_DIR}"
+#cmakedefine SCHROOT_WORK_DIR "${SCHROOT_WORK_DIR}"
 #cmakedefine SCHROOT_SYSCONF_DIR "${SCHROOT_SYSCONF_DIR}"
 #cmakedefine SCHROOT_CONF "${SCHROOT_CONF}"
 #cmakedefine SCHROOT_CONF_CHROOT_D "${SCHROOT_CONF_CHROOT_D}"
--- a/man/config.man.cmake
+++ b/man/config.man.cmake
@@ -6,6 +6,7 @@
 .ds SCHROOT_FILE_UNPACK_DIR ${SCHROOT_FILE_UNPACK_DIR}
 .ds SCHROOT_OVERLAY_DIR ${SCHROOT_OVERLAY_DIR}
 .ds SCHROOT_UNDERLAY_DIR ${SCHROOT_UNDERLAY_DIR}
+.ds SCHROOT_WORK_DIR ${SCHROOT_WORK_DIR}
 .ds SCHROOT_SYSCONF_DIR ${SCHROOT_SYSCONF_DIR}
 .ds SCHROOT_CONF ${SCHROOT_CONF}
 .ds SCHROOT_CONF_CHROOT_D ${SCHROOT_CONF_CHROOT_D}
--- a/test/sbuild/chroot/chroot.h
+++ b/test/sbuild/chroot/chroot.h
@@ -160,6 +160,7 @@
 
         un->set_union_overlay_directory("/overlay");
         un->set_union_underlay_directory("/underlay");
+        un->set_union_work_directory("/work");
         un->set_union_mount_options("union-mount-options");
 
         session_union =
@@ -329,6 +330,7 @@
     keyfile.set_value(group, "union-mount-options", "union-mount-options");
     keyfile.set_value(group, "union-overlay-directory", "/overlay");
     keyfile.set_value(group, "union-underlay-directory", "/underlay");
+    keyfile.set_value(group, "union-work-directory", "/work");
   }
 
   void setup_keyfile_union_session (sbuild::keyfile&   keyfile,
@@ -338,6 +340,7 @@
     keyfile.set_value(group, "union-mount-options", "union-mount-options");
     keyfile.set_value(group, "union-overlay-directory", "/overlay/test-union-session-name");
     keyfile.set_value(group, "union-underlay-directory", "/underlay/test-union-session-name");
+    keyfile.set_value(group, "union-work-directory", "/work/test-union-session-name");
   }
 #endif // SBUILD_FEATURE_UNION
 
--- a/test/sbuild/chroot/directory.cc
+++ b/test/sbuild/chroot/directory.cc
@@ -136,6 +136,7 @@
   expected.add("CHROOT_UNION_MOUNT_OPTIONS",      "union-mount-options");
   expected.add("CHROOT_UNION_OVERLAY_DIRECTORY",  "/overlay/test-union-session-name");
   expected.add("CHROOT_UNION_UNDERLAY_DIRECTORY", "/underlay/test-union-session-name");
+  expected.add("CHROOT_UNION_WORK_DIRECTORY", "/work/test-union-session-name");
 
   ChrootBase::test_setup_env(session_union, expected);
 }
--- a/test/sbuild/chroot/block-device.cc
+++ b/test/sbuild/chroot/block-device.cc
@@ -153,6 +153,7 @@
   expected.add("CHROOT_UNION_MOUNT_OPTIONS",      "union-mount-options");
   expected.add("CHROOT_UNION_OVERLAY_DIRECTORY",  "/overlay");
   expected.add("CHROOT_UNION_UNDERLAY_DIRECTORY", "/underlay");
+  expected.add("CHROOT_UNION_WORK_DIRECTORY", "/work");
 
   ChrootBase::test_setup_env(chroot_union, expected);
 }
@@ -172,6 +173,7 @@
   expected.add("CHROOT_UNION_MOUNT_OPTIONS",      "union-mount-options");
   expected.add("CHROOT_UNION_OVERLAY_DIRECTORY",  "/overlay/test-union-session-name");
   expected.add("CHROOT_UNION_UNDERLAY_DIRECTORY", "/underlay/test-union-session-name");
+  expected.add("CHROOT_UNION_WORK_DIRECTORY", "/work/test-union-session-name");
   ChrootBase::test_setup_env(session_union, expected);
 }
 
--- a/test/sbuild/chroot/loopback.cc
+++ b/test/sbuild/chroot/loopback.cc
@@ -161,6 +161,7 @@
   expected.add("CHROOT_UNION_MOUNT_OPTIONS",      "union-mount-options");
   expected.add("CHROOT_UNION_OVERLAY_DIRECTORY",  "/overlay");
   expected.add("CHROOT_UNION_UNDERLAY_DIRECTORY", "/underlay");
+  expected.add("CHROOT_UNION_WORK_DIRECTORY", "/work");
 
   ChrootBase::test_setup_env(chroot_union, expected);
 }
@@ -181,6 +182,7 @@
   expected.add("CHROOT_UNION_MOUNT_OPTIONS",      "union-mount-options");
   expected.add("CHROOT_UNION_OVERLAY_DIRECTORY",  "/overlay/test-union-session-name");
   expected.add("CHROOT_UNION_UNDERLAY_DIRECTORY", "/underlay/test-union-session-name");
+  expected.add("CHROOT_UNION_WORK_DIRECTORY", "/work/test-union-session-name");
   ChrootBase::test_setup_env(session_union, expected);
 }
 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.alioth.debian.org/pipermail/buildd-tools-devel/attachments/20151219/64c87068/attachment.sig>


More information about the Buildd-tools-devel mailing list