Expand root script not working f2fs

Having just upgraded my NanoPi R5S to 25.12.2, I wanted to expand the filesystem (I’m using squashfs on the eMMC). I followed the instructions at https://openwrt.org/docs/guide-user/advanced/expand_root in the section Automated Post 25.12. The device reboots and I can see /etc/uci-defaults/70-rootpt-resize and /etc/uci-defaults/80-rootfs-resize have been created and those lines added to /etc/sysupgrade.conf

After the reboot, /etc/rootpt-resize and /etc/rootfs-resize have been created, but the filesystem is still the same size.

I see nothing in the log, though obviously it reboots. I added read -n 1 -s -r -p "press any key to reboot" before the reboot command in both scripts hoping I would see some output, but nothing is echoed to the console
Can someone suggest a way to troubleshoot this, please?.

Similar thread yesterday:

1 Like

Thanks, but all that does different, is to modify 70-rootpt-resize to take 584MiB instead of the full disk (its default behaviour), The rest of the steps concern themselves with formatting the rest of the block device as a data partition.

The script isn't doing anything (as far as I can tell)

OK, now I'm confused. Why is mmcblk1p1 ext4?

root@Liberator:~# blkid
/dev/nvme0n1p1: LABEL="rootfs" UUID="966a04b3-d5f2-461c-8685-1af7bd2e604d" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="rootfs" PARTUUID="35a0bafe-a0bc-4500-a95b-3668c6782e56"
/dev/loop0: LABEL="rootfs_data" UUID="68b3f11d-5d4e-4d14-a8c0-acd6a8079f5d" BLOCK_SIZE="4096" TYPE="f2fs"
/dev/mmcblk1p1: LABEL="kernel" UUID="84173db5-fa99-e35a-95c6-28613cc79ea9" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="d0f6e5b4-01"
/dev/mmcblk1p2: BLOCK_SIZE="262144" TYPE="squashfs" PARTUUID="d0f6e5b4-02"
root@Liberator:~# lsblk
NAME         MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0          7:0    0  14.5G  0 loop /overlay
mmcblk1      179:0    0  14.6G  0 disk
├─mmcblk1p1  179:1    0    16M  0 part
└─mmcblk1p2  179:2    0  14.5G  0 part /rom
mmcblk1boot0 179:32   0     4M  1 disk
mmcblk1boot1 179:64   0     4M  1 disk
nvme0n1      259:0    0 465.8G  0 disk
└─nvme0n1p1  259:1    0 465.7G  0 part

Looking at your output, I need to clarify something:

Your eMMC (mmcblk1p2) is already 14.5GB out of 14.6GB total - it's already using the full disk. You also have a 465GB NVMe drive that's unused.

What exactly are you trying to achieve? Are you trying to:

  • Expand the eMMC root (already maxed out)?
  • Move OpenWrt to the NVMe?
  • Use the NVMe as extra storage?

The expand_root script only works when there's unused space on the boot device.

I know we're not really fond of images, but here's LuCI showing disk space as being 98MiB
I'm trying to use the full eMMC for OpenWrt. The NanoPi R5S can't boot from the NVMe unfortunately (there are pads for a NOR, but one was not provided for some bizarre reason, or instructions for adding one). I'm not interested in bootstrapping either.

Just want to fill the eMMC wiith OpenWrt and I don't understand why there's an ext4 partition there. It would be helpful if the expand_root script either saved a log somewhere, or at least echoed to the console. It appears to be working properly, as evidenced by the creation of /etc/rootpt_resize and /etc/rootfs_resize, however, it clearly isn't :man_shrugging:

Did you flash squashfs image? Also first partition will stay ext4. May I ask why you want to allocate the entire storage to the second partition? When you sysupgrade your data will get overwritten if I'm not mistaken that's why I proposed 2nd partition 512MB and rest for persistent user data

I flashed openwrt-25.12.2-rockchip-armv8-friendlyarm_nanopi-r5s-squashfs-sysupgrade.img.gz

Why will the first partition stay ext4?

I have no need of more than 1 partition and I don't understand why there is an ext4 partition. I was simply trying to expand to filesystem to use the entire space on the eMMC, nothing else should reside there.

If I understand correctly, that's what the script is designed to do isn't it? Expand the filesystem from the default to 100%. The wiki page says it supports both squashfs and ext4.
Am I missing something? Is it not possible to use the entire eMMC?

Yep you're correct. Well tbh I'm no expert in Linux stuff but I've raspberry pi4 with 64GB storage. Here are my partitions:

Device         Boot   Start       End   Sectors  Size Id Type
/dev/mmcblk0p1 *       8192    139263    131072   64M  c W95 FAT32 (LBA)
/dev/mmcblk0p2       147456   1196031   1048576  512M 83 Linux
/dev/mmcblk0p3      1196032 125173759 123977728 59.1G 83 Linux
root@OpenWrt:~# block info
/dev/loop0: UUID="b3ff9a9d-3989-4971-98bd-83921dd7a0a3" LABEL="rootfs_data" VERSION="1.0" MOUNT="/overlay" TYPE="ext4"
/dev/mmcblk0p1: UUID="69C4-4111" LABEL="boot" VERSION="FAT16" MOUNT="/boot" TYPE="vfat"
/dev/mmcblk0p2: UUID="2d31e17b-aef250c9-ce174ab0-de14e42b" VERSION="4.0" MOUNT="/rom" TYPE="squashfs"
/dev/mmcblk0p3: UUID="bca0c9ac-71dc-4f06-a033-5a7ded10fee3" LABEL="storage" VERSION="1.16" MOUNT="/sda0" TYPE="f2fs"

If you leave the default at 100%, the root partition fills the entire SD card. During a sysupgrade, OpenWrt reflashes that entire partition, wiping all your saved data. To keep your files safe, limit the root partition (like I did 512MiB) & create a separate 3rd large partition for storage. This ensures your data survives firmware updates. So which one you want? Also are you willing reflash and start the process all over again? I'll try help you

If you want one whole root partition then just keep 100% instead 584MiB and don't bother after step 4 from my guide.

1. Reboot (if not done yet)

2. Query actual values

lsblk
df -h
ls -la /etc/rootpt-resize /etc/rootfs-resize
apk list --installed | grep -E 'parted|losetup|resize2fs'
mount | grep overlay

Please post the complete output.


Note: The expand_root scripts only run when all conditions are met (3 conditions in the first script, 5 in the second). If even one is missing, the script silently fails to execute. The above commands will show us the actual status.

1 Like

Rebooted

root@Liberator:~# lsblk
NAME         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
loop0          7:0    0 14.5G  0 loop /overlay
mmcblk1      179:0    0 14.6G  0 disk
├─mmcblk1p1  179:1    0   16M  0 part
└─mmcblk1p2  179:2    0 14.5G  0 part /rom
mmcblk1boot0 179:32   0    4M  1 disk
mmcblk1boot1 179:64   0    4M  1 disk
root@Liberator:~# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root                 3.8M      3.8M         0 100% /rom
tmpfs                     1.9G    328.0K      1.9G   0% /tmp
/dev/loop0               98.4M     42.9M     55.5M  44% /overlay
overlayfs:/overlay       98.4M     42.9M     55.5M  44% /
tmpfs                   512.0K         0    512.0K   0% /dev
root@Liberator:~# ll /etc/rootpt-resize /etc/rootfs-resize
-rw-r--r--    1 root     root             0 Mar 28 20:48 /etc/rootfs-resize
-rw-r--r--    1 root     root             0 Mar 28 20:48 /etc/rootpt-resize
root@Liberator:~# apk list --installed | grep -E 'parted|losetup|resize2fs'
libparted-3.6-r2 aarch64_generic {feeds/packages/feeds/packages/utils/parted} (GPL-3.0-or-later) [installed]
losetup-2.41.3-r1 aarch64_generic {feeds/base/utils/util-linux} (GPL-2.0-or-later) [installed]
parted-3.6-r2 aarch64_generic {feeds/packages/feeds/packages/utils/parted} (GPL-3.0-or-later) [installed]
resize2fs-1.47.3-r1 aarch64_generic {feeds/base/utils/e2fsprogs} (GPL-2.0) [installed]
root@Liberator:~# mount | grep overlay
/dev/loop0 on /overlay type f2fs (rw,lazytime,noatime,background_gc=on,nogc_merge,discard,discard_unit=block,user_xattr,inline_xattr,acl,inline_data,inline_dentry,flush_merge,barrier,extent_cache,mode=adaptive,active_logs=6,alloc_mode=reuse,checkpoint_merge,fsync_mode=posix,memory=normal,errors=continue)
overlayfs:/overlay on / type overlay (rw,noatime,lowerdir=/,upperdir=/overlay/upper,workdir=/overlay/work)

If the script silently fails to execute, how come /etc/rootpt_resize and /etc/rootfs_resize are created and reboots performed? That would seem like bad logic no?

lsblk shows loop0 with 14.5G, but df -h shows /dev/loop0 with only 98.4M.

The scripts ran through correctly from a procedural standpoint. The issue: The scripts use resize2fs (for ext4), but your overlay is f2fs. This is a design flaw in the script - it should detect the filesystem type and use the appropriate tool.


# Install f2fs-tools (if not already present)
apk add f2fs-tools

# Resize the filesystem
resize.f2fs /dev/loop0

# Reboot
reboot

After this, df -h should show /dev/loop0 with ~14.4GB available space.

According to the wiki, this script is only intended for x86, not for ARM. However, I can see it mostly worked for you - except for the filesystem resize. The script would need to be adapted for ARM systems with f2fs overlay (filesystem detection + resize.f2fs support), but that would require consultation with the developers. Currently, it's explicitly designed for x86 only, not for ARM.

Just a comment from the side..the wiki is written by users and not everything in the wiki is official. Many stuff is just provided by community for community. And you do not need to consult or make design proposals for a simple if then else to support another filesystem....

I don't really understand the distinction with architecture; x86 can boot from eMMC.

I tried your suggestion with f2fs-tools, but it complains about it being mounted

root@Liberator:~# apk add f2fs-tools
(1/2) Installing f2fsck (1.16.0-r4)
  Executing f2fsck-1.16.0-r4.post-install
(2/2) Installing f2fs-tools (1.16.0-r4)
  Executing f2fs-tools-1.16.0-r4.post-install
OK: 18.7 MiB in 161 packages
root@Liberator:~# resize.f2fs /dev/loop0
Info: Mounted device!
Info: Check FS only on RO mounted device
        Error: Failed to open the device!

If I change the following line in /etc/uci-defaults/80-rootfs-resize
resize2fs -f "${LOOP_DEV}"
to read
resize.f2fs -f "${LOOP_DEV}"
(and rm /etc/root??-resize) would that work?
If so, it should also persist across upgrades

You're right about the architecture confusion - x86 can also boot from eMMC. The real issue is the filesystem, not the architecture.

The Wiki script is designed for systems with ext4 overlay (typical on x86 with SSD/HDD). Your NanoPi R5S automatically uses f2fs overlay (because of eMMC). The critical difference: resize2fs can resize ext4 online (while mounted), but resize.f2fs requires an unmounted filesystem. Since /overlay is the active system, it cannot simply be unmounted.

This could be a solution: The trick is to create a second loop device on the same partition, briefly mount and then unmount it. Then resize.f2fs can work on this unmounted loop device.

First, reboot your system to get a clean state, then run this script and post the entire output:

bash

#!/bin/sh
echo "=== Installing required packages ==="
apk update
apk add losetup f2fs-tools

echo -e "\n=== Current status ==="
df -h | grep -E '(overlay|Filesystem)'
mount | grep overlay

echo -e "\n=== Getting loop device info ==="
LOOP="$(losetup -n -O NAME | sort | sed -n -e "1p")"
echo "Current LOOP: $LOOP"
ROOT="$(losetup -n -O BACK-FILE ${LOOP} | sed -e "s|^|/dev|")"
echo "ROOT device: $ROOT"
OFFS="$(losetup -n -O OFFSET ${LOOP})"
echo "Offset: $OFFS"

echo -e "\n=== Creating new loop device ==="
NEW_LOOP="$(losetup -f)"
echo "New LOOP: $NEW_LOOP"
losetup -o ${OFFS} ${NEW_LOOP} ${ROOT}

echo -e "\n=== Filesystem check ==="
fsck.f2fs -f ${NEW_LOOP}

echo -e "\n=== Mount/Unmount trick ==="
mount ${NEW_LOOP} /mnt && echo "Mount: OK" || echo "Mount: FAILED"
umount ${NEW_LOOP} && echo "Unmount: OK" || echo "Unmount: FAILED"

echo -e "\n=== Resizing f2fs ==="
resize.f2fs ${NEW_LOOP}

echo -e "\n=== Done - rebooting ==="
reboot

After the second reboot, run df -h and post the output.

Important: This is untested since I don't have an f2fs-based system. Worst case: reflashing might be necessary. If it works, your feedback would confirm this approach and I'd adapt the universal script accordingly.

Thanks for continuing to work on it!
The wiki page specifically says support for ext4 and squashfs, which is what led me to believe it would work.
I have included the console output from the script below in case that's any help.
df -h and LuCI now show things to be as I would have expected, although blkid shows there is still an ext4 partition?

Output of script

root@Liberator:~# . ./test_resize.sh
=== Installing required packages ===
 [https://downloads.openwrt.org/releases/25.12.2/targets/rockchip/armv8/packages/packages.adb]
 [https://downloads.openwrt.org/releases/25.12.2/packages/aarch64_generic/base/packages.adb]
 [https://downloads.openwrt.org/releases/25.12.2/targets/rockchip/armv8/kmods/6.12.74-1-e30f543625695988fdad1ed84a7518c2/packages.adb]
 [https://downloads.openwrt.org/releases/25.12.2/packages/aarch64_generic/luci/packages.adb]
 [https://downloads.openwrt.org/releases/25.12.2/packages/aarch64_generic/packages/packages.adb]
 [https://downloads.openwrt.org/releases/25.12.2/packages/aarch64_generic/routing/packages.adb]
 [https://downloads.openwrt.org/releases/25.12.2/packages/aarch64_generic/telephony/packages.adb]
 [https://downloads.openwrt.org/releases/25.12.2/packages/aarch64_generic/video/packages.adb]
OK: 10965 distinct packages available
OK: 18.7 MiB in 161 packages

=== Current status ===
Filesystem                Size      Used Available Use% Mounted on
/dev/loop0               98.4M     43.2M     55.1M  44% /overlay
overlayfs:/overlay       98.4M     43.2M     55.1M  44% /
/dev/loop0 on /overlay type f2fs (rw,lazytime,noatime,background_gc=on,nogc_merge,discard,discard_unit=block,user_xattr,inline_xattr,acl,inline_data,inline_dentry,flush_merge,barrier,extent_cache,mode=adaptive,active_logs=6,alloc_mode=reuse,checkpoint_merge,fsync_mode=posix,memory=normal,errors=continue)
overlayfs:/overlay on / type overlay (rw,noatime,lowerdir=/,upperdir=/overlay/upper,workdir=/overlay/work)

=== Getting loop device info ===
Current LOOP: /dev/loop0
ROOT device: /dev/mmcblk1p2
Offset: 3801088

=== Creating new loop device ===
New LOOP: /dev/loop1

=== Filesystem check ===
Info: Force to fix corruption
Info: MKFS version
  "Linux version 6.12.74 (builder@buildhost) (aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 14.3.0 r32802-f505120278) 14.3.0, GNU ld (GNU Binutils) 2.44) #0 SMP Wed Mar 25 20:09:53 2026"
Info: FSCK version
  from "Linux version 6.12.74 (builder@buildhost) (aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 14.3.0 r32802-f505120278) 14.3.0, GNU ld (GNU Binutils) 2.44) #0 SMP Wed Mar 25 20:09:53 2026"
    to "Linux version 6.12.74 (builder@buildhost) (aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 14.3.0 r32802-f505120278) 14.3.0, GNU ld (GNU Binutils) 2.44) #0 SMP Wed Mar 25 20:09:53 2026"
Info: superblock features = 0 :
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: Segments per section = 1
Info: Sections per zone = 1
Info: total FS sectors = 205568 (100 MB)
Info: CKPT version = 55ab23ed
Info: checkpoint state = 44 :  crc compacted_summary sudden-power-off

[FSCK] Max image size: 24 MB, Free space: 76 MB
[FSCK] Unreachable nat entries                        [Ok..] [0x0]
[FSCK] SIT valid block bitmap checking                [Ok..]
[FSCK] Hard link checking for regular file            [Ok..] [0x1]
[FSCK] valid_block_count matching with CP             [Ok..] [0x4dc]
[FSCK] valid_node_count matching with CP (de lookup)  [Ok..] [0xd6]
[FSCK] valid_node_count matching with CP (nat lookup) [Ok..] [0xd6]
[FSCK] valid_inode_count matched with CP              [Ok..] [0xd6]
[FSCK] free segment_count matched with CP             [Ok..] [0x23]
[FSCK] next block offset is free                      [Ok..]
[FSCK] fixing SIT types
[FSCK] other corrupted bugs                           [Ok..]

Done: 0.059673 secs

=== Mount/Unmount trick ===
Mount: OK
Unmount: OK

=== Resizing f2fs ===
Info: MKFS version
  "Linux version 6.12.74 (builder@buildhost) (aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 14.3.0 r32802-f505120278) 14.3.0, GNU ld (GNU Binutils) 2.44) #0 SMP Wed Mar 25 20:09:53 2026"
Info: FSCK version
  from "Linux version 6.12.74 (builder@buildhost) (aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 14.3.0 r32802-f505120278) 14.3.0, GNU ld (GNU Binutils) 2.44) #0 SMP Wed Mar 25 20:09:53 2026"
    to "Linux version 6.12.74 (builder@buildhost) (aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 14.3.0 r32802-f505120278) 14.3.0, GNU ld (GNU Binutils) 2.44) #0 SMP Wed Mar 25 20:09:53 2026"
Info: superblock features = 0 :
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: Segments per section = 1
Info: Sections per zone = 1
Info: total FS sectors = 205568 (100 MB)
Info: CKPT version = 55ab23f0
Info: Duplicate valid checkpoint to mirror position 1024 -> 512
Info: Write valid nat_bits in checkpoint
[migrate_main: 206] Info: Done to migrate Main area: main_blkaddr = 0x1000 -> 0x6c00
[migrate_ssa: 272] Info: Done to migrate SSA blocks: sum_blkaddr = 0xe00 -> 0x4e00
[migrate_nat: 389] Info: Done to migrate NAT blocks: nat_blkaddr = 0xa00 -> 0xa00
[migrate_sit: 447] Info: Done to restore new SIT blocks: 0x600
[rebuild_checkpoint: 486] Info: Overprovision ratio = 1.220%
[rebuild_checkpoint: 487] Info: Overprovision segments = 90 (GC reserved = 88)
Info: Write valid nat_bits in checkpoint
[rebuild_checkpoint: 603] Info: Done to rebuild checkpoint blocks
[update_superblock: 765] Info: Done to update superblock

Done: 2.246213 secs

=== Done - rebooting ===

Output of df -h

root@Liberator:~# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root                 3.8M      3.8M         0 100% /rom
tmpfs                     1.9G    348.0K      1.9G   0% /tmp
/dev/loop0               14.5G    291.2M     14.2G   2% /overlay
overlayfs:/overlay       14.5G    291.2M     14.2G   2% /
tmpfs                   512.0K         0    512.0K   0% /dev

Output of blkid

root@Liberator:~# blkid
/dev/loop0: LABEL="rootfs_data" UUID="68b3f11d-5d4e-4d14-a8c0-acd6a8079f5d" BLOCK_SIZE="4096" TYPE="f2fs"
/dev/mmcblk1p1: LABEL="kernel" UUID="84173db5-fa99-e35a-95c6-28613cc79ea9" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="d0f6e5b4-01"
/dev/mmcblk1p2: BLOCK_SIZE="262144" TYPE="squashfs" PARTUUID="d0f6e5b4-02"
1 Like

It worked perfectly.

The ext4 partition you're seeing is correct - that's /dev/mmcblk1p1, your boot/kernel partition (16MB). It must be ext4 for the bootloader to read it.

Your overlay is now properly f2fs with 14.2GB available. Everything looks good.

1 Like

Thanks a lot!

If you get round to modding the original script so it checks what filesystem it's working on first, let me know :smiley:
I'd like this to survive an upgrade like it does on ext4

Hi @Sm00shed,

I am trying to do the same but I have a BPI-R4 my overlay has a different name, can you help me to modify the script so it will resize after reboot/upgrade.

root@OpenWrt:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 1 29.9G 0 disk
└─sda1 8:1 1 29.9G 0 part
mtdblock0 31:0 0 2M 1 disk
mtdblock1 31:1 0 126M 0 disk
mmcblk0 179:0 0 117.8G 0 disk
├─mmcblk0p1 179:1 0 4M 0 part
├─mmcblk0p2 179:2 0 512K 0 part
├─mmcblk0p3 179:3 0 2M 0 part
├─mmcblk0p4 179:4 0 4M 0 part
├─mmcblk0p5 179:5 0 32M 0 part
├─mmcblk0p6 179:6 0 20M 0 part
└─mmcblk0p7 179:7 0 448M 0 part
ubiblock0_1 254:0 0 54.9M 0 disk
fit0 259:0 0 21.9M 1 disk /rom
fitrw 259:1 0 420.4M 0 disk /overlay

root@OpenWrt:~# df -h
Filesystem Size Used Available Use% Mounted on
/dev/root 22.0M 22.0M 0 100% /rom
tmpfs 1.9G 12.2M 1.9G 1% /tmp
/dev/fitrw 418.4M 55.2M 363.2M 13% /overlay
overlayfs:/overlay 418.4M 55.2M 363.2M 13% /
tmpfs 512.0K 0 512.0K 0% /dev

root@OpenWrt:~# ll /etc/rootpt-resize /etc/rootfs-resize
-rw-r--r-- 1 root root 0 Apr 9 20:22 /etc/rootfs-resize
-rw-r--r-- 1 root root 0 Apr 9 20:22 /etc/rootpt-resize

root@OpenWrt:~# apk list --installed | grep -E 'parted|losetup|resize2fs|f2fs-to
ols'
f2fs-tools-1.16.0-r4 aarch64_cortex-a53 {feeds/base/utils/f2fs-tools} (GPL-2.0-only) [installed]
f2fsck-1.16.0-r4 aarch64_cortex-a53 {feeds/base/utils/f2fs-tools} (GPL-2.0-only) [installed]
libf2fs6-1.16.0-r4 aarch64_cortex-a53 {feeds/base/utils/f2fs-tools} (GPL-2.0-only) [installed]
libparted-3.6-r2 aarch64_cortex-a53 {feeds/packages/feeds/packages/utils/parted} (GPL-3.0-or-later) [installed]
losetup-2.41.3-r1 aarch64_cortex-a53 {feeds/base/utils/util-linux} (GPL-2.0-or-later) [installed]
mkf2fs-1.16.0-r4 aarch64_cortex-a53 {feeds/base/utils/f2fs-tools} (GPL-2.0-only) [installed]
parted-3.6-r2 aarch64_cortex-a53 {feeds/packages/feeds/packages/utils/parted} (GPL-3.0-or-later) [installed]
resize2fs-1.47.3-r1 aarch64_cortex-a53 {feeds/base/utils/e2fsprogs} (GPL-2.0) [installed]

I already added f2fs-tools, but I want to be sure of the syntax on the script my partition overlay name is different.

Regards,

MrPLC