5 Steps to Extend a Linux LVM Volume

Luke Arntz Binary

Virtualization makes it easy to add more disk capacity to a virtual machine. Extending a virtual disk in VMware will grant the VM access to more storage, but we still have to make that storage usable to the operating system.

This post will explain the steps required to make this additional storage usable within a Linux virtual machine. These steps work with both CentOS7 and Ubuntu 16 and 17, and is done completely from the command line.

It is always best to use extreme caution when making changes to a production system. While these instructions will allow you to do this on a running system without rebooting, I would suggest using a maintenance window to perform this operation and I would not do this live on a mission critical system.

Under those circumstances I would suggest extending your volume by attaching the disk to another VM or booting from a Live CD and these instructions still apply.

That said there are many scenarios where the risk is acceptable. However, backup and verify important data before making any changes to a disk!

Before we begin we are assuming the following:

We will need to resize the disk on several “levels” before we are done.

The first level is the virtual disk itself (this is representative of a physical hard drive in a physical server). This step is performed using the virtualization manager, and isn’t covered here in detail. Level two is resizing the disk partition we will be using. Third is the physical volume. Fourth is the logical volume. Finally we resize the file system.

Step 1 - Verify the Disk Size in Linux

The first thing we need to do is make sure the operating system sees that the disk has been increased in size. The bus will be rescanned on a reboot, but what if we don’t want to reboot? To force the system to rescan a device run the following command. Note that this is disk specific. The command below will rescan /dev/sda (the first disk).

 echo 1 > /sys/block/sda/device/rescan

Here is an example where 1GB was added to a 200GB disk. Notice the Disk size after each fdisk command.

root@lasrv:~# fdisk -l
Disk /dev/sda: 200 GiB, 214748364800 bytes, 419430400 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
Disklabel type: dos
Disk identifier: 0x4756842e

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sda1  *         2048 415236095 415234048  198G 83 Linux
/dev/sda2       415238142 419428351   4190210    2G  5 Extended
/dev/sda5       415238144 419428351   4190208    2G 82 Linux swap / Solaris

root@lasrv:~# echo 1 > /sys/block/sda/dev/rescan

root@lasrv:~# fdisk -l
Disk /dev/sda: 201 GiB, 215822106624 bytes, 421527552 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
Disklabel type: dos
Disk identifier: 0x4756842e

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sda1  *         2048 415236095 415234048  198G 83 Linux
/dev/sda2       415238142 419428351   4190210    2G  5 Extended
/dev/sda5       415238144 419428351   4190208    2G 82 Linux swap / Solaris

The size shown by fdisk should match the size shown in your virtualization software. Once you’ve verified this move on to step 2.

Luke Arntz lasrv VMware Disk Extend

Step 2 - Resizing the Partition

With the OS seeing the underlying disk size correctly we can proceed to resize the physical disk partition. This is done using fdisk and requires that we delete the existing partition and create a new, larger, partition in its place.

Although this may sound scary, it is not. No data should be lost, and you have your system backed up, right? RIGHT?

Here is our starting point. Notice the size of our disk /dev/mapper/centos-root is 11.5GB.

[root@localhost ~]# fdisk -l

Disk /dev/sda: 14.0 GB, 13958643712 bytes, 27262976 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 label type: dos
Disk identifier: 0x000912b7

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
/dev/sda2         1026048    25165823    12069888   8e  Linux LVM

Disk /dev/mapper/centos-root: 11.5 GB, 11496587264 bytes, 22454272 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 /dev/mapper/centos-swap: 859 MB, 859832320 bytes, 1679360 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

Now we are going to use fdisk to delete the existing partition and create a new, larger, partition to replace it. Be sure to know whether the partition is Primary or Extended, the partition number, and the partition type. In the example below, we are working on a Primary partition and it’s is partition number 2. Linux LVM partitions are type 8e.

Be sure to change the type to 8e before writing the changes to disk. I am assuming you have some experience using fdisk, but the console log below goes through every step required. For more information the fdisk man page is a good place to start.

[root@localhost ~]# fdisk /dev/sda
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


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

Command (m for help): n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p):
Using default response p
Partition number (2-4, default 2):
First sector (1026048-27262975, default 1026048):
Using default value 1026048
Last sector, +sectors or +size{K,M,G} (1026048-27262975, default 27262975):
Using default value 27262975
Partition 2 of type Linux and of size 12.5 GiB is set

Command (m for help): t
Partition number (1,2, default 2): 8e
Partition number (1,2, default 2):
Hex code (type L to list all codes): 8e
Changed type of partition 'Linux' to 'Linux LVM'

Command (m for help): p

Disk /dev/sda: 14.0 GB, 13958643712 bytes, 27262976 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 label type: dos
Disk identifier: 0x000912b7

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
/dev/sda2         1026048    27262975    13118464   8e  Linux LVM

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.

We are almost done. We will need to tell the kernel to rescan the partition and use it’s new size. Although the suggested command above is partprobe this cannot be run (on CentOS7) on a partition that is in use. We will use the command partx instead.

[root@localhost ~]# partx -u /dev/sda

Now when we run fdisk again you will see that the block size has changed for the partition we re-created. In this case it went from 12069888 blocks to 13118464 blocks.

Step 3 - Resizing the Physical Volume

If we weren’t using LVM we could now resize the filesystem and be done. But, we are using LVM so we need to run some additional commands to use the new disk space.

The first thing we need to do is resize the physical volume. We can view the size of the physical volumes using the command pvdisplay.

[root@localhost ~]# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               centos
  PV Size               <11.51 GiB / not usable 2.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              2946
  Free PE               0
  Allocated PE          2946
  PV UUID               XepyHg-H23c-Qkma-2sDl-f5if-diC8-f7Gsn7

Note the PV Name /dev/sda2 and PV Size 11.51Gib above. Afer resizing the physical volume this will increase. To resize the physical volume we’ll use the pvresize command.

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

Now we’ll run pvdisplay again and see the new size.

[root@localhost ~]# pvdisplay 
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               centos
  PV Size               <12.51 GiB / not usable 2.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              3202
  Free PE               256
  Allocated PE          2946
  PV UUID               XepyHg-H23c-Qkma-2sDl-f5if-diC8-f7Gsn7

The PV Size now reads 12.51Gib and we can move on to resizing the logical volume.

Step 4 - Resizing the Logical Volume

Let’s take a look at the size of the logical volume using the lvdisplay command.

[root@localhost ~]# lvdisplay 
  --- Logical volume ---
  LV Path                /dev/centos/root
  LV Name                root
  VG Name                centos
  LV UUID                2j5NcR-5Uec-PPd3-z34J-ON18-k3d5-g2OuDw
  LV Write Access        read/write
  LV Creation host, time localhost, 2017-12-12 11:46:22 -0500
  LV Status              available
  # open                 1
  LV Size                <10.71 GiB
  Current LE             2741
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:0

This command will list all logical volumes on the system. In this case we are working with the root volume. Make sure you are looking at the correct volume. The two important pieces of information displayed are LV Path and LV Size. We can see above the size is listed as 10.71Gib.

Let’s extend the logical volume.

[root@localhost ~]# lvextend -l +100%FREE /dev/centos/root 
  Size of logical volume centos/root changed from <10.71 GiB (2741 extents) to <11.71 GiB (2997 extents).
  Logical volume centos/root successfully resized.

This command may need a bit of additional explanation. The switch -l tells the command we are specifying disk extents. We are telling the command to add all free extents by using +100%FREE.

You can see in the output that the volume was extended from 10.71Gib to 11.71Gib. We can verify this using the lvdisplay command again.

[root@localhost ~]# lvdisplay 
  --- Logical volume ---
  LV Path                /dev/centos/root
  LV Name                root
  VG Name                centos
  LV UUID                2j5NcR-5Uec-PPd3-z34J-ON18-k3d5-g2OuDw
  LV Write Access        read/write
  LV Creation host, time localhost, 2017-12-12 11:46:22 -0500
  LV Status              available
  # open                 1
  LV Size                <11.71 GiB
  Current LE             2997
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:0

Now we can proceed to the final step.

Step 5 - Growing the Filesystem

The commands used for this step will differ depending on the filesystem in use. By default CentOS7 uses XFS, and Ubuntu user EXT4.

First let’s see what size the OS sees using df -h.

[root@localhost ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   11G  1.1G  9.7G  11% /
devtmpfs                 486M     0  486M   0% /dev
tmpfs                    497M     0  497M   0% /dev/shm
tmpfs                    497M  6.6M  490M   2% /run
tmpfs                    497M     0  497M   0% /sys/fs/cgroup
/dev/sda1                497M  151M  347M  31% /boot
tmpfs                    100M     0  100M   0% /run/user/0

Notice that /dev/mapper/centos-root is 11G. Let’s extend this filesystem.

The command on CentOS7 (XFS):

[root@localhost ~]# xfs_growfs /dev/mapper/centos-root 
meta-data=/dev/mapper/centos-root isize=256    agcount=7, agsize=436992 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=2806784, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2806784 to 3068928

The command on Ubuntu (EXT4):

root@ubuntu:~# resize2fs /dev/ubuntu-vg/root 
resize2fs 1.43.5 (04-Aug-2017)
Filesystem at /dev/ubuntu-vg/root is mounted on /; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 2
The filesystem on /dev/ubuntu-vg/root is now 2883584 (4k) blocks long.

Notice the filesystem paths are different between CentOS7 and Ubuntu. You can use the filesystem path displayed in the df -h command.

Let’s verify our CentOS system shows the additional size for the root volume by running df -h again.

[root@localhost ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   12G  1.1G   11G  10% /
devtmpfs                 486M     0  486M   0% /dev
tmpfs                    497M     0  497M   0% /dev/shm
tmpfs                    497M  6.6M  490M   2% /run
tmpfs                    497M     0  497M   0% /sys/fs/cgroup
/dev/sda1                497M  151M  347M  31% /boot
tmpfs                    100M     0  100M   0% /run/user/0

Our work is done. We now have the additional disk space available to use within the OS. Not quite as simple as point and click, but this would be easily scriptable.

Conclusion

What we just did was walk through the steps required to make additional disk space available within the Linux OS after extending a virtual disk in VMware (or any other hypervisor).

Again, I would not do this without having a verified backup of important data. I also would not recommend doing this live unless you don’t have any other choice or it’s a system that is not critical and easily restored.