How to Add a Disk to LVM

By | 2019-06-08

Adding a disk to LVM is pretty straightforward. The typical scenario is you have a virtual machine (VM) that is running low on space, so you add another virtual disk to it. Another possible scenario is adding another physical disk to create a software mirror. Perhaps you have a new host and wish to store your application’s data on volumes separate from the OS. I will cover all three scenarios.

Partition the New Disk

LVM doesn’t require the disk to be partitioned, but I like to do it so I can use fdisk to see what the disk is for. Adding a partition table only takes a few seconds and only uses 512 bytes of space.

I just powered up my CentOS 7 VM after adding a second virtual disk. In the example below, I use lsblk to determine the device file of the new disk.

[root@centos7 ~]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0    8G  0 disk 
├─sda1            8:1    0  500M  0 part /boot
└─sda2            8:2    0  7.5G  0 part 
  ├─centos-root 253:0    0  6.7G  0 lvm  /
  └─centos-swap 253:1    0  820M  0 lvm  [SWAP]
sdb               8:16   0    8G  0 disk 
sr0              11:0    1 1024M  0 rom  

Since /dev/sdb doesn’t have a partition table and doesn’t appear to be used, it is obviously the disk I just added.

I will use fdisk to create a partition table on the new disk with a single LVM partition. LVM has a partition type code of 8e. I highlighted the fdisk commands I used. Press the Enter key to accept the default option with fdisk. In the example, prompts with no inputs are where I accepted the default.

[root@centos7 ~]# fdisk /dev/sdb
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.

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

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

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

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

Calling ioctl() to re-read partition table.
Syncing disks.

Add the Disk To LVM

Now that the disk has a partition table, adding it to LVM has two steps. The first is formatting the partition for use with LVM, the second is adding it to a volume group. To format it, use pvcreate.

[root@centos7 ~]# pvcreate /dev/sdb1
  Physical volume "/dev/sdb1" successfully created.

Now you can use the disk to create a new volume group, or add it to an existing one. To add it to an existing one, use vgextend. Use vgcreate for a new volume group. If you create a new volume group, you won’t be able to expand or mirror any of your current volumes.

To create a new volume group named new_vg, follow this example:

[root@centos7 ~]# vgcreate new_vg /dev/sdb1
  Volume group "new_vg" successfully created

If you want to add it to an existing volume group, first determine the name of the volume group. Use vgs to do so.

[root@centos7 ~]# vgs
  VG     #PV #LV #SN Attr   VSize  VFree 
  centos   1   2   0 wz--n- <7.51g 40.00m

The VG column displays the names of the volume groups. On my example system, I have a single volume group named centos.

Now use vgextend to add the disk to the centos volume group.

[root@centos7 ~]# vgextend centos /dev/sdb1
  Volume group "centos" successfully extended

Concatenation

If you wish to add space to a current logical volume, as is common in virtual environments, use lvdisplay and lvresize to view your logical volumes and resize them, respectively.

First, I will use lvdisplay to view my logical volumes.

[root@centos7 ~]# lvdisplay | grep Path
  LV Path                /dev/centos/swap
  LV Path                /dev/centos/root

I have two logical volumes in the centos volume group. I am going to add the entire disk to the root volume that is presented as the block device /dev/centos/root.

Now I use lvresize to add the extra space:

[root@centos7 ~]# lvresize -l +100%free /dev/centos/root 
  Size of logical volume centos/root changed from <6.67 GiB (1707 extents) to 14.70 GiB (3764 extents).
  Logical volume centos/root successfully resized.

LVM divides storage devices into fixed sized chunks called extents. These extents are then assigned to volumes. The -l option is used to specify how many logical extents of the volume group to allocate to a volume. In the example, I allocate all available extents in the volume group to /dev/centos/root. There are several ways to specify how much space to allocate. You can also use -L to specify the space in bytes. See the manual page for details on how to use both options.

Finally, I resize the filesystem:

[root@centos7 ~]# df -h | grep root
/dev/mapper/centos-root  6.7G  1.3G  5.5G  19% /
[root@centos7 ~]# grep root /etc/mtab
rootfs / rootfs rw 0 0
/dev/mapper/centos-root / xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0
[root@centos7 ~]# xfs_growfs /dev/mapper/centos-root
meta-data=/dev/mapper/centos-root isize=256    agcount=4, agsize=436992 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=1747968, 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 1747968 to 3854336
[root@centos7 ~]# df -h | grep root
/dev/mapper/centos-root   15G  1.3G   14G   9% /

If you are expanding a filesystem, first you need to determine which filesystem you are using. Assuming it is mounted, looking at /etc/mtab is a reliable way to do this. In my case, the volume I am expanding uses XFS. The command xfs_growfs modifies an XFS filesystem to use all of the space available on a device.

Here is the same example using ext4 instead of XFS:

[root@centos ~]# df -h | grep root
/dev/mapper/centos-root  6.5G  1.2G  5.0G  19% /
[root@centos ~]# grep root /etc/mtab
rootfs / rootfs rw 0 0
/dev/mapper/centos-root / ext4 rw,seclabel,relatime,data=ordered 0 0
[root@centos ~]# resize2fs /dev/centos/root 
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/centos/root is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 2
The filesystem on /dev/centos/root is now 3844096 blocks long.

[root@centos7 ~]# df -h | grep root
/dev/mapper/centos-root   15G  1.2G   14G   9% /

I'm sure you noticed that sometimes the logical volumes are referred to as /dev/VG_NAME/LV_NAME and sometimes /dev/mapper/VG_NAME-LV_NAME. They are the same thing. They are just symbolic links to the virtual block device files. Read up on the device mapper if you want to know more about how this works.

Mirror

First, get a list of logical volumes using lvdisplay.

[root@centos7 ~]# lvdisplay | grep Path
  LV Path                /dev/centos/swap
  LV Path                /dev/centos/root

I am going to mirror /dev/centos/root. Below, I use lvconvert to create the mirror. LVM will automatically copy the data to the physical volume added earlier. You can use lvs to view the progress.

[root@centos7 ~]# lvconvert --type raid1 --mirrors 1 centos/root
Are you sure you want to convert linear LV centos/root to raid1 with 2 images enhancing resilience? [y/n]: y
  Logical volume centos/root successfully converted.
[root@centos7 ~]# lvs
  LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root centos rwi-aor---  <6.67g                                    46.33           
  swap centos -wi-ao---- 820.00m  

LVM supports several different types of RAID. The --type option is used to specify it.

New Logical Volumes

Use lvcreate to create new logical volumes. Below, I create two logical volumes and create filesystems on them. Each volume uses half of the available space on the volume group named new_vg.

[root@centos7 ~]# lvcreate -l 50%VG -n lv1 new_vg
  Logical volume "lv1" created.
[root@centos7 ~]# lvcreate -l 50%VG -n lv2 new_vg 
  Logical volume "lv2" created.

In order to use the new volumes, I will create filesystems on the new volumes. I will use ext4 on one, and XFS on the other.

[root@centos7 ~]# mkfs.ext4 /dev/new_vg/lv1
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
262144 inodes, 1047552 blocks
52377 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=1073741824
32 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done 

[root@centos7 ~]# mkfs.xfs /dev/new_vg/lv2
meta-data=/dev/new_vg/lv2        isize=512    agcount=4, agsize=261888 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=1047552, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

Now I can mount the filesystems to make use of them.

[root@centos7 ~]# mkdir /lv1
[root@centos7 ~]# mkdir /lv2
[root@centos7 ~]# mount /dev/new_vg/lv1 /lv1
[root@centos7 ~]# mount /dev/new_vg/lv2 /lv2
[root@centos7 ~]# df -h | grep new_vg
/dev/mapper/new_vg-lv1   3.9G   16M  3.7G   1% /lv1
/dev/mapper/new_vg-lv2   4.0G   33M  4.0G   1% /lv2

References