mirror of
https://github.com/flatcar/scripts.git
synced 2025-09-23 06:31:18 +02:00
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>
This commit is contained in:
parent
23301afb5f
commit
286b5928c8
30
common.sh
30
common.sh
@ -378,6 +378,36 @@ function sudo_append() {
|
||||
sudo tee -a "$1" > /dev/null
|
||||
}
|
||||
|
||||
# Execute multiple commands in a single sudo. Generally will speed things
|
||||
# up by avoiding multiple calls to `sudo`. If any commands fail, we will
|
||||
# call die with the failing command. We can handle a max of ~100 commands,
|
||||
# but hopefully no one will ever try that many at once.
|
||||
#
|
||||
# $@ - The commands to execute, one per arg.
|
||||
function sudo_multi() {
|
||||
local i cmds
|
||||
|
||||
# Construct the shell code to execute. It'll be of the form:
|
||||
# ... && ( ( command ) || exit <command index> ) && ...
|
||||
# This way we know which command exited. The exit status of
|
||||
# the underlying command is lost, but we never cared about it
|
||||
# in the first place (other than it is non zero), so oh well.
|
||||
for (( i = 1; i <= $#; ++i )); do
|
||||
cmds+=" && ( ( ${!i} ) || exit $(( i + 10 )) )"
|
||||
done
|
||||
|
||||
# Execute our constructed shell code.
|
||||
sudo -- sh -c ":${cmds[*]}" && i=0 || i=$?
|
||||
|
||||
# See if this failed, and if so, print out the failing command.
|
||||
if [[ $i -gt 10 ]]; then
|
||||
: $(( i -= 10 ))
|
||||
die "sudo_multi failed: ${!i}"
|
||||
elif [[ $i -ne 0 ]]; then
|
||||
die "sudo_multi failed for unknown reason $i"
|
||||
fi
|
||||
}
|
||||
|
||||
# Locate all mounts below a specified directory.
|
||||
#
|
||||
# $1 - The root tree.
|
||||
|
@ -87,13 +87,16 @@ SYNCERPIDFILE="${FLAGS_chroot}/var/tmp/enter_chroot_sync.pid"
|
||||
|
||||
|
||||
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 @@ function ensure_mounted {
|
||||
# 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 @@ function setup_env {
|
||||
|
||||
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 @@ function setup_env {
|
||||
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 @@ function setup_env {
|
||||
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 @@ function setup_env {
|
||||
# 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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user