
My previous post described how I migrated my girlfriend’s father from Windows 10 to Linux Mint. While doing so, I used the default Ext4 filesystem, as opposed to Btrfs, for the root partition. No big deal, but Btrfs makes it a whole lot easier snapshotting the filesystem and rolling back if needed. Timeshift can automatically take care of all that, and it allows for some more peace of mind while configuring automatic OS updates.
I decided to document how to convert the Ext4 root filesystem to Btrfs, just in case for when I (inevitably) need to do some maintenance on my girlfriend’s father’s computer, such as an OS upgrade. I found a how-to by Klinsmann Öteyo which proved very useful for most steps, apart for some edge-cases such as Btrfs subvolume naming differences to facilitate Timeshift, or when using an encrypted setup (LUKS+LVM).
First, boot with a Linux Mint live image, and identify the partitions on disk:
root # fdisk -l
For me it was:
-
/dev/nvme0n1p1
: fat32 ESP (/boot); -
/dev/nvme0n1p2
: ext4 root (/).
Note
|
Or, if you decided to encrypt the system during installation, like so: ![]() Then you’d likely have something similar to:
If so, decrypt your LUKS encrypted partition:
And replace |
Verify the identified root filesystem is indeed Ext4:
root # file -sL /dev/nvme0n1p2
/dev/nvme0n1p2: Linux rev 1.0 ext4 filesystem data, UUID=881a1715-51b1-4448-ae03-96ff8dfa74d9 (extents) (64bit) (large files) (huge files)
As a precaution, you may wish to check the filesystem for consistency:
root # fsck.ext4 -fyv /dev/nvme0n1p2
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
473863 inodes used (45.73%, out of 1036320)
83 non-contiguous files (0.0%)
298 non-contiguous directories (0.1%)
# of inodes with ind/dind/tind blocks: 0/0/0
Extent depth histogram: 312233/16
1902834 blocks used (45.96%, out of 4140032)
0 bad blocks
1 large file
289110 regular files
21780 directories
8 character device files
0 block device files
0 fifos
0 links
162955 symbolic links (161597 fast symbolic links)
1 socket
------------
473854 files
If all is well, proceed with the actual conversion:
root # btrfs-convert /dev/nvme0n1p2
btrfs-convert from btrfs-progs v6.6.3
Source filesystem:
Type: ext2
Label:
Blocksize: 4096
UUID: 7852c210-3e66-4a19-bf1c-80f28c6de338
Target filesystem:
Label:
Blocksize: 4096
Nodesize: 16384
UUID: 1cf2c199-9cb1-4e15-9037-585577e363b1
Checksum: crc32c
Features: extref, skinny-metadata, no-holes, free-space-tree (default)
Data csum: yes
Inline data: yes
Copy xattr: yes
Reported stats:
Total space: 16957571072
Free space: 8176861184 (48.22%)
Inode count: 1036320
Free inodes: 562457
Block count: 4140032
Create initial btrfs filesystem
Create ext2 image file
Create btrfs metadata
Copy inodes [O] [ 492209/ 473863]
Free space cache cleared
Conversion complete
Once converted we need to make some changes to make sure the system properly boots.
First, mount your new Btrfs filesystem, and make a new root subvolume called @
:
root # mount /dev/nvme0n1p2 /mnt
root # btrfs subvolume create /mnt/@
Create subvolume '/mnt/@'
Then move everything in /mnt
to the @
subvolume, except the @
subvolume itself, the ext2_saved
subvolume (used for rollback purposes), and the home
directory:
root # mv /mnt/!(@|ext2_saved|home) /mnt/@/
Make a new home subvolume called @home
, move all home directories in there, and then move the emptied home
directory:
root # btrfs subvolume create /mnt/@home
root # mv /mnt/home/* /mnt/@home/
root # rmdir /mnt/home/
Now we have a properly separated subvolume structure for Timeshift. Next we need to make sure the systems boots from the new filesystem. First, identify the new UUID of the Btrfs partition:
root # blkid /dev/nvme0n1p2
/dev/nvme0n1p2: UUID="df9680d5-1381-459e-a6e4-142033afc5f9" UUID_SUB="9e5abb70-37a0-4a57-8871-8ec3a1fbf39e" BLOCK_SIZE="4096" TYPE="btrfs" PARTUUID="a6373cab-b44a-451d-81c7-b6d1b399a5e1"
Edit /mnt/@/etc/fstab
by commenting out the old root mount point, and add your new Btrfs subvolume mount points:
# UUID=be1efd93-90d3-473b-adda-eca6560055ce / ext4 errors=remount-ro 0 1
UUID=df9680d5-1381-459e-a6e4-142033afc5f9 / btrfs defaults,subvol=@ 0 1
UUID=df9680d5-1381-459e-a6e4-142033afc5f9 /home btrfs defaults,subvol=@home 0 2
Note
|
If you’re using an encrypted (LUKS+LVM) setup as earlier described and you’ve followed along thus far, then this is where to pay extra attention.
This is what you’d probably need to change in
No need to update UUIDs. |
Now we need to chroot
into the new filesystem to fix GRUB.
First, unmount /mnt
, and then remount it using the @
subvolume.
Then, also mount the ESP:
root # umount /mnt
root # mount -o subvol=@ /dev/nvme0n1p2 /mnt
root # mount /dev/nvme0n1p1 /mnt/boot/efi
Note
|
If you’re using an encrypted (LUKS+LVM) setup as earlier described and you’ve followed along thus far, then this is where to pay extra attention.
After unmount
|
Then make the necesarry arrangements to chroot
into the new system:
root # mount -t proc /proc /mnt/proc
root # mount --rbind /dev /mnt/dev
root # mount --make-rslave /mnt/dev
root # mount --rbind /sys /mnt/sys
root # mount --make-rslave /mnt/sys
root # chroot /mnt /bin/bash
Then fix GRUB, and exit the chroot
environment:
root (chroot) # grub-install /dev/nvme0n1
root (chroot) # update-grub
root (chroot) # exit
Now cleanup everything:
root # umount -R /mnt
Note
|
If you’re using an encrypted (LUKS+LVM) setup as earlier described and you’ve followed along thus far, then also properly close your LUKS encrypted partition:
No need to change |
Then reboot, remove the live image, and your system should boot using your newly converted Btrfs filesystem. From there you can open and configure Timeshift.

Then, open the Update Manager and open its preferences to configure automatic updates:

And don’t forget to remove the now unnecessary ext2_saved
subvolume if you no longer need to rollback to Ext4 again:
root # mount /dev/nvme0n1p2 /mnt
root # btrfs subvolume delete /mnt/ext2_saved
Delete subvolume 256 (no-commit): '/mnt/ext2_saved'
root # umount /mnt