electron14 » Blog Archives

Tag Archives: Storage

Storage

LVM: The Basics

Published by:

Well, I’m back from the holiday binge, and I’ve brought some shiny new 3D graphics with me! On that tangent, Blender is a pretty cool application, and I wish I had the time to get to know it better.  I’m not a 3D guru, didn’t take any classes in it, and have never used any high dollar computer modeling packages, so don’t take that as a professional endorsement, but for the curious it should prove to be a worthy diversion ( be sure to do the tutorials from their site). Update: Here is a link to the blender files used to create the images in this article.

On to the article.  The purpose here is to give someone who has never had any exposure to LVM, or Logical Volume Manager, a basic understanding of the concepts and how to use it. Later on I hope to dig deeper into the details, such as alignment with RAID volumes, snapshots, and other features.  I do assume some understanding of plain old partitioning, but will brush over that topic as well in order to highlight differences in the process.

Let’s start with the ‘why?’.  Most Linux users will be familiar with the idea of carving up their hard disk into one or more usable containers (partitions) and applying file systems to them, and for casual users, that’s generally sufficient.  The process might go something like this:

  • Start with a raw hard disk. The device name might come up as “/dev/sda”.
  • using ‘fdisk’, or if you’re fancy some graphical partitioning tool, you might assign the first 200 megabytes or so as the first partition on “/dev/sda”, creating “/dev/sda1”. You decide that this will hold your system boot data “/boot”.
  • You then assign the next  one or two gigabytes, creating “/dev/sda2”, to be used as virtual memory, or swap.
  • A casual user might then take the rest of the drive space and create “/dev/sda3” for the operating system data, user data, and everything else. They may instead choose to make more partitions, one just for the operating system, one just for user data, etc, but for the sake of simplicity we’ll stick with three partitions at the moment.
representation of a physical hard disk being partitioned into usable containers

Representation of a physical hard disk being partitioned into usable containers

  • You then create the filesystems on each partition. You can think of this as giving the partition structure or priming it for use.  For example, you’d run ‘mkswap /dev/sda2’ to make the partition we created into swap space, or ‘mkfs.ext2 /dev/sda1’ to allow you to store your boot files on partition sda1 using the ext2 filesystem.
Representation of creating swap space and a boot filesystem out of partitions.

Creating swap space and a boot file system out of partitions.

So here we have a fairly basic, standard partitioning setup, but what does a user do if they find that they’ve filled “/dev/sda3” with their movies?  Not only are they out of space, but their computer is unstable because the system doesn’t have any place to store temporary operating data.  Maybe the user desires to make “/dev/sda3” larger, but there’s no more room on the disk. Their only option is to add another hard drive, “/dev/sdb”, and create a new partition, “/dev/sdb1” to be used exclusively for “/media/movies” (or what have you), but now “/dev/sda3” is mostly an empty, oversized partition.

What would really be handy in this case is to be able to create a partition out of pieces of two different physical drives. We’d want to shrink “/dev/sda3”, use it exclusively for the system data, and then take some free space from “/dev/sda” and “/dev/sdb” and create a partition for user data.

While classic partitions can be resized with certain tools, they’re limited by the physical boundaries of the drive size, as well as the location and size of the other partitions on the drive. For example, if we wanted to grow “/dev/sda3”, we’d need some free space, and it would have to be immediately adjacent to “/dev/sda3”.  This is the basic problem that LVM is designed to solve.

The primary advantage of LVM is that it abstracts physical disk boundaries away from partitions. Instead of physical disks, you now have a pool of storage that can be made up of one, two, three and three quarters disks, or whatever you may have. That pool of storage can be metered out to partitions or taken back from them in small chunks.  Don’t forget that there are other advanced functions that also make LVM useful, but are beyond the scope of this article.

So let’s get started with an overview of LVM in action. We’ve made partitions for “/boot” and swap, but now instead of making “/dev/sda3” into “/” or the root volume, we’re going to take it and a partition from a second installed drive, “/dev/sdb1”, and create what’s called a volume group. This volume group is going to serve as the pool of storage discussed earlier.

The first step is to take our partitions and mark them as physical volumes that LVM can use in a pool. This is a simple process that involves running the ‘pvcreate’ command on each partition that we want to make available. This command, simply put, creates a metadata header on each partition that will store LVM information and allow it to work its magic.  As an aside, it’s not strictly necessary to create partitions, you can ‘pvcreate’ an entire disk if you’d like (i.e. /dev/sdb instead of /dev/sdb1).

root@linux:~# pvcreate /dev/sda3 /dev/sdb1
Physical volume “/dev/sda3” successfully created
Physical volume “/dev/sdb1” successfully created

Marking partitions as physical volumes to be used with LVM

Marking partitions as physical volumes to be used with LVM

Next, we bundle those together into a single volume group.  This is done with the ‘vgcreate’ command. This will write information about the volume group into the metadata header of each physical volume in the group.  It will also create the volume group device, such as “/dev/vg0”. Note that we can add more physical volumes to this volume group at any time, using the ‘vgextend’ command.

root@linux:~# vgcreate vg0 /dev/sda3 /dev/sdb1
Volume group “vg0” successfully created

Creating a volume group from two physical volumes

Creating a volume group from two physical volumes

Now we’ve got our big pool of storage. Notice the grid marks on it. This was my attempt to portray that the volume is divided into small pieces, or physical extents, usually 4 megabytes each by default. These physical extents are the building blocks for logical volumes, which will serve as replacements for our classic partitions.  Creating logical volumes is basically the process of assigning these extents to a defined container. These extents can come from any physical volume in the volume group, it doesn’t really matter (but can optionally be controlled, for example with the contiguous flag), we’re basically just taking pieces from the pool and assigning them to a new logical volume. This process also creates device nodes for us, “/dev/vg0/lv0” and “/dev/vg0/lv1”. Note how the node goes “/dev/<volume group name>/<logical volume name>”.

root@linux:~# lvcreate –extents 5120 –name lv0 /dev/vg0
Logical volume “lv0” created
root@linux:~# lvcreate –extents 20480 –name lv1 /dev/vg0
Logical volume “lv1” created

creating logical volumes from physical extents in pool vg0

creating logical volumes from physical extents in pool vg0

Now we’ve got logical volumes, the LVM equivalent of partitions. Note that I created a 20 gigabyte volume called “lv0” by assigning 5,120 x four megabyte extents, and an 80 gigabyte “lv1” with 20,480 extents. I did this for the sake of the example, in practice you could also use “–size 20G” instead of “–extents 5120”.  Note also that I did not use all of the volume group, there are spare extents on the right waiting to be added to lv0, lv1, or used for a new logical volume.

These new logical volumes can now be treated as normal partitions and formatted with the filesystem of your choice. In this example, we’re going to use the 20 gigabyte volume for the root filesystem “/”, and the larger, 80 gigabyte volume for user data on “/home”.

root@linux:~# mkfs.ext3 /dev/vg0/lv0

root@linux:~# mkfs.ext3 /dev/vg0/lv1

using mkfs.ext3 to format logical volumes

using mkfs.ext3 to format logical volumes

And that’s it for the basics. We’ve covered how to use LVM to create volumes that are a replacement for classic partitions, breaking physical disk barriers. One of the things I like about LVM is the simplicity. The commands are consistent, pvcreate, vgcreate, lvcreate, etc. All you have to do is remember the concepts, physical volumes to volume groups to logical volumes, and you can figure out the commands and what order to do them in.

I’ll leave you with a few examples of how to view the status of your new LVM volumes, as well as expanding a logical volume while online.

Extend logical volume:

root@linux:~# lvextend –size +5G /dev/vg0/lv0
Extending logical volume lv0 to 25.00 GB
Logical volume lv0 successfully resized

root@linux:~# lvdisplay /dev/vg0/lv0
— Logical volume —
LV Name                /dev/vg0/lv0
VG Name                vg0
LV UUID                By4T9J-wPhq-fDYt-JuNE-t3Bc-UoB8-CC6TaV
LV Write Access        read/write
LV Status              available
# open                 1
LV Size                25.00 GB
Current LE             6400
Segments               2
Allocation             inherit
Read ahead sectors     auto
– currently set to     256
Block device           254:0

Resize file system:

root@linux:~# resize2fs /dev/vg0/lv0
resize2fs 1.41.3 (12-Oct-2008)
Filesystem at /dev/vg0/lv0 is mounted on /; on-line resizing required
old desc_blocks = 2, new_desc_blocks = 2
Performing an on-line resize of /dev/vg0/lv0 to 6553600 (4k) blocks.
The filesystem on /dev/vg0/lv0 is now 6553600 blocks long.

root@linux:~# df -h /
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/vg0-lv0    25G  173M   24G   1% /

View physical volumes:

root@linux:~# pvdisplay
— Physical volume —
PV Name               /dev/sda3
VG Name               vg0
PV Size               64.76 GB / not usable 3.19 MB
Allocatable           yes (but full)
PE Size (KByte)       4096
Total PE              16578
Free PE               0
Allocated PE          16578
PV UUID               YF6kv3-xA34-4UB2-uWYc-W061-e06E-XKiGzj

— Physical volume —
PV Name               /dev/sdb1
VG Name               vg0
PV Size               74.50 GB / not usable 1.03 MB
Allocatable           yes
PE Size (KByte)       4096
Total PE              19073
Free PE               8771
Allocated PE          10302
PV UUID               G8FjdC-PkW4-L0yq-TMsz-cwh7-XoXN-swqZOY

View volume groups:

root@linux:~# vgdisplay
— Volume group —
VG Name               vg0
System ID
Format                lvm2
Metadata Areas        2
Metadata Sequence No  6
VG Access             read/write
VG Status             resizable
MAX LV                0
Cur LV                2
Open LV               1
Max PV                0
Cur PV                2
Act PV                2
VG Size               139.26 GB
PE Size               4.00 MB
Total PE              35651
Alloc PE / Size       26880 / 105.00 GB
Free  PE / Size       8771 / 34.26 GB
VG UUID               DY0Hsk-vT57-pMnV-Rrgm-u2Hb-U8kh-Xqvgcp

View logical volumes:

root@linux:~# lvdisplay
— Logical volume —
LV Name                /dev/vg0/lv0
VG Name                vg0
LV UUID                By4T9J-wPhq-fDYt-JuNE-t3Bc-UoB8-CC6TaV
LV Write Access        read/write
LV Status              available
# open                 1
LV Size                25.00 GB
Current LE             6400
Segments               2
Allocation             inherit
Read ahead sectors     auto
– currently set to     256
Block device           254:0

— Logical volume —
LV Name                /dev/vg0/lv1
VG Name                vg0
LV UUID                ZjPt4x-AHK7-Q0tj-JXSZ-p9Kw-kg2C-GIdbJN
LV Write Access        read/write
LV Status              available
# open                 0
LV Size                80.00 GB
Current LE             20480
Segments               2
Allocation             inherit
Read ahead sectors     auto
– currently set to     256
Block device           254:1