Boot from snapshots missing from GRUB menu

I said “run as root” not “use sudo to run it”. You become root and run this command. sudo -i or su -.

Ah, I understand. However, the output is still the same.

~ $ su - root sh -c '. /etc/default/grub; GRUB_FS=`stat -f -c %T /`; export SUSE_BTRFS_SNAPSHOT_BOOTING GRUB_FS; sh -x /etc/grub.d/80_suse_btrfs_snapshot'
Password: 
+ set -e
+ SNAPSHOTS=/.snapshots
+ '[' xtrue = xtrue ']'
+ '[' 'xUNKNOWN (0x0)' = xbtrfs ']'

No, you do not. You switch to root and then run this command. As two separate steps. I am not sure whether using it in the same command line as sudo or su does not break quotes.

All right. Separating it into two steps still produces the same result.

~ $ su -
Password: 
cameleon:~ # sh -c '. /etc/default/grub; GRUB_FS=`stat -f -c %T /`; export SUSE_BTRFS_SNAPSHOT_BOOTING GRUB_FS; sh -x /etc/grub.d/80_suse_btrfs_snapshot'
+ set -e
+ SNAPSHOTS=/.snapshots
+ '[' xtrue = xtrue ']'
+ '[' 'xUNKNOWN (0x0)' = xbtrfs ']'

Show

strace stat -f -c %T /

you may need to install strace first.

The output is quite long so I put it here: openSUSE Paste

Do you think there is something going on with my stat function? It seems to me there are different versions of stat depending on which shell one uses. I use fish as my default. I tried setting the --shell=/bin/sh option when running the earlier command with su but it made no difference.

Yes.

statfs("/", {f_type=BTRFS_SUPER_MAGIC, f_bsize=4096, f_blocks=487723008, f_bfree=399086329, f_bavail=399031393, f_files=0, f_ffree=0, f_fsid={val=[0xc817e64b, 0x37d0a3b7]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_RELATIME}) = 0
fstat(1, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
write(1, "UNKNOWN (0x0)\n", 14)         = 14

It gets the correct filesystem type but fails to recognize it. Run (as root)

GRUB_DEVICE="`grub2-probe --target=device /`"
GRUB_FS="`grub2-probe --device ${GRUB_DEVICE} --target=fs || echo unknown`"
echo $GRUB_DEVICE $GRUB_FS
~ $ su -
Password: 
cameleon:~ # GRUB_DEVICE="`grub2-probe --target=device /`"
cameleon:~ # GRUB_FS="`grub2-probe --device ${GRUB_DEVICE} --target=fs || echo unknown`"
cameleon:~ # echo $GRUB_DEVICE $GRUB_FS
/dev/nvme0n1p2 btrfs

So you apparently managed to hit two bugs at the same time. grub2-mkconfig has a bug that makes these commands fail and fall back to using stat -f that also fails. Wow. :slight_smile:

Edit /usr/sbin/grub2-mkconfig, somewhere around line 165 you will see

    # Filesystem for the device containing our userland.  Used for stuff like
    # choosing Hurd filesystem module.
    GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`"
    # Device containing our userland.  Typically used for root= parameter.
    GRUB_DEVICE="`${grub_probe} --target=device /`"

swap these commands. It should be

    # Device containing our userland.  Typically used for root= parameter.
    GRUB_DEVICE="`${grub_probe} --target=device /`"
    # Filesystem for the device containing our userland.  Used for stuff like
    # choosing Hurd filesystem module.
    GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`"

Or as patch

+++ /tmp/grub2-mkconfig	2024-03-24 15:05:26.580180259 +0300
@@ -162,11 +162,11 @@ if [ "x${NFSROOT_DEVICE}" != "x" ]; then
     GRUB_DEVICE_PARTUUID=""
     GRUB_FS="unknown"
 else
+    # Device containing our userland.  Typically used for root= parameter.
+    GRUB_DEVICE="`${grub_probe} --target=device /`"
     # Filesystem for the device containing our userland.  Used for stuff like
     # choosing Hurd filesystem module.
     GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`"
-    # Device containing our userland.  Typically used for root= parameter.
-    GRUB_DEVICE="`${grub_probe} --target=device /`"
     GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
     GRUB_DEVICE_PARTUUID="`${grub_probe} --device ${GRUB_DEVICE} --target=partuuid 2> /dev/null`" || true
 fi

You are using slowroll, so your version may be slightly different from Tumbleweed, but I expect the patch still applies if you prefer to use it.

After having edited the grub2-mkconfig, try running it and check the generated grub.cfg.

1 Like

Yes, that did the trick! This section is back in grub.cfg after running the grub2-mkconfig command,

### BEGIN /etc/grub.d/80_suse_btrfs_snapshot ###
btrfs-mount-subvol ($root) /.snapshots @/.snapshots
if [ -f "/.snapshots/grub-snapshot.cfg" ]; then
  source "/.snapshots/grub-snapshot.cfg"
fi
### END /etc/grub.d/80_suse_btrfs_snapshot ###

And the GRUB menu now behaves as expected on boot.

I am interested in finding out how this happened, though I suppose that is outside the scope of this thread.

Cheers!

For the archives - grub2-mkconfig bug report

https://bugzilla.opensuse.org/show_bug.cgi?id=1221904

You may consider submitting bug for the stat -f problem.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.