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