Resizing a Raw Virtual Machine LVM Partition Using fdisk

As the amount of data we store continues to grow and grow, there is bound to become a time that you will need to resize your partitions to add more disk space. On our of my MySQL replication virtual servers, I created it initially with a 200GB disk. After moving all the data over, was wishing I would have had a bit more space. Good news is this can easily be done. I should note that I am using raw image files, not lvms, so there is a bit more work required.

Before we go any further, it’s important to note that we will be modifying the partition table in this document. Modifying the partition table could result in complete data loss if not done correctly. Please make sure you have a full backup of your system before proceeding. If you’re not sure what you’re doing, it’s best to practice this on a test system first. I will not be held responsible for your failure to back up your system and/or data loss that may occur.

That being said… let’s get to the fun stuff. We will be adding an additional 50GB of space to this virtual machine.  We will begin on the host server by adding the additional space to the image file. Make sure the virtual machine is shut down first.

[root@kvmserver images]# ll -h
-rw------- 1 root root 200G Nov  1 12:44 mysqlrep1.domain.net.img

[root@kvmserver images]# qemu-img resize mysqlrep1.domain.net.img +50G
Image resized.

[root@kvmserver images]# ll -h
-rw------- 1 root root 250G Nov  1 12:44 mysqlrep1.domain.net.img

You can now start the guest virtual machine and log in. You’ll notice both df and pvdisplay still report the old partition sizes.

[root@mysqlrep1 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/vgcentos-lvroot
                      193G  120G   64G  66% /
tmpfs                 939M     0  939M   0% /dev/shm
/dev/vda1             477M   52M  400M  12% /boot


[root@mysqlrep1 ~]# pvdisplay
  --- Physical volume ---
  PV Name               /dev/vda2
  VG Name               vgcentos
  PV Size               199.51 GiB / not usable 3.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              51074
  Free PE               0
  Allocated PE          51074
  PV UUID               iqcP8l-VAjT-E6lI-SP16-Mu1k-N0AV-tcjn8H

We will be using fdisk to resize the partition. Open the disk and make a note of the current partition layout. We will need this information later. The disk size here should reflect the amount of space we added above.

[root@mysqlrep1 ~]# fdisk -cu /dev/vda

Command (m for help): p

Disk /dev/vda: 268.4 GB, 268435456000 bytes
16 heads, 63 sectors/track, 520126 cylinders, total 524288000 sectors
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 identifier: 0x000873eb

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *        2048     1026047      512000   83  Linux
/dev/vda2         1026048   419430399   209202176   8e  Linux LVM

The next two steps are where you need to exercise extreme caution. Before continuing, please reread the disclaimer regarding backups above. In order to resize the partition, we need to delete and recreate it. When you recreate the partition, you must create it with the same exact starting unit and you must create it with an ending point the same or greater unit. Delete the partition and print the partition table to verify it’s gone.

Command (m for help): d
Partition number (1-4): 2

Command (m for help): p

Disk /dev/vda: 268.4 GB, 268435456000 bytes
16 heads, 63 sectors/track, 520126 cylinders, total 524288000 sectors
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 identifier: 0x000873eb

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *        2048     1026047      512000   83  Linux

Recreate the partition using the same starting unit. In our example, the starting unit is 1026048. For the ending unit, we want the maximum amount of free disk space, which is automatically populated by default, so we left the prompt blank. Print the partition table again to verify.

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First sector (1026048-524287999, default 1026048): 1026048
Last sector, +sectors or +size{K,M,G} (1026048-524287999, default 524287999):
Using default value 524287999

Command (m for help): p

Disk /dev/vda: 268.4 GB, 268435456000 bytes
16 heads, 63 sectors/track, 520126 cylinders, total 524288000 sectors
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 identifier: 0x000873eb

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *        2048     1026047      512000   83  Linux
/dev/vda2         1026048   524287999   261630976   83  Linux

Now you’ll notice the new partition type is “83 Linux” where it was “8e Linux LVM” before. Use the type command to change the type of the new partition back to what it was to begin with. Again, print the partition table to verify. It never hurts to verify each step to ensure the commands you’re entering are being executed correctly.

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): 8e
Changed system type of partition 2 to 8e (Linux LVM)

Command (m for help): p

Disk /dev/vda: 268.4 GB, 268435456000 bytes
16 heads, 63 sectors/track, 520126 cylinders, total 524288000 sectors
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 identifier: 0x000873eb

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *        2048     1026047      512000   83  Linux
/dev/vda2         1026048   524287999   261630976   8e  Linux LVM

Compare the new partition table to the old one. The start unit should be exactly the same after as before. The end unit should be greater than or equal to what it was before. The Id/System partition types should match exactly. If everything looks okay, write the changes and reboot the system.

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.

[root@mysqlrep1 ~]# reboot

We’re not done, but getting close. Once the guest reboots, log back in. We resized the partition, but still need to resize the LVM physical volume. This is done with the pvresize command. The additional disk space should now be reflected in pvdisplay.

[root@mysqlrep1 ~]# pvresize /dev/vda2
  Physical volume "/dev/vda2" changed
  1 physical volume(s) resized / 0 physical volume(s) not resized

[root@mysqlrep1 ~]# pvdisplay
  --- Physical volume ---
  PV Name               /dev/vda2
  VG Name               vgcentos
  PV Size               249.51 GiB / not usable 2.00 MiB
  Allocatable           yes
  PE Size               4.00 MiB
  Total PE              63874
  Free PE               12800
  Allocated PE          51074
  PV UUID               iqcP8l-VAjT-E6lI-SP16-Mu1k-N0AV-tcjn8H

Assign all free space to the lv of your choice, in our case, this is lvroot

[root@mysqlrep1 ~]# lvextend -l +100%FREE /dev/vgcentos/lvroot
Size of logical volume vgcentos/lvroot changed from 195.51 GiB (50050 extents) to 245.51 GiB (62850 extents).
Logical volume lvroot successfully resized.

Lastly… resize the filesystem to make the additional space available. We are using ext4, so this is done with resize2fs. If you’re using xfs, this will be done with xfs_growfs.

[root@mysqlrep1 ~]# resize2fs /dev/vgcentos/lvroot
resize2fs 1.41.12 (17-May-2010)
Filesystem at /dev/vgcentos/lvroot is mounted on /; on-line resizing required
old desc_blocks = 13, new_desc_blocks = 16
Performing an on-line resize of /dev/vgcentos/lvroot to 64358400 (4k) blocks.
The filesystem on /dev/vgcentos/lvroot is now 64358400 blocks long.

If all goes well, you will now see the additional space in df and are done. It wouldn’t hurt to do a filesystem check with fsck just to make sure everything is in order.

[root@mysqlrep1 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/vgcentos-lvroot
                      242G  120G  111G  52% /
tmpfs                 939M     0  939M   0% /dev/shm
/dev/vda1             477M   52M  400M  12% /boot

 

Leave a Reply