Michael Boulton

Michael Boulton

  • Docs
  • Blog
  • Github

›Recent Posts

Recent Posts

  • Modifying rules to use bzlmod
  • Running openSUSE Tumbleweed using f2fs on a raspberry pi
  • Terminal/vim setup
  • Thoughts on Bazel
  • Thoughts on Go

Running openSUSE Tumbleweed using f2fs on a raspberry pi

September 18, 2023

Michael Boulton

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.

  1. Delete all paritions except the first one, this is the EFI boot partition
  2. Create a ext4 partition which is about 500MB-1GB, this will be the /boot partition.
  3. 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!

Recent Posts
  • Getting the initial SD card set up
  • Creating the partitions and filesystem
Icons from https://github.com/PKief/vscode-material-icon-theme and https://github.com/vscode-icons/vscode-icons