libguestfs/0007-inspection-Ignore-btrfs-snapshots-of-roots.patch
Richard W.M. Jones f1a7701278 Capture and raise qemu-img stderr
resolves: RHEL-92239
Ignore btrfs snapshots of roots
resolves: RHEL-93109
2025-05-27 17:10:57 +01:00

99 lines
4.1 KiB
Diff

From 8f5e4f07ba92d42506072520260d96ce77d58e21 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 22 May 2025 11:32:11 +0100
Subject: [PATCH] inspection: Ignore btrfs snapshots of roots
In SLES guests in particular, btrfs snapshots seem to be used to allow
rollback of changes made to the filesystem. Dozens of snapshots may
be present. Technically therefore these are multi-boot guests. The
libguestfs concept of "root" of an operating system does not map well
to this, causing problems in virt-inspector and virt-v2v.
In this commit we ignore these duplicates. The test is quite narrow
to avoid false positives: We only remove a duplicate if it is a member
of a parent device, both are btrfs, both the snapshot and parent have
a root role, and the roles are otherwise very similar.
There may be a case for reporting this information separately in
future, although it's also easy to find this out now. For example,
when you see a btrfs root device returned by inspect_os, you could
call btrfs_subvolume_list on the root device to list the snapshots.
Fixes: https://issues.redhat.com/browse/RHEL-93109
---
daemon/inspect.ml | 51 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/daemon/inspect.ml b/daemon/inspect.ml
index 5c6be3193..84571f582 100644
--- a/daemon/inspect.ml
+++ b/daemon/inspect.ml
@@ -61,6 +61,11 @@ let rec inspect_os () =
*)
check_for_duplicated_bsd_root |>
+ (* Check if the root filesystems are duplicated by btrfs snapshots.
+ * This happens especially for SLES guests.
+ *)
+ check_for_duplicated_btrfs_snapshots_of_root |>
+
(* For Linux guests with a separate /usr filesystem, merge some of the
* inspected information in that partition to the inspect_fs struct
* of the root filesystem.
@@ -190,6 +195,52 @@ and check_for_duplicated_bsd_root fses =
with
Not_found -> fses
+(* Check for the case where the root filesystem gets duplicated by
+ * btrfs snapshots. Ignore the snapshots in this case (RHEL-93109).
+ *)
+and check_for_duplicated_btrfs_snapshots_of_root fses =
+ eprintf "inspect_os: check_for_duplicated_btrfs_snapshots_of_root\n%!";
+
+ let fs_is_btrfs_snapshot_of_root = function
+ (* Is this filesystem a btrfs snapshot of root? *)
+ | { fs_location =
+ { mountable = { m_type = MountableBtrfsVol _; m_device = dev1 };
+ vfs_type = "btrfs" };
+ role = RoleRoot inspection_data1 } as fs1 ->
+ (* Return true if it duplicates the parent device which has
+ * a root role.
+ *)
+ List.exists (function
+ | { fs_location =
+ { mountable = { m_type = MountableDevice; m_device = dev2 };
+ vfs_type = "btrfs" };
+ role = RoleRoot inspection_data2 }
+ when dev1 = dev2 ->
+ (* Check the roles are similar enough. In my test I saw
+ * that /etc/fstab was slightly different in the parent
+ * and snapshot. It's possible this is because the snapshot
+ * was created during installation, but it's not clear.
+ *)
+ let similar =
+ inspection_data1.os_type = inspection_data2.os_type &&
+ inspection_data1.distro = inspection_data2.distro &&
+ inspection_data1.product_name = inspection_data2.product_name &&
+ inspection_data1.version = inspection_data2.version in
+ if verbose () && similar then
+ eprintf "check_for_duplicated_btrfs_snapshots_of_root: \
+ dropping duplicate btrfs snapshot:\n%s\n"
+ (string_of_fs fs1);
+ similar
+ | _ -> false
+ ) fses
+
+ (* Anything else is not a snapshot. *)
+ | _ -> false
+ in
+
+ (* Filter out the duplicates. *)
+ List.filter (Fun.negate fs_is_btrfs_snapshot_of_root) fses
+
(* Traverse through the filesystem list and find out if it contains
* the [/] and [/usr] filesystems of a Linux image (but not CoreOS,
* for which there is a separate [collect_coreos_inspection_info]).
--
2.47.1