grub2-mkconfig prefixes btrfs subvol, x86_64-efi can't find files

I have a virtual machine (KVM-qemu). Host is an Intel NUC6CAYH,CPU Celeron J3455, guest uses the q35 chipset (pc-q35-7.1) (vs. the ancient I440FX) and EFI. I downloaded the Tumbleweed (Snapshot20230111) installation DVD image and selected minimal server software. The filesystem on the root was btrfs (is the default). When finished, the VM booted with no hassle.

/boot/grub2/grub.cfg referred to files in this style: /boot/vmlinuz-6.1.7-1-default (and similarly for initrd, fonts, etc.) I copied my own /etc/default/grub onto the machine, then (having made a backup copy) I executed on the running host:

grub2-mkconfig -o /boot/grub2/grub.cfg

Now the file style was: /@/boot/vmlinuz-6.1.7-1-default with leading subvolume. Grub failed to read any of these files. I mounted the VM’s disc on the host, and edited changing ‘/@/’ to ‘/’ wherever occurring. Now it boots. In a previous iteration with snapshots enabled, the style was /@/.snapshots/1/snapshot/boot/vmlinuz-6.1.7-1-default (could not read this style either).

Can someone please give me a clue how to achieve from the command line what the installer can do, i.e. produce grub.cfg for a btrfs root, that can actually get the machine booted? Command line is needed because I’m scripting VM generation, and I’m newly trying to switch to btrfs.

More info:
When I run grub2-mkconfig with either /etc/default/grub version in place, grub.cfg is produced in both cases with prefixed subvolume paths.

It looks to me like these 3 commands all mount the root partition and deliver the same content. No snapshots in this test. The first one matches what’s in /etc/fstab; the others are from various forum posts.

mount /dev/disk/by-label/ROOT-DRAGON /mnt
mount -o "subvol=/@" /dev/disk/by-label/ROOT-DRAGON /mnt
mount -o "subvol=@" /dev/disk/by-label/ROOT-DRAGON /mnt

Here’s /etc/fstab as generated by the installer (and not subsequently hacked), to show the recommended mount options for ‘/’, i.e. no subvol specified.

LABEL=ROOT-DRAGON  /                       btrfs  defaults                      0  0
LABEL=ROOT-DRAGON  /boot/grub2/x86_64-efi  btrfs  subvol=/@/boot/grub2/x86_64-efi  0  0
LABEL=ROOT-DRAGON  /boot/grub2/i386-pc     btrfs  subvol=/@/boot/grub2/i386-pc  0  0
LABEL=SWAP-DRAGON  swap                    swap   defaults                      0  0
LABEL=EFI-DRAGON   /boot/efi               vfat   utf8                          0  2

Diff between /etc/default/grub{.orig,} (minus comments) (< = as installed, > = jimc customized)

2c2
< GRUB_DEFAULT=saved
---
> GRUB_DEFAULT=0
6,7c6,8
< GRUB_CMDLINE_LINUX_DEFAULT="splash=silent resume=/dev/disk/by-label/SWAP-DRAGON mitigations=auto quiet security=apparmor"
< GRUB_CMDLINE_LINUX=""
---
> GRUB_CMDLINE_LINUX="console=hvc0 console=tty1 hpet=disable"
> GRUB_CMDLINE_LINUX_DEFAULT="resume=LABEL=SWAP-DRAGON mitigations=auto"
> GRUB_CMDLINE_LINUX_RECOVERY="apm=off noresume nosmp maxcpus=0 edd=off powersaved=off nohz=off highres=off processor.max_cstate=1 nomodeset x11failsafe"
9a11
> GRUB_DISABLE_OS_PROBER="false"
12d13
< SUSE_BTRFS_SNAPSHOT_BOOTING="true"  ## Only significant difference
14d14
< GRUB_DISABLE_OS_PROBER="false"

/etc/default/grub (minus comments, the one giving trouble)

GRUB_DISTRIBUTOR=
GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=8
GRUB_CMDLINE_LINUX="console=hvc0 console=tty1 hpet=disable"
GRUB_CMDLINE_LINUX_DEFAULT="resume=LABEL=SWAP-DRAGON mitigations=auto"
GRUB_CMDLINE_LINUX_RECOVERY="apm=off noresume nosmp maxcpus=0 edd=off powersaved=off nohz=off highres=off processor.max_cstate=1 nomodeset x11failsafe"
GRUB_TERMINAL="gfxterm"
GRUB_GFXMODE="auto"
GRUB_DISABLE_OS_PROBER="false"
GRUB_BACKGROUND=
GRUB_THEME=/boot/grub2/themes/openSUSE/theme.txt
GRUB_USE_LINUXEFI="true"
GRUB_ENABLE_CRYPTODISK="n"
GRUB_CMDLINE_XEN_DEFAULT="vga=gfx-1024x768x16"

You blindly overwrote system configuration file, why are you surprised that you now have problems?

Correct. Upstream grub resolves pathnames on btrfs starting from the top. SUSE grub has patches to optionally resolve pathnames relatively to the default subvolume. This is controlled by SUSE_BTRFS_SNAPSHOT_BOOTING variable in /etc/default/grub. To support boot from snapshot, this variable must be set to true and both grub2-install and grub2-mkconfig must use the same value, so grub configuration matches grub setting at boot time. openSUSE installer defaults to supporting snapshots and sets this variable to true. Without this variable grub reverts to the default upstream behavior.

Thanks to @arvidjaar for the fix. When installing, I did not turn on snapshot generation for the btrfs root, wanting to try that later when I had basic btrfs working reliably. So when I saw that line in /etc/default/grub I said, “Oops, I’d better turn that off since I have no snapshots.”

I worked out the mechanism: grub2-mkconfig runs all (or most) filenames through make_system_path_relative_to_its_root (in grub-mkconfig_lib), which normally execs grub_mkrelpath $filename, except on btrfs and with SUSE_BTRFS_SNAPSHOT_BOOTING=“true” it includes the -r option, which suppresses the initial /@subvol, and the files can be read at boot time.

So my new VMs (two of them now) are booting reliably with my standard configuration on them. Thanks again.