How to use LVM on your system

I wanted to show you how easy it is to maintain a system with LVM or Logical Volume Management, and why it is good to use.

I've used the command-line because you can then use this on any distro you like. You can use a GUI tool, but I find it much easier and clearer to show all this by doing it from the command-line. Feel free to try whichever way you prefer the most, but it's just as easy from the command-line, if not perhaps quicker.

Firstly, when you use static partition types, you tend to allocate the space, and then find later you ran out. Then you're having to move/resize all your partitions about to make space. This is where LVM comes in handy. You simply just add another disk and add more space to the logical volume that requires it. Of course, you could add another disk, and just create a new partition and then move your files to this. However, LVM saves the need for moving your files.

Let's take my example here, done with Mandriva 2008.1 Spring in VMware. I simulated this way, because I set the system up normally with /dev/sda and two partitions:

Disk /dev/sda: 21.4 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x7c63a8b5

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1         125     1004031   82  Linux swap / Solaris
/dev/sda2             126        2610    19960762+  83  Linux

as you can see swap is allocated to /dev/sda1 and / is allocated to /dev/sda2. Of course, if I run out of space on /dev/sda2, I've kind of got a problem. However, I added two more disks to the system, /dev/sdb and /dev/sdc both of which are 20GB in size. /dev/sda is also 20GB in size also, which you can see from above!

Check you have LVM installed

To use LVM, we have to make sure the package is installed, so:

[[email protected] ian]# rpm -qa | grep -i lvm

shows me that the package is installed. The name of this package can vary from distro to distro, but it's generally lvm or lvm2 (at the time of writing this article).

Creating the Volume Groups and Logical Volumes

Let's assume now that on my system, I am OK with 20GB for my users files, but I wanted to create a /data partition for example to store all my files away from /home. Because usually, this could fill up my /dev/sda2 pretty quickly otherwise considering it's only 20GB in size.

I've just added two disks to the system, so I could technically do:

/dev/sdb1 = /data
/dev/sdb2 = /data2

which is OK, but then it means I've got it split in two locations. With LVM, I can use one volume across both disks. You could also install a RAID controller and use Raid 0 for the same thing, but the end result is the same, except with LVM - I don't need to buy a RAID controller. Just simply add more disks to the system.

To prepare the disks for LVM, we first have to create the partition as follows:

[[email protected] ian]# fdisk /dev/sdb
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0xea2ead97.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

The number of cylinders for this disk is set to 2610.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
Partition number (1-4): 1
First cylinder (1-2610, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-2610, default 2610):
Using default value 2610

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

Command (m for help): p

Disk /dev/sdb: 21.4 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xea2ead97

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1        2610    20964793+  8e  Linux LVM

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

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

you can see all the commands I used in fdisk to create this partition. Now we have to prepare it to use it with LVM:

[[email protected] ian]# pvcreate /dev/sdb1
  Physical volume "/dev/sdb1" successfully created

[[email protected] ian]# vgcreate datavolume /dev/sdb1
  Volume group "datavolume" successfully created

[[email protected] ian]# vgs
  /dev/cdrom: read failed after 0 of 2048 at 0: Input/output error
  VG         #PV #LV #SN Attr   VSize  VFree
  datavolume   1   0   0 wz--n- 19.99G 19.99G

Now the command explanation - the pvcreate prepared the volume. I then created a volume group called datavolume, and assigned /dev/sdb1 to this volume group. The last command vgs, shows the volume group I have, and the amount of space available.

Now, we can create a logical volume within this and mount it to /data:

[[email protected] ian]# lvcreate -l 100%VG -n data datavolume
  Logical volume "data" created

[[email protected] ian]# lvs
  LV   VG         Attr   LSize  Origin Snap%  Move Log Copy%  Convert
  data datavolume -wi-a- 19.99G

so now I have the LVM volume data created, using all 20GB of the datavolume. Technically, I could have done something like this:

lvcreate -L10G -n data datavolume

which would have allocated 10GB of this partition to data instead. I however, wanted to use the full disk, which is why I used the first command.

Now, we can create the filesystem and mount it as normally like this:

[[email protected] ian]# mke2fs -j /dev/datavolume/data
mke2fs 1.40.8 (13-Mar-2008)
Warning: 256-byte inodes not usable on older systems
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
1310720 inodes, 5240832 blocks
262041 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=0
160 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, 1605632, 2654208,

Writing inode tables: done                           
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 34 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

[[email protected] ian]# mount /dev/datavolume/data /data

[[email protected] ian]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2              19G  2.2G   16G  13% /
                       20G  173M   19G   1% /data

now you can see, I used ext3 to create the filesystem and then created the mount point /data and mounted the volume. Now I have 20GB for /data.

Oops, I just ran out of disk space, what do I do now?

OK, so let's assume, I just run out of space on my /data partition. I can now prepare the third disk and add this to the volume group and then just extend my logical volume. Sounds tricky? Not really.

You create the partition on the third disk like before, and toggle the partition type to Linux LVM. Then you do the LVM commands like this:

[[email protected] ian]# pvcreate /dev/sdc1
  Physical volume "/dev/sdc1" successfully created

[[email protected] ian]# vgextend datavolume /dev/sdc1
  Volume group "datavolume" successfully extended

[[email protected] ian]# vgs
  VG         #PV #LV #SN Attr   VSize  VFree
  datavolume   2   1   0 wz--n- 39.98G 19.99G

now you can see that I have 40GB allocated to datavolume. I just now need to allocate the extra space to /data:

[[email protected] ian]# lvextend -l100%VG /dev/datavolume/data
  Extending logical volume data to 39.98 GB
  Logical volume data successfully resized

First, I unmount /data:

[[email protected] ian]# umount /data

then I check partition for errors:

[[email protected] ian]# fsck -n /dev/datavolume/data
fsck 1.40.8 (13-Mar-2008)
e2fsck 1.40.8 (13-Mar-2008)
/dev/datavolume/data: clean, 11/1310720 files, 126323/5240832 blocks

I disable journaling, so that partition becomes ext2 (you cannot resize ext3 partitions without doing this):

[[email protected] ian]# tune2fs -O ^has_journal /dev/datavolume/data
tune2fs 1.40.8 (13-Mar-2008)

The next command has to be done before a resize can be completed:

[[email protected] ian]# e2fsck -f /dev/datavolume/data
e2fsck 1.40.8 (13-Mar-2008)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/datavolume/data: 11/1310720 files (9.1% non-contiguous), 93521/5240832 blocks

I resize to add the rest of the space to the filesystem:

[[email protected] ian]# resize2fs /dev/datavolume/data
resize2fs 1.40.8 (13-Mar-2008)
Resizing the filesystem on /dev/datavolume/data to 10481664 (4k) blocks.
The filesystem on /dev/datavolume/data is now 10481664 blocks long.

I enable journaling to go back to an ext3 filesystem:

[[email protected] ian]# tune2fs -j /dev/datavolume/data
tune2fs 1.40.8 (13-Mar-2008)
Creating journal inode: done
This filesystem will be automatically checked every 34 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

Now, I mount the disk:

[[email protected] ian]# mount /dev/datavolume/data /data

check that it is actually ext3:

[[email protected] ian]# mount
/dev/sda2 on / type ext2 (rw)
none on /proc type proc (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
none on /proc/fs/vmblock/mountPoint type vmblock (rw)
none on /sys/fs/fuse/connections type fusectl (rw)
/dev/mapper/datavolume-data on /data type ext3 (rw)

and then see how much space I have available for /data:

[[email protected] ian]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2              19G  2.2G   16G  13% /
                       40G  177M   38G   1% /data

as you can see, I now easily added 40GB to my /data partition. This was just an example, but you could do this for /home, or /vmware or whatever other mount points you have on your system!