From: Jo-Philipp Wich Date: Tue, 9 Feb 2016 12:33:17 +0000 Subject: x86: preserve partition table on sysupgrade With this patch sysupgrade will write directly to the partitions instead of to the main disk. The UUID is copied from the image to the MBR as well. This prevents the mbr from being completely overwritten and losing the partition table. The -p option has been added to maintain the original behavior and overwite the entire disk with the new image. Tests have been added to ensure that the image partitions match up with the active partitions. Signed-off-by: Rob Mosher Backport of OpenWrt r48682 diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh index 761b4c17957e2cf63b88025520b6fba59c890255..dc865544f65c16399dcced55b8b09c671b31b5d1 100644 --- a/package/base-files/files/lib/upgrade/common.sh +++ b/package/base-files/files/lib/upgrade/common.sh @@ -67,6 +67,7 @@ run_ramfs() { # [...] install_bin /usr/sbin/ubirsvol install_bin /usr/sbin/ubirmvol install_bin /usr/sbin/ubimkvol + install_bin /usr/sbin/partx for file in $RAMFS_COPY_BIN; do install_bin ${file//:/ } done diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade index ef83c4b00f1a88ae5d68fc70adf51a6af3dc109c..759c841e131a415c8009995c372cce1f55fb78a0 100755 --- a/package/base-files/files/sbin/sysupgrade +++ b/package/base-files/files/sbin/sysupgrade @@ -10,6 +10,7 @@ export INTERACTIVE=0 export VERBOSE=1 export SAVE_CONFIG=1 export SAVE_OVERLAY=0 +export SAVE_PARTITIONS=1 export DELAY= export CONF_IMAGE= export CONF_BACKUP_LIST=0 @@ -29,6 +30,7 @@ while [ -n "$1" ]; do -q) export VERBOSE="$(($VERBOSE - 1))";; -n) export SAVE_CONFIG=0;; -c) export SAVE_OVERLAY=1;; + -p) export SAVE_PARTITIONS=0;; -b|--create-backup) export CONF_BACKUP="$2" NEED_IMAGE=1; shift;; -r|--restore-backup) export CONF_RESTORE="$2" NEED_IMAGE=1; shift;; -l|--list-backup) export CONF_BACKUP_LIST=1; break;; @@ -62,6 +64,7 @@ upgrade-option: -i interactive mode -c attempt to preserve all changed files in /etc/ -n do not save configuration over reflash + -p do not attempt to restore the partition table after flash. -T | --test Verify image and config .tar.gz but do not actually flash. -F | --force diff --git a/target/linux/x86/Makefile b/target/linux/x86/Makefile index ba733c02480b248aa95331da2bcd8fee3e25f812..29a232296a02b253344927a61eecb40503473d59 100644 --- a/target/linux/x86/Makefile +++ b/target/linux/x86/Makefile @@ -13,6 +13,8 @@ FEATURES:=squashfs ext4 vdi vmdk pcmcia targz SUBTARGETS=generic xen_domu ep80579 geode kvm_guest rdc 64 MAINTAINER:=Felix Fietkau +DEFAULT_PACKAGES += partx-utils + KERNEL_PATCHVER:=3.18 KERNELNAME:=bzImage diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh index adc119c897ed840aef17c2041a48244d0922564e..c21f1a7e5feba553110f138c14977daaa472da70 100644 --- a/target/linux/x86/base-files/lib/upgrade/platform.sh +++ b/target/linux/x86/base-files/lib/upgrade/platform.sh @@ -55,12 +55,59 @@ platform_copy_config() { fi } +get_partitions() { # + local disk="$1" + local filename="$2" + + if [ -b "$disk" -o -f "$disk" ]; then + echo "Reading partition table from $filename..." + partx -r "$disk" -gbo NR,START,SECTORS > "/tmp/partx.$filename" + fi +} + platform_do_upgrade() { platform_export_bootpart + disk="${BOOTPART%[0-9]}" - if [ -b "${BOOTPART%[0-9]}" ]; then + if [ -b "$disk" ]; then sync - get_image "$@" | dd of="${BOOTPART%[0-9]}" bs=4096 conv=fsync + if [ "$SAVE_PARTITIONS" = "1" ]; then + get_partitions "$disk" bootdisk + + + #get block size + sectors="$(partx -r $disk -gbo SECTORS --nr 1:1)" + size="$(partx -r $disk -gbo SIZE --nr 1:1)" + ibs="$(($size / $sectors))" + + #extract the boot sector from the image + get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b + + get_partitions /tmp/image.bs image + + #compare tables + diff="$(grep -F -x -v -f /tmp/partx.bootdisk /tmp/partx.image)" + if [ -n "$diff" ]; then + echo "Partition layout is changed. Full image will be written." + ask_bool 0 "Abort" && exit + + get_image "$@" | dd of="$disk" bs=4096 conv=fsync + return 0 + fi + + #iterate over each partition from the image and write it to the boot disk + while read part start size; do + echo "Writing image to $disk$part..." + get_image "$@" | dd of="$disk$part" ibs="$ibs" obs=1M skip="$start" count="$size" conv=fsync + done < /tmp/partx.image + + #copy partition uuid + echo "Writing new UUID to $disk$part..." + get_image "$@" | dd of="$disk" bs=1 skip=440 count=4 seek=440 conv=fsync + else + get_image "$@" | dd of="$disk" bs=4096 conv=fsync + fi + sleep 1 fi }