btrfs migration

Published on 03.07.2017 - 01:48 - 17 minute read

Migration to btrfs

As some of you might know, it take me often quite some time to get things done. One of this ongoing issue is the migration of my filesystem. For more than two years i wanted to migrate the root filesystem of my laptop from ext4 to btrfs. In fact i did this migration two years ago, but only partly. Ever since i’m stuck with a half finished migration of btrfs.

What’s btrfs?

So for anyone who havn’t heard of btrfs. btrfs is a new type of filesystem, with similar features like zfs. Where new is new like a second-hand car. It works fine, but isn’t the newest and most shining model on the market. But it does quite good what is supposed to be there.

The feature include copy-on-write(cow), snapshot, subvolumes, data deduplication. Things a more ‘classic’ filesystem can’t do. snapshot with ext4? Only when you run lvm. What’s most interesting are the subvolumes. Compare them to a partition within the filesystem. It allows to slice the filesystem into more smaller chunk to store data. Like lvm, just within the filesystem itself. This allows to use snapshot more effective.

Migration

The migrate is quite simple:

btrfs-convert /dev/sdX

This will move all data from a extX to btrfs. In addition, the original filesystem will be preserved within a subvolume. At this stage you could validate the data of the original filesystem with the one migrated. When done, just remove the subvolume.

What’s next?

Here comes the trick part. All of the data are migrate to the top level structure of the filesystem. This allows usage of this file. However this isn’t the intended usage. In my case, the root filesystem is located here. I boot and work from this part. The right thing would be to move the data into a subvolume.

So btrfs is in place, but the problem is that i don’t use it in a desirable way. I moved all data from ext4 to btrfs and that’s it! But the idea was first to use the subvolume function and the snapshot function with snapper. Yet all of my data are in the top level container of btrfs. Creating the problem that I can’t really use the snapper function and not utilizing the snapshot at all. Even worse, this way I just use it in a traditional way.

Next step is to move the data away from the top level structure into separated subvolumes and than setup snapper.

Testing

Because my laptop is a productive system i didn’t want to mess up. I decided to get a testing environment that mimics my laptop. For this i installed a virtual machine with archlinux. The root filesystem will then migrate to btrfs. Next would be to than move all data to a subvolume and test that this migration will work. Including the boot process.

Setup a archlinux VM with vagrant

mkdir Vagrant-archlinux
cd Vagrant-archlinux
vagrant init

Note: You can download the Vagrantfile from here

Next step was to add a archlinux based box. I added one box from the http://www.vagrantbox.es/ . All of the boxes listed there are out-dated. I could have create a new one, but updating is faster. So I went with the newest box of them and updated it. This way it represented my laptop state. After the upgrade the migration to btrfs will be done to close the gap to my laptop.

vagrant box add archlinux http://vagrant.srijn.net/archlinux-x64-2014-01-07.box

I changed the default box in the to archlinux

config.vm.box = "archlinux"

Next is to start the VM:

vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'archlinux'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: Vagrant-archlinux_default_1499030023852_79753
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: 
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default: 
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
    default: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default: 
    default: Guest Additions Version: 4.3.6
    default: VirtualBox Version: 5.1
==> default: Mounting shared folders...
    default: /vagrant => /home/akendo/Vagrant-archlinux

Login into the VM

vgrant ssh
Last login: Mon Jan  6 21:50:22 2014 from 10.0.2.2
[vagrant@vagrant ~]$ 

Upgrading the old archlinux box

The upgrade was a bit trick and i had to do it twice. First was to get the newest packages

[vagrant@vagrant ~]$ sudo su -
[root@vagrant ~]# pacman -Syu
:: Synchronizing package databases...
 core                                                                                                                 124.7 KiB   291K/s 00:00 [########################################################################################] 100%
 extra                                                                                                               1664.6 KiB  2.09M/s 00:01 [########################################################################################] 100%
 community                                                                                                              3.9 MiB  3.10M/s 00:01 [########################################################################################] 100%
:: Starting full system upgrade...
:: Replace dirmngr with core/gnupg? [Y/n] 
:: Replace dnsutils with extra/bind-tools? [Y/n] 
:: Replace libdbus with core/dbus? [Y/n] 
:: Replace libltdl with core/libtool? [Y/n] 
:: Replace libusbx with core/libusb? [Y/n] 
:: Replace virtualbox-guest-modules with community/virtualbox-guest-modules-arch? [Y/n] 
resolving dependencies...
:: There are 3 providers available for libgl:
:: Repository extra
   1) libglvnd  2) nvidia-304xx-utils  3) nvidia-340xx-utils

Enter a number (default=1): 1
warning: dependency cycle detected:
warning: systemd will be installed before its cryptsetup dependency
warning: dependency cycle detected:
warning: harfbuzz will be installed before its freetype2 dependency
warning: dependency cycle detected:
warning: mesa will be installed before its libglvnd dependency
looking for inter-conflicts...

Packages (247): acl-2.2.52-3  archlinux-keyring-20170611-1  attr-2.4.47-2  autoconf-2.69-4  automake-1.15-2  bash-4.4.012-2  bind-tools-9.11.1.P1-1  binutils-2.28.0-3  bison-3.0.4-2  bzip2-1.0.6-6  ca-certificates-20170307-1
                ca-certificates-cacert-20140824-4  ca-certificates-mozilla-3.31-3  ca-certificates-utils-20170307-1  compositeproto-0.4.2-3  coreutils-8.27-1  cracklib-2.9.6-1  cronie-1.5.1-1  cryptsetup-1.7.5-1  curl-7.54.1-1
                damageproto-1.2.1-3  db-5.3.28-3  dbus-1.10.18-1  desktop-file-utils-0.23-1  device-mapper-2.02.172-1  dhcpcd-6.11.5-1  diffutils-3.6-1  dirmngr-1.1.1-1 [removal]  dnssec-anchors-20170228-1  dnsutils-9.9.2.P2-1 [removal]
                e2fsprogs-1.43.4-1  elinks-0.13-18  expat-2.2.1-1  fakeroot-1.21-2  file-5.31-1  filesystem-2017.03-2  findutils-4.6.0-2  fixesproto-5.0+9+g4292ec1-1  flex-2.6.4-1  fontconfig-2.12.3-1  fontsproto-2.1.3-2  freetype2-2.8-2
                gawk-4.1.4-2  gc-7.6.0-1  gcc-7.1.1-3  gcc-libs-7.1.1-3  gdbm-1.13-1  geoip-1.6.10-1  geoip-database-20170606-1  gettext-0.19.8.1-2  glib2-2.52.2+9+g3245eba16-1  glibc-2.25-5  gmp-6.1.2-1  gnupg-2.1.21-3  gnutls-3.5.13-1
                gpgme-1.9.0-3  gpm-1.20.7-7  graphite-1:1.3.10-1  grep-3.0-1  groff-1.22.3-7  grub-2:2.02-1  guile-2.2.2-1  gzip-1.8-2  harfbuzz-1.4.6-1  htop-2.0.2-1  hwids-20170328-1  iana-etc-20170512-1  icu-59.1-1  inetutils-1.9.4-5
                iproute2-4.11.0-1  iptables-1.6.1-1  iputils-20161105.1f2bb12-2  js185-1.0.0-3  json-c-0.12.1-1  kbd-2.0.4-1  kbproto-1.0.7-1  keyutils-1.5.10-1  kmod-24-1  krb5-1.15.1-1  ldns-1.7.0-3  less-487-1  libaio-0.3.110-1
                libarchive-3.3.1-5  libassuan-2.4.3-1  libatomic_ops-7.4.6-1  libcap-2.25-1  libdbus-1.6.18-3 [removal]  libdrm-2.4.81-1  libedit-20170329_3.1-1  libelf-0.169-1  libepoxy-1.4.3-1  libevdev-1.5.7-1  libevent-2.1.8-1
                libffi-3.2.1-2  libfontenc-1.1.3-1  libgcrypt-1.7.8-1  libglvnd-0.2.999+g4ba53457-2  libgpg-error-1.27-1  libgudev-231+1+g0841288-1  libice-1.0.9-1  libidn-1.33-1  libinput-1.7.3-1  libksba-1.3.4-2  libldap-2.4.44-5
                libltdl-2.4.2-12 [removal]  libmnl-1.0.4-1  libmpc-1.0.3-2  libnftnl-1.0.7-1  libnghttp2-1.23.1-1  libnl-3.3.0-1  libomxil-bellagio-0.9.3-1  libpcap-1.8.1-2  libpciaccess-0.13.5-1  libpipeline-1.4.1-1  libpng-1.6.29-1
                libpsl-0.17.0-2  libsasl-2.1.26-11  libseccomp-2.3.2-1  libsecret-0.18.5+14+g9980655-1  libssh2-1.8.0-2  libsystemd-233-6  libtasn1-4.12-1  libtirpc-1.0.1-3  libtool-2.4.6-8  libtxc_dxtn-1.0.1-6  libunistring-0.9.7-1
                libunwind-1.2.1-1  libusb-1.0.21-2  libusbx-1.0.17-1 [removal]  libutempter-1.1.6-2  libutil-linux-2.29.2-2  libwacom-0.24-1  libx11-1.6.5-1  libxcb-1.12-1  libxcomposite-0.4.4-2  libxdamage-1.1.4-2  libxdmcp-1.1.2-1
                libxext-1.3.3-1  libxfixes-5.0.3-1  libxfont-1.5.2-1  libxfont2-2.0.1-1  libxkbfile-1.0.9-1  libxml2-2.9.4+16+g07418011-2  libxrandr-1.5.1-1  libxrender-0.9.10-1  libxshmfence-1.2-1  libxt-1.1.5-1  libxxf86vm-1.1.4-1
                licenses-20140629-2  linux-4.11.7-1  linux-api-headers-4.10.1-1  linux-firmware-20170422.ade8332-1  llvm-libs-4.0.1-1  lm_sensors-3.4.0-2  logrotate-3.12.2-1  lua51-5.1.5-6  lvm2-2.02.172-1  lz4-1:1.7.5-1  m4-1.4.18-1
                make-4.2.1-2  man-db-2.7.6.1-2  man-pages-4.11-1  mdadm-4.0-1  mesa-17.1.4-1  mkinitcpio-23-1  mkinitcpio-busybox-1.26.1-1  mlocate-0.26-6  mpfr-3.1.5.p2-1  mtdev-1.1.5-1  nano-2.8.5-1  ncurses-6.0+20170527-1
                net-tools-1.60.20160710git-1  netctl-1.12-2  nettle-3.3-1  npth-1.5-1  nspr-4.15-1  openresolv-3.9.0-1  openssh-7.5p1-2  openssl-1.1.0.f-1  p11-kit-0.23.7-1  pacman-5.0.2-1  pacman-mirrorlist-20170628-1  pam-1.3.0-1
                patch-2.7.5-1  pciutils-3.5.4-1  pcre-8.40-1  perl-5.26.0-1  pinentry-1.0.0-1  pixman-0.34.0-1  pkg-config-0.29.2-1  popt-1.16-8  procps-ng-3.3.12-1  psmisc-22.21-3  pth-2.0.7-5  randrproto-1.5.0-1  readline-7.0.003-1
                reiserfsprogs-3.6.25-1  renderproto-0.11.1-3  rsync-3.1.2-2  run-parts-4.8.1-1  s-nail-14.8.16-2  sed-4.4-1  shadow-4.4-3  sqlite-3.19.3-1  sudo-1.8.20.p2-1  sysfsutils-2.1.0-9  systemd-233-6  systemd-sysvcompat-233-6
                tar-1.29-2  texinfo-6.4-1  thin-provisioning-tools-0.7.0-1  tmux-2.5-3  tre-0.8.0-4  tzdata-2017b-1  usbutils-008-1  util-linux-2.29.2-2  vi-1:070224-2  vim-8.0.0628-1  vim-runtime-8.0.0628-1
                virtualbox-guest-modules-4.3.6-2 [removal]  virtualbox-guest-modules-arch-5.1.22-4  virtualbox-guest-utils-5.1.22-2  wayland-1.13.0-1  wget-1.19.1-2  which-2.21-2  xcb-proto-1.12-3  xextproto-7.3.0-1
                xf86-input-evdev-2.10.5-1  xf86-input-libinput-0.25.1-1  xf86vidmodeproto-2.3.1-3  xfsprogs-4.11.0-1  xkeyboard-config-2.21-2  xorg-bdftopcf-1.0.5-1  xorg-font-util-1.3.1-1  xorg-font-utils-7.6-4
                xorg-fonts-encodings-1.0.4-4  xorg-fonts-misc-1.0.3-5  xorg-mkfontdir-1.0.7-8  xorg-mkfontscale-1.1.2-1  xorg-server-1.19.3-2  xorg-server-common-1.19.3-2  xorg-setxkbmap-1.3.1-1  xorg-xkbcomp-1.4.0-1  xorg-xrandr-1.5.0-1
                xproto-7.0.31-1  xz-5.2.3-1  zlib-1:1.2.11-1

Total Download Size:    325.87 MiB
Total Installed Size:   1238.04 MiB
Net Upgrade Size:       586.92 MiB

:: Proceed with installation? [Y/n] 

At this point i got a ton of message. I went on and accepted all of them. He will then download of the packages of the last 3 years. But the upgrade will fail because of the keyring. It’s necessary to upgrade the archlinux-keyring manual.

[root@vagrant ~]# pacman -U /var/cache/pacman/pkg/archlinux-keyring-20170611-1-any.pkg.tar.xz 
loading packages...
resolving dependencies...
looking for inter-conflicts...

Packages (1): archlinux-keyring-20170611-1

Total Installed Size:   0.89 MiB
Net Upgrade Size:       0.34 MiB

:: Proceed with installation? [Y/n] y
(1/1) checking keys in keyring                                                                                                                 [########################################################################################] 100%
(1/1) checking package integrity                                                                                                               [########################################################################################] 100%
(1/1) loading package files                                                                                                                    [########################################################################################] 100%
(1/1) checking for file conflicts                                                                                                              [########################################################################################] 100%
(1/1) checking available disk space                                                                                                            [########################################################################################] 100%
(1/1) upgrading archlinux-keyring                                                                                                              [########################################################################################] 100%
==> Appending keys from archlinux.gpg...
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   4  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1  valid:   4  signed:  72  trust: 0-, 0q, 0n, 4m, 0f, 0u
gpg: depth: 2  valid:  70  signed:  10  trust: 70-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2017-10-20
==> Locally signing trusted keys in keyring...
  -> Locally signing key DDB867B92AA789C165EEFA799B729B06A680C281...
  -> Locally signing key 0E8B644079F599DFC1DDC3973348882F6AC6A4C2...
  -> Locally signing key 684148BB25B49E986A4944C55184252D824B18E8...
  -> Locally signing key 91FFE0700E80619CEB73235CA88E23E377514E00...
  -> Locally signing key 44D4A033AC140143927397D47EFD567D4C7EA887...
  -> Locally signing key AB19265E5D7D20687D303246BA1DFB64FFF979E7...
==> Importing owner trust values...
gpg: setting ownertrust to 4
gpg: setting ownertrust to 4
==> Disabling revoked keys in keyring...
  -> Disabling key F5A361A3A13554B85E57DDDAAF7EF7873CFD4BB6...
  -> Disabling key 7FA647CD89891DEDC060287BB9113D1ED21E1A55...
  -> Disabling key D4DE5ABDE2A7287644EAC7E36D1A9E70E19DAA50...
  -> Disabling key 40440DC037C05620984379A6761FAD69BA06C6A9...
  -> Disabling key BC1FBE4D2826A0B51E47ED62E2539214C6C11350...
  -> Disabling key 9515D8A8EAB88E49BB65EDBCE6B456CAF15447D5...
  -> Disabling key 4A8B17E20B88ACA61860009B5CED81B7C2E5C0D2...
  -> Disabling key 63F395DE2D6398BBE458F281F2DBB4931985A992...
  -> Disabling key 0B20CA1931F5DA3A70D0F8D2EA6836E1AB441196...
  -> Disabling key 8F76BEEA0289F9E1D3E229C05F946DED983D4366...
  -> Disabling key 66BD74A036D522F51DD70A3C7F2A16726521E06D...
  -> Disabling key 81D7F8241DB38BC759C80FCE3A726C6170E80477...
  -> Disabling key 5E7585ADFF106BFFBBA319DC654B877A0864983E...
  -> Disabling key E7210A59715F6940CF9A4E36A001876699AD6E84...
  -> Disabling key 27FFC4769E19F096D41D9265A04F9397CDFD6BB0...
==> Updating trust database...
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   6  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1  valid:   6  signed:  72  trust: 0-, 0q, 0n, 6m, 0f, 0u
gpg: depth: 2  valid:  71  signed:  10  trust: 71-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2017-10-20

Also the ca-certificates.crt needs to be removed as you can read here

[root@vagrant ~]# rm /etc/ssl/certs/ca-certificates.crt

At this point the re-run of pacman -Syu will be successful. Almost, because the mkinitcpio script needs to be rerun before. Else the system won’t boot.

[root@vagrant ~]# mkinitcpio -p linux
==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'default'
  -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img
==> Starting build: 4.11.7-1-ARCH
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [autodetect]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
  -> Running build hook: [filesystems]
  -> Running build hook: [keyboard]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux.img
==> Image generation successful
==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'fallback'
  -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux-fallback.img -S autodetect
==> Starting build: 4.11.7-1-ARCH
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
==> WARNING: Possibly missing firmware for module: aic94xx
==> WARNING: Possibly missing firmware for module: wd719x
  -> Running build hook: [filesystems]
  -> Running build hook: [keyboard]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux-fallback.img
==> Image generation successful

Last but not least, we’ll install the btrfs package:

[root@vagrant ~]# pacman-db-upgrade
==> Pre-4.2 database format detected - upgrading...
[root@vagrant ~]# pacman -S btrfs-progs --force
...

Note: The --force is necessary. Last is to do a reboot, for testing that the system is on the newest state.

LiveCD for the migration

To perform the migration it needs to be done from a live system. At first I want to do this with the official archlinux image, yet it has an issue booting in Virtualbox. It just won’t start. Instead i took grml as live system. Poweroff the vagrant box and open it in Virtualbox. Jack in the live CD and start the VM from Virtualbox. Only importance is that the right architecture is selected. The vagrant image is x86_64 so needs grml to be in 64 Bit.

You need another system to perform the migrate. The migrate from ext4 to btrfs won’t work with a running rootfs ontop.

Now to run the migration as discussed before”

btrfs-convert /dev/sda2

This took 38 seconds for this simple filesystem.

We’ll mount the disk now:

mount /dev/sda2 /mnt/
cd /mnt
btrfs subvolume list .
ID 256 gen 3 top level 5 path ext2_saved

Seems good, finished up the migration by deleting the ext2_saved subvolume. One thing that surprised me was the name. Why wasn’t it name ext4_saved? Anyway, let’s move on:

btrfs subvolume delete ext2_saved
Delete subvolume (no-commit): '/mnt/ext2_saved'

One important change that need to be done here, the VM is configure to run with UUID, that needs to change to the block devices for now. Replace the UUID in the /etc/fstab and /boot/grub/grub.cfg. I change the parameter #GRUB_DISABLE_LINUX_UUID=true to GRUB_DISABLE_LINUX_UUID=true in /etc/default/grub and created a new config file.

[root@vagrant ~]# grub-mkconfig -o /boot/grub/grub.cfg

Before I could restart the VM I have to add btrfs hook to the /etc/mkinitcpio.conf. Else the kernel don’t know what to start from.

HOOKS="base udev autodetect modconf block filesystems keyboard fsck btrfs"

Run:

mkinitcpio -p linux
==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'default'
  -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img
==> Starting build: 4.11.7-1-ARCH
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [autodetect]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
  -> Running build hook: [filesystems]
  -> Running build hook: [keyboard]
  -> Running build hook: [fsck]
  -> Running build hook: [btrfs]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux.img
==> Image generation successful
==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'fallback'
  -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux-fallback.img -S autodetect
==> Starting build: 4.11.7-1-ARCH
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
==> WARNING: Possibly missing firmware for module: wd719x
==> WARNING: Possibly missing firmware for module: aic94xx
  -> Running build hook: [filesystems]
  -> Running build hook: [keyboard]
  -> Running build hook: [fsck]
  -> Running build hook: [btrfs]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux-fallback.img
==> Image generation successful

Note: I did this from a chroot on the liveCD

A reboot later and everything was working!

[root@vagrant ~]# mount |grep btrf
/dev/sda2 on / type btrfs (rw,relatime,space_cache,subvolid=5,subvol=/)

Doing the job

At this point we do have a similar setup as my laptop. So what’s next?

I went to the btrfs wiki to get more details. What sees to me the best practices is to create a subvolume, move all necessary data into it and mount it directly. This can be done via the mount command and the subvol parameter. This will also be the default subvolume. By setting this as default i won’t have to change anything in grub. yay

First step was to create the a readonly snapshot of the filesystem:

[root@vagrant ~]# btrfs subvolume snapshot -r / /snapshot
Create a readonly snapshot of '/' in '//snapshot'
[root@vagrant ~]# ls -l /snapshot/
total 20
lrwxrwxrwx 1 root root    7 Mar 26 21:57 bin -> usr/bin
drwxr-xr-x 1 root root    0 Jan  6  2014 boot
drwxr-xr-x 1 root root    0 Jan  6  2014 dev
drwxr-xr-x 1 root root 2268 Jul  2 21:47 etc
drwxr-xr-x 1 root root   14 Jan  6  2014 home
-rwxr-xr-x 1 root root 1588 Jan  6  2014 inside.sh
lrwxrwxrwx 1 root root    7 Mar 26 21:57 lib -> usr/lib
lrwxrwxrwx 1 root root    7 Mar 26 21:57 lib64 -> usr/lib
drwx------ 1 root root    0 Jan  6  2014 lost+found
drwxr-xr-x 1 root root    0 May 31  2013 mnt
drwxr-xr-x 1 root root    0 May 31  2013 opt
dr-xr-xr-x 1 root root    0 Jan  6  2014 proc
drwxr-x--- 1 root root   54 Jul  2 21:47 root
drwxr-xr-x 1 root root   10 Jul  2 21:46 run
lrwxrwxrwx 1 root root    7 Mar 26 21:57 sbin -> usr/bin
drwxr-xr-x 1 root root   14 May 31  2013 srv
dr-xr-xr-x 1 root root    0 Jan  6  2014 sys
drwxrwxrwt 1 root root    0 Jul  2 21:47 tmp
drwxr-xr-x 1 root root   70 Jul  2 21:27 usr
drwxr-xr-x 1 root root    0 Jul  2 21:14 vagrant
drwxr-xr-x 1 root root  116 Jul  2 21:28 var

This will create a folder in the / folder, called snapshot (surprise ;-) ).

Next on the agenda is to create the subvolume:

[root@vagrant ~]# btrfs subvolume create /rootfs
Create subvolume '//rootfs'
[root@vagrant ~]# ls -l /rootfs/
total 0

By now we have a offline copy of the rootfs in /snapshot and the destination mount point in /rootfs. This calls for rsync. Simply copy all data from the snapshot into the subvolume for rootfs.

[root@vagrant ~]# cd /snapshot/
[root@vagrant snapshot]# rsync -raPh ./* /rootfs/
...

It might be useful to run the rsync command first with -n for a dry run. Make sure that you have enough disk space. I’m not sure if the deduplication is here working. Next is to set the default subvolume:

[root@vagrant mnt]# btrfs subvolume set-default 266 /

Now to the real exciting moment, the reboot. ANNNNND it did work ;-)

vagrant ssh
Last login: Sun Jul  2 21:49:14 2017 from 10.0.2.2
[vagrant@vagrant ~]$ mount|grep btrf
/dev/sda2 on / type btrfs (rw,relatime,space_cache,subvolid=266,subvol=/rootfs)

Hurray! Last is to clean up the mess and be done with it!

[root@vagrant ~]# mount -t btrfs -o subvol=/ /dev/sda2 /mnt/
[root@vagrant ~]# cd /mnt/
[root@vagrant mnt]# btrfs subvolume delete snapshot 
[root@vagrant mnt]# rm -rvf ./{var,....}
[root@vagrant ~]# ls -lha /mnt/
total 0
drwxr-xr-x 1 root root  12 Jul  2 22:35 .
drwxr-xr-x 1 root root 174 Jul  2 22:06 ..
drwxr-xr-x 1 root root 174 Jul  2 22:06 rootfs

Be aware when you remove the files from the top level structure not to remove the roofs folder!

endgame: snapper

After this long journey we can finally install snapper!

[root@vagrant ~]# pacmann -S snapper
-bash: pacmann: command not found
[root@vagrant ~]# ^C
[root@vagrant ~]# pacman -S snapper
resolving dependencies...
looking for conflicting packages...

Packages (2) boost-libs-1.64.0-3  snapper-0.5.0-2

Total Download Size:    2.82 MiB
Total Installed Size:  13.76 MiB

:: Proceed with installation? [Y/n] y
:: Retrieving packages...
 boost-libs-1.64.0-3-x86_64                                                                                             2.3 MiB  2.52M/s 00:01 [########################################################################################] 100%
 snapper-0.5.0-2-x86_64                                                                                               546.6 KiB  14.4M/s 00:00 [########################################################################################] 100%
(2/2) checking keys in keyring                                                                                                                 [########################################################################################] 100%
(2/2) checking package integrity                                                                                                               [########################################################################################] 100%
(2/2) loading package files                                                                                                                    [########################################################################################] 100%
(2/2) checking for file conflicts                                                                                                              [########################################################################################] 100%
(2/2) checking available disk space                                                                                                            [########################################################################################] 100%
:: Processing package changes...
(1/2) installing boost-libs                                                                                                                    [########################################################################################] 100%
Optional dependencies for boost-libs
    openmpi: for mpi support
(2/2) installing snapper                                                                                                                       [########################################################################################] 100%
Optional dependencies for snapper
    pam: pam_snapper [installed]
:: Running post-transaction hooks...
(1/1) Arming ConditionNeedsUpdate...

We’ll configure snapper by running:

[root@vagrant ~]# snapper -c root create-config /
[root@vagrant ~]# snapper list
Type   | # | Pre # | Date | User | Cleanup | Description | Userdata
-------+---+-------+------+------+---------+-------------+---------
single | 0 |       |      | root |         | current     |         

pacman hooks for snapper

To meaning use snapper, we’ll use the hook function of pacman. Creating each time a new snapshot of the rootfs when an update is run. For this we can use finished script, simply install snap-pac.

[root@vagrant ~]# pacman -S snap-pac
resolving dependencies...
looking for conflicting packages...

Packages (1) snap-pac-1.1-1

Total Download Size:   0.01 MiB
Total Installed Size:  0.03 MiB

:: Proceed with installation? [Y/n] y
:: Retrieving packages...
 snap-pac-1.1-1-any                                                                                                    13.3 KiB  0.00B/s 00:00 [########################################################################################] 100%
(1/1) checking keys in keyring                                                                                                                 [########################################################################################] 100%
(1/1) checking package integrity                                                                                                               [########################################################################################] 100%
(1/1) loading package files                                                                                                                    [########################################################################################] 100%
(1/1) checking for file conflicts                                                                                                              [########################################################################################] 100%
(1/1) checking available disk space                                                                                                            [########################################################################################] 100%
:: Processing package changes...
(1/1) installing snap-pac                                                                                                                      [########################################################################################] 100%
:: Running post-transaction hooks...
(1/3) Arming ConditionNeedsUpdate...
(2/3) Performing snapper post snapshots for the following configurations...
(3/3) You are installing snap-pac, so no post transaction snapshots will be taken.

Every new installation or upgrade will lead the post/pre hook to run:

[root@vagrant ~]# pacman -Ss sipcalc
community/sipcalc 1.1.6-2
    an advanced console based ip subnet calculator.
[root@vagrant ~]# pacman -S sipcalc
resolving dependencies...
looking for conflicting packages...

Packages (1) sipcalc-1.1.6-2

Total Download Size:   0.02 MiB
Total Installed Size:  0.05 MiB

:: Proceed with installation? [Y/n] y
:: Retrieving packages...
 sipcalc-1.1.6-2-x86_64                                                                                                23.4 KiB   219K/s 00:00 [########################################################################################] 100%
(1/1) checking keys in keyring                                                                                                                 [########################################################################################] 100%
(1/1) checking package integrity                                                                                                               [########################################################################################] 100%
(1/1) loading package files                                                                                                                    [########################################################################################] 100%
(1/1) checking for file conflicts                                                                                                              [########################################################################################] 100%
(1/1) checking available disk space                                                                                                            [########################################################################################] 100%
:: Running pre-transaction hooks...
(1/1) Performing snapper pre snapshots for the following configurations...
==> root: 1
:: Processing package changes...
(1/1) installing sipcalc                                                                                                                       [########################################################################################] 100%
:: Running post-transaction hooks...
(1/2) Arming ConditionNeedsUpdate...
(2/2) Performing snapper post snapshots for the following configurations...
==> root: 2
[root@vagrant ~]# snapper list
Type   | # | Pre # | Date                            | User | Cleanup | Description       | Userdata
-------+---+-------+---------------------------------+------+---------+-------------------+---------
single | 0 |       |                                 | root |         | current           |         
pre    | 1 |       | Sun 02 Jul 2017 10:42:17 PM UTC | root | number  | pacman -S sipcalc |         
post   | 2 | 1     | Sun 02 Jul 2017 10:42:17 PM UTC | root | number  | pacman -S sipcalc |         

Awesome!

Put it all together.

It did work as intend on my laptop. I’m very happy about this! It might be interesting to see how well this snapshoting is working over time. But snapper provides also some auto clean ups. But only time can tell how well this is working.

so far so good.

best regards

Akendo

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.