Skip to content
vast-cow's blog
Go back

Procedure for Changing the rootfs of Rocky Linux 9 to F2FS

Edit page

Procedure for Changing the rootfs of Rocky Linux 9 to F2FS

When changing the root filesystem of Rocky Linux 9 to F2FS, it is difficult to complete the process using only the standard installer. In practice, the realistic workflow is to first perform a normal Rocky 9 installation using ext4, XFS, or similar, then boot from a Live USB, back up the rootfs, recreate it as F2FS, and restore it.

This article organizes the procedure under the following assumptions:

ELRepo is a repository that provides kernels, filesystem drivers, and similar packages for Enterprise Linux, and kernel-lt is provided as a long-term support kernel. When trying F2FS root on Rocky/RHEL 9 systems, assuming the use of an ELRepo kernel rather than the standard kernel is practical. (Elrepo)


1. Basic Policy

The final configuration will be as follows.

/boot      ext4 or XFS
/boot/efi  vfat
/          f2fs

The reason for not making /boot F2FS is simple: to reduce uncertainty around GRUB and early boot. If only the rootfs is F2FS, GRUB reads the kernel and initramfs from /boot as usual, and the rootfs is mounted by the F2FS driver inside the initramfs.


2. Install Rocky 9 Normally

First, install Rocky Linux 9 normally.

At this point, the rootfs may be ext4, XFS, or similar.

Example partition layout:

/dev/nvme0n1p1  /boot/efi
/dev/nvme0n1p2  /boot
/dev/nvme0n1p3  /

What matters is keeping /boot separate from /.


3. Set SELinux to permissive

After conversion to F2FS, there is a possibility of running into issues involving SELinux labels or extended attributes. Therefore, set SELinux to permissive before the work.

sudo vi /etc/selinux/config
SELINUX=permissive

Reboot after making the change.

sudo reboot

After booting, check the status.

getenforce
Permissive

4. Install ELRepo’s kernel-lt

Use ELRepo’s kernel-lt instead of the standard Rocky 9 kernel.

sudo dnf install https://www.elrepo.org/elrepo-release-9.el9.elrepo.noarch.rpm
sudo dnf --enablerepo=elrepo-kernel install kernel-lt

Caution is required if Secure Boot is enabled. According to ELRepo’s explanation, kernel-ml and kernel-lt are not signed with a Secure Boot key. In a Secure Boot environment, you must either disable Secure Boot or sign the kernel yourself and register it with MOK. (Elrepo)

Reboot.

sudo reboot

Select ELRepo’s kernel-lt in GRUB, then verify after booting.

uname -r

Confirm that the system has booted with a kernel version containing elrepo.

Also check whether the F2FS module can be used.

sudo modprobe f2fs
grep f2fs /proc/filesystems

If this fails, you should not proceed with converting the rootfs to F2FS.


5. Create a dracut Configuration to Include the F2FS Driver

Once the rootfs is F2FS, the F2FS driver is needed during the initramfs stage. Therefore, persist the dracut configuration.

sudo tee /etc/dracut.conf.d/90-f2fs-root.conf >/dev/null <<'EOF'
add_drivers+=" f2fs "
EOF

In dracut.conf, kernel modules specified in add_drivers can be added to the initramfs. Specify the module name without .ko. (Ubuntu Manpages)

You may also use force_drivers if necessary.

sudo tee /etc/dracut.conf.d/90-f2fs-root.conf >/dev/null <<'EOF'
force_drivers+=" f2fs "
EOF

Like add_drivers, force_drivers includes the module, but it is a setting intended to have it modprobed at an earlier stage. (Ubuntu Manpages)

Rebuild the initramfs.

sudo dracut -f /boot/initramfs-$(uname -r).img $(uname -r)

Check its contents.

lsinitrd /boot/initramfs-$(uname -r).img | grep f2fs

It is sufficient if f2fs.ko is included.


6. Boot from a Live USB

From here, boot using an Ubuntu Live USB or similar and perform the work.

First, check the disk layout.

sudo lsblk -f
sudo blkid

Here, assume the following example:

/dev/nvme0n1p1  /boot/efi
/dev/nvme0n1p2  /boot
/dev/nvme0n1p3  /

The rootfs is assumed to be /dev/nvme0n1p3.


7. Record the UUID of the rootfs

Under this policy, the same UUID as the original rootfs is specified when running mkfs.f2fs.

First, save the current UUID.

OLD_UUID=$(sudo blkid -s UUID -o value /dev/nvme0n1p3)
echo "$OLD_UUID"

Use this UUID when creating the F2FS filesystem as well.


8. Back Up the rootfs Before Conversion

Mount the rootfs before conversion.

sudo mkdir -p /mnt/src
sudo mount /dev/nvme0n1p3 /mnt/src

Mount the backup destination. Example:

sudo mkdir -p /mnt/backup
sudo mount /dev/sdX1 /mnt/backup

When backing up with tar, make sure not to lose SELinux contexts, xattrs, ACLs, or ownership information.

sudo tar \
  --one-file-system \
  --xattrs --xattrs-include='*' \
  --acls \
  --selinux \
  --numeric-owner \
  --sparse \
  -cpf /mnt/backup/rocky-root.tar \
  -C /mnt/src .

This backup is a logical backup of the rootfs.

As additional insurance, it is also a good idea to back up the entire pre-conversion partition using partclone or similar. A partclone backup serves as insurance for “restoring the original ext4/XFS rootfs if the conversion fails.”

After backing up, unmount it.

sudo umount /mnt/src

9. Create the rootfs as F2FS

Now recreate the rootfs partition as F2FS.

If your version of mkfs.f2fs supports specifying a UUID, specify the original UUID.

sudo mkfs.f2fs -f -l rocky-root -U "$OLD_UUID" /dev/nvme0n1p3

After creation, check whether the UUID is the same.

sudo blkid /dev/nvme0n1p3

Expected state:

UUID="<OLD_UUID>" TYPE="f2fs"

Whether mkfs.f2fs -U can be used may depend on the version of f2fs-tools, so check in advance.

mkfs.f2fs -h

If you can keep the same UUID, you can avoid making major changes to root=UUID=... in BLS/GRUB. However, you must change the filesystem type in fstab to F2FS.


10. Restore the rootfs

Mount the rootfs that was converted to F2FS.

sudo mkdir -p /mnt/dst
sudo mount -t f2fs /dev/nvme0n1p3 /mnt/dst

Restore from the tar archive.

sudo tar \
  --xattrs --xattrs-include='*' \
  --acls \
  --selinux \
  --numeric-owner \
  --same-owner \
  --sparse \
  -xpf /mnt/backup/rocky-root.tar \
  -C /mnt/dst

Sync.

sudo sync

11. Edit /etc/fstab

Edit the restored fstab.

sudo vi /mnt/dst/etc/fstab

Change the rootfs line to F2FS.

Example:

UUID=<OLD_UUID>  /  f2fs  defaults,noatime  0  0

Because the UUID is kept the same in this procedure, the UUID itself does not need to be changed.

However, this must be changed:

ext4 or xfs → f2fs

If prioritizing recoverability, set the final pass number to 0 at first.

UUID=<OLD_UUID>  /  f2fs  defaults,noatime  0  0

If you can reliably include fsck.f2fs in the initramfs and operate it that way, review this later.


12. Mount /boot and Check the BLS Entries

Since /boot is a separate partition, be sure to mount it.

sudo mount /dev/nvme0n1p2 /mnt/dst/boot

In a UEFI environment, also mount the EFI System Partition.

sudo mount /dev/nvme0n1p1 /mnt/dst/boot/efi

Check the BLS entries.

grep -R "root=" /mnt/dst/boot/loader/entries/*.conf

Since the UUID is kept the same, root=UUID=... can basically remain unchanged.

However, it is clearer to add rootfstype=f2fs.

Chroot and add it with grubby.

sudo mount --rbind /dev /mnt/dst/dev
sudo mount --make-rslave /mnt/dst/dev
sudo mount -t proc proc /mnt/dst/proc
sudo mount -t sysfs sysfs /mnt/dst/sys
sudo mount -t tmpfs tmpfs /mnt/dst/run

sudo chroot /mnt/dst /bin/bash

Run the following inside the chroot.

grubby --update-kernel=ALL --args="rootfstype=f2fs"

On RHEL 9 systems, boot entry kernel command lines can be changed with grubby. Red Hat documentation also shows grubby --update-kernel=ALL --args=... as a method for adding kernel parameters to all boot entries. (Red Hat Documentation)

Check the result.

grep -R "root=" /boot/loader/entries/*.conf
grep -R "rootfstype" /boot/loader/entries/*.conf

13. Regenerate the initramfs Inside the chroot

When chrooting from a Live USB, do not use uname -r.

This is because uname -r returns the kernel version of the Live USB environment.

Check the Rocky-side kernel versions in /lib/modules.

ls /lib/modules

Target the ELRepo kernel.

KVER=$(ls /lib/modules | grep elrepo | tail -n 1)
echo "$KVER"

Prioritizing recoverability, first create a broader initramfs.

dracut -f \
  --no-hostonly \
  --force-drivers "f2fs" \
  "/boot/initramfs-${KVER}.img" \
  "${KVER}"

dracut is a tool for creating initramfs images; it collects the necessary tools/files from the installed system and builds the initramfs. (GitHub)

Check it.

lsinitrd "/boot/initramfs-${KVER}.img" | grep f2fs

Confirm that f2fs.ko is included.


14. Schedule an SELinux Relabel

Even if xattrs and SELinux contexts were preserved with tar, it is safer to schedule a relabel on the first boot.

Inside the chroot:

touch /.autorelabel

A relabel will run after the first boot.


15. Exit the chroot and Reboot

Exit the chroot.

exit

Unmount.

sudo sync
sudo umount -R /mnt/dst

Reboot.

sudo reboot

In GRUB, select ELRepo’s kernel-lt.


16. Check After Booting

If the system boots successfully, check whether the rootfs is F2FS.

findmnt -no SOURCE,FSTYPE,OPTIONS /

Expected output:

/dev/nvme0n1p3 f2fs ...

Also check the kernel.

uname -r

Confirm that it is the ELRepo kernel.

grep f2fs /proc/filesystems

SELinux can remain permissive for now.

getenforce

If there are no problems, switch it back to enforcing as needed.

sudo vi /etc/selinux/config
SELINUX=enforcing

Check again after rebooting.

getenforce

Recovery Procedure If the System Does Not Boot

If the system does not boot after converting to F2FS, recover by chrooting from an Ubuntu Live USB.

1. Boot from a Live USB and Check

sudo lsblk -f
sudo blkid

Check whether the rootfs is recognized as F2FS.

sudo file -s /dev/nvme0n1p3

2. Mount the rootfs, boot, and EFI

sudo mkdir -p /mnt/sysroot
sudo mount -t f2fs /dev/nvme0n1p3 /mnt/sysroot

Mount /boot.

sudo mount /dev/nvme0n1p2 /mnt/sysroot/boot

For UEFI:

sudo mount /dev/nvme0n1p1 /mnt/sysroot/boot/efi

This is important.

If you run dracut without mounting /boot, the initramfs will be created in the empty directory inside the rootfs, not in the actual /boot.


3. chroot

sudo mount --rbind /dev /mnt/sysroot/dev
sudo mount --make-rslave /mnt/sysroot/dev
sudo mount -t proc proc /mnt/sysroot/proc
sudo mount -t sysfs sysfs /mnt/sysroot/sys
sudo mount -t tmpfs tmpfs /mnt/sysroot/run
sudo chroot /mnt/sysroot /bin/bash

4. Check fstab

cat /etc/fstab

Confirm that the rootfs is F2FS.

UUID=<OLD_UUID>  /  f2fs  defaults,noatime  0  0

5. Check the BLS Entries

grep -R "root=" /boot/loader/entries/*.conf
grep -R "rootfstype" /boot/loader/entries/*.conf

If the UUID is kept the same, root=UUID=... can basically remain unchanged.

However, if rootfstype=f2fs is missing, add it.

grubby --update-kernel=ALL --args="rootfstype=f2fs"

6. Explicitly Specify the Target Kernel and Re-run dracut

Do not use uname -r here either.

ls /lib/modules

Select the ELRepo kernel.

KVER=$(ls /lib/modules | grep elrepo | tail -n 1)
echo "$KVER"

Rebuild the initramfs.

dracut -f \
  --no-hostonly \
  --force-drivers "f2fs" \
  "/boot/initramfs-${KVER}.img" \
  "${KVER}"

Check it.

lsinitrd "/boot/initramfs-${KVER}.img" | grep f2fs

7. Schedule an SELinux Relabel

touch /.autorelabel

8. Exit the chroot and Reboot

exit
sudo sync
sudo umount -R /mnt/sysroot
sudo reboot

Select ELRepo kernel-lt in GRUB.


Common Causes of Failure

SymptomCause
unknown filesystem type 'f2fs'The F2FS module is not included in the initramfs
VFS: Unable to mount root fsThe rootfs specification, initramfs, or kernel module is incorrect
UUID=... does not existThe UUID changed, or the UUID was specified incorrectly
Drops into emergency shellfstab, root specification, initramfs, or SELinux issue
Does not boot with standard kernelThe Rocky 9 standard kernel side does not have the F2FS root module, or it is not in the initramfs
Still not fixed after running dracut in chrootThe initramfs was created without mounting /boot
dracut -f $(uname -r) failsThe Live USB kernel version is being used

Summary

The procedure for changing the rootfs of Rocky Linux 9 to F2FS is safer when done as follows.

1. Install Rocky 9 normally with /boot as a separate partition
2. Set SELinux to permissive
3. Install ELRepo kernel-lt
4. Boot with kernel-lt and check the f2fs module
5. Persistently add f2fs to dracut
6. Boot from an Ubuntu Live USB
7. Back up the rootfs with tar, including xattrs/ACLs/SELinux
8. Record the original rootfs UUID
9. Specify the original UUID when running mkfs.f2fs
10. Restore the rootfs
11. Change the rootfs type in /etc/fstab to f2fs
12. Add rootfstype=f2fs to the BLS entries
13. Explicitly specify the target kernel inside the chroot and regenerate dracut
14. Create /.autorelabel
15. Boot with ELRepo kernel-lt

The following four points are especially important.

- Always keep /boot separate
- Include f2fs.ko in the initramfs
- Confirm that the UUID remains the same after mkfs.f2fs
- If the system does not boot, recover using Live USB + chroot + dracut

If you keep the UUID the same as before, you can avoid changing root=UUID=..., which makes the work considerably simpler. However, the filesystem type in /etc/fstab and the F2FS module in the initramfs must be configured correctly.


Edit page
Share this post:

Comments


Previous Post
Creating and Mounting a QEMU qcow2 Image on Ubuntu
Next Post
PDF Page Combining Tool