parent
c2068dfc11
commit
7e93c69a0c
@ -0,0 +1,102 @@
|
|||||||
|
From e7b84271536782fbc8673ef4573e155e1dfa850e Mon Sep 17 00:00:00 2001
|
||||||
|
From: pcahyna <pcahyna@users.noreply.github.com>
|
||||||
|
Date: Wed, 1 Nov 2023 12:53:33 +0100
|
||||||
|
Subject: [PATCH] Merge pull request #3061 from
|
||||||
|
pcahyna/save-lvm-poolmetadatasize
|
||||||
|
|
||||||
|
Save LVM pool metadata volume size in disk layout
|
||||||
|
---
|
||||||
|
.../layout/save/GNU/Linux/220_lvm_layout.sh | 39 ++++++++++++-------
|
||||||
|
1 file changed, 24 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh
|
||||||
|
index f21845df9..42f0e4126 100644
|
||||||
|
--- a/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh
|
||||||
|
+++ b/usr/share/rear/layout/save/GNU/Linux/220_lvm_layout.sh
|
||||||
|
@@ -18,7 +18,7 @@ local already_processed_lvs=()
|
||||||
|
local lv_layout_supported lvs_fields
|
||||||
|
local origin lv vg
|
||||||
|
local layout modules
|
||||||
|
-local thinpool chunksize stripes stripesize segmentsize
|
||||||
|
+local thinpool chunksize stripes stripesize segmentsize poolmetadatasize
|
||||||
|
local kval infokval
|
||||||
|
local lvs_exit_code
|
||||||
|
|
||||||
|
@@ -130,7 +130,7 @@ local lvs_exit_code
|
||||||
|
echo "# Skipping PV $pdev that is not part of a valid VG (VG '$vgrp' empty or more than one word):"
|
||||||
|
contains_visible_char "$vgrp" || vgrp='<missing_VG>'
|
||||||
|
echo "# lvmdev /dev/$vgrp $pdev $uuid $size"
|
||||||
|
- # Continue with the next line in the output of "lvm pvdisplay -c"
|
||||||
|
+ # Continue with the next line in the output of "lvm pvdisplay -C"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# With the above example the output is:
|
||||||
|
@@ -138,10 +138,10 @@ local lvs_exit_code
|
||||||
|
echo "lvmdev /dev/$vgrp $pdev $uuid $size"
|
||||||
|
|
||||||
|
done
|
||||||
|
- # Check the exit code of "lvm pvdisplay -c"
|
||||||
|
- # in the "lvm pvdisplay -c | while read line ; do ... done" pipe:
|
||||||
|
+ # Check the exit code of "lvm pvdisplay -C"
|
||||||
|
+ # in the "lvm pvdisplay -C ... | while read line ; do ... done" pipe:
|
||||||
|
pvdisplay_exit_code=${PIPESTATUS[0]}
|
||||||
|
- test $pvdisplay_exit_code -eq 0 || Error "LVM command 'lvm pvdisplay -c' failed with exit code $pvdisplay_exit_code"
|
||||||
|
+ test $pvdisplay_exit_code -eq 0 || Error "LVM command 'lvm pvdisplay -C ... -o pv_name,vg_name,pv_size,pv_uuid' failed with exit code $pvdisplay_exit_code"
|
||||||
|
|
||||||
|
# Get the volume group configuration:
|
||||||
|
# Format: lvmgrp <volume_group> <extentsize> [<size(extents)>] [<size(bytes)>]
|
||||||
|
@@ -200,17 +200,17 @@ local lvs_exit_code
|
||||||
|
|
||||||
|
# Specify the fields for the lvs command depending on whether or not the 'lv_layout' field is supported:
|
||||||
|
if is_true $lv_layout_supported ; then
|
||||||
|
- lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size"
|
||||||
|
+ lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size,lv_metadata_size"
|
||||||
|
else
|
||||||
|
# Use the 'modules' field as fallback replacement when the 'lv_layout' field is not supported:
|
||||||
|
- lvs_fields="origin,lv_name,vg_name,lv_size,modules,pool_lv,chunk_size,stripes,stripe_size,seg_size"
|
||||||
|
+ lvs_fields="origin,lv_name,vg_name,lv_size,modules,pool_lv,chunk_size,stripes,stripe_size,seg_size,lv_metadata_size"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Example output of "lvs --separator=':' --noheadings --units b --nosuffix -o $lvs_fields"
|
||||||
|
- # with lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size"
|
||||||
|
+ # with lvs_fields="origin,lv_name,vg_name,lv_size,lv_layout,pool_lv,chunk_size,stripes,stripe_size,seg_size,lv_metadata_size"
|
||||||
|
# i.e. when the 'lv_layout' field is supported:
|
||||||
|
- # :root:system:19927138304:linear::0:1:0:19927138304
|
||||||
|
- # :swap:system:1535115264:linear::0:1:0:1535115264
|
||||||
|
+ # :root:system:19927138304:linear::0:1:0:19927138304:
|
||||||
|
+ # :swap:system:1535115264:linear::0:1:0:1535115264:
|
||||||
|
# There are two leading blanks in the output (at least on SLES12-SP4 with LVM 2.02.180).
|
||||||
|
lvm lvs --separator=':' --noheadings --units b --nosuffix -o $lvs_fields | while read line ; do
|
||||||
|
|
||||||
|
@@ -261,14 +261,23 @@ local lvs_exit_code
|
||||||
|
# With the above example segmentsize=19927138304 and segmentsize=1535115264
|
||||||
|
segmentsize="$( echo "$line" | awk -F ':' '{ print $10 }' )"
|
||||||
|
|
||||||
|
- # TODO: Explain what that code is meant to do.
|
||||||
|
- # In particular a more explanatory variable name than 'kval' might help.
|
||||||
|
- # In 110_include_lvm_code.sh there is a comment what 'kval' means there
|
||||||
|
- # # kval: "key:value" pairs, separated by spaces
|
||||||
|
- # so probably 'kval' means the same here, but what is 'infokval'?
|
||||||
|
+ # With the above example poolmetadatasize=""
|
||||||
|
+ poolmetadatasize="$( echo "$line" | awk -F ':' '{ print $11 }' )"
|
||||||
|
+
|
||||||
|
+ # kval is a string of space-separated key:value pairs. Key names are chosen to represent
|
||||||
|
+ # long options to lvcreate, and value will be the parameter for each long option.
|
||||||
|
+ # e.g. "chunksize:${chunksize}b" will eventually become a --chunksize=${chunksize}b
|
||||||
|
+ # argument to lvcreate.
|
||||||
|
+ # This way 110_include_lvm_code.sh which constructs the arguments to lvcreate
|
||||||
|
+ # can be kept generic and does not need to be updated every time an argument is added,
|
||||||
|
+ # as long as the argument can follow this generic scheme.
|
||||||
|
+ # infokval are key:value pairs that are not used when restoring the layout
|
||||||
|
+ # and are kept in disklayout.conf only as comments for information
|
||||||
|
+ # (because the setting is not easy or desirable to preserve).
|
||||||
|
kval=""
|
||||||
|
infokval=""
|
||||||
|
[ -z "$thinpool" ] || kval="${kval:+$kval }thinpool:$thinpool"
|
||||||
|
+ [ -z "$poolmetadatasize" ] || kval="${kval:+$kval }poolmetadatasize:${poolmetadatasize}b"
|
||||||
|
[ $chunksize -eq 0 ] || kval="${kval:+$kval }chunksize:${chunksize}b"
|
||||||
|
[ $stripesize -eq 0 ] || kval="${kval:+$kval }stripesize:${stripesize}b"
|
||||||
|
[ $segmentsize -eq $size ] || infokval="${infokval:+$infokval }segmentsize:${segmentsize}b"
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,85 @@
|
|||||||
|
diff --git a/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh b/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh
|
||||||
|
index d57077791..87ab5d691 100644
|
||||||
|
--- a/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh
|
||||||
|
+++ b/usr/share/rear/layout/prepare/GNU/Linux/133_include_mount_filesystem_code.sh
|
||||||
|
@@ -29,6 +29,7 @@ mount_fs() {
|
||||||
|
case $name in
|
||||||
|
(options)
|
||||||
|
# Do not mount nodev, as chrooting later on would fail:
|
||||||
|
+ # FIXME: naive approach, will replace any "nodev" inside longer options/values
|
||||||
|
value=${value//nodev/dev}
|
||||||
|
# btrfs mount options like subvolid=259 or subvol=/@/.snapshots/1/snapshot
|
||||||
|
# from the old system cannot work here for recovery because btrfs subvolumes
|
||||||
|
@@ -147,6 +148,27 @@ mount_fs() {
|
||||||
|
echo "mount $mountopts,remount,user_xattr $device $TARGET_FS_ROOT$mountpoint"
|
||||||
|
) >> "$LAYOUT_CODE"
|
||||||
|
;;
|
||||||
|
+ (xfs)
|
||||||
|
+ # remove logbsize=... mount option. It is a purely performance/memory usage optimization option,
|
||||||
|
+ # which can lead to mount failures, because it must be an integer multiple of the log stripe unit
|
||||||
|
+ # and the log stripe unit can be different in the recreated filesystem from the original filesystem
|
||||||
|
+ # (for example when using MKFS_XFS_OPTIONS, or in some exotic situations involving an old filesystem,
|
||||||
|
+ # see GitHub issue #2777 ).
|
||||||
|
+ # If logbsize is not an integer multiple of the log stripe unit, mount fails with the warning
|
||||||
|
+ # "XFS (...): logbuf size must be greater than or equal to log stripe size"
|
||||||
|
+ # in the kernel log
|
||||||
|
+ # (and a confusing error message
|
||||||
|
+ # "mount: ...: wrong fs type, bad option, bad superblock on ..., missing codepage or helper program, or other error."
|
||||||
|
+ # from the mount command), causing the layout restoration in the recovery process to fail.
|
||||||
|
+ # Wrong sunit/swidth can cause mount to fail as well, with this in the kernel log:
|
||||||
|
+ # "kernel: XFS (...): alignment check failed: sunit/swidth vs. agsize",
|
||||||
|
+ # so remove the sunit=.../swidth=... mount options as well.
|
||||||
|
+ mountopts="$( remove_mount_options_values "$mountopts" logbsize sunit swidth )"
|
||||||
|
+ (
|
||||||
|
+ echo "mkdir -p $TARGET_FS_ROOT$mountpoint"
|
||||||
|
+ echo "mount $mountopts $device $TARGET_FS_ROOT$mountpoint"
|
||||||
|
+ ) >> "$LAYOUT_CODE"
|
||||||
|
+ ;;
|
||||||
|
(*)
|
||||||
|
(
|
||||||
|
echo "mkdir -p $TARGET_FS_ROOT$mountpoint"
|
||||||
|
diff --git a/usr/share/rear/lib/filesystems-functions.sh b/usr/share/rear/lib/filesystems-functions.sh
|
||||||
|
index afdd3f24c..658d757f4 100644
|
||||||
|
--- a/usr/share/rear/lib/filesystems-functions.sh
|
||||||
|
+++ b/usr/share/rear/lib/filesystems-functions.sh
|
||||||
|
@@ -239,3 +239,40 @@ function xfs_parse
|
||||||
|
# Output xfs options for further use
|
||||||
|
echo "$xfs_opts"
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# $1 is a mount command argument (string containing comma-separated
|
||||||
|
+# mount options). The remaining arguments to the function ($2 ... )
|
||||||
|
+# specify the mount options to remove from $1, together with a trailing "="
|
||||||
|
+# and any value that follows each option.
|
||||||
|
+# For example, the call
|
||||||
|
+# "remove_mount_options_values nodev,uid=1,rw,gid=1 uid gid"
|
||||||
|
+# returns "nodev,rw".
|
||||||
|
+# There is no support for removing a mount option without a value and "=",
|
||||||
|
+# so "remove_mount_options_values nodev,uid=1,rw,gid=1 rw" will not work.
|
||||||
|
+# The function will return the modified string on stdout.
|
||||||
|
+
|
||||||
|
+function remove_mount_options_values () {
|
||||||
|
+ local str="$1"
|
||||||
|
+
|
||||||
|
+ shift
|
||||||
|
+ # First add a comma at the end so that it is easier to remove a mount option at the end:
|
||||||
|
+ str="${str/%/,}"
|
||||||
|
+ for i in "$@" ; do
|
||||||
|
+ # FIXME this also removes trailing strings at the end of longer words
|
||||||
|
+ # For example if one wants to remove any id=... option,
|
||||||
|
+ # the function will also replace "uid=1" by "u" by removing
|
||||||
|
+ # the trailing "id=1", which is not intended.
|
||||||
|
+ # Not easy to fix because $str can contain prefixes which are not
|
||||||
|
+ # mount options but arguments to the mount command itself
|
||||||
|
+ # (in particluar, "-o ").
|
||||||
|
+ # FIXME this simple approach would fail in case of mount options
|
||||||
|
+ # containing commas, for example the "context" option values,
|
||||||
|
+ # see mount(8)
|
||||||
|
+
|
||||||
|
+ # the extglob shell option is enabled in rear
|
||||||
|
+ str="${str//$i=*([^,]),/}"
|
||||||
|
+ done
|
||||||
|
+ # Remove all commas at the end:
|
||||||
|
+ echo "${str/%,/}"
|
||||||
|
+}
|
Loading…
Reference in new issue