aboutsummaryrefslogtreecommitdiff
path: root/content/permadraft/000_arch_kernel_updates.md
blob: 9b29dbfd28433ab0be590d8b5afeadc975bbb2c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Title: The Kernel is dead! Long live the Kernel
Category: Blog
Tags: /dev/diary, linux, arch linux, pacman
Date: 2018-02-08
Status: Draft 


So I run Arch Linux and mostly I love it (I'm weird, I know 😝). But there is one thing that's really been annoying me which happens after some `pacman -Syyu` runs: all of my old kernel modules become unavailable, forcing me to do a reboot. But recently I found some stuff online to prevent that from happening so let's document all of it here.

I have similar hooks, with a slight difference - keep `/usr/lib/modules/$(uname -r)` looking exactly the same as before the upgrade.

We need a hook that is run before a pacman transaction

```
# /etc/pacman.d/hooks/linux-modules-pre.hook

[Trigger]
Operation = Upgrade
Type = Package
Target = linux

[Action]
Description = Save Linux kernel modules
When = PreTransaction
Depends = rsync
Exec = /bin/sh -c 'KVER="${KVER:-$(uname -r)}"; if test -e "/lib/modules/${KVER}"; then rsync -AHXal --delete-after "/lib/modules/${KVER}" /lib/modules/backup/; fi'
```

And another hook that is run after a pacman transaction (duh 😜)

```
# /etc/pacman.d/hooks/linux-modules-post.hook

[Trigger]
Operation = Upgrade
Type = Package
Target = linux

[Action]
Description = Restore Linux kernel modules
When = PostTransaction
Depends = coreutils
Depends = rsync
Exec = /bin/sh -xc 'KVER="${KVER:-$(uname -r)}"; if test -e "/lib/modules/backup/${KVER}"; then rsync -AHXal --ignore-existing "/lib/modules/backup/${KVER}" /lib/modules/; fi; rm -rf /lib/modules/backup'
```

But that's only half of the problem. When we eventually reboot we want to clean up the old modules. This means writing a systemd service which cleas up our old modules when we finally start the new kernel.

```
# /etc/systemd/system/linux-modules-cleanup.service

[Unit]
Description=Clean up modules from old kernels

[Service]
Type=oneshot
ExecStart=/bin/bash -exc 'for i in /usr/lib/modules/[0-9]*; do if [[ $${i##*/} = \'%v\' ]] || pacman -Qo "$${i}"; then continue; fi; rsync -AHXal "$${i}" /usr/lib/modules/.old/; rm -rf "$${i}"; done'

[Install]
WantedBy=basic.target
```

You can specify how long you want to keep your old kernel modules in this config file as well

```
# /etc/tmpfiles.d/linux-modules-cleanup.conf

R! /usr/lib/modules/.old/* - - - 4w    
```


I use `rsync --ignore-existing` to merge the backup even if `/lib/modules/$(uname -r)` still exists, in case most of its contents have disappeared in the upgrade but the directory still exists due to a stray file untracked by pacman.