Disk storage space is always at a premium. No matter how much space one has, it always seems to shrink. In this article, the author suggests a solution to this problem with the Linux-based Logical Volume Manager (LVM).
“A hundred gigs ought to be enough for my home partition!” is what you might have said before you typed those fateful commands into fdisk. Little did you realise that six months later, you’d be regretting that decision.
When I bought a 1TB external hard drive last year, I thought I was set for five years at the very least. Barely eight months on, I’ve already used up 80 per cent of the disk. And I’m using the rest up at an alarming rate. Trust me, today what might seem like more than enough storage for the rest of your life, will seem like a floppy disk half a year from now. You need to do something about it.
So what can you do? You can’t go out and buy an exabyte of storage now. That’s too expensive. What you can do is buy as much as you need now, and just keep adding to it as and when you need more storage. Simple, right? Only if you could take the hassle out of partitioning, filesystems, migration and what not. Well, with Linux, you can.
The logical volume manager or LVM
The big problem with storage seems to be partitions. You never know just how much you’re going to need. You can’t just dump everything into one partition – not only is that very bad housekeeping, but it’s also a good idea to keep system and data separated because if your system goes down, you can wipe it and start over without worrying about your data.
Partitioning wouldn’t be all that bad if you could only grow, shrink and throw those partitions around whenever you felt like it (or needed to). Well, with LVM, you can.
The big idea behind LVM is that you don’t need to bother if the partitions you store your data in are really physical partitions. All they need to be are logical units – volumes. With LVM, you don’t divide your disk into different partitions; you create logical volumes on them, and then you are free to do whatever you want with them. If a volume is filling up, just increase its size. If you have no space to do that, just shrink a lesser used partition to make some space.
And LVM really comes into its own when you need to add capacity. Running really low on space? Go out and buy another drive. It can be anything – a 2TB platter drive or a shiny new 256 GB SSD. Or even one of those new fangled Fusion Drives. LVM doesn’t care what it is, as long as it has storage space in it. Connect the drive to your system, tell LVM it’s there, and then grow your volumes, which will now use up the new space available in the new drive.
‘If it’s that good, there’s got to be some catch!you say, deciding that, ‘Maybe it’s slow. Well, the magic thing is, it’s not. You might think that layering your filesystem over one additional volume manager might be slow, but it’s not. LVM is built into the Linux kernel, and it uses the same mechanisms to manage disk access that filesystem drivers use. LVM doesn’t change the data when you store it; it only manages where it is stored on the disk. You certainly won’t feel a difference in performance if you use LVM. If you measure it, you’ll find that the performance drop is negligible, and in most cases, immeasurable.
Getting started with LVM
LVM has two types of volumes you need to be concerned about – physical and logical volumes. Physical volumes are the actual disks (or partitions, loop files or any block device) that store your LVM set. Logical volumes are the volumes that you actually mount and store your data in.
In between the physical and the logical volumes lies the volume group. You create a volume group on one or more physical volumes, and then you create logical volumes inside a volume group.
The additional abstraction of a volume group might not seem very intuitive at first, but consider that you can’t resize physical volumes at will. You can, however, resize volume groups in that you can extend them to use an arbitrary number of physical volumes. Logical volumes must reside inside their volume group. So the volume group serves as an elastic container for your volumes.
Now let’s get around to using it. To begin using LVM, you need some physical volumes first. You need an old fashioned partition. This is what the partition table on my laptop looks like:
Node Size Code Name sda1 512.0 MiB EF00 EFI System sda2 127.5 GiB 0700 Microsoft basic data sda3 337.8 GiB 8E00 Linux LVM
Yes, since I use UEFI, I have a 512 MB EFI system partition up front. That’s FAT32. Then there’s a 127.5 GB NTFS partition that holds Windows 8.1 for me. The rest, as you can see, is a LVM partition. 8e00 is its type ID. 8e00 is the partition type for a LVM physical volume. Yes, when I said the days of partitioning are over, I lied a bit. Even if you want to dedicate an entire disk to LVM, you need to create at least one partition on it and mark it 8e00 (or just 8e if you’re using MBR partitions).
So now that I’ve created a partition for my LVM physical volume, how do I use it? Well, I need to initialise it first (format it with an LVM, if you will), and to do that, I type in the following command:
$: sudo pvcreate /dev/sda3
replacing sda3 with whatever my node is. If you’re using a SSD and want to make sure your blocks are aligned to 1MB, you might want to run the following command instead:
$: sudo pvcreate --dataalignment 1m /dev/sda3
And we’ve just created a physical volume. I now run:
$: sudo pvdisplay
And the system gives me a ton of information about my newly created physical volume. Running pvdisplay on my laptop gives me the following:
--- Physical volume --- PV Name /dev/sda3 VG Name VolGroup PV Size 337.76 GiB / not usable 4.01 MiB Allocatable yes PE Size 4.00 MiB Total PE 86466 Free PE 40386 Allocated PE 46080 PV UUID AkEk7x-aPzN-yLPl-F6u3-d1gy-wbdn-SNxZfD
So now that I have a physical volume to play around with, why not create a volume group on it? Let’s say I want a volume group called VolGroup, then I run the following command:
$: sudo vgcreate VolGroup /dev/sda3
My volume group is ready. I can now begin creating my volumes on it, but how do I do that? To create a standard volume, I can use the following command:
$: sudo lvcreate -L 64G VolGroup -n Root
I just created a 64 GB logical volume in the VolGroup volume group and named it ‘Root’. It’ll now show up as /dev/VolGroup/Root and /dev/mapper/VolGroup-Root. I can use whichever node strikes my fancy. Now I can create a filesystem on it and mount it somewhere, like shown below:
$: sudo mkfs.ext4 /dev/VolGroup/Root $: sudo mount /dev/VolGroup/Root /mnt
If I wanted a swap partition inside my volume group, I could just create a standard volume, but it might be a good choice to mark the volume as contiguous, so that the volume is stored on concurrent blocks on a single physical volume. This takes away a lot of the flexibility offered by LVM, but to minimise disk access time, this is a good option. Let’s run the following command:
$: sudo lvcreate -C y -L 4G VolGroup -n Swap
Of course, you might also want to remove logical volumes once in a while. The command to do that is dead simple:
$: sudo lvremove /dev/VolGroup/Swap
Replace the device node in the above command to match the volume you want to remove. Just remember to unmount the volume first.
Remember that unless you’re using GRUB 2, your /boot partition cannot reside inside an LVM. If you’re using EFI, you’d use the ESP as a boot partition, but if you’re on BIOS systems and you don’t like GRUB 2, you’re going to need a separate standard partition to boot from, preferably formatted with ext2. I’ll show you how to boot from LVM using GRUB 2 later in the article.
That’s it about creating LVM sets. Now let’s move on to growing, shrinking and throwing things around.
Extending LVM sets
Let’s assume we want 20 additional gigabytes on the ‘Root’ volume we created. The command we’d need to run is as follows:
$: sudo lvresize -L +20G VolGroup/Root
Yes, that’s just VolGroup/Root. You don’t have to supply the device node. Anyway, the logical volume has just grown, but we still need to grow the filesystem inside it to make use of the additional space available. Assuming you’re running ext4 (LVM and ext4 were just made for each other it seems), you can use the following command:
$: sudo resize2fs /dev/VolGroup/Root
And the filesystem will grow to take up all the space in the volume. What if you needed to reduce the size of your volume? That’s easy too, though not as easy as growing one. We’ll do it in three steps.
First, you need to figure out the new, reduced size of the volume. Let’s say you want to reduce ‘Root’ to 48 GB. Let’s begin by resizing the filesystem inside ‘Root’ to take up 47 GB of space. Let’s make it smaller than we need to so that when we resize the logical volume, we don’t accidentally slice off the filesystem’s tail.
$: sudo resize2fs /dev/VolGroup/Root 47G
Of course, this won’t work if you have more than 47 GB of data in ‘Root’. Anyway, once we’ve got the filesystem sorted, we’ll actually reduce the LV’s size, as follows:
$: sudo lvreduce -L 48G VolGroup/Root
And that’s done. Now, to grow the filesystem inside to take up the additional 1 GB or so that we left as an error margin, just run the following:
$: sudo resize2fs /dev/VolGroup/Root
So we’ve seen two commands that deal with the sizing of logical volumes ‘lvresize and lvreduce. There’s a third, called lvextend.
The basic idea is that you use lvreduce and lvextend when you know the exact final size of the volume you want. If you want to grow ‘Root’ to 100 GB, you can use the command given below:
$: sudo lvextend -L 100G VolGroup/Root
Similarly, to shrink it to 32 GB, you can run the following:
$: sudo lvreduce -L 32G VolGroup/Root
And as a shortcut, if you want your volume to grow to the maximum size possible, taking all the free space in the volume group, run the command given below:
$: sudo lvextend -l +100%FREE VolGroup/Root
Yes, that last command uses a lowercase ‘l’. So why would you need lvresize? Well, for relative resizing. Say you want to grow ‘Root’ by 4 GB, you can run the following command:
$: sudo lvresize -L +4G VolGroup/Root
Or if you want to shrink it by 2 GB, you run:
$: sudo lvresize -L -2G VolGroup/Root
A bit convoluted, I know, but still pretty nice, right? Just remember to resize the filesystems that are inside, afterwards.
LVM and more disks
So far, I’ve assumed you have some free space in your volume group. What if you’ve run out? What if you need to bring in some new hardware? Let’s suppose you’ve just installed a new hard drive into your system and want to dedicate the whole thing to LVM. Let’s say the drive shows up as /dev/sdb.
Start off by creating a partition inside the hard drive that takes up the whole drive, and give it a type ID of 8e00. It doesn’t matter if you use GPT or MBR. You could even use Apple Partition Map. All that is needed is a valid partition table on the drive. (Strictly speaking, you don’t need it. In fact, you could very well just use /dev/sdb as a superfloppy and run pvcreate on that, but that isn’t considered very safe.)
Now, create a physical volume on /dev/sdb1:
$: sudo pvcreate /dev/sdb1
If you’ve got an SSD, I’ve already told you what to do. Now comes the interesting part. We won’t create a new volume group; instead, we’ll tell the old one to use the space available in the new physical volume, like shown below:
$: sudo vgextend VolGroup /dev/sdb1
It’s that simple. You can now go ahead and grow your volumes as you need.
LVM and migration
LVM has even more magic. It allows migration with zero downtime.
Let’s start with the simplest of cases. If your hard disk has just started making clicking noises and you want to retire it before it crashes for good, since you’re using LVM, you don’t have to worry.
Let’s say /dev/sdb1 is failing. If you have enough space on the rest of the physical volumes in the volume group, your life is very easy. All you need to do is use the following command:
$: sudo pvmove /dev/sdb1
And all the data from /dev/sdb1 will be redistributed amongst the other physical volumes that constitute your volume group. Now you can just kick the physical volume out of your volume group, as follows:
$: sudo vgreduce VolGroup /dev/sdb1
But what if you didn’t have the luck of having free space in your volume group? Well, one way of addressing this would be to buy a new disk, add it to your volume group, then run pvmove and the rest of the commands.
You could also move the contents of one physical volume to another physical volume in the same volume group. Start by creating a single partition on the disk, giving it a type ID 8e00, and running pvcreate on it. Let’s say the new device node is /dev/sdc1.
Now run:
$: sudo vgextend VolGroup /dev/sdc1 $: sudo pvmove /dev/sdb1 /dev/sdc1
You can now remove /dev/sdb1 from your volume group.
Remember that pvmove moves data, block by block, extent by extent, and while it’s generally safe to leave everything mounted and in-use, pvmove does take a lot of time and uses a lot of disk I/O, so disk access is going to be very slow while pvmove does its thing. Also, do make sure you have a UPS system, because if the power goes off while you’re moving data around, your volume group is pretty much toasted.
LVM snapshots
LVM also allows you to create snapshots of logical volumes, and these are writeable snapshots. LVM snapshots are ‘copy-on-write’, which means that when you create a snapshot, it hardly takes up any space because the files in the snapshot are just pointers to the existing data. As you modify data in the snapshot, the pointers for the changed data begin to point to the new files, while the pointers to the unchanged data continue to point to the old files.
To create a snapshot, you need to decide how much write-space you want to dedicate to it. If you give 2 GB of write-space to a snapshot, you’ll be able to accumulate 2 GB of changes to your snapshot.
This is how you create a snapshot:
$: sudo lvcreate -L 2G -n RootSnapshot --snapshot /dev/VolGroup/Root
The snapshot will be available at /dev/VolGroup/RootSnapshot and /dev/mapper/VolGroup-RootSnapshot for you to mount and use.
Encryption
LVM also allows you to create mirrored volumes, and there are some pretty complex migration recipes that allow you to do anything from distributing specific logical volumes on specific physical volumes to migrating logical volumes between multiple volume groups, and more; but trust me when I say you don’t want your head to explode now. LVM is very powerful. You should probably read TLDP’s ‘LVM-Howto’ if you want to get really serious with LVM.
Since LVM exports its volumes as standard Linux block devices, you can do anything you ever wanted to do with standard block devices. You can use them as disks for KVM, or you can create a physical volume inside a logical volume, and create an LVM set inside an LVM set. But one of the more useful things you can do with logical volumes is encryption.
There are two standard encryption recipes that you use with LVM – LVM inside an encrypted block device, or encryption on an LVM logical volume. I’ll stick with the latter, since that’s the cleaner solution, and the only one you can use if you’re spanning across multiple disks.
You can use TrueCrypt or LUKS. I’ll talk about LUKS, since it’s a bit more flexible.
Let’s say you want to encrypt ‘Root’. Start out by setting up LUKS, as shown below:
$: sudo cryptsetup luksFormat /dev/VolGroup/Root
Once you’re done, you can unlock the volume with the following command:
$: sudo cryptsetup open --type luks /dev/VolGroup/Root CryptRoot
This makes the encrypted volume available at /dev/mapper/CryptRoot. Create a filesystem on it, as follows:
$: sudo mkfs.ext4 /dev/mapper/CryptRoot
Yes, remember to create a filesystem on the encrypted volume, not the LVM logical volume holding it. Now mount the volume with the command shown below:
$: sudo mount /dev/mapper/CryptRoot /mnt
That’s it. Now what happens if you want to grow the logical volume? You begin by unmounting the filesystem and locking the volume, with the following command:
$: sudo umount /dev/mapper/CryptRoot
$: sudo cryptsetup luksClose /dev/VolGroup/Root
Then you resize the actual logical volume, with the following command:
$: sudo lvresize +10G VolGroup/Root
Then, unlock the encrypted volume again:
$: sudo cryptsetup open --type luks /dev/VolGroup/Root CryptRoot $: sudo umount /dev/mapper/CryptRoot # In case it was auto-mounted
Resize the LUKS container:
$: sudo cryptsetup resize CryptRoot
Resize the filesystem within it:
$: sudo e2fsck -f /dev/mapper/CryptRoot $: sudo resize2fs /dev/mapper/CryptRoot
And you’re done. You can now go ahead and use that volume.
A detailed review of all the options available with LUKS is outside the scope of this article, and you’ll have to refer to your distribution’s manual on setting up an encrypted root using LVM and LUKS (or just ask around on StackOverflow, or better yet, Google around for a solution). But this should give you an idea of how to get started with encryption over LVM.
GRUB 2 and booting off LVM
If you’re using GRUB 2, you can leave the /boot partition inside LVM. Make sure you install GRUB to the MBR, and in your grub.cfg file, make sure the following are present:
1. Before the menuentry lines, you should have insmod lvm
2. Inside the menuentry section, specify your root like this: set root=lvm/VolGroup-Root
Here’s an example of a grub.cfg excerpt:
insmod lvm menuentry "Arch Linux" { set root=lvm/VolGroup-Root linux /vmlinuz-linux root=/dev/VolGroup/Root rw quiet initrd /initramfs-linux.img }
To conclude
There are three commands that you can use to get a quick overview of your LVM set-up. The first is pvs, and it displays information on your physical volumes. Shown below is the output of sudo pvs on my system:
PV VG Fmt Attr PSize PFree
/dev/sda3 VolGroup lvm2 a– 337.76g 157.76g
The next is vgs, and running it gives information about all the volume groups in the system. Here is its output on my system:
VG #PV #LV #SN Attr VSize VFree
VolGroup 1 3 0 wz–n- 337.76g 157.76g
Finally, you have lvs, which shows you your logical volumes. This is what it says on my machine:
LV VG Attr LSize
Arch VolGroup -wi-ao—- 48.00g
Home VolGroup -wi-ao—- 128.00g
Swap VolGroup -wc-ao—- 4.00g
You also have pvdisplay, vgdisplay and lvdisplay if you want detailed information.
That’s all from me. Until next time, fellow Tuxers!
Wonderful write-up.