{"id":133662,"date":"2023-05-12T08:00:00","date_gmt":"2023-05-12T08:00:00","guid":{"rendered":"https:\/\/fedoramagazine.org\/?p=38259"},"modified":"2023-05-12T08:00:00","modified_gmt":"2023-05-12T08:00:00","slug":"make-use-of-btrfs-snapshots-to-upgrade-fedora-linux-with-easy-fallback","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2023\/05\/12\/make-use-of-btrfs-snapshots-to-upgrade-fedora-linux-with-easy-fallback\/","title":{"rendered":"Make use of Btrfs snapshots to upgrade Fedora Linux with easy fallback"},"content":{"rendered":"<p>Back in 2018, a <a href=\"https:\/\/fedoramagazine.org\/use-lvm-upgrade-fedora\/\" target=\"_blank\" rel=\"noreferrer noopener\">previous article<\/a> demonstrated how to use LVM to clone the root filesystem before upgrading Fedora Linux so as to have a fallback in the unlikely event that something goes wrong. Today, the default Fedora Workstation install uses Btrfs. Now you can use a Btrfs snapshot to make creating a bootable fallback much easier. Note that converting or migrating a system to Btrfs from another filesystem is outside the scope of this article.<\/p>\n<p> <span id=\"more-38259\"><\/span> <\/p>\n<h2 class=\"wp-block-heading\">Check that root filesystem is Btrfs<\/h2>\n<p>This example uses a Pinebook aarch64 laptop. Before proceeding, first make sure that Btrfs is being used for the root (system) filesystem. Not every spin or image uses Btrfs by default.<\/p>\n<pre class=\"wp-block-preformatted\">$ df -T\nFilesystem Type 1K-blocks Used Available Use% Mounted on\ndevtmpfs devtmpfs 4096 0 4096 0% \/dev\ntmpfs tmpfs 998992 0 998992 0% \/dev\/shm\ntmpfs tmpfs 399600 6360 393240 2% \/run\n\/dev\/mmcblk2p3 btrfs 56929280 39796116 15058348 73% \/\ntmpfs tmpfs 998996 24 998972 1% \/tmp\ntmpfs tmpfs 5242880 0 5242880 0% \/var\/lib\/mock\n\/dev\/mmcblk2p3 btrfs 56929280 39796116 15058348 73% \/f34\n\/dev\/mmcblk2p3 btrfs 56929280 39796116 15058348 73% \/home\n\/dev\/mmcblk2p2 ext4 996780 551888 376080 60% \/boot\n\/dev\/mmcblk2p1 vfat 194348 31648 162700 17% \/boot\/efi\ntmpfs tmpfs 199796 100 199696 1% \/run\/user\/1000\ntmpfs tmpfs 199796 84 199712 1% \/run\/user\/0<\/pre>\n<h2 class=\"wp-block-heading\">List the existing Btrfs subvolumes<\/h2>\n<p>The above example output shows that the file system mounted on &#8220;root&#8221; (&#8220;\/&#8221;) is type Btrfs. Notice that three mountpoints show the same backing device and the same <em>Used<\/em> and <em>Available<\/em> blocks. This is because they are parts (subvolumes) mounted from a single Btrfs filesystem. The <em>\/f34<\/em> subvolume is my bootable snapshot from last year.<\/p>\n<p>A default Fedora Btrfs install creates one Btrfs filesystem with two subvolumes &#8212; <em>root<\/em> and <em>home<\/em> &#8212; mounted on \/ and \/home respectively. Let&#8217;s see what other subvolumes I&#8217;ve added:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvol list \/\nID 272 gen 110428 top level 5 path root\nID 273 gen 110426 top level 5 path home\nID 300 gen 109923 top level 5 path f34\nID 301 gen 95852 top level 5 path home.22Jul26\nID 302 gen 95854 top level 5 path f36.22Jul26<\/pre>\n<p>There is an <em>f34<\/em> subvol from the last system-upgrade and two readonly snapshots of <em>home<\/em> and <em>f36<\/em>. The easiest way to add and delete snapshots is to mount the Btrfs root. I will update the system and create a new snapshot of the current f36 <em>root<\/em> subvolume. If you have renamed your <em>root<\/em> subvolume, then you presumably know enough to adjust the following example accordingly for your system.<\/p>\n<h2 class=\"wp-block-heading\">Create the Btrfs fallback snapshot<\/h2>\n<pre class=\"wp-block-preformatted\">$ sudo dnf update --refresh\n... lots of stuff updated (reboot if kernel updated)\n$ sudo mkdir -p \/mnt\/root\n$ sudo mount \/dev\/mmcblk2p3 \/mnt\/root\n$ cd \/mnt\/root\n$ ls\nf34 f36.22Jul26 home home.22Jul26 root\n$ sudo btrfs subvol snapshot root f36\nCreate a snapshot of 'root' in '.\/f36'<\/pre>\n<p>Because Btrfs snapshots are filesystem based, it is not necessary to &#8220;sync&#8221; before the snapshot, as I recommended for LVM. To boot from the new subvol as a fallback, you will need to edit \/mnt\/root\/f36\/etc\/fstab with your favorite editor. If you are a beginner, nano is a dirt simple text editor with minimal features. Here are some lines from my <em>fstab<\/em> file:<\/p>\n<pre class=\"wp-block-preformatted\">LABEL=PINE \/ btrfs subvol=root,compress=zstd:1 1 1\nUUID=e31667fb-5b6f-48d9-aa90-f2fd6aa5f005 \/boot ext4 defaults 1 2\nUUID=75DB-5832 \/boot\/efi vfat umask=0077,shortname=winnt 0 2\nLABEL=PINE \/home btrfs subvol=home,compress=zstd:1 1 1\nLABEL=SWAP swap swap\tdiscard=once\t0 0<\/pre>\n<p>Change <em>subvol=root<\/em> to <em>subvol=f36<\/em>. This change is to the file in the snapshot, not your production <em>fstab<\/em>. You can compare them with <kbd>diff \/etc\/fstab \/mnt\/root\/f36\/etc\/fstab<\/kbd>. In my case, I also deleted my <em>f34<\/em> snapshot from last year with <kbd>sudo btrfs subvol delete f34<\/kbd>.<\/p>\n<h2 class=\"wp-block-heading\">Test the Btrfs fallback snapshot<\/h2>\n<p>Now you are ready to test the fallback. You could use <a href=\"https:\/\/fedoramagazine.org\/setting-kernel-command-line-arguments-with-fedora-30\/\" target=\"_blank\" rel=\"noreferrer noopener\">grubby<\/a> or edit an entry in \/boot\/loader\/entries to change <em>subvol=root<\/em> to <em>subvol=f36<\/em>. But in the interest of safety for beginners, I will have you edit the GRUB entry at boot time instead. Checkout <a href=\"https:\/\/fedoramagazine.org\/boot-earlier-kernel\/\" target=\"_blank\" rel=\"noreferrer noopener\">this article on GRUB<\/a> for tips on getting to the GRUB menu. Once you are there, press the <strong>e<\/strong> key to edit the default kernel entry. Don&#8217;t worry &#8212; your changes are in volatile memory only. If you mess up, reboot to start over. Just like with fstab, find <em>subvol=root<\/em> and change it to <em>subvol=f36<\/em>. Press <strong>F10<\/strong> or <strong>Ctrl<\/strong>+<strong>X<\/strong> to boot your modified entry. With these changes, the system should boot into your new snapshot. Look at \/etc\/fstab to make sure you are booting from the right subvol, or enter <kbd>mount | grep subvol<\/kbd> to see what subvolume is mounted on &#8220;\/&#8221;. <\/p>\n<h2 class=\"wp-block-heading\">Do the Fedora Linux system upgrade<\/h2>\n<p>If your fallback is working, reboot back to your normal root filesystem (and confirm as above). Then proceed with the standard system-upgrade outlined on the <a href=\"https:\/\/docs.fedoraproject.org\/en-US\/quick-docs\/dnf-system-upgrade\/\" target=\"_blank\" rel=\"noreferrer noopener\">wiki page<\/a>. TIP: Before running <kbd>dnf system-upgrade reboot<\/kbd>, make another snapshot of root. Call it something like <em>root.dl<\/em>. That way, you don&#8217;t have to download five gigabytes of packages again should you discover that there wasn&#8217;t enough free space. The snapshot will not take up any additional space because all but the downloaded packages are shared with <em>root<\/em> and <em>f36<\/em>. About that sharing of disk blocks \u2026 <\/p>\n<p><kbd>dnf system-upgrade<\/kbd> gets confused about free space as reported by Btrfs because the f36 files in the <em>root<\/em> subvolume use the same disk locations as the same files in the <em>f36<\/em> subvolume. So removing them from the <em>root<\/em> subvolume during the upgrade process doesn&#8217;t actually free up any space. If you run out of space, and you reboot &#8212; the graphical user interface (GUI) won&#8217;t start. Use <strong>Ctrl<\/strong>+<strong>Alt<\/strong>+<strong>F2<\/strong> to login on a text console and practice your command line interface skills. Figuring out what to remove to free up space or how to expand the root filesystem is beyond the scope of this article (mine is often on an LVM volume and can be expanded). Having more than 50% free for the upgrade is a safe bet.<\/p>\n<h2 class=\"wp-block-heading\">Recovery<\/h2>\n<p>Should something go wrong, you can reboot and edit the GRUB entry to boot the fallback. If you are a beginner, you&#8217;ll want some hand holding if you do end up needing to change the GRUB entry on disk (so you don&#8217;t have to edit at each boot). It is straight forward to delete or rename the broken <em>root<\/em> subvol. Snapshot the <em>f36<\/em> subvol (or the <em>root.dl<\/em> snapshot) to try the system-upgrade process again. Here is an example of starting over after booting into the fallback system on subvol f36:<\/p>\n<pre class=\"wp-block-preformatted\">$ mount | grep subvol\n$ sudo mount \/dev\/mmcblk2p3 \/mnt\/root\n$ cd \/mnt\/root\n$ sudo mv root root.failed\n$ sudo btrfs subvol snapshot f36 root\nCreate a snapshot of 'f36' in '.\/root' Don't forget to edit \/mnt\/root\/root\/etc\/fstab to change the subvol mounted on \"\/\" to \"root\".<\/pre>\n<p>As it turns out, the new kernel-6.2.11 for f38 did not boot on my Pinebook after the system-upgrade! (Don&#8217;t worry, ARM is an alternative CPU architecture for Fedora Linux &#8212; this is very unlikely to happen to you on a mainstream device.) I was indeed able to boot back to f36 by editing the GRUB entry for kernel-6.2.10 at boot time as described above. I am now using f38 again &#8212; but with kernel-6.2.10 from f36. <\/p>\n<p><strong>Update<\/strong>: <em>kernel-6.2.12 is out and it works on the Pinebook.<\/em><\/p>\n<h2 class=\"wp-block-heading\">Expiration<\/h2>\n<p>As you update the f38 system, it will eventually want to delete the last f36 kernel from \/boot. That is normally not a problem, as by that time you have settled into f38, and the f36 snapshot is just an archive. If you want to keep your fork (f36 snapshot) bootable indefinitely, you should preserve a working f36 kernel under \/boot. The simplest way to do so is to set <em>installonly_limit=0<\/em> in \/etc\/dnf\/dnf.conf and manually remove old kernels. It is simple and safe (but annoying).<\/p>\n<p>Outline of a more complex solution (not for beginners): Run <kbd>find \/boot -name \"*fc36*\"<\/kbd> to list all the kernel and GRUB files for your f36 subvolume snapshot that are under \/boot (which is not in the snapshot). Copy them to a backup location (I would mount the f36 subvolume and copy to a backup directory there). While booted from f38, for each f36 kernel version, use dnf to remove that specific kernel version (for example, <kbd>dnf remove kernel-core-5.19.11-200.fc36<\/kbd>). Do not remove the f38 kernels! Now restore the f36 kernels you saved to \/boot. The f38 system doesn&#8217;t know about f36 kernels anymore, and it will not remove them from \/boot.<\/p>\n<p>The problem with that method is the danger of accidentally removing the running f38 kernel. If anyone has a better method, let me know in the comments.<\/p>\n<h2 class=\"wp-block-heading\">Future directions<\/h2>\n<p>Those comfortable with modifying GRUB entries might consider creating a snapshot subvolume named <em>f38<\/em>, modifying the current GRUB entry to boot into that, rebooting, and running the system-upgrade in that subvolume. Then always name the subvol for the root filesystem after the Fedora Linux release it contains. I did not do that for this article for two reasons.<\/p>\n<ol>\n<li>Naming the current active subvolume <em>root<\/em> matches the Fedora Linux default.<\/li>\n<li>Sticking with <em>root<\/em> for the current subvol does not require any permanent changes outside of the normal system-upgrade procedure.<\/li>\n<\/ol>\n<p>As this article has demonstrated, readonly snapsnots are useful as local restore points in case things go wrong when making significant system changes (such as a system release upgrade). These snapshots can also be sent to a remote backup using Btrfs&#8217; <em>send<\/em> subcommand. (And if the remote backup device already contains previous backups, Btrfs can do an incremental send that only transmits changed files to save time and space.) If you intend to archive these snapshots long term, the key to not getting confused about which ones are which and what order to restore them is to use a consistent naming convention. See the article on <a href=\"https:\/\/fedoramagazine.org\/btrfs-snapshots-backup-incremental\/\" target=\"_blank\" rel=\"noreferrer noopener\">Btrfs snapshots for backup<\/a> for more information about using Btrfs&#8217; <em>send<\/em> command to create backups.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Back in 2018, a previous article demonstrated how to use LVM to clone the root filesystem before upgrading Fedora Linux so as to have a fallback in the unlikely event that something goes wrong. Today, the default Fedora Workstation install uses Btrfs. Now you can use a Btrfs snapshot to make creating a bootable fallback [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48],"tags":[1157,606,45,46,47,1480,1481],"class_list":["post-133662","post","type-post","status-publish","format-standard","hentry","category-fedora-os","tag-btrfs","tag-faqs-and-guides","tag-fedora","tag-magazine","tag-news","tag-snapshot","tag-system-upgrade"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/133662","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=133662"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/133662\/revisions"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=133662"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=133662"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=133662"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}