[buildd-tools-devel] [PATCH 7/8] Add filesystem union support to loopback chroots
Jan-Marek Glogowski
glogow at fbihome.de
Wed May 20 17:55:57 UTC 2009
As unioning filesystems just work with directories, the 10mount
script first mounts the loopback device to a directory named
after the contained filesystem UUID in the SCHROOT_MOUNT_DIR.
This directory is used as the read-only branch.
As this chroot now inherits from two chroot based classes, it has
to change the behaviour of the chroot::get_keyfile function, which
won't clean the group of the supplied keyfile anymore, otherwise
the keys from the first class (fs-union) will be lost.
---
etc/setup.d/10mount | 45 +++++++++++++++++++++++++++++++++-
man/schroot.conf.5.in | 12 +++++----
sbuild/sbuild-chroot-loopback.cc | 49 ++++++++++++++++++++++++++++---------
sbuild/sbuild-chroot-loopback.h | 7 ++++-
test/Makefile.am | 7 +++++
test/sbuild-chroot-loopback.cc | 5 ++-
test/test-sbuild-chroot.h | 15 ++++++++++-
7 files changed, 115 insertions(+), 25 deletions(-)
diff --git a/etc/setup.d/10mount b/etc/setup.d/10mount
index 8dc7b48..c659bfa 100755
--- a/etc/setup.d/10mount
+++ b/etc/setup.d/10mount
@@ -182,8 +182,6 @@ if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROO
UNPACK_LOCATION="${UNPACK_DIR}/${SESSION_ID}"
CHROOT_MOUNT_OPTIONS="--bind"
CHROOT_MOUNT_DEVICE="$UNPACK_LOCATION"
- elif [ "$CHROOT_TYPE" = "loopback" ]; then
- CHROOT_MOUNT_OPTIONS="$CHROOT_MOUNT_OPTIONS -o loop"
fi
if [ $1 = "setup-start" ] || [ $1 = "setup-recover" ]; then
@@ -199,6 +197,39 @@ if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROO
exit 1
fi
+ if [ "$CHROOT_TYPE" = "loopback" ]; then
+ LOOP_DEVICE=$(losetup -j ${CHROOT_FILE} | sed -e 's/:.*$//')
+ if [ "xyes" = "x${CREATE_FS_UNION}" ]; then
+ if [ "x" = "x${LOOP_DEVICE}" ]; then
+ LOOP_DEVICE=$(losetup -f)
+ losetup -r "${LOOP_DEVICE}" "${CHROOT_FILE}"
+
+ if ! do_mount_block_device "${CHROOT_MOUNT_OPTIONS}" "${LOOP_DEVICE}"
+ then
+ losetup -d ${LOOP_DEVICE}
+ exit 1
+ fi
+ else
+ if ! do_mount_block_device "${CHROOT_MOUNT_OPTIONS}" "${LOOP_DEVICE}"
+ then
+ exit 1
+ fi
+ fi
+ CHROOT_MOUNT_DEVICE="${LOOP_DEVICE}"
+ CHROOT_MOUNT_OPTIONS=""
+ CHROOT_FS_UNION_RO_BRANCH="${MOUNT_DIR}/${CHROOT_MOUNT_UUID}"
+ else
+ if [ "x" != "x${LOOP_DEVICE}" ]; then
+ echo "The file '${CHROOT_FILE}' is already associated" \
+ "with device '${LOOP_DEVICE}'."
+ exit 1
+ else
+ CHROOT_MOUNT_DEVICE="${CHROOT_FILE}"
+ CHROOT_MOUNT_OPTIONS="${CHROOT_MOUNT_OPTIONS} -o loop"
+ fi
+ fi
+ fi
+
# If recovering, we want to remount all filesystems to ensure
# a sane state.
if [ $1 = "setup-recover" ]; then
@@ -251,6 +282,16 @@ if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROO
rmdir "${UUID_MOUNT}" 2>/dev/null
fi
set -e
+
+ if [ "$CHROOT_TYPE" = "loopback" ]; then
+ LOOP_DEVICE=$(losetup -j ${CHROOT_FILE} | sed -e 's/:.*$//')
+ if [ "x" != "x$LOOP_DEVICE" ]; then
+ MOUNT_POINT=$(get_mount_point "${LOOP_DEVICE}")
+ if [ "x" = "x$MOUNT_POINT" ]; then
+ losetup -d $LOOP_DEVICE
+ fi
+ fi
+ fi
fi
if [ "$CHROOT_TYPE" != "file" ]; then
diff --git a/man/schroot.conf.5.in b/man/schroot.conf.5.in
index fad5890..b41be81 100644
--- a/man/schroot.conf.5.in
+++ b/man/schroot.conf.5.in
@@ -189,12 +189,14 @@ Loopback chroots
.PP
Chroots of type \[oq]loopback\[cq] are a filesystem available as a file on
disk, accessed via a loopback mount. The file will be loopback mounted and
-unmounted on demand. They implement the \fBmountable chroot\fP options (see
-\[lq]\fIMountable chroot options\fP\[rq], below), plus an additional option:
+unmounted on demand. They implement the \fBmountable chroot\fP and
+\fBfs-union chroot\fP options (see \[lq]\fIMountable chroot options\fP\[rq]
+and \[lq]\fIFilesystem Union chroot options\fP\[rq], below), plus an
+additional option:
.TP
-\f[CBI]file=\fP\f[CI]file\fP This is the filename of the file containing the
-filesystem, including the absolute path. For example,
-\[lq]/srv/chroot/sid\[rq].
+\f[CBI]file=\fP\f[CI]filename\fP
+This is the filename of the file containing the filesystem, including the
+absolute path. For example \[lq]/srv/chroot/sid\[rq].
.SS
Block device chroots
.PP
diff --git a/sbuild/sbuild-chroot-loopback.cc b/sbuild/sbuild-chroot-loopback.cc
index e191d68..361910e 100644
--- a/sbuild/sbuild-chroot-loopback.cc
+++ b/sbuild/sbuild-chroot-loopback.cc
@@ -32,7 +32,7 @@ using boost::format;
using namespace sbuild;
chroot_loopback::chroot_loopback ():
- chroot(),
+ chroot_fs_union(),
chroot_mountable(),
file()
{
@@ -48,6 +48,19 @@ chroot_loopback::clone () const
return ptr(new chroot_loopback(*this));
}
+sbuild::chroot::ptr
+chroot_loopback::clone_source () const
+{
+ ptr clone;
+
+ if (get_fs_union_configured()) {
+ clone = ptr(new chroot_loopback(*this));
+ chroot_source::clone_source_setup(clone);
+ }
+
+ return ptr(clone);
+}
+
std::string const&
chroot_loopback::get_file () const
{
@@ -58,7 +71,7 @@ void
chroot_loopback::set_file (std::string const& file)
{
if (!is_absname(file))
- throw error(file, FILE_ABS);
+ throw chroot::error(file, FILE_ABS);
this->file = file;
chroot_mountable::set_mount_device(file);
@@ -81,7 +94,7 @@ chroot_loopback::get_chroot_type () const
void
chroot_loopback::setup_env (environment& env)
{
- chroot::setup_env(env);
+ chroot_fs_union::setup_env(env);
chroot_mountable::setup_env(env);
env.add("CHROOT_FILE", get_file());
@@ -99,27 +112,39 @@ chroot_loopback::setup_lock (chroot::setup_type type,
// NOTE: taken from chroot_config::check_security.
if (file_status.uid() != 0)
- throw error(this->file, FILE_OWNER);
+ throw chroot::error(this->file, FILE_OWNER);
if (file_status.check_mode(stat::PERM_OTHER_WRITE))
- throw error(this->file, FILE_PERMS);
+ throw chroot::error(this->file, FILE_PERMS);
if (!file_status.is_regular())
- throw error(this->file, FILE_NOTREG);
+ throw chroot::error(this->file, FILE_NOTREG);
}
- /* By default, loopback chroots do no locking. */
+ /**
+ * By default, loopback chroots do no locking, but can create sessions
+ * using filesystem unions.
+ */
+ if (get_fs_union_configured() &&
+ ((type == SETUP_START && lock == true) ||
+ (type == SETUP_STOP && lock == false && status == 0)))
+ {
+ bool start = (type == SETUP_START);
+ setup_session_info(start);
+ }
}
sbuild::chroot::session_flags
chroot_loopback::get_session_flags () const
{
- return SESSION_NOFLAGS | chroot_mountable::get_session_flags();
+ return SESSION_NOFLAGS
+ | chroot_mountable::get_session_flags()
+ | chroot_fs_union::get_session_flags();
}
void
chroot_loopback::get_details (format_detail& detail) const
{
- this->chroot::get_details(detail);
- this->chroot_mountable::get_details(detail);
+ chroot_fs_union::get_details(detail);
+ chroot_mountable::get_details(detail);
if (!this->file.empty())
detail.add(_("File"), get_file());
@@ -128,7 +153,7 @@ chroot_loopback::get_details (format_detail& detail) const
void
chroot_loopback::get_keyfile (keyfile& keyfile) const
{
- chroot::get_keyfile(keyfile);
+ chroot_fs_union::get_keyfile(keyfile);
chroot_mountable::get_keyfile(keyfile);
keyfile::set_object_value(*this, &chroot_loopback::get_file,
@@ -139,7 +164,7 @@ void
chroot_loopback::set_keyfile (keyfile const& keyfile,
string_list& used_keys)
{
- chroot::set_keyfile(keyfile, used_keys);
+ chroot_fs_union::set_keyfile(keyfile, used_keys);
chroot_mountable::set_keyfile(keyfile, used_keys);
keyfile::get_object_value(*this, &chroot_loopback::set_file,
diff --git a/sbuild/sbuild-chroot-loopback.h b/sbuild/sbuild-chroot-loopback.h
index a19ad0c..818a26d 100644
--- a/sbuild/sbuild-chroot-loopback.h
+++ b/sbuild/sbuild-chroot-loopback.h
@@ -19,7 +19,7 @@
#ifndef SBUILD_CHROOT_LOOPBACK_H
#define SBUILD_CHROOT_LOOPBACK_H
-#include <sbuild/sbuild-chroot.h>
+#include <sbuild/sbuild-chroot-fs-union.h>
#include <sbuild/sbuild-chroot-mountable.h>
namespace sbuild
@@ -30,7 +30,7 @@ namespace sbuild
*
* The file will be mounted on demand.
*/
- class chroot_loopback : virtual public chroot,
+ class chroot_loopback : public chroot_fs_union,
public chroot_mountable
{
protected:
@@ -45,6 +45,9 @@ namespace sbuild
virtual chroot::ptr
clone () const;
+
+ virtual chroot::ptr
+ clone_source () const;
/**
* Get the file containing the chroot.
diff --git a/test/Makefile.am b/test/Makefile.am
index 4a4cd31..f729230 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -72,6 +72,11 @@ sbuild_chroot_blockdev_sources = \
sbuild-chroot-block-device.cc
endif
+if BUILD_LOOPBACK
+sbuild_chroot_loopback_sources = \
+ sbuild-chroot-loopback.cc
+endif
+
if BUILD_LVMSNAP
sbuild_chroot_lvmsnap_sources = \
sbuild-chroot-lvm-snapshot.cc
@@ -83,8 +88,10 @@ sbuild_chroot_SOURCES = \
sbuild-chroot-file.cc \
sbuild-chroot-directory.cc \
$(sbuild_chroot_blockdev_sources) \
+ $(sbuild_chroot_loopback_sources) \
$(sbuild_chroot_lvmsnap_sources) \
test-sbuild-chroot.h
+
sbuild_chroot_LDADD = libtest.la
sbuild_chroot_config_SOURCES = sbuild-chroot-config.cc
diff --git a/test/sbuild-chroot-loopback.cc b/test/sbuild-chroot-loopback.cc
index 395bc4c..64e453f 100644
--- a/test/sbuild-chroot-loopback.cc
+++ b/test/sbuild-chroot-loopback.cc
@@ -111,7 +111,7 @@ public:
expected.add("CHROOT_MOUNT_OPTIONS", "-t jfs -o quota,rw");
expected.add("CHROOT_SCRIPT_CONFIG", sbuild::normalname(std::string(PACKAGE_SYSCONF_DIR) + "/script-defaults"));
expected.add("CHROOT_SESSION_CLONE", "false");
- expected.add("CHROOT_SESSION_CREATE", "false");
+ expected.add("CHROOT_SESSION_CREATE", "true");
expected.add("CHROOT_SESSION_PURGE", "false");
expected.add("CHROOT_FS_UNION_TYPE", "none");
}
@@ -134,6 +134,7 @@ public:
setup_env_common(expected);
expected.add("CHROOT_FILE", loopback_file);
+ expected.add("CHROOT_MOUNT_DEVICE", loopback_file);
expected.add("CHROOT_MOUNT_UUID", FS_UUID);
test_chroot_base<chroot_loopback>::test_setup_env(expected);
@@ -142,7 +143,7 @@ public:
void test_session_flags()
{
CPPUNIT_ASSERT(chroot->get_session_flags() ==
- sbuild::chroot::SESSION_NOFLAGS);
+ sbuild::chroot::SESSION_CREATE);
}
void test_print_details()
diff --git a/test/test-sbuild-chroot.h b/test/test-sbuild-chroot.h
index e7d0c88..60fc7d0 100644
--- a/test/test-sbuild-chroot.h
+++ b/test/test-sbuild-chroot.h
@@ -19,6 +19,8 @@
#ifndef TEST_SBUILD_CHROOT_H
#define TEST_SBUILD_CHROOT_H
+#include <unistd.h>
+
#include <sbuild/sbuild-chroot.h>
#include <algorithm>
@@ -34,12 +36,21 @@ class test_chroot_base : public TestFixture
{
protected:
sbuild::chroot::ptr chroot;
+ std::string abs_testdata_dir;
public:
test_chroot_base():
TestFixture(),
- chroot()
- {}
+ chroot(),
+ abs_testdata_dir()
+ {
+ char cwd[FILENAME_MAX];
+ if (NULL != getcwd(cwd, FILENAME_MAX))
+ {
+ abs_testdata_dir = std::string(cwd);
+ abs_testdata_dir.append("/" TESTDATADIR);
+ }
+ }
virtual ~test_chroot_base()
{}
--
1.6.3.1
More information about the Buildd-tools-devel
mailing list