{"id":130878,"date":"2022-12-30T08:00:00","date_gmt":"2022-12-30T08:00:00","guid":{"rendered":"https:\/\/fedoramagazine.org\/?p=37233"},"modified":"2022-12-30T08:00:00","modified_gmt":"2022-12-30T08:00:00","slug":"working-with-btrfs-snapshots","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2022\/12\/30\/working-with-btrfs-snapshots\/","title":{"rendered":"Working with Btrfs \u2013 Snapshots"},"content":{"rendered":"<p>This article will explore what Btrfs snapshots are, how they work, and how you can benefit from taking snapshots in every-day situations. This is part of a series that takes a closer look at Btrfs, the default filesystem for Fedora Workstation and Fedora Silverblue since Fedora Linux 33. <\/p>\n<p>In case you missed it, here&#8217;s the previous article from this series: <a href=\"https:\/\/fedoramagazine.org\/working-with-btrfs-subvolumes\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/fedoramagazine.org\/working-with-btrfs-subvolumes\/<\/a><\/p>\n<p> <span id=\"more-37233\"><\/span> <\/p>\n<h2>Introduction<\/h2>\n<p>Imagine you work on a file over extended periods of time, repeatedly adding changes and undoing them. Then, at some point you realize: Parts of the changes you undid two hours ago would be very helpful now. And yesterday you had already changed this particular bit, too, before you trashed that design. But of course, because you regularly save your files, old changes are lost. Many people have probably experienced a situation like this before. Wouldn&#8217;t it be great if you could recover old file versions without having to manually copy them at regular intervals?<\/p>\n<p>This is just one typical situation where Btrfs snapshots can help you out. When used correctly, snapshots also give you a great backup solution for your PC. <\/p>\n<p>Below you will find a lot of examples related to snapshots. If you want to follow along, you must have access to a Btrfs filesystem and root access. You can check the file system of a directory using the following command:<\/p>\n<pre class=\"wp-block-preformatted\">$ findmnt -no FSTYPE \/home\nbtrfs<\/pre>\n<p>Here the <em>findmnt <\/em> command shows the type of filesystem for your <em>\/home\/<\/em> directory. If it says <em>btrfs<\/em>, you&#8217;re all set. Let&#8217;s create a new directory in which to perform some experiments:<\/p>\n<pre class=\"wp-block-preformatted\">$ mkdir ~\/btrfs-snapshot-test\n$ cd ~\/btrfs-snapshot-test<\/pre>\n<p>In the text below, you will find lots of command responses in boxes such as shown above. Please keep in mind while reading\/comparing command output that the <strong>box contents may be wrapped at the end of the line<\/strong>. This may make it difficult to recognize long lines that are broken across multiple lines for readability. When in doubt, try to resize your browser window and see how the text behaves!<\/p>\n<h2>Snapshots in Btrfs<\/h2>\n<p>Let&#8217;s start with an elementary question: What is a Btrfs snapshot? If you look in the Docs <a href=\"#sources\">[1]<\/a> and Wiki <a href=\"#sources\">[2]<\/a>, you won&#8217;t immediately find an answer to this question. In fact, it is nowhere to be found in the &#8220;Features&#8221; section. If you search a little, you will find snapshots mentioned extensively along with Btrfs subvolumes <a href=\"https:\/\/btrfs.readthedocs.io\/en\/latest\/Subvolumes.html\">[3]<\/a>. So now what?<\/p>\n<p>Remember that snapshots were both mentioned in the previous articles of this series? There it said: <\/p>\n<blockquote class=\"wp-block-quote\">\n<p>What is the advantage of CoW? In simple terms: a history of the modified and edited files can be kept. Btrfs will keep the references to the old file versions (inodes) somewhere they can be easily accessed. This reference is a <em>snapshot<\/em>: An image of the filesystem state at some point in time.<\/p>\n<p><cite><a href=\"https:\/\/fedoramagazine.org\/working-with-btrfs-general-concepts\/\" target=\"_blank\" rel=\"noreferrer noopener\">Working with Btrfs: General Concepts<\/a><\/cite><\/p><\/blockquote>\n<p>and also:<\/p>\n<blockquote class=\"wp-block-quote\">\n<p>Another advantage of separating <em>\/<\/em> and <em>\/home<\/em> is that you can take <em>snapshots<\/em> separately. A subvolume is a boundary for snapshots, and snapshots will never contain the contents of other subvolumes below the subvolume that the snapshot is taken of.<\/p>\n<p><cite><a href=\"https:\/\/fedoramagazine.org\/working-with-btrfs-subvolumes\/\" target=\"_blank\" rel=\"noreferrer noopener\">Working with Btrfs: Subvolumes<\/a><\/cite><\/p><\/blockquote>\n<p>It seems snapshots have something to do with Btrfs subvolumes. You may have heard about snapshots in other contexts before, for example with LVM, the Logical Volume Manager. While technically they serve the same purpose, they are different in terms of how they reach their goal.<\/p>\n<p>Every Btrfs snapshot is a subvolume. However, not every subvolume is a snapshot. The difference is in what the subvolume contains. A snapshot is a subvolume with added content: it holds references to current and\/or past versions of files (inodes). Let&#8217;s see where snapshots come from!<\/p>\n<h2>Creating Btrfs snapshots<\/h2>\n<p>To use snapshots, you need a Btrfs subvolume to take snapshots of. Let&#8217;s create one inside our test folder (~\/btrfs-snapshot-test):<\/p>\n<pre class=\"wp-block-preformatted\">$ cd ~\/btrfs-snapshot-test\n$ sudo btrfs subvolume create demo\nCreate subvolume '.\/demo'\n$ sudo chown -R $(id -u):$(id -g) demo\/\n$ cd demo<\/pre>\n<p>Since by default Btrfs subvolumes are owned by root, you must call <em>chown<\/em> to modify the files in the subvolume to be owned by a regular user. Now add a few files inside it:<\/p>\n<pre class=\"wp-block-preformatted\">$ touch foo bar baz\n$ echo \"Lorem ipsum dolor sit amet, \" &gt; foo<\/pre>\n<p>Your directory now looks something like this:<\/p>\n<pre class=\"wp-block-preformatted\">$ ls -l\ntotal 4\n-rw-r--r--. 1 hartan hartan 0 Dec 20 08:11 bar\n-rw-r--r--. 1 hartan hartan 0 Dec 20 08:11 baz\n-rw-r--r--. 1 hartan hartan 29 Dec 20 08:11 foo<\/pre>\n<p>Let&#8217;s create the very first snapshot from that:<\/p>\n<pre class=\"wp-block-preformatted\">$ cd ..\n$ sudo btrfs subvolume snapshot demo demo-1\nCreate a snapshot of 'demo' in '.\/demo-1'<\/pre>\n<p>And that&#8217;s it. Let&#8217;s see what was achieved:<\/p>\n<pre class=\"wp-block-preformatted\">$ ls -l\ntotal 0\ndrwxr-xr-x. 1 hartan hartan 18 Dec 20 08:11 demo\ndrwxr-xr-x. 1 hartan hartan 18 Dec 20 08:11 demo-1\n$ tree\n.\n\u251c\u2500\u2500 demo\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 bar\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 baz\n\u2502&nbsp;&nbsp; \u2514\u2500\u2500 foo\n\u2514\u2500\u2500 demo-1 \u251c\u2500\u2500 bar \u251c\u2500\u2500 baz \u2514\u2500\u2500 foo 2 directories, 6 files<\/pre>\n<p>It seems it made a copy! To verify, let&#8217;s read the contents of <em>foo<\/em> from the snapshot:<\/p>\n<pre class=\"wp-block-preformatted\">$ cat demo\/foo\nLorem ipsum dolor sit amet,\n$ cat demo-1\/foo\nLorem ipsum dolor sit amet,<\/pre>\n<p>The real effect becomes apparent when we modify the original file:<\/p>\n<pre class=\"wp-block-preformatted\">$ echo \"consectetur adipiscing elit, \" &gt;&gt; demo\/foo\n$ cat demo\/foo\nLorem ipsum dolor sit amet, consectetur adipiscing elit,\n$ cat demo-1\/foo\nLorem ipsum dolor sit amet,<\/pre>\n<p>This shows that the snapshot still holds the &#8220;old&#8221; version of the data: The content of <em>foo<\/em> hasn&#8217;t changed. So far, you could have achieved the exact same thing with a simple file copy. You can now go ahead and continue working on the old file, too:<\/p>\n<pre class=\"wp-block-preformatted\">$ echo \"sed do eiusmod tempor incididunt\" &gt;&gt; demo-1\/foo\n$ cat demo-1\/foo\nLorem ipsum dolor sit amet, sed do eiusmod tempor incididunt<\/pre>\n<p>Under the hood, however, our snapshot is in fact a new Btrfs subvolume. You can verify this with the following command:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume list -o .\nID 259 gen 265 top level 256 path home\/hartan\/btrfs-snapshot-test\/demo\nID 260 gen 264 top level 256 path home\/hartan\/btrfs-snapshot-test\/demo-1<\/pre>\n<h2>Btrfs snapshots vs. file copies<\/h2>\n<p>So what&#8217;s the point of all this? Up until now snapshots seem to be a complicated way to copy files around. In fact, there is more to snapshots than meets the eye. Let&#8217;s create a bigger file:<\/p>\n<pre class=\"wp-block-preformatted\">$ dd if=\/dev\/urandom of=demo\/bigfile bs=1M count=512\n512+0 records in\n512+0 records out\n536870912 bytes (537 MB, 512 MiB) copied, 1.3454 s, 399 MB\/s<\/pre>\n<p>There is now a new file <em>demo\/bigfile<\/em> that is 512 MiB in size. Let&#8217;s make another snapshot so you don&#8217;t lose it when you modify the data:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume snapshot demo demo-2\nCreate a snapshot of 'demo' in '.\/demo-2'<\/pre>\n<p>Now let&#8217;s simulate some changes by appending a small string to the file:<\/p>\n<pre class=\"wp-block-preformatted\">$ echo \"small changes\" &gt;&gt; demo\/bigfile<\/pre>\n<p>Here&#8217;s the resulting file structure:<\/p>\n<pre class=\"wp-block-preformatted\">$ tree\n.\n\u251c\u2500\u2500 demo\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 bar\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 baz\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 bigfile\n\u2502&nbsp;&nbsp; \u2514\u2500\u2500 foo\n\u251c\u2500\u2500 demo-1\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 bar\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 baz\n\u2502&nbsp;&nbsp; \u2514\u2500\u2500 foo\n\u2514\u2500\u2500 demo-2 \u251c\u2500\u2500 bar \u251c\u2500\u2500 baz \u251c\u2500\u2500 bigfile \u2514\u2500\u2500 foo 3 directories, 11 files<\/pre>\n<p>But the real magic happens somewhere else. Had you copied <em>demo\/bigfile<\/em>, you would now have two files of about 512 MiB in size with mostly the same content. However, since they are distinct copies, they would occupy about 1 GiB of storage total. Keep in mind that the difference between both files is hardly more than 10 Bytes &#8211; that&#8217;s almost nothing compared to the original file size.<\/p>\n<p>Btrfs snapshots work different than file copies: They keep references to current and past inodes instead. When you appended the change to the file, under the hood Btrfs allocated some more space to store the changes in and added a reference to this new data to the original inode. The previous contents remain untouched. If it helps your mental model, you can think of this as &#8220;storing&#8221; merely the difference between the original file and the modified version.<\/p>\n<p>Let&#8217;s have a look at the effect of this:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo compsize .\nProcessed 11 files, 5 regular extents (9 refs), 3 inline.\nType Perc Disk Usage Uncompressed Referenced TOTAL 100% 512M 512M 1.0G none 100% 512M 512M 1.0G<\/pre>\n<p>The interesting figure here is seen in line &#8220;TOTAL&#8221;:<\/p>\n<ul>\n<li>&#8220;Referenced&#8221; is the total size of all the files in the current directory, summed up<\/li>\n<li>&#8220;Disk Usage&#8221; is the amount of storage space allocated on your disk to store the files<\/li>\n<\/ul>\n<p>While you have a total of 1 GiB files, it takes merely 512 MiB to store them.<\/p>\n<h2>Btrfs snapshots and backups<\/h2>\n<p>So far, in this article, you have seen how to create Btrfs snapshots and what makes them so special. One may be tempted to think: If I take a series of Btrfs snapshots locally on my PC, I have a solid backup strategy. <strong>This is not the case<\/strong>. If the underlying data, which is shared by Btrfs subvolumes, is accidentally damaged (by something outside of Btrfs&#8217; influence, e.g. cosmic rays), all the subvolumes pointing to this data contain the same error.<\/p>\n<p>To turn the snapshots into real backups you should store them on a different Btrfs filesystem, such as on an external drive. For the purposes of this article let&#8217;s create a new Btrfs filesystem contained inside a file and mount it to simulate an external drive. If you have an external drive formatted with Btrfs lying around, feel free to substitute all the paths mentioned in the following commands to try it out! Let&#8217;s create a new Btrfs filesystem:<\/p>\n<p><strong>Note<\/strong>: The commands below will create a new file of 8 GB size on your filesystem. If you want to follow the steps below, please ensure you have at least 8 GB of disk space available. Do not allocate less than 8 GB to the file, as Btrfs may otherwise encounter issues during mounting.<\/p>\n<pre class=\"wp-block-preformatted\">$ truncate -s 8G btrfs_filesystem.img\n$ sudo mkfs.btrfs -L \"backup-drive\" btrfs_filesystem.img\nbtrfs-progs v5.18\nSee http:\/\/btrfs.wiki.kernel.org for more information. [ ... ] Devices: ID SIZE PATH 1 8.00GiB btrfs_filesystem.img<\/pre>\n<p>These commands created a new file of 8 GB in size named <em>btrfs_filesystem.img<\/em> and formatted a Btrfs filesystem inside it. Now you can mount it as if it were an external drive:<\/p>\n<pre class=\"wp-block-preformatted\">$ mkdir backup-drive\n$ sudo mount btrfs_filesystem.img backup-drive\n$ sudo chown -R $(id -u):$(id -g) backup-drive\n$ ls -lh\ntotal 4.7M\ndrwxr-xr-x. 1 hartan hartan 0 Dec 20 08:35 backup-drive\n-rw-r--r--. 1 hartan hartan 8.0G Dec 20 08:37 btrfs_filesystem.img\ndrwxr-xr-x. 1 hartan hartan 32 Dec 20 08:14 demo\ndrwxr-xr-x. 1 hartan hartan 18 Dec 20 08:11 demo-1\ndrwxr-xr-x. 1 hartan hartan 32 Dec 20 08:14 demo-2<\/pre>\n<p>Great, now there is an independent Btrfs filesystem mounted under <em>backup-drive<\/em>! Let&#8217;s try to take another snapshot and place it there:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume snapshot demo backup-drive\/demo-3\nCreate a snapshot of 'demo' in 'backup-drive\/demo-3'\nERROR: cannot snapshot 'demo': Invalid cross-device link<\/pre>\n<p>What happened? Well, you tried to take a snapshot of <em>demo<\/em> and store it in a different Btrfs filesystem (a different device from Btrfs&#8217; point of view). Remember that a Btrfs subvolume only holds references to files and their contents (inodes)? This is exactly the problem: The files and contents exist in our home filesystem, but not in the newly-created <em>backup-drive<\/em>. You have to find a way to transfer the subvolume along with its contents to the new filesystem.<\/p>\n<h3>Storing snapshots on a different Btrfs filesystem<\/h3>\n<p>The Btrfs utilities include two special commands for this purpose. Let&#8217;s see how they work first:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs send demo | sudo btrfs receive backup-drive\/\nERROR: subvolume \/home\/hartan\/btrfs-snapshot-test\/demo is not read-only\nERROR: empty stream is not considered valid<\/pre>\n<p>Another error! This time it tells you that the subvolume we&#8217;re trying to transfer is not read-only. This is true: You can write new contents to all of the snapshots\/subvolumes created so far. You can create read-only snapshots like this:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume snapshot -r demo demo-3-ro\nCreate a readonly snapshot of 'demo' in '.\/demo-3-ro'<\/pre>\n<p>Unlike previously, here the <em>-r<\/em> option is added to the <em>snapshot<\/em> subcommand. This creates a read-only snapshot, which is easily verified:<\/p>\n<pre class=\"wp-block-preformatted\">$ touch demo-3-ro\/another-file\ntouch: cannot touch 'demo-3-ro\/another-file': Read-only file system<\/pre>\n<p>Now you can retry transferring the subvolumes:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs send demo-3-ro | sudo btrfs receive backup-drive\/\nAt subvol demo-3-ro\nAt subvol demo-3-ro\n$ tree \u251c\u2500\u2500 backup-drive\n\u2502&nbsp;&nbsp; \u2514\u2500\u2500 demo-3-ro\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 bar\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 baz\n\u2502&nbsp;&nbsp; \u251c\u2500\u2500 bigfile\n\u2502&nbsp;&nbsp; \u2514\u2500\u2500 foo\n\u251c\u2500\u2500 btrfs_filesystem.img\n\u251c\u2500\u2500 demo\n[ ... ]\n\u2514\u2500\u2500 demo-3-ro \u251c\u2500\u2500 bar \u251c\u2500\u2500 baz \u251c\u2500\u2500 bigfile \u2514\u2500\u2500 foo 6 directories, 20 files<\/pre>\n<p>It worked! You have successfully transferred a read-only snapshot of our original subvolume <em>demo<\/em> to an external Btrfs filesystem.<\/p>\n<h3>Storing snapshots on non-Btrfs filesystems<\/h3>\n<p>Above you have seen how you can store Btrfs subvolumes\/snapshots on another Btrfs filesystem. But what can you do if you do not have another Btrfs filesystem and cannot create one, for example because the external drives need a filesystem that allows compatibility with Windows or MacOS hosts? In such cases you can store subvolumes in files:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs send -f demo-3-ro-subvolume.btrfs demo-3-ro\nAt subvol demo-3-ro\n$ ls -lh demo-3-ro-subvolume.btrfs -rw-------. 1 root root 513M Dec 21 10:39 demo-3-ro-subvolume.btrfs<\/pre>\n<p>The file <em>demo-3-ro-subvolume.btrfs<\/em> now contains everything that is needed to recreate the <em>demo-3-ro<\/em> subvolume at a later point in time.<\/p>\n<h3>Incrementally sending subvolumes<\/h3>\n<p>If you perform this action repeatedly for different subvolumes, you will notice at some point that the different subvolumes do not share their file contents any more. This is because when sending a subvolume such as above, all the data needed to recreate this standalone subvolume is transferred to the target. You can, however, instruct Btrfs to only send the difference between two subvolumes to the target! This so-called incremental send will ensure that shared references remain shared between the subvolumes. To demonstrate this, add a few more changes to our original subvolume:<\/p>\n<pre class=\"wp-block-preformatted\">$ echo \"a few more changes\" &gt;&gt; demo\/bigfile<\/pre>\n<p>Next create another read-only snapshot:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume snapshot -r demo demo-4-ro\nCreate a readonly snapshot of 'demo' in '.\/demo-4-ro'<\/pre>\n<p>And now send it:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs send -p demo-3-ro demo-4-ro | sudo btrfs receive backup-drive\nAt subvol demo-4-ro\nAt snapshot demo-4-ro<\/pre>\n<p>In the command above, the <em>-p<\/em> option specifies a parent subvolume, against which the differences are calculated. It is important to keep in mind that both the source and target Btrfs filesystem must contain the same, unmodified parent subvolume! Ensure that the new subvolume is really there:<\/p>\n<pre class=\"wp-block-preformatted\">$ ls backup-drive\/\ndemo-3-ro demo-4-ro\n$ ls -lR backup-drive\/demo-4-ro\/\nbackup-drive\/demo-4-ro\/:\ntotal 524296\n-rw-r--r--. 1 hartan hartan 0 Dec 20 08:11 bar\n-rw-r--r--. 1 hartan hartan 0 Dec 20 08:11 baz\n-rw-r--r--. 1 hartan hartan 536870945 Dec 21 10:49 bigfile\n-rw-r--r--. 1 hartan hartan 59 Dec 20 08:13 foo<\/pre>\n<p>But how do you know whether the incremental send only transferred the difference between both subvolumes? Let&#8217;s transfer the data stream to a file and see how big it is:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs send -f demo-4-ro-diff.btrfs -p demo-3-ro demo-4-ro\nAt subvol demo-4-ro\n$ ls -l demo-4-ro-diff.btrfs -rw-------. 1 root root 315 Dec 21 10:55 demo-4-ro-diff.btrfs<\/pre>\n<p>According to ls, the file is merely 315 bytes in size! This means that the incremental send only transferred the changes between the two subvolumes, along with additional Btrfs-specific metadata.<\/p>\n<h3>Restoring subvolumes from snapshots<\/h3>\n<p>Before continuing, let&#8217;s do some cleaning up of the things you don&#8217;t need at the moment:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo rm -rf demo-4-ro-diff.btrfs demo-3-ro-subvolume.btrfs\n$ sudo btrfs subvolume delete demo-1 demo-2 demo-3-ro demo-4-ro\n$ ls -l\ntotal 531516\ndrwxr-xr-x. 1 hartan hartan 36 Dec 21 10:50 backup-drive\n-rw-r--r--. 1 hartan hartan 8589934592 Dec 21 10:51 btrfs_filesystem.img\ndrwxr-xr-x. 1 hartan hartan 32 Dec 20 08:14 demo<\/pre>\n<p>So far you have managed to create read\/write and read-only snapshots of Btrfs subvolumes and send them to an external location. In order to turn this into a backup strategy, however, there has to be a way to send the subvolumes back to the original filesystem and make them writable again. For this purpose, let&#8217;s move the demo subvolume somewhere else and try to recreate it from the most recent snapshot. First: Rename the &#8220;broken&#8221; subvolume. It will be deleted once the restore was successful:<\/p>\n<pre class=\"wp-block-preformatted\">$ mv demo demo-broken<\/pre>\n<p>Second: Transfer the most recent snapshot back to this filesystem:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs send backup-drive\/demo-4-ro | sudo btrfs receive .\nAt subvol backup-drive\/demo-4-ro\nAt subvol demo-4-ro\n[hartan@fedora btrfs-snapshot-test]$ ls\nbackup-drive btrfs_filesystem.img demo-4-ro demo-broken<\/pre>\n<p>Third: Create a read-write subvolume from the snapshot:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume snapshot demo-4-ro demo\nCreate a snapshot of 'demo-4-ro' in '.\/demo'\n$ ls\nbackup-drive btrfs_filesystem.img demo demo-4-ro demo-broken<\/pre>\n<p>The last step is important: You cannot just rename <em>demo-4-ro<\/em> to <em>demo<\/em>, because it would still be a read-only subvolume! Finally you can check whether everything you need is there:<\/p>\n<pre class=\"wp-block-preformatted\">$ tree demo\ndemo\n\u251c\u2500\u2500 bar\n\u251c\u2500\u2500 baz\n\u251c\u2500\u2500 bigfile\n\u2514\u2500\u2500 foo 0 directories, 4 files\n$ tail -c -19 demo\/bigfile a few more changes<\/pre>\n<p>The last command above tells you that the last 19 characters in <em>bigfile<\/em> are in fact the change last performed. At this point, you may want to copy recent changes from <em>demo-broken<\/em> to the new <em>demo<\/em> subvolume. Since you didn&#8217;t perform any other changes, you can now delete the obsolete subvolumes:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume delete demo-4-ro demo-broken\nDelete subvolume (no-commit): '\/home\/hartan\/btrfs-snapshot-test\/demo-4-ro'\nDelete subvolume (no-commit): '\/home\/hartan\/btrfs-snapshot-test\/demo-broken'<\/pre>\n<p>And that&#8217;s it! You have successfully restored the <em>demo<\/em> subvolume from a snapshot that was previously stored on a different Btrfs filesystem (external media).<\/p>\n<h2>Subvolumes as boundary for snapshots<\/h2>\n<p>In the second article of this series I mentioned that subvolumes are boundaries for snapshots, but what exactly does that mean? In simple terms, a snapshot of a subvolume will only contain the content of this particular subvolume, and none of the nested subvolumes below. Let&#8217;s have a look at this:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume create demo\/nested\nCreate subvolume 'demo\/nested'\n$ sudo chown -R $(id -u):$(id -g) demo\/nested\n$ touch demo\/nested\/another_file<\/pre>\n<p>Let&#8217;s take a snapshot as before:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume snapshot demo demo-nested\nCreate a snapshot of 'demo' in '.\/demo-nested'<\/pre>\n<p>And check out the contents:<\/p>\n<pre class=\"wp-block-preformatted\">$ tree demo-nested\ndemo-nested\n\u251c\u2500\u2500 bar\n\u251c\u2500\u2500 baz\n\u251c\u2500\u2500 bigfile\n\u251c\u2500\u2500 foo\n\u2514\u2500\u2500 nested 1 directory, 4 files $ tree demo\ndemo\n\u251c\u2500\u2500 bar\n\u251c\u2500\u2500 baz\n\u251c\u2500\u2500 bigfile\n\u251c\u2500\u2500 foo\n\u2514\u2500\u2500 nested \u2514\u2500\u2500 another_file 1 directory, 5 files<\/pre>\n<p>Notice that <em>another_file<\/em> is missing, even though the folder <em>nested<\/em> is present. This happens because <em>nested<\/em> is a subvolume: The snapshot of <em>demo<\/em> contains the folder (mountpoint) for the nested subvolume, but its contents aren&#8217;t present. Currently there is no way to perform snapshots recursively to include nested subvolumes. However, we can take advantage of this to exclude folders from snapshots! This is typically useful for data that you can reproduce easily, or that will rarely change. Examples include virtual machine or container images, movies, game files and more.<\/p>\n<p>Before we wrap up the article, let&#8217;s remove everything we created while testing:<\/p>\n<pre class=\"wp-block-preformatted\">$ sudo btrfs subvolume delete demo\/nested demo demo-nested\nDelete subvolume (no-commit): '\/home\/hartan\/btrfs-snapshot-test\/demo\/nested'\nDelete subvolume (no-commit): '\/home\/hartan\/btrfs-snapshot-test\/demo'\nDelete subvolume (no-commit): '\/home\/hartan\/btrfs-snapshot-test\/demo-nested'\n$ sudo umount backup-drive\n$ cd ..\n$ rm -rf btrfs-snapshot-test\/<\/pre>\n<h2>Final thoughts on Btrfs-based backups<\/h2>\n<p>If you decide you want to use Btrfs to perform regular backups of your data, you may want to use a tool that automates this task for you. The Btrfs wiki has a list of backup tools specialized on Btrfs <a href=\"#sources\">[4]<\/a>. On this page you will also find another summary of the steps to perform Btrfs backups by hand. Personally, I have had a lot of good experiences with <em>btrbk<\/em> <a href=\"#sources\">[5]<\/a> and I am using it to perform my own backups. In addition to backups, <em>btrbk<\/em> can also keep a list of Btrfs snapshots locally on your PC. I use this to safeguard against accidental data deletion.<\/p>\n<p>If you want to know more about performing backups using Btrfs, leave a comment below and I&#8217;ll consider writing a follow-up article that deals exclusively with this topic.<\/p>\n<h2>Conclusion<\/h2>\n<p>This article investigated Btrfs snapshots, which are Btrfs subvolumes under the hood. You learned how to create read\/write and read-only snapshots, and how this mechanism can help safeguard against data loss.<\/p>\n<p>The next articles in this series will deal with:<\/p>\n<ul>\n<li>Compression \u2013 Transparently saving storage space<\/li>\n<li>Qgroups \u2013 Limiting your filesystem size<\/li>\n<li>RAID \u2013 Replace your mdadm configuration<\/li>\n<\/ul>\n<p>If there are other topics related to Btrfs that you want to know more about, have a look at the Btrfs Wiki <a href=\"#sources\">[2]<\/a> and Docs <a href=\"#sources\">[1]<\/a>. Don\u2019t forget to check out the first two articles of this series, if you haven\u2019t already! If you feel that there is something missing from this article series, let me know in the comments below. See you in the next article!<\/p>\n<h2 id=\"sources\">Sources<\/h2>\n<p>[1]: <a href=\"https:\/\/btrfs.readthedocs.io\/en\/latest\/Introduction.html\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/btrfs.readthedocs.io\/en\/latest\/Introduction.html<\/a><br \/>[2]: <a href=\"https:\/\/btrfs.wiki.kernel.org\/index.php\/Main_Page\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/btrfs.wiki.kernel.org\/index.php\/Main_Page<\/a><br \/>[3]: <a href=\"https:\/\/btrfs.readthedocs.io\/en\/latest\/Subvolumes.html\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/btrfs.readthedocs.io\/en\/latest\/Subvolumes.html<\/a><br \/>[4]: <a href=\"https:\/\/btrfs.wiki.kernel.org\/index.php\/Incremental_Backup#Available_Backup_Tools\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/btrfs.wiki.kernel.org\/index.php\/Incremental_Backup#Available_Backup_Tools<\/a><br \/>[5]: <a href=\"https:\/\/github.com\/digint\/btrbk\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/digint\/btrbk<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article will explore what Btrfs snapshots are, how they work, and how you can benefit from taking snapshots in every-day situations. This is part of a series that takes a closer look at Btrfs, the default filesystem for Fedora Workstation and Fedora Silverblue since Fedora Linux 33. In case you missed it, here&#8217;s the [&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":[45,61,46,47],"class_list":["post-130878","post","type-post","status-publish","format-standard","hentry","category-fedora-os","tag-fedora","tag-fedora-project-community","tag-magazine","tag-news"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/130878","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=130878"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/130878\/revisions"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=130878"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=130878"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=130878"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}