x86: preserve partition table on sysupgrade
authorJo-Philipp Wich <jow@openwrt.org>
Tue, 9 Feb 2016 12:33:17 +0000 (12:33 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Tue, 9 Feb 2016 12:33:17 +0000 (12:33 +0000)
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 <nyt-openwrt@countercultured.net>
SVN-Revision: 48682

package/base-files/files/lib/upgrade/common.sh
package/base-files/files/sbin/sysupgrade
target/linux/x86/Makefile
target/linux/x86/base-files/lib/upgrade/platform.sh

index f894f3155b51454da361068be574aa871dd88ddf..0383d253a3230423163be013401134817e066377 100644 (file)
@@ -68,6 +68,7 @@ run_ramfs() { # <command> [...]
        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
index 93f0749108ec7ae5c3d8f77c84a3cb95bf8a5ff6..2f441f868badb57ed70d67b15117c2bdd47cc137 100755 (executable)
@@ -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
index e4bc0d9a50b242a67be2bf0edb20f9d53d9334e8..45bb8c7cac25a5f3565fbd0c36a893300bdcda02 100644 (file)
@@ -13,6 +13,8 @@ FEATURES:=squashfs ext4 vdi vmdk pcmcia targz
 SUBTARGETS=generic xen_domu ep80579 geode kvm_guest 64
 MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
 
+DEFAULT_PACKAGES += partx-utils
+
 KERNEL_PATCHVER:=4.4
 
 KERNELNAME:=bzImage
index 73ab5ef0794c942495d18865fa2c2498b84e63e6..86696aec04de272019f5e16d931b6cd84aeb4d36 100644 (file)
@@ -55,12 +55,59 @@ platform_copy_config() {
        fi
 }
 
+get_partitions() { # <device> <filename>
+       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
 }