Resizing on the first boot on disks with MBR scheme
Important notices
Before you add a new report, we ask you kindly to acknowledge the following:
- [X] I have read the contributing guide lines at https://github.com/opnsense/core/blob/master/CONTRIBUTING.md
- [X] I am convinced that my issue is new after having checked both open and closed issues at https://github.com/opnsense/core/issues?q=is%3Aissue
Describe the bug
The resize of the root file system on ARM64 systems is not working when the image uses MBR partition scheme. This happens in 25.1, I don't know when started, but 24.7 is also affected.
To Reproduce
I compile opnsense here for NanoPi R5S, but it was tested on the NanoPi R4S conf available on opnsense repository as well.
Just issue:
make DEVICE=R4S base;
make DEVICE=R4S kernel;
make DEVICE=R4S ports;
make DEVICE=R4S plugins;
make DEVICE=R4S core;
make DEVICE=R4S packages;
make DEVICE=R4S arm;
and write the final image to a micoSD. The boot will go fine, but root FS won't resize. I run this on ARM64 box (Raspberry Pi 5).
Expected behavior
The boot script will try to resize partition with ID 1 using gpart, and on MBR scheme the root FS is ID 2 (ID 1 is vfat for EFI files). Then there will be message as:
mmcsd0s1 resized
growfs: requested size 2.9GB is equal to the current filesystem size 2.9GB
If the right partition is addressed, the resize runs fine and after the first boot the root FS uses all microSD space.
Describe alternatives you considered
A clear and concise description of any alternative solutions or workaround you considered. The script has an "if" test that when MBR scheme is present (and this is the default for the arch as R4S uses on default R4S.conf), it always returns IDX=1. So gpart runs on partition 1. I took the liberty to create another test here. The line:
local IDX=${1##"${DEV}p"}
Won't match for MBR cases, where the pattern will be like ada0s2, as the "p" looks like GPT scheme. So here I created the test:
if [ "${SCHEME}" = "MBR" ]; then
# MBR, the device slice will not end in pX, but sX, as in "ada0s2a"
local SLICE=${1##"${DEV}s"}
# Need to get only the index of the partition, the letter for BSD label should go
local IDX=$(echo "${SLICE}" | cut -c1)
else
# No MBR, as was treated befoe
local IDX=${1##"${DEV}p"}
fi
I had to change a few lines also on the main code (outside the grow_partition function), as after the gpart resize running on ARM64, it tells on the console to run gpart issuing the commit comand:
mmcsd0 recovering is not needed
GEOM_PART: ufs/OPNsense was automatically resized.
Use `gpart commit ufs/OPNsense` to save changes or `gpart undo ufs/OPNsense` to revert them.
mmcsd0s2 resized
So the lines were added:
# Find out if its a MBR scheme, as the ones on ARM64 boards
DEV=$(echo "${ROOT_IS_UFS}" | awk 'match($0, /^[a-z]+[0-9]+/) { print substr( $0, RSTART, RLENGTH )}')
SCHEME=$(gpart list $DEV | grep scheme | awk '{print $2}')
if [ "${SCHEME}" = "MBR" ]; then
# Need to run gpart commit to keep going the resizing
gpart commit $FS_LABEL
fi
Screenshots Relevant log files Additional context
For more information, I have the full thread on opnsense forum in https://forum.opnsense.org/index.php?topic=46663.15
There is a suggested core/src/etc/rc file on that thread, that I have tested here but my resources are far smaller than yours, as are my skills.
The rc was tested on Nano images for AMD64 as well.
Environment
Software version used and hardware type if relevant, e.g.: OPNsense 25.1.3 and 25.1.4 running on R5S and R4S
DMS?
I'm unsure we really need to have a preinstalled jail for every DMS across the world.
The filters are principally OK (it's just additional file unless referenced), but the jail.conf will be always used, and every jail costs time (even if not enabled)...
I must think about some encapsulation of jails/filters in new version, either by some additional groups or probably much better:
a remodeling moving jail info (default port, logpath, etc) to the filter and remove all "non-generic" (or even completely all) jails from jail.conf, so if one would add new section for the jail in jail.local, everything else would work out-of-the-box.
That's actually great idea. Maybe add the filter and reference the example jail in the filter so if anyone wants to use the filter knows how to set the jail also. That way we can add more filters for option but at the same time not consuming time because the jail.conf. should I remove the jail from this PR and add the example jail in the filter?
DMS? I'm unsure we really need to have a preinstalled jail for every DMS across the world. The filters are principally OK (it's just additional file unless referenced), but the
jail.confwill be always used, and every jail costs time (even if not enabled)... I must think about some encapsulation of jails/filters in new version, either by some additional groups or probably much better: a remodeling moving jail info (default port, logpath, etc) to the filter and remove all "non-generic" (or even completely all) jails from jail.conf, so if one would add new section for the jail injail.local, everything else would work out-of-the-box.
Not yet, maybe later... IIRC, the jail is mandatory right now.
Not yet, maybe later... IIRC, the jail is mandatory right now.
Just a thought, how about commenting out the jails no need to be there always. That shouldn't affect the time consumption. Will it work?
Well, doesn't matter currently, to be covered correctly by the test-suite it shall be with a jail, so if jail gets commented it'd produce at least this error: https://github.com/fail2ban/fail2ban/blob/c76e90fbb17115b90ca5b641c2183c0e3e644942/fail2ban/tests/clientreadertestcase.py#L889
Well, doesn't matter currently, to be covered correctly by the test-suite it shall be with a jail, so if jail gets commented it'd produce at least this error: https://github.com/fail2ban/fail2ban/blob/c76e90fbb17115b90ca5b641c2183c0e3e644942/fail2ban/tests/clientreadertestcase.py#L889
Well I also thought it won't be that easy or you would have implemented that already. I think it's because the verification on line 873