Merge pull request #1367 from linux-surface/kernel-watchdog-v3

Another kernel-watchdog update for btrfs
This commit is contained in:
Dorian Stoll 2024-03-01 11:55:23 +01:00 committed by GitHub
commit 3187d8c8db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 90 additions and 26 deletions

View file

@ -0,0 +1,87 @@
#!/usr/bin/env python3
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
from typing import Any
def grub2_editenv(*args: Any, **kwargs: Any) -> str:
subprocess.run(["grub2-editenv", *args], check=True, **kwargs)
def main() -> int:
boot: Path = Path("/boot")
mid: Path = Path("/etc/machine-id")
if not boot.exists():
print("ERROR: /boot directory does not exist")
return 1
if not mid.exists():
print("ERROR: /etc/machine-id does not exist")
return 1
blsdir: Path = boot / "loader" / "entries"
if not blsdir.exists():
print("ERROR: /boot/loader/entries does not exist")
return 1
try:
grub2_editenv("--help", capture_output=True)
except:
print("ERROR: grub2-editenv is not working")
return 1
# Get list of surface kernels sorted by timestamp.
#
# We use creation time here because it represents when the kernel was installed.
# Modification time can be a bit wonky and seems to correspond to the build date.
kernels: list[Path] = sorted(
boot.glob("vmlinuz-*.surface.*"),
key=lambda x: x.stat().st_ctime,
reverse=True,
)
if len(kernels) == 0:
print("ERROR: Failed to find a surface kernel")
return 1
# The saved_entry property from grubenv determines what kernel is booted by default.
# Its value is the filename of the BLS entry in /boot/loader/entries minus the file extension.
#
# The BLS files are named using a combination of the machine ID and the version string
# of the kernel that is being booted. Since we have the vmlinux, we can get the version
# from its name, and the machine ID from /etc/machine-id.
#
# This allows setting the default kernel without calling grubby or having to figure out
# which path GRUB will use to boot the kernel.
kernel: Path = kernels[0]
machineid: str = mid.read_text().strip()
version: str = kernel.name.lstrip("vmlinuz-")
blscfg: Path = blsdir / "{}-{}.conf".format(machineid, version)
# Make sure the config really exists
if not blscfg.exists():
print("ERROR: {} does not exist".format(blscfg))
return 1
print("Kernel: {}".format(kernel))
print("BLS entry: {}".format(blscfg))
grub2_editenv("-", "set", "saved_entry={}".format(blscfg.stem))
# Update timestamp for rEFInd and ensure it is marked as latest across all kernels
kernel.touch(exist_ok=True)
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -3,4 +3,4 @@ Description=linux-surface default kernel watchdog
[Service]
Type=oneshot
ExecStart=/usr/bin/linux-surface-default-watchdog.sh
ExecStart=/usr/bin/linux-surface-default-watchdog.py

View file

@ -1,23 +0,0 @@
#!/bin/bash
set -euo pipefail
# Get list of surface kernels with timestamp
KERNELS="$(
find /boot -maxdepth 1 -name 'vmlinuz-*.surface.*' -print0 | xargs -0 -I '{}' \
stat -c "%W %n" {}
)"
# Sort by timestamp
KERNELS="$(echo "${KERNELS}" | sort -n)"
# Get latest kernel (last line) and extract the path
VMLINUX="$(echo "${KERNELS}" | tail -n1 | cut -d' ' -f2)"
echo "${VMLINUX}"
# update GRUB config
grubby --set-default "$(grub2-mkrelpath "${VMLINUX}")"
# Update timestamp for rEFInd
# Ensure it's marked as latest across all kernels, not just surface ones
touch "${VMLINUX}"

View file

@ -19,7 +19,7 @@ index 43dce82a9d36..28df94e561d4 100644
+Source4100: linux-surface-default-watchdog.path
+Source4101: linux-surface-default-watchdog.service
+Source4102: linux-surface-default-watchdog.sh
+Source4102: linux-surface-default-watchdog.py
+Source4103: 90-linux-surface-default-watchdog.preset
+
## Patches needed for building this package
@ -81,7 +81,7 @@ index 43dce82a9d36..28df94e561d4 100644
%endif
+%files default-watchdog
+%{_bindir}/linux-surface-default-watchdog.sh
+%{_bindir}/linux-surface-default-watchdog.py
+%{_unitdir}/linux-surface-default-watchdog.path
+%{_unitdir}/linux-surface-default-watchdog.service
+%{_presetdir}/90-linux-surface-default-watchdog.preset