From 793d096a61b97334a2e9c3ac62077c7926ef41cf Mon Sep 17 00:00:00 2001
From: Petr Pavlu <petr.pavlu@suse.com>
Date: Thu, 12 Sep 2019 09:24:13 +0200
Subject: [PATCH] Improve handling of partition label type for multipath disks

When recording information about a multipath disk, ReaR did not store
information about its partition label type (280_multipath_layout.sh).
The recovery code create_multipath() (210_load_multipath.sh) ->
create_partitions() (100_include_partition_code.sh) then tried to
automatically detect the label type using a heuristic that depends on
GPT partition names. The logic would incorrectly detect the device as
having the MBR label type instead of GPT if one of the partition names
was exactly "primary", "extended" or "logical".

The patch fixes the problem by explicitly storing the partition label
type for multipath devices as is already done for normal disks. The
restore logic is accordingly updated to utilize this information.

Fixes #2234.
---
 doc/user-guide/06-layout-configuration.adoc                     | 5 +++++
 usr/share/rear/layout/prepare/GNU/Linux/210_load_multipath.sh   | 7 ++++---
 usr/share/rear/layout/prepare/default/520_exclude_components.sh | 2 +-
 usr/share/rear/layout/save/GNU/Linux/280_multipath_layout.sh    | 6 +++++-
 usr/share/rear/layout/save/default/320_autoexclude.sh           | 2 +-
 usr/share/rear/lib/layout-functions.sh                          | 2 +-
 6 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/doc/user-guide/06-layout-configuration.adoc b/doc/user-guide/06-layout-configuration.adoc
index 0798ed99..4758e5d8 100644
--- a/doc/user-guide/06-layout-configuration.adoc
+++ b/doc/user-guide/06-layout-configuration.adoc
@@ -598,6 +598,11 @@ part <disk name> <size(B)> <start(B)> <partition name/type> <flags/"none"> <part
 raid /dev/<name> level=<RAID level> raid-devices=<nr of devices> [uuid=<uuid>] [spare-devices=<nr of spares>] [layout=<RAID layout>] [chunk=<chunk size>] devices=<device1,device2,...>
 ----------------------------------
 
+=== Multipath ===
+----------------------------------
+multipath /dev/<name> <size(B)> <partition label> <slave1,slave2,...>
+----------------------------------
+
 === Physical Volumes ===
 ----------------------------------
 lvmdev /dev/<volume group name> <device> <UUID> [<size(K)>]
diff --git a/usr/share/rear/layout/prepare/GNU/Linux/210_load_multipath.sh b/usr/share/rear/layout/prepare/GNU/Linux/210_load_multipath.sh
index 3c91c3be..c1057fbb 100644
--- a/usr/share/rear/layout/prepare/GNU/Linux/210_load_multipath.sh
+++ b/usr/share/rear/layout/prepare/GNU/Linux/210_load_multipath.sh
@@ -111,9 +111,10 @@ fi
 
 ### Create multipath devices (at least partitions on them).
 function create_multipath() {
-    local device=$1
-    if grep "^multipath $device " "$LAYOUT_FILE" 1>&2 ; then
+    local component device size label junk
+    read component device size label junk < <(grep "^multipath $1 " "$LAYOUT_FILE")
+    if [[ "$device" ]]; then
         Log "Found current or former multipath device $device in $LAYOUT_FILE: Creating partitions on it"
-        create_partitions "$device"
+        create_partitions "$device" "$label"
     fi
 }
diff --git a/usr/share/rear/layout/prepare/default/520_exclude_components.sh b/usr/share/rear/layout/prepare/default/520_exclude_components.sh
index 553d00ac..3b5e6437 100644
--- a/usr/share/rear/layout/prepare/default/520_exclude_components.sh
+++ b/usr/share/rear/layout/prepare/default/520_exclude_components.sh
@@ -7,7 +7,7 @@ for component in "${EXCLUDE_RECREATE[@]}" ; do
 done
 
 ### Make sure we have all dependencies for multipath devices in place.
-while read multipath device dm_size slaves junk ; do
+while read multipath device dm_size label slaves junk ; do
     local -a devices=()
 
     OIFS=$IFS
diff --git a/usr/share/rear/layout/save/GNU/Linux/280_multipath_layout.sh b/usr/share/rear/layout/save/GNU/Linux/280_multipath_layout.sh
index 2bc95920..8a03ad07 100644
--- a/usr/share/rear/layout/save/GNU/Linux/280_multipath_layout.sh
+++ b/usr/share/rear/layout/save/GNU/Linux/280_multipath_layout.sh
@@ -23,7 +23,11 @@ while read dm_name junk ; do
         slaves="$slaves$(get_device_name ${slave##*/}),"
     done
 
-    echo "multipath /dev/mapper/$dm_name $dm_size ${slaves%,}" >> $DISKLAYOUT_FILE
+    dm_disktype=$(parted -s $dev_name print | grep -E "Partition Table|Disk label" | cut -d ":" -f "2" | tr -d " ")
+
+    echo "# Multipath /dev/mapper/$dm_name" >> $DISKLAYOUT_FILE
+    echo "# Format: multipath <devname> <size(bytes)> <partition label type> <slaves>" >> $DISKLAYOUT_FILE
+    echo "multipath /dev/mapper/$dm_name $dm_size $dm_disktype ${slaves%,}" >> $DISKLAYOUT_FILE
 
     extract_partitions "/dev/mapper/$dm_name" >> $DISKLAYOUT_FILE
 done < <( dmsetup ls --target multipath )
diff --git a/usr/share/rear/layout/save/default/320_autoexclude.sh b/usr/share/rear/layout/save/default/320_autoexclude.sh
index 9fb2888d..3031ce2b 100644
--- a/usr/share/rear/layout/save/default/320_autoexclude.sh
+++ b/usr/share/rear/layout/save/default/320_autoexclude.sh
@@ -97,7 +97,7 @@ if is_true "$AUTOEXCLUDE_DISKS" ; then
 fi
 
 ### Prevent partitioning of the underlying devices on multipath
-while read multipath device dm_size slaves junk ; do
+while read multipath device dm_size label slaves junk ; do
     local -a devices=()
 
     OIFS=$IFS
diff --git a/usr/share/rear/lib/layout-functions.sh b/usr/share/rear/lib/layout-functions.sh
index 6180e3b3..3b3f5839 100644
--- a/usr/share/rear/lib/layout-functions.sh
+++ b/usr/share/rear/lib/layout-functions.sh
@@ -187,7 +187,7 @@ generate_layout_dependencies() {
                 ;;
             multipath)
                 name=$(echo "$remainder" | cut -d " " -f "1")
-                disks=$(echo "$remainder" | cut -d " " -f "3" | tr "," " ")
+                disks=$(echo "$remainder" | cut -d " " -f "4" | tr "," " ")
 
                 add_component "$name" "multipath"
 
-- 
2.16.4

