Running openSUSE Tumbleweed using f2fs on a raspberry pi
I wanted to try running k3s on a raspberry pi 3 and tried to change the root filesystem to f2fs to see if it would help (spoiler: it's not powerful enough). This required quite a few extra steps which might be useful to someone else, even if you're not running on a raspberry pi.
You will need a USB SD card adapter and 2 SD cards for this, one to bootstrap the other one. One will probably come with the raspberry pi, so use this slow one as the bootstrap card. For this, I had the original 16GB SD card that came with the pi and I bought a separate Sandisk 128GB A2 SD card. There's a load of different rating for SD cards, this page has a sort of explainer on A1 vs A2: https://www.mymemory.co.uk/blog/a1-vs-a2-sandisk-microsd-card-whats-the-difference/
Getting the initial SD card set up
Download the basic 'jeos' image from one of the links on the openSUSE wiki.
You can mount partitions from this by using mount
, but messing around with fil eoffsets is a bit annoying. You can
use losetup
to automatically find the correct offsets and put them into
/dev/loopX
:
# Note: this and all future commands assume you're running as root already.
losetup --partscan --find --show openSUSE-Tumbleweed-ARM-JeOS-raspberrypi.aarch64.raw
# Create a folder under /mnt specifically for the jeos root image
mkdir -p /mnt/jeos
# or wherever it's been mounted
mount -o ro /dev/loop2p3 /mnt/jeos/
Plug in the bootstrap SD card and copy the jeos image to it using dd
. This shouldn't take too long.
# replace /dev/sda with your SD card (find it with fdisk -l)
umount /dev/sda*
dd if=openSUSE-Tumbleweed-ARM-JeOS-raspberrypi.aarch64.raw of=/dev/sda bs=8M status=progress
Plug in your second SD card (the one you actually want to use f2fs on) and do the same thing, but note here that you
don't really need to copy the whole disk as we'll be changing the partitions, so run it and ctrl-c the command after
it's copied the first 500MB or so then run sync
to make sure it's finished copying whatever it wanted.
Creating the partitions and filesystem
Open your favourite disk partitioner (fdisk
, gparted
, the YaST partitioner...) and create the partitions. This is
what I went for on a 128GB card - note that you need the extended partition because you can only have 4 partitions by
default.
- Delete all paritions except the first one, this is the EFI boot partition
- Create a ext4 partition which is about 500MB-1GB, this will be the /boot partition.
- Create an extended partition that fills up the rest of the disk. Under this extended partition, create:
- swap partition - make it ~2x your RAM to be safe. SD cards are big.
- f2fs partition (your root)
- optional - any other separate partitions (maybe a xfs partition for any database data)
I went for a 90GB root partition and filled the rest of the extended partition with an xfs partition.
Create the f2fs filesystem on your root partition:
# sda6 should be your root partition if you've followed the previous instructions
mkfs.f2fs -l mylabel -O extra_attr,inode_checksum,sb_checksum,compression /dev/sda6
Mount this partition and rsync the original contents of the image (currently mounted in /mnt/jeos
)
mkdir -p /mnt/sdcard/
mount -o compress_algorithm=zstd:6,compress_chksum,atgc,gc_merge,lazytime /dev/sda6 /mnt/sdcard/
cd /mnt/jeos
rsync -avHAXP --exclude root /mnt/jeos /mnt/sdcard
Now edit the fstab
on the SD card to mount the partitions correctly. The UUIDs of each partition will change, but it
should look something like this:
# UUID of /dev/sda6
UUID=5c6a356c-7a08-4a1c-970c-3f2cc7a50b08 / f2fs extra_attr,inode_checksum,sb_checksum,compression 0 1
# UUID of /dev/sda2
UUID=318224cd-a802-4132-ab4b-154e2a7c1f1f /boot/ ext4 defaults 0 2
# UUID of /dev/sda1
UUID=ABCD-EFGH /boot/efi vfat defaults 0 0
# UUID of /dev/sda4
UUID=22592dc0-890a-4149-9399-649d94c0247b swap swap defaults 0 0
# if you created a data partition
UUID=b610a9c9-256c-4ad0-8c36-3946424482c0 /data xfs defaults 0 3
Now the difficult bit. Boot your raspberry pi from the bootstrap SD card. This should boot into a normal Tumbleweed root terminal. Plug in the SD card adapter with your fast SD card, and mount the partitions for your new SD card in the correct hierarchy. For example, this might be:
# on the pi!
mkdir -p /mnt
mount /dev/sda6 /mnt -o compress_algorithm=zstd:6,compress_chksum,atgc,gc_merge,lazytime
mount /dev/sda2 /mnt/boot
mount /dev/sda3 /mnt/boot/efi
mount -t proc /proc /mnt/proc/
mount --rbind /sys /mnt/sys/
mount --rbind /dev /mnt/dev/
Now /mnt will have the same hierarchy as your final SD card. chroot
into this and fix the bootloader.
chroot /mnt
# you're now inside the chroot for the new SD card.
# Update the bootloader
update-bootloader
# Required because it doesn't have this driver by default.
dracut -f --add-drivers f2fs
After this, exit the chroot.
Now you need to manually edit the initial bootloader in the EFI boot partition currently mounted on /mnt/boot/efi
.
There is a grub.cfg
in a subfolder (/mnt/boot/efi/EFI/BOOT
) with a line like this:
search --fs-uuid --set=root b606c027-e908-4b63-bb97-278097ff4ff2
You need to edit this so it points to the uuid of your new ext4 partition (in my example, /dev/sda2
). You can find
this using blkid
. In the fstab example above, this is '318224cd-a802-4132-ab4b-154e2a7c1f1f'.
The final thing to do is to fix the linux kernel image. There is definitely a better way of doing this, but this is a
quick hacky way that works. The problem is that the kernel image is actually symlinked to something
like ../usr/lib/modules/...
which won't exist because it's on a different partition that doesn't exist at boot time.
To fix this, go into /mnt/boot
, find what the symlink should point to (using a command like stat
or file
), and
replace the symlink with the actual file.
Run sync
one final time, then shutdown -hP now
. The second (fast) SD card hsould now be set up to boot onto an f2fs
filesystem with compression enabled!