Skip to content

Commit

Permalink
base-files: sysupgrade: always setup overlay when creating backup
Browse files Browse the repository at this point in the history
Setting overlay while creating backup allows including extra files in
archive without actually writing them to flash. Right now this feature
is limited to /etc/backup/ directory and is used only for including
installed_packages.txt.

Extend this solution to make it more generic:
1. Always mount overlay while creating backup
2. Overlay whole / to don't limit it to /etc/backup/

This allows including any additional files in backups and adding more
sysupgrade features.

Cc: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Cc: Christian Marangi <ansuelsmth@gmail.com>
Cc: Jo-Philipp Wich <jo@mein.io>
Cc: Jonas Gorski <jonas.gorski@gmail.com>
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
  • Loading branch information
Rafał Miłecki committed Feb 19, 2024
1 parent 700907b commit 4fa9aaf
Showing 1 changed file with 20 additions and 16 deletions.
36 changes: 20 additions & 16 deletions package/base-files/files/sbin/sysupgrade
Expand Up @@ -24,7 +24,6 @@ export NEED_IMAGE=
export HELP=0
export FORCE=0
export TEST=0
export UMOUNT_ETCBACKUP_DIR=0

# parse options
while [ -n "$1" ]; do
Expand Down Expand Up @@ -224,6 +223,8 @@ include /lib/upgrade

do_save_conffiles() {
local conf_tar="$1"
local tmp
local dir

[ "$(rootfs_type)" = "tmpfs" ] && {
echo "Cannot save config while running from ramdisk." >&2
Expand All @@ -234,41 +235,44 @@ do_save_conffiles() {
run_hooks "$CONFFILES" $sysupgrade_init_conffiles
ask_bool 0 "Edit config file list" && vi "$CONFFILES"

# Mount root directory with temporary overlay on top of it.
# This allows including extra (temporary) files in backup archive
# without messing actual rootfs.
tmp="$(mktemp -d -t overlay.XXXXXX)"
mkdir -p "$tmp/upper" "$tmp/work" "$tmp/backup"
dir="$tmp/backup"
if ! mount -t overlay overlay -o lowerdir=/,upperdir="$tmp/upper",workdir="$tmp/work" "$dir"; then
echo "Cannot mount backup overlay to $dir." >&2
ask_bool 0 "Abort" && exit
dir=""
fi

if [ "$SAVE_INSTALLED_PKGS" -eq 1 ]; then
echo "${INSTALLED_PACKAGES}" >> "$CONFFILES"
mkdir -p "$ETCBACKUP_DIR"
# Avoid touching filesystem on each backup
RAMFS="$(mktemp -d -t sysupgrade.XXXXXX)"
mkdir -p "$RAMFS/upper" "$RAMFS/work"
mount -t overlay overlay -o lowerdir=$ETCBACKUP_DIR,upperdir=$RAMFS/upper,workdir=$RAMFS/work $ETCBACKUP_DIR &&
UMOUNT_ETCBACKUP_DIR=1 || {
echo "Cannot mount '$ETCBACKUP_DIR' as tmpfs to avoid touching disk while saving the list of installed packages." >&2
ask_bool 0 "Abort" && exit
}
mkdir -p "$dir/$ETCBACKUP_DIR"

# Format: pkg-name<TAB>{rom,overlay,unkown}
# rom is used for pkgs in /rom, even if updated later
find /usr/lib/opkg/info -name "*.control" \( \
\( -exec test -f /rom/{} \; -exec echo {} rom \; \) -o \
\( -exec test -f /overlay/upper/{} \; -exec echo {} overlay \; \) -o \
\( -exec echo {} unknown \; \) \
\) | sed -e 's,.*/,,;s/\.control /\t/' > ${INSTALLED_PACKAGES}
\) | sed -e 's,.*/,,;s/\.control /\t/' > "$dir/${INSTALLED_PACKAGES}"
fi

v "Saving config files..."
[ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
sed -i -e 's,^/,,' "$CONFFILES"
tar c${TAR_V}zf "$conf_tar" -C / -T "$CONFFILES"
tar c${TAR_V}zf "$conf_tar" -C "${dir:-/}" -T "$CONFFILES"
local err=$?
if [ "$err" -ne 0 ]; then
echo "Failed to create the configuration backup."
rm -f "$conf_tar"
fi

[ "$UMOUNT_ETCBACKUP_DIR" -eq 1 ] && {
umount "$ETCBACKUP_DIR"
rm -rf "$RAMFS"
}
umount "$dir"
rm -rf "$tmp"

rm -f "$CONFFILES"

return "$err"
Expand Down

1 comment on commit 4fa9aaf

@luizluca
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit breaks the backup of files outside the root filesystem (see 14ac91c#commitcomment-138828645).

Overlay does not seem (by design) to be following mounted filesystems in lowerdir. I did a quick check and I couldn't an option to change that behavior. You need to mount a new overlay for each mounted filesystems into the backup rootfs to get access to those files (and unmount them afterwards).

Another option is to focus on a solution just to protect the directory you actually need to change. For example, we can overlay the directories we actually need to change (/etc/backup, /etc/uci-defaults), exclude them from rootfs backup and append the overlay-etc backup content. If we include the whole /etc/, it might still suffer the same issue if someone mounted a different filesystem there.

Please sign in to comment.