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
- LVM Official Site
- LVM2 man pages
- LVM Wikipedia page