I occasionally have had the need to increase disk space available on one of my virtual CentOS 7 servers. Every time I do, I have to search for a good guide on how to do it. There are a million and one ways to do it. Some guides walk through how to expand a virtual disk and then format the extra space on the disk to add as a new physical disk to an existing LVM PV in order to expand an LV. But I do not want to end up with a PV that has 10 different physical disk blocks (i.e. sda2-sda11) because I have increased the disk multiple times.
I am writing this guide to explain a simple way to increase the size of a virtual disk and then simply increase the size of the PV to use the additional space, and then increase the size of the LV to claim the additional space, and finally to extend the filesystem on the LV.
WARNING: BACKUP FIRST
Before proceeding with this guide, I highly suggest backing up any data on the disk you plan to modify. If done incorrectly, or even if some kind of failure is encountered, this process can result in an unusable storage device requiring manual recovery. I will not be held responsible for any lost data.
What is LVM? (A quick crash course)
I am assuming that you are already familiar with LVM and the basics and that you already have a system running on an LVM managed disk. If not, here is a quick rundown.
LVM (Logical Volume Management) provides a way to manage partitions on a pool of disks. A pool can be a simple single disk or partition or multiple disks or partitions.
The base component in LVM is a PV (Physical Volume). A PV can be configured on a full physical disk (i.e. sda, sdb, etc.) or a specific physical partition of a disk (i.e. sda1, sdb1, etc.). By creating a PV on a block device, you are allocating that disk, or part of a disk, to be used by LVM.
The next component in LVM is a VG (Volume Group). VGs are created on top of one or more PVs to create a storage pool. VGs can be simple volumes (i.e., one disk, or spanned across multiple disks) or can be RAID type volumes (i.e. mirrored, striped, etc.) using each PV in the VG.
The final component of LVM is a LV (Logical Volume). LVs are the partitions of the LVM volume. Each LV will then be formatted as a filesystem (i.e., xfs, ext3, ext4, swap, etc.) which can then be mounted on the system. You can have multiple LVs within a single VG.
When going through the CentOS 7 installer, unless you make any custom changes, you will end up with an LVM formatted system. The /boot partition (usually sda1) will be a standard Linux type partition, usually formatted as xfs, which is used to boot the system and the rest of the disk (usually sda2) will be partitioned as Linux LVM type and used to create a PV. A new VG, named “centos”, will be created on top of the sda2 PV. Two LVs will be created on the “centos” VG: “swap” and “root”. “Swap”, of course, is the swap space and “root” will be formatted, likely as xfs, and mounted as “/”.
Preparing to resize the disk
First things first, you need to know which physical block device you are increasing the space on. In my example for this guide, I will be increasing my root (/) file system which is mounted from /dev/mapper/centos-root. This path is a symbolic link for the LV “root”, which is a logical volume on the VG “centos”, which is stored on the PV “sda2”. You can determine this information by running the following commands:
df -h /
The first command “df -h /” lists the filesystem space stats for mounted filesystems. The -h flag says to print the values in human readable numbers (I.e. Megabytes or Gigabytes instead of numbers of blocks/bytes.) And by adding the “/” to the end of the command, the output is limited to only filesystems or mountpoints matching “/” rather than outputting all filesystems. We can see from the output that “/” is mounted from /dev/mapper/centos-root. As stated previously, this path is a symbolic link for LVs and is derived from the LV name (root) and VG name (centos).
The second command “lvdisplay centos” lists information about Logical Volumes on the system. By adding “centos” to the end of the command, the output is limited to only LVs on the “centos” VG. If you run “lvdisplay” without a VG name, all LVs on the system will be listed. You can see in the output that the VG name is provided for each LV.
The third command “vgdisplay centos” lists information about Volume Groups on the system. Again, by adding “centos” to the command, the output is limited only to the volume group named “centos”. Leaving the VG name off will output all VGs available on the system.
The fourth command “pvdisplay” lists all Physical Volumes on the system. For each PV, you will see the VG Name of the VG that is using this PV. In this case, “centos” is a simple volume group with a single PV “/dev/sda2”. So the disk I want to resize here, in order to resize my root “/” filesystem, will be sda2.
fdisk -l /dev/sda
This last command “fdisk -l /dev/sda” isn’t exactly necessary, but this lists the physical aspects of the disk “sda”. You can see there are two physical partitions: “/dev/sda1” is system type “Linux”, and “/dev/sda2” is system type “Linux LVM”. In my case, /dev/sda1 is used for my boot partition and is a simple Linux partition and is formatted as an xfs filesystem.
Increasing the physical disk
First, you will need to increase the disk size of the virtual disk. This is done in your hypervisor. I use ESXi as my hypervisor. In ESXi, you simply edit the settings of an existing VM and update the size of the disk to a larger size. For example, if it was 8GB, I can set it to 12GB to grow the disk by 4GB.
I am not currently aware of a sure fire way to know which virtual disk correlates to which block device in your VM. Generally, though, the virtual disk order in the VM settings should correlate to the order of the block device names. For example, my first disk in my VM settings is attached to SCSI port 0:0 which equates to /dev/sda. When I added a second disk, it was attached to SCSI port 0:1 which equates to /dev/sdb. Be careful to increase the size for the correct disk as you generally cannot decrease the size of a virtual disk.
If you do this while the VM is running, you will need to restart your VM in order for the new disk size to be scanned. There are ways of doing this as well by requesting a rescan of the SCSI/IDE host controller, but I’m not going to get into that due to varying methods, so I will just say to reboot your VM. You can search Google for “how to rescan scsi bus” or something similar for a way to rescan the bus without a reboot.
After rebooting, you can use “fdisk -l /dev/sda” to confirm your disk size reflects the new size.
fdisk -l /dev/sda
Comparing the original output of “fdisk -l /dev/sda”, I can confirm that my disk has successfully increased from 8GB to 12GB.
At this point, the physical device is larger, but the LVM configuration has not changed at all, so there remains unallocated space at the end of the disk.
Using “pvdisplay” again, we can confirm that the PV size is still the original size.
Since the PV (/dev/sda2) is a physical partition, we need to resize this partition to include the additional unallocated space of “sda”. We will use the fdisk utility to temporarily delete and re-create this partition. If you are resizing a non-system disk, you should unmount the disk first. If you are re-sizing the system disk, as I am with this example, or any mounted filesystem, then you will have to reboot the system immediately after these changes in order for the partition changes to be read.
This will start fdisk interactively with the sda device. If you have not used fdisk before, you can enter the letter “m” followed by enter to see a list of available commands. Each command is started by entering a single letter for the command and pressing enter. Please note that no changes are made to the disk until you use the “w” command to write changes to disk. If you make a mistake, you can always use the command “q” or CTRL+C to immediately quit fdisk without saving any changes.
First, print the current disk layout using command “p”:
It is important to note the start sector here for sda2. When re-creating the partition, it must start at the same sector and the ending sector must be equal to or larger than the current end sector. If these values are not correct, you will end up creating the partition outside of the scope of the existing partition’s sectors which will make data on sectors outside the partition inaccessible, thus corrupting the entire filesystem.
Type “d” to delete a partition and then type “2” to confirm we are deleting the second partition. Note that for any input requirements, fdisk will provide all valid input options and the default option in parenthesis. If the default option is correct, you can simply press enter without typing anything to accept the default.
Now type “n” to create a new partition. Then enter “p” for a primary partition. Enter “2” to create a new sda2 partition. Now enter the starting sector. This must be the same as the original starting sector from above. The default should generally be correct, but double check to verify. For the last sector, enter the ending sector that the partition should use. You can see in my example output above that the total number of sectors available was 25165824. You cannot use the very last sector, so in my case, the last available sector would be 25165823. This should be the default value. This value should also be higher than the original End sector as seen from the original disk layout.
Now we need to specify that this partition is for use by LVM. Type “t” to change the partition type. Type “2” to select the sda2 partition that we just created, and enter “8e” to specify Linux LVM. You can type “L” here to see a full list of all available partition types.
Before writing changes to disk, lets use the “p” command again to print the new disk layout:
We can see here that my sda2 partition now extends to the end of the disk at sector 25165823 and is using system type Linux LVM. If everything looks correct, go ahead and type “w” to write the changes to disk. If you are working with a mounted filesystem then you will see an error as shown below. This just indicates that you need to reboot the system so the partition table will be re-read before the filesystems are mounted.
Resize the LVM volume
Now that the physical disk has been resized, it is time to resize the LVM volume. LVM does not automatically detect disk changes.
First, we need to increase the size of the PV. We do this with the “pvresize” command:
The output indicates that the PV has been successfully resized/updated. Since the PV size has increased, so should the VG residing on this PV. You can confirm with the “vgdisplay” command which will now show the size has increased.
The next, and penultimate, step is to resize the LV. In my case, this is the “root” LV. We will use the “lvresize” command to resize the LV.
lvresize -l +100%FREE /dev/mapper/centos-root
The -l option says we are specifying extents to resize the volume by, and the +100%FREE says to increase by 100% of the free extents available on the PV. The last part of the command specifies the path to the LV. I used the filesystem path used by CentOS. You could also use the actual LV Path (obtained from “lvdisplay”) which would have been /dev/centos/root. Both of these are actually symlinks to the real block device created for the LV which in my case is /dev/dm-0, which could also be used as a valid LV path in the “lvresize” command.
Resize the filesystem
Finally, at this point you have successfully increased the physical disk size and the LVM PV and LV sizes. However, if you were to run “df -h” again at this point, you would see that the filesystem still shows the original size. This is because the filesystem now needs to be extended to utilize the new freespace.
The method for this depends upon the filesystem that you are using. In my case, the “root” filesystem is formatted as xfs, so I will use the “xfs_growfs” command to extend this filesystem.
The “xfs_growfs” command accepts either the block device path (i.e. /dev/mapper/centos-root, /dev/centos/root, or /dev/dm-0) or a mounted filesystem path (i.e. “/”). This commands just says to extend the end of the filesystem to the last available extent of the underlying partition. If you are using ext4, then you would use the “resize2fs” command in a similar way to extend the filesystem. For other filesystems, you will need to do a little Google search for exact steps.
Now, if you run “df -h /” again, you will see that the new size is being reported.
If you made it this far, congratulations. You’ve just successfully resized a virtual disk inside a CentOS 7 virtual machine using the LVM storage manager. Please let me know in the comments below if this guide was useful for you or if you have any suggestions or recommendations to make this better. I always love the feedback. Thanks for reading!