UPDATE as of 10/30/26
See Tuning HDMI Monitors to work flawlessly with OpenSUSE Tumbleweed
END UPDATE
Converting a server (such as a high-density virtualization platform) to Thin XFS LVM Provisioning with Libvirt-Hooks solves the fundamental performance bottlenecks and management complexities inherent in running virtual machines on top of a native or hybrid Btrfs storage architecture.
While Btrfs excels at features like transparent compression, file-level subvolumes, and data scrubbing, its structural design makes it highly inefficient for heavy virtual machine disk (.qcow2 or .img) storage. Moving to a thin-provisioned LVM layer running XFS-orchestrated dynamically via Libvirt event hooks - provides enterprise-grade predictability, raw block speed, and automated lifecycle management.
The core issue with openSUSE Tumbleweed is problem with native HDMI Monitors support. OverlayFS may be setup on F45 Server on top of mixed BTRFS/XFS layout as shown below and you would have an option with Btrfs low level CLI (mv,snaphot commands) to rollback the main instance to previous safe state via Overlay instances available as options provided by Grub submenu. However, BTRFS support on F45 will stay as experimental feature vs Enterprise grade solutions provided by Suse flavors headless servers.
Final disk layout ( bare metal case )
root@server45fedora:~# hostnamectl
Static hostname: server45fedora
Icon name: computer-desktop
Chassis: desktop
Chassis Asset Tag: To be filled by O.E.M.
Machine ID: c97053a998854caa9178705b31914bc3
Boot ID: 17bfefb60d0b4623a61b0bc44157819b
Product UUID: af95be8a-eace-8515-aaa1-00d861d9318b
Operating System: Fedora Linux 45 (Server Edition)
CPE OS Name: cpe:/o:fedoraproject:fedora:45
OS Support End: Wed 2027-11-24
OS Support Remaining: 1y 1month
Kernel: Linux 7.2.11-300.fc45.x86_64
Architecture: x86-64
Hardware Vendor: Micro-Star International Co., Ltd.
Hardware Model: MS-7C37
Hardware Serial: To be filled by O.E.M.
Hardware Version: 3.0
Firmware Version: H.60
Firmware Date: Wed 2019-11-06
Firmware Age: 6y 11month 2w 3d
root@server45fedora:~# findmnt -t btrfs
TARGET SOURCE FSTYPE OPTIONS
/ /dev/nvme0n1p4[/@-0] btrfs rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=260,subvol=/@-0
├─/.snapshots
│ /dev/nvme0n1p4[/snapshots]
│ btrfs rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=256,subvol=/snapsho
├─/etc/libvirt/qemu
│ /dev/nvme0n1p4[/@qemu] btrfs rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=267,subvol=/@qemu
├─/home /dev/nvme0n1p4[/@home] btrfs rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=257,subvol=/@home
├─/var/cache
│ /dev/nvme0n1p4[/@cache] btrfs rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=259,subvol=/@cache
└─/var/log
/dev/nvme0n1p4[/@log] btrfs rw,relatime,seclabel,compress=zstd:1,ssd,discard=async,space_cache=v2,subvolid=258,subvol=/@log
root@server45fedora:~# lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
sr0
zram0 swap 1 zram0 10432693-2e2c-4c5c-8f6e-01f787c76c37 [SWAP]
nvme1n1 ( Tumbleweed drive )
├─nvme1n1p1 vfat FAT32 61BC-A4BF
├─nvme1n1p2 ext4 1.0 c6a99ff4-3bf8-4d50-809f-db6259935a55
├─nvme1n1p3 LVM2_member LVM2 001 aMgkVz-72ia-dHzo-8Q2p-haHX-VoKU-bv5Bce
│ ├─vg_suse-tp_suse_kvm_tmeta
│ │ └─vg_suse-tp_suse_kvm-tpool
│ │ ├─vg_suse-tp_suse_kvm
│ │ └─vg_suse-vol_suse_thin xfs 0f543732-acde-4d36-bc88-b75e9e8c8cc4
│ └─vg_suse-tp_suse_kvm_tdata
│ └─vg_suse-tp_suse_kvm-tpool
│ ├─vg_suse-tp_suse_kvm
│ └─vg_suse-vol_suse_thin xfs 0f543732-acde-4d36-bc88-b75e9e8c8cc4
└─nvme1n1p4 btrfs 800c9083-38bd-4fab-b916-0bce438442ab
nvme0n1 ( F45 Server's drive )
├─nvme0n1p1 vfat FAT32 E005-797D 590.9M 1% /boot/efi
├─nvme0n1p2 ext4 1.0 d2c18aab-3ead-4abe-b1a4-9ef47b6b61a4 1.2G 29% /boot
├─nvme0n1p3 LVM2_member LVM2 001 EuwX4s-zJJ3-eL0g-IsAi-AmJC-Z7XI-bxomP6
│ ├─vg_fedora-tp_fedora_kvm_tmeta
│ │ └─vg_fedora-tp_fedora_kvm-tpool
│ │ │
│ │ ├─vg_fedora-tp_fedora_kvm
│ │ └─vg_fedora-vol_fedora_thin xfs f13011c1-1835-4347-addc-8f37b23475a6 142.3G 6% /var/lib/libvirt/images
│ └─vg_fedora-tp_fedora_kvm_tdata
│ └─vg_fedora-tp_fedora_kvm-tpool
│ │
│ ├─vg_fedora-tp_fedora_kvm
│ └─vg_fedora-vol_fedora_thin xfs f13011c1-1835-4347-addc-8f37b23475a6 142.3G 6% /var/lib/libvirt/images
└─nvme0n1p4 btrfs ff4229bc-cf09-4b53-8edc-52611c83c4f5 248.9G 8% /var/log
/var/cache
/home
/etc/libvirt/qemu
/.snapshots
#########################################################
Convertion XFS partition been setup via Anaconda deployment phase into Thin XFS provisioned LVM via reinitializing #########################################################
# 1. Ensure the target NVMe partition is completely clean
sudo umount /dev/nvme0n1p3 2>/dev/null
sudo wipefs --all /dev/nvme0n1p3
# 2. Bind the NVMe partition to LVM with 500M metadata room
sudo pvcreate --metadatasize 500M /dev/nvme0n1p3
# 3. Create your dedicated vg_fedora Volume Group container
sudo vgcreate vg_fedora /dev/nvme0n1p3
# 4. Instantiate the Thin Pool (Using 152G to respect 80/20 strategy buffer)
sudo lvcreate -L 152G --chunksize 128K --thinpool tp_fedora_kvm vg_fedora
# 5. Carve out the virtual thin volume named 'vol_fedora_thin'
sudo lvcreate -n vol_fedora_thin -V 152G --thinpool vg_fedora/tp_fedora_kvm
# Format the thin volume enabling fast VFS-level copy-on-write pointer sharing
sudo mkfs.xfs -K -m reflink=1,crc=1 /dev/vg_fedora/vol_fedora_thin
sudo mkdir -p /var/lib/libvirt/images
# Append your optimized thin block map permanently into the layout tables
echo '/dev/vg_fedora/vol_fedora_thin /var/lib/libvirt/images xfs defaults,noatime,logbufs=8,logbsize=256k 0 0' | sudo tee -a /etc/fstab
# Rebuild systemd configuration targets and mount the new thin pool volume
sudo systemctl daemon-reload
sudo mount -a
################################################## Create the target nested storage hierarchy
##################################################
Apply strict operational permissions for the libvirt engine
sudo chown root:root /var/lib/libvirt
sudo chmod 711 /var/lib/libvirt
sudo chmod 711 /var/lib/libvirt/images
# Apply SELinux context rules for KVM operation on Fedora
sudo semanage fcontext -a -t virt_image_t "/var/lib/libvirt/images(/.*)?" 2>/dev/null || true
sudo restorecon -R -v /var/lib/libvirt/images
System reboot
########################################################
Creating /etc/libvirt/hooks/qemu and service lvm-thin-snapshot.service ########################################################
root@fedoraSRV:~# cat /etc/libvirt/hooks/qemu
#!/bin/bash
GUEST_NAME="$1"
ACTION="$2"
PHASE="$3"
STORAGE_DIR="/var/lib/libvirt/images"
BACKUP_DIR="${STORAGE_DIR}/.snapshots_${GUEST_NAME}"
[ ! -d "$STORAGE_DIR" ] && exit 0
if [ "$ACTION" = "prepare" ] || [ "$ACTION" = "stopped" ]; then
/usr/bin/systemctl start lvm-thin-snapshot.service &
(
/usr/bin/sleep 2
/usr/bin/mkdir -p "$BACKUP_DIR"
for disk_path in "${STORAGE_DIR}"/*"${GUEST_NAME}"*.qcow2; do
[ ! -f "$disk_path" ] && continue
disk_file=$(/usr/bin/basename "$disk_path")
timestamp=$(/usr/bin/date +%Y%m%d_%H%M%S)
/usr/bin/cp --reflink=always "$disk_path" "${BACKUP_DIR}/${disk_file}.snap_${timestamp}"
# FEDORA FIX: Match Fedora execution user account permissions
/usr/bin/chown qemu:qemu "${BACKUP_DIR}/${disk_file}.snap_${timestamp}" 2>/dev/null
done
/usr/bin/ls -tp "${BACKUP_DIR}"/* | /usr/bin/grep -v '/$' | /usr/bin/tail -n +6 | /usr/bin/xargs -I {} /usr/bin/rm -- "{}" 2>/dev/null
) & disown
elif [ "$ACTION" = "define" ] || [ "$ACTION" = "undefine" ]; then
/usr/bin/systemctl start lvm-thin-snapshot.service &
fi
exit 0
root@fedoraSRV:~# cat /etc/systemd/system/lvm-thin-snapshot.service
[Unit]
Description=Rotate Pristine LVM Thin Pool Snapshot on Libvirt Changes
After=local-fs.target
[Service]
Type=oneshot
User=root
Environment=VG_NAME=vg_fedora
Environment=SNAP_NAME=snap_working_vms
Environment=THIN_VOL=vol_fedora_thin
Environment=IMG_DIR=/var/lib/libvirt/images
ExecStart=/bin/bash -c '\
echo "Current allocated qcow2 image count: $(ls -1 ${IMG_DIR}/*.qcow2 2>/dev/null | wc -l)"; \
echo "Removing old snapshot if present..."; \
/usr/sbin/lvremove -f "${VG_NAME}/${SNAP_NAME}" 2>/dev/null || true; \
echo "Creating pristine baseline snapshot..."; \
/usr/sbin/lvcreate -s --name "${SNAP_NAME}" "${VG_NAME}/${THIN_VOL}"'
[Install]
WantedBy=multi-user.target
################################
Healthy system status verification
################################
root@server45fedora:~# ls -Zla /var/lib/libvirt/images
total 6730604
drwxr-xr-x. 4 root root system_u:object_r:virt_image_t:s0 112 Oct 23 11:32 .
drwx--x--x. 1 root root system_u:object_r:virt_var_lib_t:s0 118 Sep 28 14:43 ..
-rw-------. 1 qemu qemu system_u:object_r:virt_image_t:s0 21478375424 Oct 23 11:59 ArchPlasma.qcow2
-rw-------. 1 qemu qemu system_u:object_r:virt_image_t:s0 21478375424 Oct 23 11:31 ArchServer.qcow2
drwxr-xr-x. 2 root root system_u:object_r:virt_image_t:s0 4096 Oct 23 11:59 .snapshots_ArchPlasma
drwxr-xr-x. 2 root root system_u:object_r:virt_image_t:s0 4096 Oct 23 11:31 .snapshots_ArchServer
############################################################
FEDORA 45 UNIVERSAL GLOBAL DISASTER RECOVERY ENGINE (ZERO XML EDITS)
############################################################
#!/bin/bash
set -e
TARGET_MNT="/var/lib/libvirt/images"
VG_NAME="vg_fedora"
THIN_VOL="vol_fedora_thin"
SNAP_NAME="snap_working_vms"
GUEST_NAME="ArchServer" # Simply toggle this variable to match your target VM name
echo "=== PHASE 1: RE-ARM IMMUNE STORAGE MATRIX BASELINE ==="
sudo lvremove -f ${VG_NAME}/${SNAP_NAME} 2>/dev/null || true
sudo lvcreate -s --name ${SNAP_NAME} ${VG_NAME}/${THIN_VOL}
sudo lvs ${VG_NAME}
echo "=== PHASE 2: CATASTROPHIC DISASTER SIMULATION ==="
sudo virsh destroy ${GUEST_NAME} 2>/dev/null || true
echo "==> Waiting for hook script background backup copy to complete..."
while pgrep -f "cp --reflink=always" >/dev/null || systemctl is-active --quiet lvm-thin-snapshot.service; do
sleep 2
done
echo "==> Hook script finished! Storage layer is quiet."
# Dynamically find and corrupt ONLY the disks belonging to the targeted VM
for disk in ${TARGET_MNT}/*"${GUEST_NAME}"*.qcow2; do
[ ! -f "$disk" ] && continue
echo "==> Corrupting: $(basename "$disk")"
sudo dd if=/dev/urandom of="$disk" bs=1M count=500 conv=notrunc
done
echo "=== PHASE 3: SYNCHRONOUS WAIT-FOR-EXIT CODE FENCE ==="
sudo systemctl stop virtqemud.socket virtqemud-ro.socket virtqemud-admin.socket virtqemud.service 2>/dev/null || true
sudo pkill -9 qemu 2>/dev/null || true
sudo fuser -kM "${TARGET_MNT}" 2>/dev/null || true
echo "==> Executing standard physical unmount loop..."
COUNTER=1
while [ $COUNTER -le 20 ]; do
if sudo umount ${TARGET_MNT} 2>/dev/null; then
echo "==> SUCCESS: Filesystem detached cleanly with exit code 0."
break
fi
sleep 3
COUNTER=$((COUNTER + 1))
done
if [ $COUNTER -gt 20 ]; then
exit 1
fi
echo "=== PHASE 4: ATOMIC METADATA MERGE ==="
sudo lvconvert --merge ${VG_NAME}/${SNAP_NAME}
echo "=== PHASE 5: PURGE TRANSIENT GRAPH FILES & FIX SECURITY ==="
sudo mount ${TARGET_MNT}
# 1. Force the kernel and storage layers to settle after the merge mount
sudo udevadm settle
sync
# 2. ISOLATED CLEANUP: Clear background tokens ONLY for the targeted guest
sudo rm -f ${TARGET_MNT}/*"${GUEST_NAME}"*.lock 2>/dev/null
sudo rm -f /var/run/libvirt/qemu/"${GUEST_NAME}".xml 2>/dev/null
sudo rm -rf /var/cache/libvirt/qemu/"${GUEST_NAME}" 2>/dev/null
sudo rm -rf /var/lib/libvirt/qemu/remembered/"${GUEST_NAME}" 2>/dev/null
# 3. FIXED & COMPREHENSIVE XATTR PURGE: Completely strip ALL hidden libvirt security keys
echo "==> Clearing all hidden libvirt security locks from ${GUEST_NAME}..."
for disk in ${TARGET_MNT}/*"${GUEST_NAME}"*.qcow2; do
[ ! -f "$disk" ] && continue
# This loops through and aggressively drops any trusted.libvirt keys frozen in the file metadata
sudo getfattr -m "trusted.libvirt.security" --dump "$disk" 2>/dev/null | grep -oP '^trusted\.libvirt\.security\.[a-z_]+' | while read -r attr; do
sudo setfattr -x "$attr" "$disk" 2>/dev/null || true
done
done
# 4. TARGETED SECURITY REMAPPING: Process ONLY the targeted VM files
echo "==> Resetting permissions and SELinux contexts strictly for ${GUEST_NAME}..."
for disk in ${TARGET_MNT}/*"${GUEST_NAME}"*.qcow2; do
[ ! -f "$disk" ] && continue
sudo chown qemu:qemu "$disk"
sudo chmod 600 "$disk"
# Restore standard system-defined defaults so Libvirt can assign dynamic labels cleanly
sudo restorecon -Fv "$disk"
done
# Restart systemd cgroup containment tracking profiles safely
sudo systemctl restart systemd-machined
sleep 2
# Re-activate the modular listener sockets
sudo systemctl start virtqemud.socket virtqemud-ro.socket virtqemud-admin.socket virtqemud.service
sleep 1
echo "=== PHASE 6: POWER ON RECOVERED GUEST ==="
# Verify if the domain state registry dropped during the socket tear-down
if sudo virsh list --all | grep -qw "${GUEST_NAME}"; then
sudo virsh start ${GUEST_NAME}
else
echo "==> Re-registering transient XML map for ${GUEST_NAME}..."
sudo virsh define /etc/libvirt/qemu/"${GUEST_NAME}".xml 2>/dev/null || true
sudo virsh start ${GUEST_NAME}
fi