Moving home partition to a btrfs subvolume

Back when I installed Garuda on August 2021, I followed this video tutorial. I ended up with a separate btrfs partition for /home.

I would like to get rid of the mentioned partition and move /home to a @home subvolume, the way is default in a straight forward Garuda installation, without having to reinstall the whole system. I want to do this because of the way subvolumes manage space dinamically.

Any lead on where to look or the kind of operation needed will be appreciated.

I append the output of cat /etc/fstab, btrfs subvolume list / and garuda-inxi.

# /etc/fstab: static file system information.
# Use 'blkid' to print the universally unique identifier for a device; this may
# be used with UUID= as a more robust way to name devices that works even if
# disks are added and removed. See fstab(5).
# <file system>             <mount point>  <type>  <options>  <dump>  <pass>
UUID=5065-8560                            /boot/efi      vfat    umask=0077 0 2
UUID=65b1555e-e8e7-41cb-84a2-63265cdbd7db swap           swap    defaults,noatime 0 0
UUID=543c6354-5d39-4703-bb64-407600dc772d / btrfs subvol=/@,defaults,noatime,noautodefrag,compress=zstd 0 0 
UUID=543c6354-5d39-4703-bb64-407600dc772d /root btrfs subvol=/@root,defaults,noatime,noautodefrag,compress=zstd 0 0 
UUID=543c6354-5d39-4703-bb64-407600dc772d /srv btrfs subvol=/@srv,defaults,noatime,noautodefrag,compress=zstd 0 0
UUID=543c6354-5d39-4703-bb64-407600dc772d /var/cache btrfs subvol=/@cache,defaults,noatime,noautodefrag,compress=zstd 0 0 
UUID=543c6354-5d39-4703-bb64-407600dc772d /var/log btrfs subvol=/@log,defaults,noatime,noautodefrag,compress=zstd 0 0
UUID=543c6354-5d39-4703-bb64-407600dc772d /var/tmp btrfs subvol=/@tmp,defaults,noatime,noautodefrag,compress=zstd 0 0
UUID=2e159e97-2728-4e48-9ef8-9fe16862426c /home btrfs defaults,noatime,noautodefrag,compress=zstd 0 0
ID 257 gen 287690 top level 5 path @root
ID 258 gen 238310 top level 5 path @srv
ID 259 gen 288102 top level 5 path @cache
ID 260 gen 288302 top level 5 path @log
ID 261 gen 288300 top level 5 path @tmp
ID 935 gen 288300 top level 5 path @
ID 1698 gen 288114 top level 935 path .snapshots
ID 1730 gen 287668 top level 1698 path .snapshots/21/snapshot
ID 1731 gen 287670 top level 1698 path .snapshots/22/snapshot
ID 1732 gen 287745 top level 1698 path .snapshots/23/snapshot
ID 1733 gen 287746 top level 1698 path .snapshots/24/snapshot
ID 1734 gen 287751 top level 1698 path .snapshots/25/snapshot
ID 1735 gen 287752 top level 1698 path .snapshots/26/snapshot
ID 1736 gen 287960 top level 1698 path .snapshots/27/snapshot
ID 1737 gen 287962 top level 1698 path .snapshots/28/snapshot
ID 1738 gen 288086 top level 1698 path .snapshots/29/snapshot
ID 1739 gen 288088 top level 1698 path .snapshots/30/snapshot

  Kernel: 6.1.9-zen1-1-zen arch: x86_64 bits: 64 compiler: gcc v: 12.2.1
    parameters: BOOT_IMAGE=/@/boot/vmlinuz-linux-zen
    root=UUID=543c6354-5d39-4703-bb64-407600dc772d rw [email protected]
    quiet splash rd.udev.log_priority=3 vt.global_cursor_default=0
    resume=UUID=65b1555e-e8e7-41cb-84a2-63265cdbd7db loglevel=3
  Desktop: KDE Plasma v: 5.26.5 tk: Qt v: 5.15.8 wm: kwin_x11 vt: 1 dm: SDDM
    Distro: Garuda Linux base: Arch Linux
  Type: Desktop System: ASUS product: N/A v: N/A serial: <superuser required>
  Mobo: ASUSTeK model: TUF GAMING B550M-PLUS (WI-FI) v: Rev X.0x
    serial: <superuser required> UEFI: American Megatrends v: 2423
    date: 08/10/2021
  Device-1: hidpp_battery_0 model: Logitech MX Keys Wireless Keyboard
    serial: <filter> charge: 10% (should be ignored) rechargeable: yes
    status: discharging
  Device-2: hidpp_battery_1 model: Logitech Wireless Mouse M325
    serial: <filter> charge: 55% (should be ignored) rechargeable: yes
    status: discharging
  Info: model: AMD Ryzen 5 5600X bits: 64 type: MT MCP arch: Zen 3 gen: 4
    level: v3 note: check built: 2021-22 process: TSMC n7 (7nm)
    family: 0x19 (25) model-id: 0x21 (33) stepping: 0 microcode: 0xA201016
  Topology: cpus: 1x cores: 6 tpc: 2 threads: 12 smt: enabled cache:
    L1: 384 KiB desc: d-6x32 KiB; i-6x32 KiB L2: 3 MiB desc: 6x512 KiB
    L3: 32 MiB desc: 1x32 MiB
  Speed (MHz): avg: 3654 high: 3700 min/max: 2200/4650 boost: enabled
    scaling: driver: acpi-cpufreq governor: performance cores: 1: 3700 2: 3700
    3: 3632 4: 3627 5: 3590 6: 3700 7: 3614 8: 3600 9: 3596 10: 3700 11: 3700
    12: 3700 bogomips: 88801
  Flags: avx avx2 ht lm nx pae sse sse2 sse3 sse4_1 sse4_2 sse4a ssse3 svm
  Vulnerabilities: <filter>
  Device-1: NVIDIA GP108 [GeForce GT 1030] vendor: ASUSTeK driver: nvidia
    v: 525.85.05 alternate: nouveau,nvidia_drm non-free: 525.xx+
    status: current (as of 2022-12) arch: Pascal code: GP10x
    process: TSMC 16nm built: 2016-21 pcie: gen: 3 speed: 8 GT/s lanes: 4
    bus-ID: 07:00.0 chip-ID: 10de:1d01 class-ID: 0300
  Device-2: Logitech Webcam C270 type: USB driver: snd-usb-audio,uvcvideo
    bus-ID: 3-2:3 chip-ID: 046d:0825 class-ID: 0102 serial: <filter>
  Display: x11 server: X.Org v: 21.1.6 with: Xwayland v: 22.1.7
    compositor: kwin_x11 driver: N/A display-ID: :0 screens: 1
  Screen-1: 0 s-res: 1920x1080 s-dpi: 81 s-size: 602x343mm (23.70x13.50")
    s-diag: 693mm (27.28")
  Monitor-1: HDMI-0 res: 1920x1080 hz: 60 dpi: 82
    size: 598x336mm (23.54x13.23") diag: 686mm (27.01") modes: N/A
  API: OpenGL v: 4.6.0 NVIDIA 525.85.05 renderer: NVIDIA GeForce GT
    1030/PCIe/SSE2 direct render: Yes
  Device-1: NVIDIA GP108 High Definition Audio vendor: ASUSTeK
    driver: snd_hda_intel bus-ID: 1-9:7 v: kernel chip-ID: 0499:1509 pcie:
    gen: 3 class-ID: ff00 speed: 8 GT/s lanes: 4 bus-ID: 07:00.1
    chip-ID: 10de:0fb8 class-ID: 0403
  Device-2: AMD Starship/Matisse HD Audio vendor: ASUSTeK
    driver: snd_hda_intel v: kernel pcie: gen: 4 speed: 16 GT/s lanes: 16
    bus-ID: 09:00.4 chip-ID: 1022:1487 class-ID: 0403
  Device-3: Yamaha Steinberg UR22 type: USB driver: snd-usb-audio
  Device-4: Logitech Webcam C270 type: USB driver: snd-usb-audio,uvcvideo
    bus-ID: 3-2:3 chip-ID: 046d:0825 class-ID: 0102 serial: <filter>
  Sound API: ALSA v: k6.1.9-zen1-1-zen running: yes
  Sound Server-1: PulseAudio v: 16.1 running: no
  Sound Server-2: PipeWire v: 0.3.65 running: yes
  Device-1: Intel Wi-Fi 6 AX200 driver: iwlwifi v: kernel pcie: gen: 2
    speed: 5 GT/s lanes: 1 bus-ID: 05:00.0 chip-ID: 8086:2723 class-ID: 0280
  IF: wlp5s0 state: up mac: <filter>
  Device-2: Realtek RTL8125 2.5GbE vendor: ASUSTeK driver: r8169 v: kernel
    pcie: gen: 2 speed: 5 GT/s lanes: 1 port: f000 bus-ID: 06:00.0
    chip-ID: 10ec:8125 class-ID: 0200
  IF: enp6s0 state: down mac: <filter>
  Device-1: Intel AX200 Bluetooth type: USB driver: btusb v: 0.8 bus-ID: 1-5:2
    chip-ID: 8087:0029 class-ID: e001
  Report: bt-adapter ID: hci0 rfk-id: 1 state: down
    bt-service: enabled,running rfk-block: hardware: no software: yes
    address: N/A
  Local Storage: total: 1.14 TiB used: 837.48 GiB (71.9%)
  SMART Message: Required tool smartctl not installed. Check --recommends
  ID-1: /dev/nvme0n1 maj-min: 259:0 vendor: Western Digital
    model: WDS250G3X0C-00SJG0 size: 232.89 GiB block-size: physical: 512 B
    logical: 512 B speed: 31.6 Gb/s lanes: 4 type: SSD serial: <filter>
    rev: 111110WD temp: 40.9 C scheme: GPT
  ID-2: /dev/sda maj-min: 8:0 type: USB vendor: Seagate
    model: ST1000LM035-1RK172 size: 931.51 GiB block-size: physical: 4096 B
    logical: 512 B type: HDD rpm: 5400 serial: <filter> rev: 1053 scheme: MBR
  ID-1: / raw-size: 100 GiB size: 100 GiB (100.00%) used: 38.22 GiB (38.2%)
    fs: btrfs dev: /dev/nvme0n1p3 maj-min: 259:3
  ID-2: /boot/efi raw-size: 300 MiB size: 299.4 MiB (99.80%)
    used: 592 KiB (0.2%) fs: vfat dev: /dev/nvme0n1p1 maj-min: 259:1
  ID-3: /home raw-size: 128.59 GiB size: 128.59 GiB (100.00%)
    used: 43.56 GiB (33.9%) fs: btrfs dev: /dev/nvme0n1p4 maj-min: 259:4
  ID-4: /var/log raw-size: 100 GiB size: 100 GiB (100.00%)
    used: 38.22 GiB (38.2%) fs: btrfs dev: /dev/nvme0n1p3 maj-min: 259:3
  ID-5: /var/tmp raw-size: 100 GiB size: 100 GiB (100.00%)
    used: 38.22 GiB (38.2%) fs: btrfs dev: /dev/nvme0n1p3 maj-min: 259:3
  Kernel: swappiness: 133 (default 60) cache-pressure: 100 (default)
  ID-1: swap-1 type: zram size: 15.53 GiB used: 0 KiB (0.0%) priority: 100
    dev: /dev/zram0
  ID-2: swap-2 type: partition size: 4 GiB used: 0 KiB (0.0%) priority: -2
    dev: /dev/nvme0n1p2 maj-min: 259:2
  System Temperatures: cpu: 38.5 C mobo: 37.0 C gpu: nvidia temp: 42 C
  Fan Speeds (RPM): fan-1: 1047 fan-2: 1390 fan-3: 1088 fan-7: 0
  Processes: 334 Uptime: 2h 48m wakeups: 23 Memory: 15.53 GiB
  used: 4.45 GiB (28.6%) Init: systemd v: 252 default: graphical
  tool: systemctl Compilers: gcc: 12.2.1 clang: 15.0.7 Packages: 1877
  pm: nix-default pkgs: 0 pm: nix-sys pkgs: 0 pm: nix-usr pkgs: 2 pm: pacman
  pkgs: 1875 libs: 442 tools: aura,paru Shell: fish v: 3.6.0 default: Bash
  v: 5.1.16 running-in: yakuake inxi: 3.3.24
Garuda (2.6.14-1):
  System install date:     2022-10-23
  Last full system update: 2023-02-05
  Is partially upgraded:   No
  Relevant software:       snapper NetworkManager mkinitcpio nvidia-dkms
  Windows dual boot:       No/Undetected
  Failed units:            

Btrfs makes this quite easy.

Take a read-only snapshot of the btrfs partition you have mounted at /home. Then use btrfs send/btrfs receive to send it to the other filesystem you have naming it @home.

Then edit /etc/fstab to point to the new subvolume.


Thanks for your kindness @dalto, I'll carry out your instructions and report back here as soon as I can.

I'll be backing up before of course, but nevertheless I wonder: how safe do you consider the mentioned actions?

Afterwards I'll be deleting the /home partition and resizing the system partition to take the remaining space. Can I do all this from GParted (for example), or is it a better approach to use a btrfs tool for resizing?

For real life experience, I use btrfs send almost every day to backup on external drives and they boot right up (BIOS LEGACY, it's super easy) every time with data as expected. They are bootable backup drives in my case.

I have done and am currently doing btrfs resizing and I have no issue to report.
I do all that through KDE Partition Manager which is very similar to GParted, I think.


Now I'm stuck at the first step. I haven´t found a way to snapshot the whole filesystem. I mean, my /home partition is Btrfs indeed, but there are no subvolumes to snapshot: sudo btrfs subvolume list /home outputs nothing.

For what I've researched, I figured this approach:
(1) Mount my system's partition to /mnt (mention in this post, but I 'm hesitant of (re)mounting this device with my system running because, I suppose, is already mounted :thinking:).
(2) Create a top level subvolume called @home
(3) Copy the contents of my /home folder to @home's location (given enough space for the operation).
(4) Change fstab to mount @home to /home (instead of the other btrfs partition).
(5) $ reboot
(6) If everything is working, delete the previous /home partition and resize the other partition to occupy the whole disk.

What do you guys think? Is the caveat mentioned in (1) matter of concern?

sudo btrfs subvolume snapshot -r /home /home/snapshot_to_transfer

Afterwards I did sudo btrfs send /home/snapshot_to_transfer | sudo btrfs receive /. This makes konsole crash after a little while (30 seconds of intense cpu activity). I check with sudo btrfs subvolume list /: the subvolume doesn´t show, neither the directory with ls /.

I tried this twice. =/

edit: I see it appears in btrfs assistant indicating 0.00 size and 0.00 exclusive. But I figure its the original snapshot of /home

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.

Thanks both @dalto and @FGD for your input. I managed to solve the problem as @dalto specified. I don´t know what went wrong the first times I tried to send/receive. Maybe it had to do with the fact I had just cleaned caches using Stacer and had done a balance (using the recommend command by @tbg applied to /home).

The steps I followed and what I learned:


  1. Create a read-only snapshot of my /home btrfs partition (lesson: the filesystem volume is itself a subvolume) called home-transfer. This needs to be created inside the same device:
    # btrfs subvolume snapshot -r /home /home/home-transfer
    Only read-only subvolumes can be send/received across devices.

  2. Mount the (hidden) top level volume of the system by mounting the corresponding device or partition (in my case this is /dev/nvme0n1p3):
    # mkdir /mnt/btrfs && mount /dev/nvme0n1p3 /mnt/btrfs/
    We do this so we can access the top level and keep a consistent (flat) subvolume layout. It's still hard to wrap my head around the possibility of mounting the very filesystem being used on a directory inside itself. Even weirder was that this filesystem wasn't actually mounted, but a subvolume of it on /. A filesystem can be mounted on multiple directories with no issues, as mentioned in the man page of mount:

    The same filesystem may be mounted more than once, and in some cases (e.g., network filesystems) the same filesystem may be mounted on the same mountpoint
    multiple times.

  3. Transfer the subvolume (across devices), placing it at the top level:
    # btrfs send /home/home-transfer | btrfs receive /mnt/btrfs/
    Confirm the operation with
    # btrfs subvolume list /

  4. Now create a writable snapshot of the transfered subvolume called @home:
    # btrfs subvolume snapshot /mnt/btrfs/home-transfer /mnt/btrfs/@home
    Its good time now to delete the read-only snapshot:
    # btrfs subvolume delete /mnt/btrfs/home-transfer

  5. Then modify the fstab accordingly. I changed the/home mount point line so the UUID pointed to the same device as the other system subvolumes, instead of my original /home partition UUID, and added the option [email protected]. Not without making a backup file before:
    # cp /etc/fstab /etc/fstab.bak

  6. Then $ reboot to the new configuration. Everything should be working as nothing had happened.

  7. Now we can clean our mess by removing the auxiliary mounting directory and backup fstab:
    # rmdir /mnt/btrfs && rm /etc/fstab.bak

I still have to erase the now obsolete partition and grow my system's partition, but this is no issue.
Thanks for all your help.

PS, after mounting the top level subvolume I discovered a timeshift-btrfs directory with some old snapshot's json files, which I deleted at once.

Reference: Btrfs subvolumes and snapshots


This topic was automatically closed after 45 hours. New replies are no longer allowed.