Introduction
I recently had the task of fixing up an old Dell laptop to make it usable again. The laptop ran Windows 10, but it was very slow. After looking at the specs, I understood why. The laptop ran off an HDD and had only 4 GB of memory. Not great for Windows 10. However, there was one thing which made this laptop different. It had a small ~14 GB Intel Optane SSD.
For those who haven’t heard of the technology, Intel Optane is a specialized high endurance SSD and corresponding software which allows the SSD to be used as a cache. Unfortunately, the software is not available for Linux. Instead, I found a similar Linux software called bcache which can utilize a storage device as a cache.
Project Goals
To fix up the laptop, I choose to install Linux Mint on it. It runs much faster than Windows and has a fairly similar interface.
For the filesystem, I choose to use BTRFS. This is not the default for a standard Linux Mint install, but I felt like some of the features it offers, namely compression and snapshots, could be useful for the system.
On the Intel Optane SSD, I decided to use it for both extra swap space and a a bcache cache device. Since the system only has 4GB of RAM, it definitely needs some swap. While I could put that swap directly on the cached hard drive, I figure it is probably more efficient to reserve some space on the SSD. The rest of the space can be used for bcache.
Installing Mint
Linux Mint is relatively easy to install, at least for a standard installation. First, download Linux Mint from the Mint website, flash it to a USB, and resize the Windows partition using the Windows disk manager to leave free space for Linux. From there, it is very straightforward to boot from the USB and run the installer to setup dual booting. To install with BTRFS and bcache, however, things get a bit trickier. The standard Mint installer does not provide default options for BTRFS or bcache.
Fortunately, I found this tutorial describing how to setup bcache on a new Linux install. The trick is to first install Mint on a small 16 GB partition. After booting into it, you can setup the real partition as a bcache backing device and copy everything over to it.
To install with BTRFS and bcache, you’ll want to choose a custom partition setup in the Mint install. Create a small ~500 MB /boot partition, optionally on the SSD, and a small 16 GB BTRFS root partition on the HDD. After setting up the partitions, you can continue as normal with the Mint install.
If you intend to use BTRFS, I recommend creating the temporary small 16 GB root partitions as BTRFS, even if you intend to later copy the files to a new bigger partition. Otherwise, the @root and @home subvolumes won’t be automatically created and setup to mount in fstab. It is certainly possible to adjust this later, but if you aren’t familiar with BTRFS and fstab, it might be a challenge.
Setting up Bcache
After installing Mint, reboot and make sure it boots into the freshly installed OS. After connecting to the Internet, you’ll want to install a couple tools which will be used for the setup.
sudo apt update
sudo apt install bcache-tools gparted
Using GParted, create an “unformatted” partition with the remaining free space on the HDD. This is where the actual filesystem and the bcache “backing” device will go. After creating the new partition and hitting apply, make note of the device name listed in GParted. You can use this to create the backing device.
# sdb# = backing partiton on HDD
make-bcache -B /dev/sdb#
This is were I diverge from the tutorial a little bit. The tutorial suggests using rsync to copy files over to the new partition. However, since I am using BTRFS, I didn’t want to mess with recreating the subvolumes. Instead, I decided to use dd. Use it with caution and make sure to specify the right partitions!
# old root new cached root
dd if=/dev/sdb# of=/dev/bache0 status=progress bs=1M
After running this command, the root partition is now duplicated onto the backing bcache0 device. At this point, there are now two root partitions with the same UUID. This will cause confusion, especially at boot, so we need to change the UUIDs to be unique.
Boot into the live USB and start GParted. Select the small 16 GB root partition and click change UUID. If you are confident the copy went well, you can also go ahead and format the partition in a swap partition. On the next boot, GRUB should look for the partition by UUID, find the new cached root on bcache0, and boot from that.
Now is also a good time to resize the BTRFS partition to take up the full space. GParted doesn’t find bcache devices by default, so you will need to open it from the terminal. Open the terminal and run gparted /dev/bcache0. GParted should open the large bcache0 device and a small 16 GB BTRFS partition. Right click it and choose resize to fill the full space.
If all went well, you should now be booting from bcache0. To be sure, make sure the old 16 GB root is formatted as swap.
BTRFS Compression
One advantage of BTRFS is that it supports block level compression. Especially for slow mediums like HDDs, this compression is basically free. First, you will need to pick an algorithm and compression level. Based on this benchmark, I decided to go with a zstd and a compression level of 2. It is possible I could go even higher for a slow HDD, but given the older processor on the laptop, I decided to stick with level 2.
To add this, edit /etc/fstab, and add either compress=zstd:2 or compress-force=zstd:2 to the entries for root and home. The first option will attempt to compress the start of each file and will give up if it doesn’t become smaller. The second option always tries to compress the entire file before giving up. Depending on your use case, either option can be a good choice. This is also a good time to add the noatime option if you want it. After adding the options to fstab and rebooting, compression should be enabled for new files.
Compressing Existing Files
Compressing existing files is a bit trickier. Due to some issues I ran into, I recommend performing this from the live installation media. You will need to manually mount /dev/bcache0 to do this. For the BTRFS, the defrag command is used to apply compression. You will need to run it with the recursive command and specify the compression type.
Run this with caution. When I ran it, it failed to defragment /var/log/syslog and /var/log/kern.log. Later, I discovered that these files had somehow been corrupted. Running from the live USB instead may prevent this.
# Register the bcache device
sudo su
echo /dev/sdb# > /sys/fs/bcache/register
# Mount the bcache device
mkdir root
mount /dev/bcache0 ./root/
# Defragment
btrfs filesystem defrag -r -czstd ./root/
Fixing BTRFS Corruption
Sometime after I ran defrag on the live system, it suddenly failed to boot with BTRFS checksum errors in the log. This is quite concerning, since it either indicates faulty memory, a failing hard drive, or a bug in BTRFS. According to the ArchWiki, BTRFS and bcache have had compatibility issues in the past, but this was supposedly fixed in kernel 3.19.
I ran couple passes of the memory test builtin to the Linux Mint, but nothing showed up. It’s still possible the memory is going bad, but it at least isn’t completely failing yet. Whatever the issue, if it continues, BTRFS should make the issue obvious when is recurs.
To fix the corrupt filesystem, I first booted up the live USB and registered the bcache device. Next, I ran btrfs check to make sure the filesystem itself wasn’t damaged. This ran successfully, so I moved onto scrub. The btrfs scrub command goes through all files and ensures the checksum is correct. It runs in the background and takes some time to complete, so you can watch the status with btrfs scrub status.
# Register the bcache device
sudo su
echo /dev/sdb# > /sys/fs/bcache/register
# Check the filesystem
btrfs check /dev/bcache0
# Check the checksums
btrfs scrub start /dev/bcache0
watch btrfs scrub status
# Find the names of failed files
dmesg
After the scrub finished, it found two files with errors. Looking in dmesg, I found the name of those files to be /var/log/syslog and /var/log/kern.log. These are the same files which failed to defrag earlier. Fortunately, since these were just log files, I felt safe deleting them. After deleting the files and rebooting, the system seemed to work like normal.
Configuring Swap
Before adding the actual cache device on the Intel Optane SSD, I wanted to setup a small swap. Since the laptop only has 4 GB of RAM, the extra SSD swap could definitely be helpful. I created a 4 GB swap partition on the SSD with GParted. Together with the 16 GB HDD swap partition, this gives 20 GB of swap for the laptop.
Obviously, swap on the SSD is going to be much faster than swap on the HDD. Because of this, I decided to set swap priorities to make the SSD be used first. This can be setup in fstab, as shown below.
After creating your desired swap partition in GParted, note down their UUIDs. You can get the UUID of a device using the blkid command, as shown below. Edit fstab and add entries with the UUIDs and your desired priorities. The Mint installer likely added a swapfile. You can disable this if you don’t think it will be needed.
# To get the UUID of a partition
blkid /dev/...
nano /etc/fstab
# /swapfile none swap sw,pri=1 0 0
UUID=*SSD 4GB uuid* none swap sw,pri=2 0 0
UUID=*HDD 16GB uuid* none swap sw,pri=3 0 0
# To reload the swap without a reboot
swapoff -a
swapon -a
Adding the Cache Device
Finally, it is time to add the bcache cache device on the Optane SSD. First, partition the remaining space on the SSD as unformatted in GParted. Next, initialize the bcache cache on the empty partition, as shown below. Finally, you will need to register the cache device as the cache for the backing hard drive partition, which is also shown below.
# sdc# = cache partition on SSD
make-bcache -C /dev/sdc#
sudo su
echo <CSET-UUID> > /sys/block/bcache0/bcache/attach
The CSET-UUID should be provided when you run the make-bcache command. If you loose the output, you can find it again with ls /sys/fs/bcache.
After registering the new device, reboot a few times and appreciate the performance benefits bcache provides.