[buildd-tools-devel] [PATCH 13/17] [chroot_fs_union] Generalize and simplify unions

Jan-Marek Glogowski glogow at fbihome.de
Tue Jun 30 18:05:51 UTC 2009


Adds a union underlay directory and drop most of the special
handling (filesystem UUID) in the 05fsunion script.
---
 bin/schroot/Makefile.am           |    1 +
 configure.ac                      |    7 +-
 etc/setup.d/00check               |   10 ++-
 etc/setup.d/05fsunion             |   22 +++-
 etc/setup.d/10mount               |  224 +++++++++----------------------------
 man/schroot-setup.5.in            |   16 +++
 man/schroot.conf.5.in             |   52 +++++----
 sbuild/sbuild-chroot-directory.cc |   13 +--
 sbuild/sbuild-chroot-directory.h  |    3 +-
 sbuild/sbuild-chroot-file.cc      |    2 +-
 sbuild/sbuild-chroot-fs-union.cc  |  145 ++++++++++++++----------
 sbuild/sbuild-chroot-fs-union.h   |   91 +++++++++-------
 sbuild/sbuild-session.cc          |   15 ++-
 test/sbuild-chroot-directory.cc   |    2 +
 14 files changed, 281 insertions(+), 322 deletions(-)

diff --git a/bin/schroot/Makefile.am b/bin/schroot/Makefile.am
index f0ccb45..6711a21 100644
--- a/bin/schroot/Makefile.am
+++ b/bin/schroot/Makefile.am
@@ -56,4 +56,5 @@ install-data-hook:
 	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_SESSION_DIR)
 	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_FILE_UNPACK_DIR)
 	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_OVERLAY_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SCHROOT_UNDERLAY_DIR)
 
diff --git a/configure.ac b/configure.ac
index dac5306..1b29cff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -621,11 +621,16 @@ AC_SUBST([SCHROOT_FILE_UNPACK_DIR])
 AH_TEMPLATE(SCHROOT_FILE_UNPACK_DIR, [schroot file unpack directory])
 AC_DEFINE_UNQUOTED(SCHROOT_FILE_UNPACK_DIR, ["$SCHROOT_FILE_UNPACK_DIR"])
 
-SCHROOT_OVERLAY_DIR="${PACKAGE_LOCALSTATE_DIR}/lib/${PACKAGE}/overlay"
+SCHROOT_OVERLAY_DIR="${PACKAGE_LOCALSTATE_DIR}/lib/${PACKAGE}/union/overlay"
 AC_SUBST([SCHROOT_OVERLAY_DIR])
 AH_TEMPLATE(SCHROOT_OVERLAY_DIR, [schroot overlay directory])
 AC_DEFINE_UNQUOTED(SCHROOT_OVERLAY_DIR, ["$SCHROOT_OVERLAY_DIR"])
 
+SCHROOT_UNDERLAY_DIR="${PACKAGE_LOCALSTATE_DIR}/lib/${PACKAGE}/union/underlay"
+AC_SUBST([SCHROOT_UNDERLAY_DIR])
+AH_TEMPLATE(SCHROOT_UNDERLAY_DIR, [schroot underlay directory])
+AC_DEFINE_UNQUOTED(SCHROOT_UNDERLAY_DIR, ["$SCHROOT_UNDERLAY_DIR"])
+
 dnl Set PACKAGE_SYSCONF_DIR in config.h.
 AH_TEMPLATE(PACKAGE_SYSCONF_DIR, [Package system configuration directory])
 if test "x${sysconfdir}" = 'x${prefix}/etc'; then
diff --git a/etc/setup.d/00check b/etc/setup.d/00check
index 68f2736..9bded7e 100755
--- a/etc/setup.d/00check
+++ b/etc/setup.d/00check
@@ -19,6 +19,11 @@
 
 set -e
 
+# Plain chroots should not be able to use scripts - check anyway
+if [ $CHROOT_TYPE = "plain" ]; then
+    exit 1
+fi
+
 if [ -f "$CHROOT_SCRIPT_CONFIG" ]; then
     . "$CHROOT_SCRIPT_CONFIG"
 elif [ "$2" = "ok" ]; then
@@ -53,8 +58,9 @@ if [ $1 = "setup-start" ] || [ $1 = "setup-recover" ]; then
 	if [ -n "$CHROOT_FS_UNION_TYPE" ] && [ "$CHROOT_FS_UNION_TYPE" != "none" ]; then
 	    echo "CHROOT_FS_UNION_TYPE=$CHROOT_FS_UNION_TYPE"
 	    echo "CHROOT_FS_UNION_OVERLAY_DIRECTORY=$CHROOT_FS_UNION_OVERLAY_DIRECTORY"
+	    echo "CHROOT_FS_UNION_UNDERLAY_DIRECTORY=$CHROOT_FS_UNION_UNDERLAY_DIRECTORY"
 	fi
-	if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ]; then
+	if [ "$CHROOT_TYPE" = "directory" ]; then
 	    echo "CHROOT_DIRECTORY=$CHROOT_DIRECTORY"
 	elif [ "$CHROOT_TYPE" = "file" ]; then
 	    echo "CHROOT_FILE=$CHROOT_FILE"
@@ -77,7 +83,7 @@ if [ $1 = "setup-start" ] || [ $1 = "setup-recover" ]; then
     fi
 
     case "$CHROOT_TYPE" in
-	plain | directory)
+	directory)
 	    if [ ! -d "$CHROOT_DIRECTORY" ]; then
 		echo "Directory '$CHROOT_DIRECTORY' does not exist"
 		exit 1
diff --git a/etc/setup.d/05fsunion b/etc/setup.d/05fsunion
index c8c454f..e0e52cd 100755
--- a/etc/setup.d/05fsunion
+++ b/etc/setup.d/05fsunion
@@ -23,21 +23,26 @@ if [ -f "$CHROOT_SCRIPT_CONFIG" ]; then
     . "$CHROOT_SCRIPT_CONFIG"
 fi
 
-if [ "xnone" != "x${CHROOT_FS_UNION_TYPE:-none}" ]; then
+if [ "none" != "${CHROOT_FS_UNION_TYPE:-none}" ]; then
 
     if [ $1 = "setup-start" ]; then
 	if [ "$CHROOT_SESSION_PURGE" = "true" ]; then
-		mkdir "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}"
+	    mkdir "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}"
+	    mkdir "${CHROOT_FS_UNION_UNDERLAY_DIRECTORY}"	
 	fi
 
     elif [ $1 = "setup-recover" ]; then
-        if [ ! -d "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}" ]; then
+	if [ ! -d "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}" ]; then
 	    echo "Missing overlay directory for session - can't restore"
 	    exit 1
-        fi
+	fi
+	if [ ! -d "${CHROOT_FS_UNION_UNDERLAY_DIRECTORY}" ]; then
+	    echo "Missing underlay directory for session - can't restore"
+	    exit 1
+	fi
 
     elif [ $1 = "setup-stop" ]; then
-        if [ "$CHROOT_SESSION_PURGE" = "true" ]; then
+	if [ "$CHROOT_SESSION_PURGE" = "true" ]; then
 	    if [ "$AUTH_VERBOSITY" = "verbose" ]; then
 		echo "Purging $CHROOT_FS_UNION_OVERLAY_DIRECTORY"
 	    fi
@@ -45,6 +50,13 @@ if [ "xnone" != "x${CHROOT_FS_UNION_TYPE:-none}" ]; then
 		rm -rf "${CHROOT_FS_UNION_OVERLAY_DIRECTORY}"
 	    fi
 	fi
+
+	if [ "$AUTH_VERBOSITY" = "verbose" ]; then
+	    echo "Removing $CHROOT_FS_UNION_UNDERLAY_DIRECTORY"
+	fi
+	if [ -d "${CHROOT_FS_UNION_UNDERLAY_DIRECTORY}" ]; then
+	    rmdir "${CHROOT_FS_UNION_UNDERLAY_DIRECTORY}"
+	fi
     fi
 
 fi
diff --git a/etc/setup.d/10mount b/etc/setup.d/10mount
index b3596f9..bf621b2 100755
--- a/etc/setup.d/10mount
+++ b/etc/setup.d/10mount
@@ -1,5 +1,6 @@
 #!/bin/sh
 # Copyright © 2005-2007  Roger Leigh <rleigh at debian.org>
+#	   © 2009       Jan-Marek Glogowski <glogow at fbihome.de>
 #
 # schroot is free software: you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -41,47 +42,10 @@ do_mount()
     fi
     if [ ! -d "$3" ]; then
 	echo "$3 does not exist, and could not be created"
-	return 1
+	exit 1
     fi
 
-    set +e
     mount $VERBOSE $1 "$2" "$3"
-    RESULT=$?
-    set -e
-
-    return $RESULT
-}
-
-# Find mount point for block device
-# $1: block device
-get_mount_point()
-{
-    df "${1}" 2>/dev/null | sed -n -e "s#^${1} ##p" | sed -n -e "s#[^/]\+##p"
-}
-
-# Mounts a block-device ro by UUID to ${MOUNT_DIR}/<UUID>
-# $1: options
-# $2: block device
-do_mount_block_device()
-{
-    if [ ! -b "${2}" ] || [ "x" = "x${CHROOT_MOUNT_UUID}" ]; then
-	return 255
-    fi
-
-    UUID_MOUNT="${MOUNT_DIR}/${CHROOT_MOUNT_UUID}"
-
-    MOUNT_POINT=$(get_mount_point "${2}")
-    if [ "x" = "x${MOUNT_POINT}" ]; then
-	do_mount "${1} -o ro" "${2}" "${UUID_MOUNT}"
-        return $?
-    else
-	if [ "x${MOUNT_POINT}" = "x${UUID_MOUNT}" ]; then
-	    return 0
-	else
-	    echo "The device '${2}' is already in use on '${MOUNT_POINT}'"
-	    return 254
-	fi
-    fi
 }
 
 # Unmount all filesystems under specified location
@@ -90,69 +54,49 @@ do_umount_all()
 {
     if [ -d "$1" ]; then
 	mounts="$("$LIBEXEC_DIR/schroot-listmounts" -m "$1")"
-	if [ "x$mounts" != 'x' ]; then
-            echo "$mounts" |
-            while read mountloc; do
+	if [ -n "$mounts" ]; then
+	    echo "$mounts" |
+	    while read mountloc; do
 		if [ "$AUTH_VERBOSITY" = "verbose" ]; then
-                    echo "Unmounting $mountloc"
+		    echo "Unmounting $mountloc"
 		fi
 		umount "$mountloc" || exit 1
-            done || exit 1
+	    done || exit 1
 	fi
     fi
 }
 
 # Mount a filesystem union
-# $1: read-only branch
 do_mount_fs_union()
 {
-    MOUNT_RES=255
-
     # Try mounting the filesystem module
     if ! grep -q "${CHROOT_FS_UNION_TYPE}$" /proc/filesystems; then
-	set +e
 	modprobe ${CHROOT_FS_UNION_TYPE} &> /dev/null
-	set -e
     fi
 
-    # Skip fs if not available
+    # Fail if union fs type is not available
     if ! grep -q "${CHROOT_FS_UNION_TYPE}$" /proc/filesystems; then
-	# branch config just works with the first fs
-	CHROOT_FS_UNION_BRANCH_CONFIG=""
-	continue
+	exit 1
     fi
 
     # Prepare branch config for fs type
-    if [ -z "${CHROOT_FS_UNION_BRANCH_CONFIG}" ]; then
+    if [ -z "${CHROOT_FS_UNION_MOUNT_OPTIONS}" ]; then
 	case $CHROOT_FS_UNION_TYPE in
 	unionfs)
-	    CHROOT_FS_UNION_BRANCH_CONFIG="dirs=${CHROOT_FS_UNION_OVERLAY_DIRECTORY}=rw,${1}=ro"
+	    CHROOT_FS_UNION_MOUNT_OPTIONS="dirs=${CHROOT_FS_UNION_OVERLAY_DIRECTORY}=rw,${CHROOT_FS_UNION_UNDERLAY_DIRECTORY}=ro"
 	    ;;
 	aufs)
-	    CHROOT_FS_UNION_BRANCH_CONFIG="br:${CHROOT_FS_UNION_OVERLAY_DIRECTORY}:${1}=ro"
+	    CHROOT_FS_UNION_MOUNT_OPTIONS="br:${CHROOT_FS_UNION_OVERLAY_DIRECTORY}:${CHROOT_FS_UNION_UNDERLAY_DIRECTORY}=ro"
 	    ;;
 	esac
     fi
 
     # Try mounting fs
-    set +e
-    mount -t $CHROOT_FS_UNION_TYPE -o "$CHROOT_FS_UNION_BRANCH_CONFIG" ${CHROOT_NAME} ${CHROOT_MOUNT_LOCATION}
-    MOUNT_RES=$?
-    set -e
-    if [ 0 -eq $MOUNT_RES ]; then
-	break
-    fi
-
-    if [ 0 -ne $MOUNT_RES ]; then
-	echo "Mounting filesystem union failed"
-	return 1
-    fi
+    mount -t $CHROOT_FS_UNION_TYPE -o "$CHROOT_FS_UNION_MOUNT_OPTIONS" ${CHROOT_NAME} "${CHROOT_FS_UNION_MOUNT_LOCATION}"
 
     if [ "$AUTH_VERBOSITY" = "verbose" ]; then
 	echo "Using '$CHROOT_FS_UNION_TYPE' for filesystem union"
     fi
-
-    return 0
 }
 
 if [ "$AUTH_VERBOSITY" = "verbose" ]; then
@@ -160,9 +104,9 @@ if [ "$AUTH_VERBOSITY" = "verbose" ]; then
 #  FSCK_VERBOSE="-V"
 fi
 
-if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROOT_TYPE" = "file" ] || [ "$CHROOT_TYPE" = "file" ] || [ "$CHROOT_TYPE" = "loopback" ] || [ "$CHROOT_TYPE" = "block-device" ] || [ "$CHROOT_TYPE" = "lvm-snapshot" ]; then
+if [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROOT_TYPE" = "file" ] || [ "$CHROOT_TYPE" = "file" ] || [ "$CHROOT_TYPE" = "loopback" ] || [ "$CHROOT_TYPE" = "block-device" ] || [ "$CHROOT_TYPE" = "lvm-snapshot" ]; then
 
-    if [ "xnone" != "x${CHROOT_FS_UNION_TYPE:-none}" ] \
+    if [ "none" != "${CHROOT_FS_UNION_TYPE:-none}" ] \
 	&& [ "$CHROOT_SESSION_PURGE" = "true" ];
     then
 	CREATE_FS_UNION="yes"
@@ -170,139 +114,76 @@ if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROO
 	CREATE_FS_UNION="no"
     fi
 
-    if [ "$CHROOT_TYPE" = "plain" ]; then
-	CHROOT_MOUNT_OPTIONS="--rbind"
-	CHROOT_MOUNT_DEVICE="$CHROOT_DIRECTORY"
-	CHROOT_FS_UNION_RO_BRANCH="$CHROOT_DIRECTORY"
-    elif [ "$CHROOT_TYPE" = "directory" ]; then
+    if [ "$CHROOT_TYPE" = "directory" ]; then
 	CHROOT_MOUNT_OPTIONS="--bind"
 	CHROOT_MOUNT_DEVICE="$CHROOT_DIRECTORY"
-	CHROOT_FS_UNION_RO_BRANCH="$CHROOT_DIRECTORY"
+
     elif [ "$CHROOT_TYPE" = "file" ]; then
 	UNPACK_LOCATION="${UNPACK_DIR}/${SESSION_ID}"
 	CHROOT_MOUNT_OPTIONS="--bind"
 	CHROOT_MOUNT_DEVICE="$UNPACK_LOCATION"
+
+    elif [ "$CHROOT_TYPE" = "loopback" ]; then
+	LOOP_DEVICE=$(losetup -j ${CHROOT_FILE} | sed -e 's/:.*$//')
+	if [ -z "${LOOP_DEVICE}" ]; then
+	    CHROOT_MOUNT_DEVICE="${CHROOT_FILE}"
+	    CHROOT_MOUNT_OPTIONS="${CHROOT_MOUNT_OPTIONS} -o loop"
+	else
+	    CHROOT_MOUNT_DEVICE="${LOOP_DEVICE}"
+	    CHROOT_MOUNT_OPTIONS=""
+	fi
+
+    elif [ "$CHROOT_TYPE" = "block-device" ]; then
+	CHROOT_MOUNT_DEVICE="$CHROOT_DEVICE"
     fi
 
     if [ $1 = "setup-start" ] || [ $1 = "setup-recover" ]; then
-
-        # fsck doesn't like being run non-interactively
+	# fsck doesn't like being run non-interactively
 	#/sbin/fsck $FSCK_VERBOSE -n "$CHROOT_MOUNT_DEVICE"
 
-        if [ ! -d "$CHROOT_MOUNT_LOCATION" ]; then
+	if [ ! -d "$CHROOT_MOUNT_LOCATION" ]; then
 	    mkdir -p "$CHROOT_MOUNT_LOCATION"
-        fi
+	fi
 	if [ ! -d "$CHROOT_MOUNT_LOCATION" ]; then
 	    echo "$CHROOT_MOUNT_LOCATION does not exist, and could not be created"
 	    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
+	if [ "yes" = "${CREATE_FS_UNION}" ]; then
+	    CHROOT_FS_UNION_MOUNT_LOCATION="${CHROOT_MOUNT_LOCATION}"
+	    CHROOT_MOUNT_LOCATION="${CHROOT_FS_UNION_UNDERLAY_DIRECTORY}"
 
-	elif [ "$CHROOT_TYPE" = "block-device" ]; then
-	    if [ "xyes" = "x${CREATE_FS_UNION}" ]; then
-		if ! do_mount_block_device "$CHROOT_MOUNT_OPTIONS" "$CHROOT_MOUNT_DEVICE"
-		then
-		    exit 1
-		fi
-		CHROOT_FS_UNION_RO_BRANCH="${MOUNT_DIR}/${CHROOT_MOUNT_UUID}"
-	    else
-		CHROOT_MOUNT_DEVICE="$CHROOT_DEVICE"
+	    if [ $1 = "setup-recover" ]; then
+		do_umount_all "$CHROOT_FS_UNION_MOUNT_LOCATION"
 	    fi
 	fi
 
-        # If recovering, we want to remount all filesystems to ensure
-        # a sane state.
+	# If recovering, we want to remount all filesystems to ensure
+	# a sane state.
 	if [ $1 = "setup-recover" ]; then
 	    do_umount_all "$CHROOT_MOUNT_LOCATION"
 	fi
 
-	if [ "xyes" = "x${CREATE_FS_UNION}" ]; then
-	    if ! do_mount_fs_union "$CHROOT_FS_UNION_RO_BRANCH"
-	    then
-		if [ "x" != "x${UUID_MOUNT}" ]; then
-		    set +e
-		    if umount "${UUID_MOUNT}" 2>/dev/null
-		    then
-			rmdir "${UUID_MOUNT}" 2>/dev/null
-		    fi
-		    set -e
-		fi
-		exit 1
-	    fi
-	else
-	    if ! do_mount "$CHROOT_MOUNT_OPTIONS" "$CHROOT_MOUNT_DEVICE" "$CHROOT_MOUNT_LOCATION"
-	    then
-		exit 1
-	    fi
+	do_mount "$CHROOT_MOUNT_OPTIONS" "$CHROOT_MOUNT_DEVICE" "$CHROOT_MOUNT_LOCATION"
+	if [ "yes" = "${CREATE_FS_UNION}" ]; then
+	    do_mount_fs_union
 	fi
 
-	if [ "$CHROOT_TYPE" != "plain" ]; then
-	    if [ -n "$FSTAB" ]; then
-		if [ -f "$FSTAB" ]; then
-		    "$LIBEXEC_DIR/schroot-mount" $VERBOSE \
-			-f "$FSTAB" -m "$CHROOT_PATH"
-		else
-		    echo "fstab file '$FSTAB' does not exist"
-		    exit 1
-		fi
+	if [ -n "$FSTAB" ]; then
+	    if [ -f "$FSTAB" ]; then
+		"$LIBEXEC_DIR/schroot-mount" $VERBOSE \
+		    -f "$FSTAB" -m "$CHROOT_PATH"
+	    else
+		echo "fstab file '$FSTAB' does not exist"
+		exit 1
 	    fi
 	fi
 
     elif [ $1 = "setup-stop" ]; then
 
 	do_umount_all "$CHROOT_MOUNT_LOCATION"
-
-	if [ "xyes" = "x${CREATE_FS_UNION}" ] \
-	    && [ "x" != "x${CHROOT_MOUNT_UUID}" ];
-	then
-	    UUID_MOUNT="${MOUNT_DIR}/${CHROOT_MOUNT_UUID}"
-	    set +e
-	    if umount "${UUID_MOUNT}" 2>/dev/null
-	    then
-		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
+	if [ "yes" = "${CREATE_FS_UNION}" ]; then
+	    do_umount_all "$CHROOT_FS_UNION_UNDERLAY_DIRECTORY"
 	fi
 
 	if [ "$CHROOT_TYPE" != "file" ]; then
@@ -314,6 +195,5 @@ if [ "$CHROOT_TYPE" = "plain" ] || [ "$CHROOT_TYPE" = "directory" ] || [ "$CHROO
 	fi
 
     fi
-
 fi
 
diff --git a/man/schroot-setup.5.in b/man/schroot-setup.5.in
index 9a570f3..496aa7e 100644
--- a/man/schroot-setup.5.in
+++ b/man/schroot-setup.5.in
@@ -128,6 +128,19 @@ Options to pass to
 CHROOT_LOCATION
 The location of the chroot inside the mount point.  This allows the existence
 of multiple chroots on a single filesystem.
+.SS Filesystem union variables
+.TP
+CHROOT_FS_UNION_TYPE
+Union filesystem type.
+.TP
+CHROOT_FS_UNION_MOUNT_OPTIONS
+Union filesystem mount options.
+.TP
+CHROOT_FS_UNION_OVERLAY_DIRECTORY
+Union filesystem overlay directory (writable).
+.TP
+CHROOT_FS_UNION_UNDERLAY_DIRECTORY
+Union filesystem underlay directory (read-only).
 .SS Block device variables
 .TP
 CHROOT_DEVICE
@@ -156,6 +169,9 @@ Print debugging diagnostics and perform basic sanity checking.
 \f[BI]05file\fP
 Unpack, clean up, and repack file-based chroots.
 .TP
+\f[BI]05fsunion\fP
+Create and remove union filesystems.
+.TP
 \f[BI]05lvm\fP
 Create and remove LVM snapshots.
 .TP
diff --git a/man/schroot.conf.5.in b/man/schroot.conf.5.in
index b41be81..fc2879e 100644
--- a/man/schroot.conf.5.in
+++ b/man/schroot.conf.5.in
@@ -277,32 +277,40 @@ example, if the filesystem contains a chroot in \fI/chroot/sid\fP, you would
 specify \[lq]/chroot/sid\[rq] here.  If the chroot is the only thing on the
 filesystem, i.e. \fI/\fP is the root filesystem for the chroot, this option
 should be left blank, or omitted entirely.
-.SS Filesystem Union chroot options
-Some chroots allow to create a session using filesystem unions to overlay the
-real data and redirect all modifications to a session-dependant directory.
-To activate this feature you have to set the \f[CI]fs-union-type\fP to any
-supported value.  If \[lq]\fIFilesystem Union\fP\[rq] is enabled the chroot
-will also be a \fBsource chroot\fP, which wil provide additional options
-(see \[lq]\fISource chroot options\fP\[rq], above).  All entries are optional.
+.SS Filesystem union chroot options
+Some chroots allow creation of a session using filesystem unions to overlay the
+real data and redirect all modifications to a session-dependant directory.  To
+activate this feature, set \f[CI]fs\-union\-type\fP to any supported value.  If
+enabled, the chroot will also be a \fBsource chroot\fP, which will provide
+additional options (see \[lq]\fISource chroot options\fP\[rq], above).  All
+entries are optional.
 .TP
-\f[CBI]fs-union-type=\fP\f[CI]type\fP
-Allows to set the used filesystem.  This is especially important, if you use
-the \fIfs-branch-config\fP option to specify different options.  Currently
-supported filesystems are \[oq]aufs\[cq] and \[oq]unionfs\[cq].  Default is 
-\[oq]none\[cq], so this feature is disabled.
+\f[CBI]fs\-union\-type=\fP\f[CI]type\fP
+Set the union filesystem type.  This is especially important if you use the
+\fIfs\-union\-mount\-options\fP option to specify filesystem-specific options.
+Currently supported filesystems are \[oq]aufs\[cq] and \[oq]unionfs\[cq].  The
+default is \[oq]none\[cq], which disables this feature.
 .TP
-\f[CBI]fs-union-branch-config=\fP\f[CI]branch_config\fP
-The branch configuration is used for the first filesystem in the 
-\fIfs-union-type\fP filesystem list.  It replaces the complete \[lq]\-o\[rq] 
-string for mount and allows to make complex filesystem unions.
+\f[CBI]fs\-union\-mount\-options=\fP\f[CI]options\fP
+Union filesystem mount options (branch configuration), used for mounting the
+union filesystem specified with \fIfs\-union\-type\fP.  This replaces the 
+complete \[lq]\-o\[rq] string for mount and allows for the creation of complex
+filesystem unions.
 .B Note:
-You can use the variables \[lq]${CHROOT_FS_UNION_OVERLAY_DIRECTORY}\[rq] and
-\[lq]${CHROOT_LOCATION}\[rq] in this option string, which will be replaced
-with the writeable session directory and the source-chroot directory.
+One can use the variables \[lq]${CHROOT_UNION_OVERLAY_DIRECTORY}\[rq] and
+\[lq]${CHROOT_UNION_UNDERLAY_DIRECTORY}\[rq] to refer to the writable overlay
+session directory and read-only underlying directory which are to form the
+union.  See
+.BR schroot\-setup (5)
+for a complete variable list.
 .TP
-\f[CBI]fs-union-overlay-base=directory
-This specifies the base directory, where the session writeable directories
-will be created. Default is \[oq]@SCHROOT_OVERLAY_DIR@\[cq].
+\f[CBI]fs\-union\-overlay\-directory\fP\f[CI]=directory\fP
+Specify the directory where the writeable overlay session directories will be
+created.  The default is \[oq]@SCHROOT_OVERLAY_DIR@\[cq].
+.TP
+\f[CBI]fs\-union\-underlay\-directory\fP\f[CI]=directory\fP
+Specify the directory where the read-only underlying directories will be
+created.  The default is \[oq]@SCHROOT_UNDERLAY_DIR@\[cq].
 .SS Localisation
 .PP
 Some keys may be localised in multiple languages.  This is achieved by adding
diff --git a/sbuild/sbuild-chroot-directory.cc b/sbuild/sbuild-chroot-directory.cc
index 210bd09..2859cc9 100644
--- a/sbuild/sbuild-chroot-directory.cc
+++ b/sbuild/sbuild-chroot-directory.cc
@@ -64,14 +64,7 @@ chroot_directory::clone_source () const
 std::string
 chroot_directory::get_path () const
 {
-  // When running setup scripts, we are session-capable, so the path
-  // is the bind-mounted location, rather than the original location.
-  if (get_fs_union_configured())
-    return chroot_fs_union::get_path();
-  if (get_run_setup_scripts() == true)
-    return get_mount_location();
-  else
-    return get_directory();
+  return get_mount_location();
 }
 
 void
@@ -108,9 +101,7 @@ chroot_directory::get_session_flags () const
 {
   if (get_fs_union_configured())
     return chroot_fs_union::get_session_flags();
-  if (get_run_setup_scripts() == true)
-    return SESSION_CREATE;
-  return SESSION_NOFLAGS;
+  return SESSION_CREATE;
 }
 
 void
diff --git a/sbuild/sbuild-chroot-directory.h b/sbuild/sbuild-chroot-directory.h
index 574aaf1..10638f6 100644
--- a/sbuild/sbuild-chroot-directory.h
+++ b/sbuild/sbuild-chroot-directory.h
@@ -28,7 +28,8 @@ namespace sbuild
   /**
    * A chroot located in the filesystem.
    */
-  class chroot_directory : public chroot_fs_union, public chroot_plain
+  class chroot_directory : public chroot_plain,
+			   public chroot_fs_union
   {
   protected:
     /// The constructor.
diff --git a/sbuild/sbuild-chroot-file.cc b/sbuild/sbuild-chroot-file.cc
index d54584b..aef8664 100644
--- a/sbuild/sbuild-chroot-file.cc
+++ b/sbuild/sbuild-chroot-file.cc
@@ -142,7 +142,7 @@ chroot_file::setup_lock (chroot::setup_type type,
     }
 }
 
-sbuild::chroot::session_flags
+chroot::session_flags
 chroot_file::get_session_flags () const
 {
   return SESSION_CREATE | chroot_source::get_session_flags();
diff --git a/sbuild/sbuild-chroot-fs-union.cc b/sbuild/sbuild-chroot-fs-union.cc
index 5f2b2f6..dd90dfd 100644
--- a/sbuild/sbuild-chroot-fs-union.cc
+++ b/sbuild/sbuild-chroot-fs-union.cc
@@ -1,4 +1,5 @@
 /* Copyright © 2008-2009  Jan-Marek Glogowski <glogow at fbihome.de>
+ * Copyright © 2009       Roger Leigh <rleigh at debian.org>
  *
  * schroot is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
@@ -52,7 +53,9 @@ error<chroot_fs_union::error_code>::error_strings
 
 chroot_fs_union::chroot_fs_union ():
   chroot_source(),
-  fs_union_type("none")
+  fs_union_type("none"),
+  fs_union_overlay_directory(SCHROOT_OVERLAY_DIR),
+  fs_union_underlay_directory(SCHROOT_UNDERLAY_DIR)
 {
 }
 
@@ -68,19 +71,35 @@ chroot_fs_union::get_fs_union_configured () const
 }
 
 std::string const&
-chroot_fs_union::get_overlay_session_directory () const
+chroot_fs_union::get_fs_union_overlay_directory () const
 {
-  return overlay_session_directory;
+  return fs_union_overlay_directory;
 }
 
 void
-chroot_fs_union::set_overlay_session_directory
-(std::string const& overlay_session_directory)
+chroot_fs_union::set_fs_union_overlay_directory
+(std::string const& directory)
 {
-  if (!is_absname(overlay_session_directory))
-    throw chroot::error(overlay_session_directory, chroot::LOCATION_ABS);
+  if (!is_absname(directory))
+    throw chroot::error(directory, chroot::LOCATION_ABS);
 
-  this->overlay_session_directory = overlay_session_directory;
+  fs_union_overlay_directory = directory;
+}
+
+std::string const&
+chroot_fs_union::get_fs_union_underlay_directory () const
+{
+  return fs_union_underlay_directory;
+}
+
+void
+chroot_fs_union::set_fs_union_underlay_directory
+(std::string const& directory)
+{
+  if (!is_absname(directory))
+    throw chroot::error(directory, chroot::LOCATION_ABS);
+
+  fs_union_underlay_directory = directory;
 }
 
 std::string const&
@@ -90,32 +109,27 @@ chroot_fs_union::get_fs_union_type () const
 }
 
 void
-chroot_fs_union::set_fs_union_type (std::string const& fs_union_type)
+chroot_fs_union::set_fs_union_type (std::string const& type)
 {
-  if ((fs_union_type == "aufs") || (fs_union_type == "unionfs"))
-    {
-      this->fs_union_type = fs_union_type;
-    }
+  if (type == "aufs" ||
+      type == "fs-unionfs" ||
+      type == "none")
+    fs_union_type = type;
   else
-    {
-      if (fs_union_type == "none")
-	this->fs_union_type = fs_union_type;
-      else
-	throw error(fs_union_type, FS_TYPE_UNKNOWN);
-    }
+    throw error(type, FS_TYPE_UNKNOWN);
 }
 
 std::string const&
-chroot_fs_union::get_fs_union_branch_config () const
+chroot_fs_union::get_fs_union_mount_options () const
 {
-  return fs_union_branch_config;
+  return fs_union_mount_options;
 }
 
 void
-chroot_fs_union::set_fs_union_branch_config
-(std::string const& fs_union_branch_config)
+chroot_fs_union::set_fs_union_mount_options
+(std::string const& union_mount_options)
 {
-  this->fs_union_branch_config = fs_union_branch_config;
+  fs_union_mount_options = union_mount_options;
 }
 
 void
@@ -126,23 +140,15 @@ chroot_fs_union::setup_env (environment& env)
   env.add("CHROOT_FS_UNION_TYPE", get_fs_union_type());
   if (get_fs_union_configured())
     {
+      env.add("CHROOT_FS_UNION_MOUNT_OPTIONS",
+	      get_fs_union_mount_options());
       env.add("CHROOT_FS_UNION_OVERLAY_DIRECTORY",
-        get_overlay_session_directory());
-      env.add("CHROOT_FS_UNION_BRANCH_CONFIG",
-        get_fs_union_branch_config());
+	      get_fs_union_overlay_directory());
+      env.add("CHROOT_FS_UNION_UNDERLAY_DIRECTORY",
+	      get_fs_union_underlay_directory());
     }
 }
 
-std::string
-chroot_fs_union::get_path() const
-{
-  /// @todo: Remove need for this by passing in group name
-  const chroot *base = dynamic_cast<const chroot *>(this);
-  assert(base != 0);
-
-  return base->get_mount_location();
-}
-
 chroot::session_flags
 chroot_fs_union::get_session_flags () const
 {
@@ -158,12 +164,15 @@ chroot_fs_union::get_details (format_detail& detail) const
 {
   chroot_source::get_details(detail);
 
-  if (!this->overlay_session_directory.empty())
+  if (!fs_union_mount_options.empty())
+    detail.add(_("Filesystem union mount options"),
+	       get_fs_union_mount_options());
+  if (!fs_union_overlay_directory.empty())
     detail.add(_("Filesystem union overlay directory"),
-      get_overlay_session_directory());
-  if (!this->fs_union_branch_config.empty())
-    detail.add(_("Filesystem union branch config"),
-      get_fs_union_branch_config());
+	       get_fs_union_overlay_directory());
+  if (!fs_union_underlay_directory.empty())
+    detail.add(_("Filesystem union underlay directory"),
+	       get_fs_union_underlay_directory());
 }
 
 void
@@ -180,15 +189,19 @@ chroot_fs_union::get_keyfile (keyfile& keyfile) const
 			    "fs-union-type");
 
   keyfile::set_object_value(*this,
-			    &chroot_fs_union::get_fs_union_branch_config,
+			    &chroot_fs_union::get_fs_union_mount_options,
+			    keyfile, base->get_keyfile_name(),
+			    "fs-union-mount-options");
+
+  keyfile::set_object_value(*this,
+			    &chroot_fs_union::get_fs_union_overlay_directory,
 			    keyfile, base->get_keyfile_name(),
-			    "fs-union-branch-config");
+			    "fs-union-overlay-directory");
 
-  if (base->get_active())
-    keyfile::set_object_value(*this,
-			      &chroot_fs_union::get_overlay_session_directory,
-			      keyfile, base->get_keyfile_name(),
-			      "fs-union-overlay-session-directory");
+  keyfile::set_object_value(*this,
+			    &chroot_fs_union::get_fs_union_underlay_directory,
+			    keyfile, base->get_keyfile_name(),
+			    "fs-union-underlay-directory");
 }
 
 void
@@ -207,20 +220,28 @@ chroot_fs_union::set_keyfile (keyfile const& keyfile,
   used_keys.push_back("fs-union-type");
 
   keyfile::get_object_value(*this,
-			    &chroot_fs_union::set_fs_union_branch_config,
+			    &chroot_fs_union::set_fs_union_mount_options,
+			    keyfile, base->get_keyfile_name(),
+			    "fs-union-mount-options",
+			    keyfile::PRIORITY_OPTIONAL);
+  used_keys.push_back("fs-union-mount-options");
+
+  keyfile::get_object_value(*this,
+			    &chroot_fs_union::set_fs_union_overlay_directory,
+			    keyfile, base->get_keyfile_name(),
+			    "fs-union-overlay-directory",
+			    (base->get_active() && get_fs_union_configured())?
+			    keyfile::PRIORITY_REQUIRED :
+			    keyfile::PRIORITY_OPTIONAL);
+  used_keys.push_back("fs-union-overlay-directory");
+
+  keyfile::get_object_value(*this,
+			    &chroot_fs_union::set_fs_union_underlay_directory,
 			    keyfile, base->get_keyfile_name(),
-			    "fs-union-branch-config",
+			    "fs-union-underlay-directory",
+			    (base->get_active() && get_fs_union_configured())?
+			    keyfile::PRIORITY_REQUIRED :
 			    keyfile::PRIORITY_OPTIONAL);
-  used_keys.push_back("fs-union-branch-config");
-
-  if (base->get_active())
-    keyfile::get_object_value(*this,
-			      &chroot_fs_union::set_overlay_session_directory,
-			      keyfile, base->get_keyfile_name(),
-			      "fs-union-overlay-session-directory",
-			      (get_fs_union_configured() ?
-			       keyfile::PRIORITY_REQUIRED :
-			       keyfile::PRIORITY_OPTIONAL));
-  used_keys.push_back("fs-union-overlay-session-directory");
+  used_keys.push_back("fs-union-underlay-directory");
 }
 
diff --git a/sbuild/sbuild-chroot-fs-union.h b/sbuild/sbuild-chroot-fs-union.h
index 495f307..aa49f0e 100644
--- a/sbuild/sbuild-chroot-fs-union.h
+++ b/sbuild/sbuild-chroot-fs-union.h
@@ -34,7 +34,7 @@ namespace sbuild
    * chroot_source::clone_source() function, depending on the
    * setting of get_fs_union_configured().
    */
-  class chroot_fs_union : public chroot_source
+  class chroot_fs_union : virtual public chroot_source
   {
   protected:
     /// The constructor.
@@ -62,67 +62,78 @@ namespace sbuild
     get_fs_union_configured () const;
 
     /**
-     * Get the union filesystem type.
+     * Get the union filesystem type
      *
      * @see set_fs_union_type
-     * @returns the union filesytem type.
+     * @returns the union filesytem type
      */
     virtual std::string const&
     get_fs_union_type () const;
 
     /**
-     * Get the union filesystem branch configuration.
+     * Set the union type.
      *
-     * @see set_fs_union_branch_config
-     * @returns the union filesystem branch configuration.
-     */
-    virtual std::string const&
-    get_fs_union_branch_config () const;
+     * Currently supported values are aufs, unionfs and none.
+     *
+     * @param union_type the union type.
+     **/
+    virtual void
+    set_fs_union_type (std::string const& union_type);
 
     /**
-     * Get the writeable overlay directory of the session.
+     * Get the union branch configuration.
      *
-     * @see set_overlay_session_directory
-     * @returns the writeable overlay directory.
+     * @see set_fs_union_mount_options
+     * @returns the union branch configuration.
      */
     virtual std::string const&
-    get_overlay_session_directory () const;
+    get_fs_union_mount_options () const;
 
     /**
-     * Set the union filesystem type.
+     * Set a complex branch configuration.
      *
-     * Currently supported values are aufs, unionfs and none.
+     * Normally a temporary directory is used as the writeable branch,
+     * which is removed on session end. This allows to build a complex
+     * union chroot which can merge multiple branches. The string has
+     * to be constructed as expected by the union filesystem type and
+     * is directly used as the mount '-o' option string.
      *
-     * @param fs_union_type the filesystem type.
+     * @param union_mount_options a @fs_type specific branch description
      **/
     virtual void
-    set_fs_union_type (std::string const& fs_union_type);
+    set_fs_union_mount_options (std::string const& union_mount_options);
 
     /**
-     * Set a complex branch configuration.
+     * Get the union overlay directory.
      *
-     * Normally a temporary directory is used as the writeable branch, which 
-     * is removed on session end. This allows to build a complex union chroot 
-     * which can merge multiple branches. The string has to be constructed as 
-     * expected by the union filesystem type and is directly used as the mount
-     * '-o' option string.
+     * @returns the writeable overlay directory.
+     */
+    virtual std::string const&
+    get_fs_union_overlay_directory () const;
+
+    /**
+     * Set the union overlay directory.
      *
-     * @param fs_union_branch_config a @fs_type specific branch description
-     **/
+     * @returns the writeable overlay directory.
+     */
     virtual void
-    set_fs_union_branch_config (std::string const& fs_union_branch_config);
+    set_fs_union_overlay_directory (std::string const& directory);
 
     /**
-     * Allows schrooot to set the session dependant overlay directory.
+     * Get the union underlay directory.
      *
-     * @param the absolute path of the overlay_session_directory.
-     **/
-    virtual void
-    set_overlay_session_directory 
-    (std::string const& overlay_session_directory);
+     * @returns the writeable underlay directory.
+     */
+    virtual std::string const&
+    get_fs_union_underlay_directory () const;
 
-    virtual std::string
-    get_path () const;
+    /**
+     * Set the union underlay directory.
+     *
+     * @returns the writeable underlay directory.
+     */
+    virtual void
+    set_fs_union_underlay_directory (std::string const& directory);
 
     virtual void
     setup_env (environment& env);
@@ -142,12 +153,14 @@ namespace sbuild
                  string_list&   used_keys);
 
   private:
-    /// Union filesystem type
+    /// Union filesystem type.
     std::string fs_union_type;
-    /// Complex branch configuration to pass directly as mount option
-    std::string fs_union_branch_config;
-    /// Writeable directory used as the overlay write branch
-    std::string overlay_session_directory;
+    /// Union mount options (branch configuration).
+    std::string fs_union_mount_options;
+    /// Union read-write overlay directory.
+    std::string fs_union_overlay_directory;
+    /// Union read-only underlay directory.
+    std::string fs_union_underlay_directory;
   };
 }
 
diff --git a/sbuild/sbuild-session.cc b/sbuild/sbuild-session.cc
index 8d46cc0..172251b 100644
--- a/sbuild/sbuild-session.cc
+++ b/sbuild/sbuild-session.cc
@@ -647,13 +647,16 @@ session::run_impl ()
 	    }
 #endif // SBUILD_FEATURE_LVMSNAP
 
-	  /* Filesystem unions need the overlay directory specifying. */
-	  chroot_fs_union *overlay = 0;
-	  if ((overlay = dynamic_cast<chroot_fs_union *>(chroot.get())) != 0)
+	  chroot_fs_union *fsunion;
+	  if ((fsunion = dynamic_cast<chroot_fs_union *>(chroot.get())) != 0)
 	    {
-	      std::string dir = SCHROOT_OVERLAY_DIR;
-              dir += "/" + this->session_id;
-	      overlay->set_overlay_session_directory(dir);
+	      std::string overlay = SCHROOT_OVERLAY_DIR;
+	      overlay += "/" + this->session_id;
+	      fsunion->set_fs_union_overlay_directory(overlay);
+
+	      std::string underlay = SCHROOT_UNDERLAY_DIR;
+	      underlay += "/" + this->session_id;
+	      fsunion->set_fs_union_underlay_directory(underlay);
 	    }
 
 	  try
diff --git a/test/sbuild-chroot-directory.cc b/test/sbuild-chroot-directory.cc
index 8748256..ab135bc 100644
--- a/test/sbuild-chroot-directory.cc
+++ b/test/sbuild-chroot-directory.cc
@@ -120,6 +120,8 @@ public:
     expected.add("CHROOT_PATH",           "/mnt/mount-location");
     expected.add("CHROOT_SCRIPT_CONFIG",  sbuild::normalname(std::string(PACKAGE_SYSCONF_DIR) + "/script-defaults"));
     expected.add("CHROOT_SESSION_CLONE",  "true");
+    expected.add("CHROOT_FS_UNION_OVERLAY_DIRECTORY",  SCHROOT_OVERLAY_DIR);
+    expected.add("CHROOT_FS_UNION_UNDERLAY_DIRECTORY", SCHROOT_UNDERLAY_DIR);
     expected.add("CHROOT_FS_UNION_TYPE",  "aufs");
 
     test_chroot_base<chroot_directory>::test_setup_env(expected);
-- 
1.6.3.2




More information about the Buildd-tools-devel mailing list