Extending Disks on a Linux Virtual Machine

If you’ve done any work with virtual machines for any amount of time, you’ve probably ran into the problem that virtual machines tend to fill up their disks quite rapidly. On a Windows VM it usually isn’t a problem, since you usually assign a virtual hard drive per system volume, but on Linux even if you try to just give it a single physical disk and tell it to just use the whole disk, it’ll still create a pesky swap partition at the end of the disk.

This is an issue, since the VMware expand operation (and all other hypervisors I’m aware of for that matter) adds new space at the end of the disk, and if you aren’t trying to expand the swap partition, you are stuck since the new space and the partition you’re looking to extend need to be next to each other.

I know that there are ways around this, like creating a separate virtual hard disk for the swap partition at the time of creating the virtual machine, or creating a new partition from the new space and then somehow merging that with the one you’re fixing to extend. However, the first alternative requires foresight, which of course only works after the fact, and the latter alternative is quite complicated and creates a mess that’s hard to figure out after the fact when something needs the be changed at a later date, so, think of the next guy that needs to fix this, cause the next guy is probably going to be you.

Now, the solution is quite easy, just delete the swap partition and recreate it after extending the main partition, and since the swap partition only contains junk anyhow, this isn’t as bad as it sounds.

So, let’s go through it step by step:

1. Extend Disk in VMware

(Optional: Shut down the virtual machine before extending the disk, this saves you a reboot after expanding the disk, and snapshots will be quicker)

Extend the disk in VMware to the new size you’re after.

(Optional: Add a second disk for the swap partition while you’re at it, this way you don’t need to do all the following malarkey next time you need to extend the root partition)

Take a snapshot of the VM, just in case something goes wrong, since there’s a real risk that a mistake might cause the VM to not boot again. Normally you take the snapshot before doing anything, but since snapshots block extending the disk, we’ll take it right after instead.

Reboot (or restart) the virtual machine so that it notices that the disk has magically grown.

2. Reconfigure the Partition Table

Run sudo su to become root since some of these commands doesn’t work with sudo very well.

Disable the swap partition so that we can get rid of it for the duration of our operation

root@debian:~# swapoff -a

Then we need to delete all partitions using fdisk and recreate them. We’re only changing the partition table, so don’t worry, this doesn’t touch the data on the disk. However, this is a bit dangerous since you can cause the VM to not ever boot again.

Next we run fdisk -l to list all partitions that are available to us.

root@debian:~# fdisk -l
Disk /dev/sdb: 16 GiB, 17179869184 bytes, 33554432 sectors
Disk model: Virtual disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/sda: 160 GiB, 171798691840 bytes, 335544320 sectors
Disk model: Virtual disk
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: 0xfb97cb09

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sda1  *         2048 234881023 234878976  112G 83 Linux
/dev/sda2       234883070 251656191  16773122    8G  5 Extended
/dev/sda5       234883072 251656191  16773120    8G 82 Linux swap / Solaris

You can now see the existing partitions as well as the new swap disk sdb I added earlier.

Next we need to delete every single partition on the disk from the partition table and recreate them as we want them. This isn’t touching the data on the disk, so it isn’t as dramatic as it sounds.

root@debian:~# fdisk /dev/sda

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


Command (m for help): p
Disk /dev/sda: 160 GiB, 171798691840 bytes, 335544320 sectors
Disk model: Virtual disk
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: 0xfb97cb09

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sda1  *         2048 234881023 234878976  112G 83 Linux
/dev/sda2       234883070 251656191  16773122    8G  5 Extended
/dev/sda5       234883072 251656191  16773120    8G 82 Linux swap / Solaris

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

Partition 5 has been deleted.

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

Partition 2 has been deleted.

Command (m for help): d
Selected partition 1
Partition 1 has been deleted.

After this, we can recreate the primary partition and let it use the whole disk. If you don’t use my trick of moving swap to a different disk drive, then you need to make the new primary partition smaller than the whole disk, but this is easy as fdisk will do all the calculations for you, so if you need a 120 GB partition on a 130 GB disk, just enter +120g instead of the end sector as I do here.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-335544319, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-335544319, default 335544319):

Created a new partition 1 of type 'Linux' and of size 160 GiB.
Partition #1 contains a ext4 signature.

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

Command (m for help): p

Disk /dev/sda: 160 GiB, 171798691840 bytes, 335544320 sectors
Disk model: Virtual disk
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: 0xfb97cb09

Device     Boot Start       End   Sectors  Size Id Type
/dev/sda1        2048 335544319 335542272  160G 83 Linux

Command (m for help): w
The partition table has been altered.
Syncing disks.

That’s all for sda, now we can move to sdb for the swap partition. If you have only one disk, just continue without writing the partition table to disk.

The procedure is the same as before, but we need to change the partition type to 82 instead of the default partition type of 83 since this is going to be a swap partition.

root@debian:~# fdisk /dev/sdb

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

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xdf14e2c4.

Command (m for help): p
Disk /dev/sdb: 16 GiB, 17179869184 bytes, 33554432 sectors
Disk model: Virtual disk
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: 0xdf14e2c4

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-33554431, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-33554431, default 33554431):

Created a new partition 1 of type 'Linux' and of size 16 GiB.

Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): 82
Changed type of partition 'Linux' to 'Linux swap / Solaris'.

Command (m for help): p
Disk /dev/sdb: 16 GiB, 17179869184 bytes, 33554432 sectors
Disk model: Virtual disk
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: 0xdf14e2c4

Device     Boot Start      End  Sectors Size Id Type
/dev/sdb1        2048 33554431 33552384  16G 82 Linux swap / Solaris

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Now we can list all partitions again and make sure fdisk got it right

root@debian:~# fdisk -l
Disk /dev/sdb: 16 GiB, 17179869184 bytes, 33554432 sectors
Disk model: Virtual disk
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: 0xdf14e2c4

Device     Boot Start      End  Sectors Size Id Type
/dev/sdb1        2048 33554431 33552384  16G 82 Linux swap / Solaris


Disk /dev/sda: 160 GiB, 171798691840 bytes, 335544320 sectors
Disk model: Virtual disk
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: 0xfb97cb09

Device     Boot Start       End   Sectors  Size Id Type
/dev/sda1        2048 335544319 335542272  160G 83 Linux

3. Make /swap Great Again

Next we need to create the initialise the new swap partition we created.

root@debian:~# mkswap /dev/sdb1
Setting up swapspace version 1, size = 16 GiB (17178816512 bytes)
no label, UUID=cafd36d2-91e0-4a63-ac43-ad4f3d3ade8d

The UUID is important, so copy that somewhere safe. Next we need to edit /etc/fstab (the file system table) so that the OS knows which partition to use. We only need to do this for the swap partition, as the old root partition still has the same UUID as before.

root@debian:~# nano /etc/fstab

This opens up the file in nano, and as you can see below, I’ve changed the UUID for the swap partition. Save the file when you’re done!

# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda1 during installation
UUID=32b125ce-99bf-479d-95d4-610e3c3d0320 /               ext4    errors=remount-ro 0       1
# swap was on /dev/sda5 during installation
UUID=cafd36d2-91e0-4a63-ac43-ad4f3d3ade8d none            swap    sw              0       0
/dev/sr0        /media/cdrom0   udf,iso9660 user,noauto     0       0

After this, we can allow the system to used the swap space again by issuing swapon -a

root@debian:~# swapon -a

4. Resize the File System

Next we can finally do what we came here to do, extend the root partition.

resize2fs does just that, it’ll extend the filesystem to the new size of the partition.

root@debian:~# resize2fs /dev/sda1
resize2fs 1.44.5 (15-Dec-2018)
Filesystem at /dev/sda1 is mounted on /; on-line resizing required
old_desc_blocks = 14, new_desc_blocks = 20
The filesystem on /dev/sda1 is now 41942784 (4k) blocks long.

Epilogue

Now you may ask, what’s the point of moving the swap partition to a separate virtual disk? After a decade of running virtual Linux machines, I’m of the firm standpoint that the best way to get configure swap drives in VMware is to separate them out to their own disc. That way this process is a lot simpler when you want to extend a volume at a later date, as there’s only a single partition per virtual disk.



Categories: Tech

Tags: , , ,

2 replies

  1. Nice tutorial, On systems with LVM, before extending the disk, you need to use “pvresize /dev/sdx1” for it to take the new space on the partition and throw it to the PV.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.