LVM – Logical Volume Manager
LVM is a logical volume manager for Linux that was first written back in 1998. The goal of LVM is to provide an abstraction layer between the filesystem (Ext2/3/4, XFS, ReiserFS, FAT, NTFS…) and the physical disk it lies on. This howto will give you a quick tour of the LVM architecture, as well as the most common use cases for it.
The LVM Architecture
LVM incorporates three types of objects:
- PV: Physical Volume, an on-disk partition formatted for LVM
- VG: Volume Group, a group of PVs in a RAID-0/JBOD fashion
- LV: Logical Volume, a pseudo block device located in a VG, on which you create a filesystem.
Physical Volumes, or PV, are created on top of regular disk partitions (like /dev/sdb2, for example). Then, those PVs are used to make one or more Volume Groups, or VG. A VG is basically a pool of physical volumes merged together, like in a RAID-0 (or “JBOD“) setup. You can add new PVs to a VG later, to make for additional space.
Once your physical volumes are aggregated into a volume group, you can create Logical Volumes, or LV, in the VG. The LV will reserve space in the VG. You can of course create multiple LV in a single VG. Once a LV has been created, it will expose a new virtual block device under /dev/mapper. This is the block device that will be used to create the filesystem (using mkfs), which is then mounted like a regular filesystem.
Initial setup
We will go through the steps required to mount a filesystem based on an LVM volume. This procedure has been performed on a Debian GNU/Linux 9 (stretch) system, but should work on any Linux 3.2+-based system.
0 – Install the LVM tools
If not already done, you need to install the LVM tools.
Debian users:
% sudo apt-get install lvm2
RHEL-based system users:
% sudo yum install lvm2-cluster
1 – Prepare a physical partition
In this case, we have a virtual machine running with two emulated physical disks: one where the system is installed (/dev/vda), and one that we will use for LVM : /dev/vdb.
root@test-lvm:~# fdisk /dev/vdb Welcome to fdisk (util-linux 2.29.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. Created a new DOS disklabel with disk identifier 0x38bc0c25. Command (m for help): p Disk /dev/vdb: 25 GiB, 26843545600 bytes, 52428800 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: 0xa5e9965b
We initialize the empty disk with a new primary partition that will be used as a LVM Physical Volume (PV).
Command (m for help): n Partition type p primary (0 primary, 0 extended, 4 free) e extended (container for logical partitions) Select (default p): <strong>p</strong> Partition number (1-4, default 1): First sector (2048-52428799, default 2048): <RETURN> Last sector, +sectors or +size{K,M,G,T,P} (2048-52428799, default 52428799): <RETURN> Created a new partition 1 of type 'Linux' and of size 25 GiB. Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Syncing disks.
The kernel re-reads the partition table and populates the new block device /dev/vdb1, which is our new primary partition.
2 – Creating the LVM resources
We initialize it for use by LVM with the pvcreate command:
# pvcreate /dev/vdb1 Physical volume "/dev/vdb1" successfully created.
We can check the attributes of the PV with the pvdisplay command:
# pvdisplay --- Physical volume --- PV Name /dev/vdb1 VG Name vg-demo PV Size 25.00 GiB / not usable 3.00 MiB Allocatable yes PE Size 4.00 MiB Total PE 6399 Free PE 6399 Allocated PE 0 PV UUID 2POxXh-S7Gx-zd6v-RnK0-OFt9-RYb0-SIVBbF
Then, we initialize a new Volume Group (VG) with this PV:
# vgcreate vgdemo /dev/vdb1 Volume group "vgdemo" successfully created
We can also check its attributes with the vgdisplay command:
# vgdisplay --- Volume group --- VG Name vgdemo System ID Format lvm2 Metadata Areas 1 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 1 Act PV 1 VG Size 25.00 GiB PE Size 4.00 MiB Total PE 6399 Alloc PE / Size 0 / 0 Free PE / Size 6399 / 25.00 GiB VG UUID 2Sp2pp-17jB-eNCN-vjQu-YF40-kiUw-9i2Rd9
Two shorter commands (pvs and vgs) are also available to view the status of PVs and VGs:
# pvs PV VG Fmt Attr PSize PFree /dev/vdb1 vgdemo lvm2 a-- 25.00g 25.00g # vgs VG #PV #LV #SN Attr VSize VFree vgdemo 1 0 0 wz--n- 25.00g 25.00g
As we can see, all the space is still available in the VG, since no Logical Volume (LV) has been created yet. Let’s fix that and create a 10 GiB volume using the lvcreate command:
# lvcreate vgdemo -L10G -n lvtest1 Logical volume "lvtest1" created.
Here we first specify the VG on which to create our LV, then its size using the -L option, and finally its name using -n. As previously, we can get quick informations about our volumes using the lvs command:
# lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert lvtest1 vgdemo -wi-a----- 10.00g
A new block device has been created: /dev/dm-0. A symbolic link also exists in /dev/mapper for easier reference by the system administrator; the naming convention is <vgname>-<lvname>:
# ls -l /dev/mapper total 0 crw------- 1 root root 10, 236 Aug 1 15:37 control lrwxrwxrwx 1 root root 7 Aug 1 15:42 vgdemo-lvtest1 -> ../dm-0
As we can see, in the VG, there’s now only 15 GiB left, since we allocated 10 GiB to the new LV.
# vgs VG #PV #LV #SN Attr VSize VFree vgdemo 1 1 0 wz--n- 25.00g 15.00g
All the steps required to create a logical volume are now done, it’s time to format with a filesystem using mkfs.
3 – Creating and mounting the filesystem
Here at Jaguar Network, we are big fans of XFS, a filesystem developed by SGI in 1993. Most Linux kernels, including the Debian’s one, come with XFS support, but you might need to install userland programs to format it:
# apt-get install xfsprogs
Next, we create the filesystem on the LV block device:
# mkfs.xfs /dev/mapper/vgdemo-lvtest1 meta-data=/dev/mapper/vgdemo-lvtest1 isize=512 agcount=4, agsize=655360 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=0, rmapbt=0, reflink=0 data = bsize=4096 blocks=2621440, 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
We can now mount it into any directory:
# mount -t xfs /dev/mapper/vgdemo-lvtest1 /mnt/test1
Let’s check the available space:
# df -h /mnt/test1 Filesystem Size Used Avail Use% Mounted on /dev/mapper/vgdemo-lvtest1 10G 43M 10G 1% /mnt/test1
All is good! In the next tutorial, we’ll show you how to create additional logical volumes, how to extend volume groups with new physical volumes, and lots of interesting things with LVM.