[HOWTO] Resizing root partition on x86

I recently answered a question about this and thought that the answer I gave could be expanded ever-so-slightly to become a more general guide. So here goes...

This HOWTO is intended for users who have some experience in general computing and system administration but are relatively new to OpenWrt. It is loosely based on the relevant sections of the official OpenWrt on x86 Hardware page:

https://openwrt.org/docs/guide-user/installation/openwrt_x86

The Root Cause

The origins of OpenWrt lie far outside of the x86 ecosystem. As a result, it is distributed in a way that is not common in the x86 ecosystem. There is no installation media and no installer; rather, one must copy the installation image to the target system's hard drive or SSD. Because of this, a new installation of OpenWrt 22.x.x. typically has a boot drive with approximately 120 MB of total space, regardless of the actual capacity of the drive. There are two ways to reclaim the remaining capacity. One is to resize the root partition of the OpenWrt installation, and this is what this HOWTO is about. The other is to create one or more additional partitions, but we will not cover it here (it's a general Linux topic for which multiple tutorials are available).

The Complication

There are four mainstream images one can use to implement an OpenWrt system on x86 hardware. They form a sort of 2x2 matrix:

  • generic-ext4-combined-efi.img.gz is an image that produces a UEFI system with an ext4 file system on the root partition
  • generic-ext4-combined.img.gz is an image that produces a BIOS system with an ext4 file system on the root partition
  • generic-squashfs-combined-efi.img.gz is an image that produces a UEFI system with a SquashFS file system on the root partition
  • generic-squashfs-combined.img.gz is an image that produces a BIOS system with a SquashFS file system on the root partition

Both the nature of the firmware (BIOS vs. UEFI) and the type of file system on the root partition (ext4 vs. SquashFS) have implications for partition resizing. So the first step in resizing your root partition is to know what kind of system you have or, said another way, which image was used to install the system.

Resizing the root partition on a BIOS system is simpler. Only two steps are required:

  • Resize the root partition (done the same way for ext4 and SquashFS), and
  • Resize the root file system (done differently depending on whether the file system is ext4 or SquashFS)

On a UEFI system, there is an additional step required. UEFI, unlike BIOS, keeps track of partition identifiers. At boot, UEFI will allow the system to load only from a partition it recognizes. When we resize the root partition, its ID will change, so we'll have to communicate those changes to the UEFI. This is done by editing the grub configuration file located at /boot/grub/grub.cfg. In order to know what changes to make to this file, it helps to see how partition configuration has changed. In other words, it is a good idea to have a record of both partition configurations, old and new. So in case of a UEFI system, we end up with a four-step process:

  • Capture the initial partition configuration (done the same way for ext4 and SquashFS),
  • Resize the root partition (done the same way for ext4 and SquashFS),
  • Update /boot/grub/grub.cfg (done the same way for ext4 and SquashFS), and
  • Resize the root file system (done differently depending on whether the file system is ext4 or SquashFS)

A note on safety
Technically, both resizing operations (resizing a partition and resizing a file system), if done on "live" drives, carry a risk of file system corruption. So in a perfect world, we should be doing this with the relevant drive unmounted (this can be achieved by booting the device from a USB stick). In practice, however, this works in an overwhelming majority of cases, especially when the device is essentially idle.

With this in mind, let's get some supplies.

Preparations

You will need a few utilities, which you probably don't have installed. So let's get them. The set of utilities needed will depend on the file system we want to extend.

If you are on an ext4 system, run:

opkg update && opkg install lsblk fdisk losetup resize2fs

On a SquashFS system, the shopping list will be slightly different:

opkg update && opkg install lsblk fdisk losetup f2fs-tools

These should take us through the process.

Capture the Current Partition Configuration

If you have a BIOS system, skip this section and go straight to Resize the Root Partition. On a UEFI system, run:

lsblk -o PATH,SIZE,PARTUUID

This wlll tell you the current partition layout, including each partition's unique identifier. Save this for future reference. If you're working over SSH, I would suggest saving it on the administrator's computer. Copy it from the terminal and save it as a text file. If you have a monitor and keyboard connected to your device, save it into a text file on the device. For example:

lsblk -o PATH,SIZE,PARTUUID > /root/lsblk_old.txt

Just in case, you may want to copy this file to a USB stick.

Next, you may want to take a look at the grub configuration file:

cat /boot/grub/grub.cfg

The goal is to see where partitions' unique identifiers are used and, therefore, where you will need to replace them when the time comes. Take a look at this example:

root@OpenWrt:~# lsblk -o PATH,SIZE,PARTUUID
PATH        SIZE PARTUUID
/dev/sda    120M
/dev/sda1    16M c959470f-01
/dev/sda2   104M c959470f-02

root@OpenWrt:~# cat /boot/grub/grub.cfg
serial --unit=0 --speed=38400 --word=8 --parity=no --stop=1 --rtscts=off
terminal_input console serial; terminal_output console serial

set default="0"
set timeout="5"
set root='(hd0,msdos1)'

menuentry "OpenWrt" {
        linux /boot/vmlinuz root=PARTUUID=c959470f-02 rootwait   console=tty0 console=ttyS0,38400n8 noinitrd
}
menuentry "OpenWrt (failsafe)" {
        linux /boot/vmlinuz failsafe=true root=PARTUUID=c959470f-02 rootwait   console=tty0 console=ttyS0,38400n8 noinitrd
}
root@OpenWrt:~#

It's easy to see that partition /dev/sda2 has a unique identifier c959470f-02, and that identifier is used in grub configuration in two places to designate a root partition, first for the normal boot, then for the failsafe mode. So now you have a mind map of what you will be doing a little later.

Resize the Root Partition

This is done nearly identically in all cases by running an interactive fdisk session. The listing below shows a mix of fdisk output and manual inputs. To distinguish the manual inputs, I have enclosed them [[in double square brackets]]; the [[]] sequence indicates pressing Enter with no visible input. Obviously, when you enter commands or data, you won't need any square brackets; I'm just using them as markers. It's a bit confusing, but I can't come up with a better formatting scheme right now. So here goes:

root@OpenWrt:~# [[fdisk /dev/sda]] 

Welcome to fdisk (util-linux 2.37.3).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.


Command (m for help): [[p]]

Disk /dev/sda: 59.63 GiB, 64023257088 bytes, 125045424 sectors
Disk model: ADATA_IM2S3134N-
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc120d9f5

Device     Boot Start       End   Sectors  Size Id Type
/dev/sda1  *      512     33279     32768   16M 83 Linux
/dev/sda2       33792    246783    212992  104M 83 Linux

Command (m for help): [[d]]
Partition number (1,2, default 2): [[2]]

Partition 2 has been deleted.

Command (m for help): [[n]]
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): [[p]]
Partition number (2-4, default 2): [[2]]
First sector (33280-31277231, default 34816): [[33792]]
Last sector, +/-sectors or +/-size{K,M,G,T,P} 
    (33792-125045423, default 125045423): [[]]

Created a new partition 2 of type 'Linux' and of size 59.6 GiB.
Partition #2 contains a squashfs signature.

Do you want to remove the signature? [Y]es/[N]o: [[n]]

Command (m for help): [[w]]

The partition table has been altered.
Syncing disks.

root@OpenWrt:~# 

A few important notes:

  1. This has worked despite the "bad idea" warning.
  2. Technically, we didn't "extend" the partition; rather, we deleted one, then created a new one starting at the same location and gobbling up all available disk space. However, since there was no write command in-between, the net result was a new, larger partition that "inherited" all data located on the old small partition.
  3. The number 33792 specified in response to the First sector prompt came from the disk information table produced in response to the p command.
  4. Depending on what kind of system you have, you may or may not be asked whether you want a primary or extended partition. Otherwise, the process should be identical.

To verify that the partition has been resized, you can run fdisk -l or start another interactive session (fdisk /dev/sda) and issue a p command to show the partition layout followed by a q command to quit.

Update grub Configuration

If you have a BIOS system, skip this section and go straight to Resize the Root File System. On a UEFI system, run:

lsblk -o PATH,SIZE,PARTUUID

Compare the output to its earlier version that you saved. You will see that the unique identifier for the /dev/sda2 partition has changed. Use your new identifier to replace the old one in grub configuration. For example, if you use vi, you can do:

vi /boot/grub/grub.cfg

From your earlier review of grub configuration, you would know how many instances of partition ID require replacement. Make the changes, save the file, and exit the text editor.

Resize the Root File System

This is the final step, and it is done differently depending on whether you have an ext4 file system or a SquashFS file system. You should take care to execute the commands given below one by one (meaning, don't paste all of them into the command line at once; allow one command to finish before entering the next one).

On an ext4 System

BOOT="$(sed -n -e "/\s\/boot\s.*$/{s///p;q}" /etc/mtab)"
DISK="${BOOT%%[0-9]*}"
PART="$((${BOOT##*[^0-9]}+1))"
ROOT="${DISK}${PART}"
LOOP="$(losetup -f)"
losetup ${LOOP} ${ROOT}
fsck.ext4 -y -f ${LOOP}
resize2fs ${LOOP}
reboot

On a SquashFS System

LOOP="$(losetup -n -O NAME | sort | sed -n -e "1p")"
ROOT="$(losetup -n -O BACK-FILE ${LOOP} | sed -e "s|^|/dev|")"
OFFS="$(losetup -n -O OFFSET ${LOOP})"
LOOP="$(losetup -f)"
losetup -o ${OFFS} ${LOOP} ${ROOT}
fsck.f2fs -y -f ${LOOP}
mount ${LOOP} /mnt
umount ${LOOP}
resize.f2fs ${LOOP}
reboot

Concluding Notes

If all of the above worked, congratulations! You have successfully resized the root partition on your OpenWrt device.

Early in this guide, we discussed the two options for reclaiming disk space, extending the root partition and creating additional partitions. Those are not mutually exclusive; it is entirely possible to use them together (extending the root partition part-way and setting up new partition or partitions in the still-free disk space). Read up on fdisk and its use in partition setup; this will allow you to create all kinds of configurations.

5 Likes

could you please add this to wiki ?

2 Likes

Seconded. This truly belongs in the wiki, excellent write up, @NC1!

All of it is on the wiki already. And not just on the wiki, on a single page:

https://openwrt.org/docs/guide-user/installation/openwrt_x86

I only pulled out the parts that were relevant to a narrower topic (resizing the root partition, rather than a general overview of OpenWrt on x86) and added a little discussion of how the parts fit together to make it easier to digest and act upon for a less experienced administrator.

Also, since I am not a member of the development team, I have no visibility into how long these recommendations will remain relevant. In fact, I have no idea how far back into the version history they are applicable. I know this tends to work on the 22.x.x branch and probably on the 21.x.x branch, but that's it.

This said, if someone wanted to link to this thread from the wiki or use the material presented here in any way, verbatim or reworked, they are welcome to it, no attribution necessary. In the meanwhile, search engines can find it here just as easily as on the wiki (after this thread gets indexed, of course)...