AI Translation
Original Chinese
Some time ago, my system alerted me to insufficient space in the root directory. I didn’t pay much attention, but to my dismay, the next day, I couldn’t log in after entering the password no error message, just failure.
Troubleshooting Process
Since I was using systemd-homed with encryption enabled, I initially suspected that a rolling update or improper shutdown might have left the /home directory in a dirty state1.
I was devastated 😢, but thankfully, a flash of insight struck me: logging in as root since the root user doesn’t rely on homed, though this might not always work.. Unfortunately, I had disabled root login. My next idea was to use a LiveOS to re-enable root access. Worse yet, my previous LiveOS USB was formatted for temporary file transfers! Who can understand this pain? Luckily, I had another computer handy, so I downloaded a new image, booted into LiveOS, and re-enabled the root user.
Afterward, I tried logging in as root, and it worked! Suspecting that a rolling update caused the issue, I used Timeshift to roll back Timeshift saved my life!, but to no avail. Then I attempted homectl authenticate xxx to access my home directory, but the system reported insufficient space for mounting. Apologies for not capturing or documenting this error message at the time. This was a valuable clue it suggested that the /home directory was likely intact.
I immediately deleted some Timeshift snapshots and reduced my home directory’s size to 240 GB from 350 GB previously.. Afterward, everything worked as expected.
Solution Selection
Now that I understood the root cause insufficient space the solution was simple: add more space. Fortunately, I had a spare 512 GB hard drive Yes, my computer has two drives. One is from my old laptop, detailed in my earlier post Xianyu Sales Log, and the other came with this system..
The challenge now was determining how to add it. My current setup involves full-disk encryption with LUKS for the root directory See: Full Disk Encryption Guide, with Btrfs as the filesystem atop the encrypted block device. My home directory is managed using systemd-homed.
Here were my options:
- Use LVM to pool both drives into a single virtual volume. However, I didn’t set up LVM during installation, so this route was a dead end.
- Directly use Btrfs’s
btrfs device addto expand the storage pool dynamically. Btrfs offers some LVM-like functionality. - Mount the additional drive directly to the
/homedirectory.
Initially, I leaned toward the third option, thinking it would make it easier to preserve the /home partition during future system reinstalls. However, I realized that I usually perform clean installs, starting from scratch. Since I also have a habit of making casual backups, losing important files wasn’t a major concern.
This led me to choose the second option. Honestly, I had no idea how to implement this at first. I scoured the internet for tutorials and solutions but found nothing that exactly matched my needs. This article is the result of that frustration.Special thanks to the archlinux-cn-offtopic and archlinux-cn communities for their support. These are some of the most welcoming communities I’ve encountered online in recent years. I highly recommend them to fellow Arch users.
Adding the New Hard Drive
Once the plan was clear, I got to work.
Here’s the disk layout at the time. The loop0 device is a local loopback-mounted encrypted home directory managed by systemd-homed. nvme0n1 is the new drive to be added.
NAME TYPE SIZE PTTYPE FSTYPE MOUNTPOINTS
loop0 loop 300G crypto_LUKS
└─home-xxx crypt 300G btrfs /home/xxx
zram0 disk 4G swap [SWAP]
nvme0n1 disk 476.9G gpt
├─nvme0n1p1 part 1G gpt vfat /efi
└─nvme0n1p2 part 475.9G gpt crypto_LUKS
└─linuxroot crypt 475.9G btrfs /home
/root
/var/log
/var/cache
/tmp
/usr-local
/var/lib/docker
/var/tmp
/var/lib/libvirt
/var/lib/containers
/srv
/
nvme1n1 disk 476.9G crypto_LUKSPartitioning
Since the existing drive was encrypted, the new one should also be encrypted. First, I wiped the new drive:
wipefs -af /dev/nvme1n1Then I created a partition table:
partprobe /dev/nvme1n1Next, I added a full-disk partition:
sgdisk -n 0:0:0 -t 0:8309 -c 0:luks /dev/nvme1n1Encryption
I encrypted the new partition (/nvme1n1p1):
cryptsetup luksFormat /dev/nvme1n1p1A critical step follows: ensuring the system can recognize and decrypt the new drive at boot. Without this, Btrfs would fail to find the disk, preventing the system from booting.
First, I retrieved the partition UUID using blkid:
blkid/dev/mapper/linuxroot: LABEL="linuxroot" UUID="2d160a68-3525-4d3e-a536-6d5ba958b768" UUID_SUB="fc945959-b8c7-41b8-9fe1-aea5642d6275" BLOCK_SIZE="4096" TYPE="btrfs"
/dev/nvme0n1p1: LABEL_FATBOOT="EFI" LABEL="EFI" UUID="169B-94E9" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="esp" PARTUUID="fbfee40e-e0cd-47a4-a2e7-6649abdce0be"
/dev/nvme0n1p2: UUID="149d82cd-e65e-46a3-8182-e60a30a77cba" TYPE="crypto_LUKS" PARTLABEL="luks" PARTUUID="f13bf7af-7b8d-40c7-963f-d3761d36268e"
/dev/mapper/home-xxx: LABEL="xxx" UUID="a007119c-2334-4bd9-a5e8-023e0aa24a81" UUID_SUB="10c4fc22-f75f-4343-ba06-27b010d4f6d7" BLOCK_SIZE="4096" TYPE="btrfs"
/dev/loop0: UUID="d19148f0-419c-4cbe-b5bb-679447f3e227" LABEL="lyle" SUBSYSTEM="systemd-home" TYPE="crypto_LUKS"
/dev/mapper/linuxroot2: LABEL="linuxroot" UUID="2d160a68-3525-4d3e-a536-6d5ba958b768" UUID_SUB="05b643c3-54f7-4e04-b317-586f0928ec51" BLOCK_SIZE="4096" TYPE="btrfs"
/dev/nvme1n1p1: UUID="70b0a7d3-9968-4a63-b244-884ca28f85ad" TYPE="crypto_LUKS" PARTLABEL="luks" PARTUUID="8f33a848-8590-4d41-ac68-3ff541051730"
/dev/zram0: LABEL="zram0" UUID="f574f838-3ff9-40c1-8e09-97742b8757a0" TYPE="swap"I added the new UUID to /etc/cmdline.d/root.conf:
rd.luks.name=149d82cd-e65e-46a3-8182-e60a30a77cba=linuxroot rd.luks.name=70b0a7d3-9968-4a63-b244-884ca28f85ad=linuxroot2 root=/dev/mapper/linuxroot rootfstype=btrfs rootflags=subvol=/@ rwAfterward, I rebuilt the initramfs:
mkinitcpio -PTo unlock the new encrypted disk, I used:
cryptsetup open /dev/nvme1n1p1 linuxroot2Adding the Disk to Btrfs
This step was straightforward. I executed:
btrfs device add /dev/mapper/linuxroot2 /It’s crucial to specify the mapped path (e.g., /dev/mapper/linuxroot2) rather than the raw partition (e.g., /dev/nvme1n1p1). Using the raw path can lead to errors if the device path changes. Also, avoid formatting the new partition; it should remain untouched.
Finally, I verified the setup:
btrfs filesystem show /Label: 'linuxroot' uuid: 2d160a68-3525-4d3e-a536-6d5ba958b768
Total devices 2 FS bytes used 392.91GiB
devid 1 size 475.92GiB used 392.91GiB path /dev/mapper/linuxroot
devid 2 size 476.92GiB used 000.00GiB path /dev/mapper/linuxroot2Or:
btrfs filesystem usage -T /And that’s it! 🎉 The new drive is successfully added.