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
Changes from the previous edition
- The Diagnostics section added (a big thank-you to @efahl for the suggestion!)
- The Resize the Root File System section: command listings have been updated to match the current guidance on the wiki
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:
opkg update && opkg install lsblk fdisk losetup resize2fs
These should take us through the process.
Diagnostics
So far so good, but what if I don't know which image was used to install OpenWrt? Say, someone else did the installation or I simply forgot? Here are two simple tests.
First, let's figure out the ext4 vs. SquashFS question:
df -Th
This command will output a list of filesystems with types indicated. Look for a filesystem named /dev/root
. Its type will be either ext4
or squashfs
.
How about BIOS vs. UEFI, then? Also not very hard:
ls /sys/firmware/efi
On a UEFI system, a directory named /sys/firmware/efi
must exist. So if the command above gives you a normal-looking directory listing, your system is UEFI; if you get an error message that says No such file or directory
, your system is BIOS.
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 will 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:
- This has worked despite the "bad idea" warning.
- 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.
- The number
33792
specified in response to theFirst sector
prompt came from the disk information table produced in response to thep
command. - 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).
Watch the output of the resize2fs
command. Normally, you would see some indication of file system size change. If, on the other hand, resize2fs
indicated it has nothing to do, reboot your device and repeat this step in its entirety. Rebooting will ensure that the changes made during the previous steps are applied to the system.
On an ext4 System
BOOT="$(sed -n -e "\|\s/boot\s.*$|{s///p;q}" /etc/mtab)"
PART="${BOOT##*[^0-9]}"
DISK="${BOOT%${PART}}"
ROOT="${DISK}$((PART+1))"
LOOP="$(losetup -f)"
losetup ${LOOP} ${ROOT}
resize2fs -f ${LOOP}
reboot
On a SquashFS System
BOOT="$(sed -n -e "\|\s/boot\s.*$|{s///p;q}" /etc/mtab)"
PART="${BOOT##*[^0-9]}"
DISK="${BOOT%${PART}}"
ROOT="${DISK}$((PART+1))"
LOOP="$(losetup -n -l | sed -n -e "\|\s.*\s${ROOT#/dev}\s.*$|{s///p;q}")"
resize2fs -f ${LOOP}
reboot
Concluding Notes
If all of the above worked, congratulations! You have successfully resized the root partition on your OpenWrt device. You may want to reboot your device to ensure that everything starts up correctly.
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.