enter_chroot: merge multiple mount requests into a single sudo
Every invocation of `sudo` delays things, so merge all of the mounts
into a single `sudo` command when possible. This saves over 1 second
on initial execution (out of ~4 seconds total).
BUG=None
TEST=`cros_sdk --enter true` still mounts & unmounts properly
Change-Id: Ibc66507dc21250a81207d2f940645eaebe93c79c
Reviewed-on: https://gerrit.chromium.org/gerrit/10901
Reviewed-by: David James <davidjames@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
Commit-Ready: Mike Frysinger <vapier@chromium.org>
diff --git a/sdk_lib/enter_chroot.sh b/sdk_lib/enter_chroot.sh
index 377e565..26df65b 100755
--- a/sdk_lib/enter_chroot.sh
+++ b/sdk_lib/enter_chroot.sh
@@ -87,13 +87,16 @@
MOUNTED_PATH=$(readlink -f "$FLAGS_chroot")
-function ensure_mounted {
+function mount_queue_init {
+ MOUNT_QUEUE=()
+}
+
+function queue_mount {
# If necessary, mount $source in the host FS at $target inside the
# chroot directory with $mount_args.
local source="$1"
local mount_args="$2"
local target="$3"
- local warn="$4"
local mounted_path="${MOUNTED_PATH}$target"
@@ -102,29 +105,23 @@
# Already mounted!
;;
*)
- # Attempt to make the mountpoint as the user. This depends on the
- # fact that all mountpoints that should be owned by root are
- # already present. However, when distributions add new paths (such as
- # Ubuntu 11.10's /run), it might not yet exist in the chroot. If that
- # happens, just create it as root.
- if ! mkdir -p "${mounted_path}" 2>/dev/null; then
- sudo mkdir -p "${mounted_path}"
- fi
-
- # NB: mount_args deliberately left unquoted
- debug mount ${mount_args} "${source}" "${mounted_path}"
- if ! sudo -- mount ${mount_args} "${source}" "${mounted_path}" ; then
- if [ -z "${warn}" ]; then
- die "Could not mount ${source} on ${mounted_path}"
- else
- warn "Failed to mount ${source}; perhaps it's on NFS?"
- warn "${warn}"
- fi
- fi
+ MOUNT_QUEUE+=(
+ "mkdir -p '${mounted_path}'"
+ # The args are left unquoted on purpose.
+ "mount ${mount_args} '${source}' '${mounted_path}'"
+ )
;;
esac
}
+function process_mounts {
+ if [[ ${#MOUNT_QUEUE[@]} -eq 0 ]]; then
+ return 0
+ fi
+ sudo_multi "${MOUNT_QUEUE[@]}"
+ mount_queue_init
+}
+
function env_sync_proc {
# This function runs and performs periodic updates to the chroot env, if
# necessary.
@@ -238,17 +235,18 @@
debug "Mounting chroot environment."
MOUNT_CACHE=$(mount)
- ensure_mounted none "-t proc" /proc
- ensure_mounted none "-t sysfs" /sys
- ensure_mounted /dev "--bind" /dev
- ensure_mounted none "-t devpts" /dev/pts
+ mount_queue_init
+ queue_mount none "-t proc" /proc
+ queue_mount none "-t sysfs" /sys
+ queue_mount /dev "--bind" /dev
+ queue_mount none "-t devpts" /dev/pts
if [ -d /run ]; then
- ensure_mounted /run "--bind" /run
+ queue_mount /run "--bind" /run
if [ -d /run/shm ]; then
- ensure_mounted /run/shm "--bind" /run/shm
+ queue_mount /run/shm "--bind" /run/shm
fi
fi
- ensure_mounted "${FLAGS_trunk}" "--bind" "${CHROOT_TRUNK_DIR}"
+ queue_mount "${FLAGS_trunk}" "--bind" "${CHROOT_TRUNK_DIR}"
if [ $FLAGS_ssh_agent -eq $FLAGS_TRUE ]; then
if [ -n "${SSH_AUTH_SOCK}" -a -d "${HOME}/.ssh" ]; then
@@ -258,10 +256,24 @@
cp "${HOME}"/.ssh/{known_hosts,*.pub} "${TARGET_DIR}/" 2>/dev/null || :
copy_ssh_config "${TARGET_DIR}"
ASOCK=${SSH_AUTH_SOCK%/*}
- ensure_mounted "${ASOCK}" "--bind" "${ASOCK}"
+ queue_mount "${ASOCK}" "--bind" "${ASOCK}"
fi
fi
+ if [ -d "$HOME/.subversion" ]; then
+ TARGET="/home/${USER}/.subversion"
+ mkdir -p "${FLAGS_chroot}${TARGET}"
+ queue_mount "${HOME}/.subversion" "--bind" "${TARGET}"
+ fi
+
+ if DEPOT_TOOLS=$(type -P gclient) ; then
+ DEPOT_TOOLS=${DEPOT_TOOLS%/*} # dirname
+ debug "Mounting depot_tools"
+ queue_mount "$DEPOT_TOOLS" --bind "$INNER_DEPOT_TOOLS_ROOT"
+ fi
+
+ process_mounts
+
CHROME_ROOT="$(readlink -f "$FLAGS_chrome_root" || :)"
if [ -z "$CHROME_ROOT" ]; then
CHROME_ROOT="$(cat "${FLAGS_chroot}${CHROME_ROOT_CONFIG}" \
@@ -279,16 +291,11 @@
debug "Mounting chrome source at: $INNER_CHROME_ROOT"
sudo bash -c "echo '$CHROME_ROOT' > \
'${FLAGS_chroot}${CHROME_ROOT_CONFIG}'"
- ensure_mounted "$CHROME_ROOT" --bind "$INNER_CHROME_ROOT"
+ queue_mount "$CHROME_ROOT" --bind "$INNER_CHROME_ROOT"
fi
fi
- if DEPOT_TOOLS=$(type -P gclient) ; then
- DEPOT_TOOLS=${DEPOT_TOOLS%/*} # dirname
- debug "Mounting depot_tools"
- ensure_mounted "$DEPOT_TOOLS" --bind "$INNER_DEPOT_TOOLS_ROOT" \
- "This may impact chromium build."
- fi
+ process_mounts
# Install fuse module. Skip modprobe when possible for slight
# speed increase when initializing the env.
@@ -313,12 +320,6 @@
# Always write the temp file so we can read it when exiting
echo "${SAVED_PREF:-false}" > "${FLAGS_chroot}${SAVED_AUTOMOUNT_PREF_FILE}"
- if [ -d "$HOME/.subversion" ]; then
- TARGET="/home/${USER}/.subversion"
- mkdir -p "${FLAGS_chroot}${TARGET}"
- ensure_mounted "${HOME}/.subversion" "--bind" "${TARGET}"
- fi
-
# Configure committer username and email in chroot .gitconfig. Change
# to the root directory first so that random $PWD/.git/config settings
# do not get picked up. We want to stick to ~/.gitconfig only.