Logical Volume Management (LVM) - Basics and Resizing

Over the years I've allowed a couple (Linux) OS installers to use LVM on my systems. So two of my antique laptops that I've resuscitated recently have a volume/partition management system on them that's essentially foreign to me. Understand: I genuinely like fdisk. Most people consider it a horror show (and they're not wrong), but I'm so familiar with it I actually look forward to using it. But the reality is that LVM ("Logical Volume Management") is a better way of managing your disks that eases resizing and repartitioning. So it's time for me to get my head around the basics.

The "Commands" section is unashamedly cribbed from Packt's Linux Utilities Cookbook (it needed an editor, but in most respects a very good book that's taught me a great deal about utilities I thought I knew). I'm also stealing from other sources as well.

Definitions

Physical Volume (PV): think "standard hard disk," like /dev/sda on a Linux system (I suspect it's more complex than that, but it's a good place to start)

Volume Group (VG): composed of one or more PVs

Logical Volume (LV): think of it as a partition: it's the thing you write a file system to and would deal with similarly to /dev/sda2 on a Linux system

File System: the organisational structure that gets written to partitions and LVs: most Linux users use ext4, but there are a multitude of other options like vfat, xfs, ntfs, etc.

Non-Destructive Commands

Logical Volume Management has a butt-load of commands associated with it. Everything in this section should be safe to run on any system as they're reporting tools, not modifying tools.

The test system used to record the responses below has only one HD, only on VG, and thus no LVs that span HDs or LVs.

Most commands return nothing on a system that isn't currently using LVM.

pvdisplay - this will show you the Physical Volumes attached to the system

# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda1
  VG Name               stray
  PV Size               149.05 GiB / not usable 2.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              38156
  Free PE               0
  Allocated PE          38156
  PV UUID               lvHo6Z-SarK-gpEN-xI7T-MH7w-dT68-ubKsMR

pvscan - scan your Physical Volumes

# pvscan
  PV /dev/sda1   VG stray           lvm2 [149.05 GiB / 0    free]
  Total: 1 [149.05 GiB] / in use: 1 [149.05 GiB] / in no VG: 0 [0   ]

OR "No matching physical volumes found" on a non-LVM system.

vgdisplay - shows attributes of the volume groups

# vgdisplay
  --- Volume group ---
  VG Name               stray
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  5
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                4
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               149.05 GiB
  PE Size               4.00 MiB
  Total PE              38156
  Alloc PE / Size       38156 / 149.05 GiB
  Free  PE / Size       0 / 0
  VG UUID               tf6BGN-tERD-qjxz-EiwF-5jfl-jEsj-8lnHa1

vgs - information about the Volume Groups

# vgs
  VG    #PV #LV #SN Attr   VSize   VFree
  stray   1   4   0 wz--n- 149.05g    0

Zero answer on a non-LVM system.

vgscan - scan disks for Volume Groups

# vgscan
  Reading volume groups from cache.
  Found volume group "stray" using metadata type lvm2

Just "Reading volume groups from cache." if the system doesn't use LVM.

lvdisplay - show the details of the Logical Volumes (this looks like the one you're going to use a lot ... also a big output)

# lvdisplay
  --- Logical volume ---
  LV Path                /dev/stray/boot1
  LV Name                boot1
  VG Name                stray
  LV UUID                0WH8Da-PC1X-Io5T-umBc-s0Al-RNnm-bTcNsx
  LV Write Access        read/write
  LV Creation host, time stray, 2016-08-27 17:23:45 -0400
  LV Status              available
  # open                 0
  LV Size                9.54 GiB
  Current LE             2441
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:2

  --- Logical volume ---
  LV Path                /dev/stray/boot2
  LV Name                boot2
  VG Name                stray
  LV UUID                libxXi-TZ2H-fuV6-aI9d-R417-WqA7-DwQfqw
  LV Write Access        read/write
  LV Creation host, time stray, 2016-08-27 17:24:11 -0400
  LV Status              available
  # open                 1
  LV Size                9.54 GiB
  Current LE             2441
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0

  --- Logical volume ---
  LV Path                /dev/stray/swap
  LV Name                swap
  VG Name                stray
  LV UUID                RCtdFn-jmOC-mkWg-ETyi-HDtr-47SU-z71Ueh
  LV Write Access        read/write
  LV Creation host, time stray, 2016-08-27 17:24:46 -0400
  LV Status              available
  # open                 0
  LV Size                1.91 GiB
  Current LE             488
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:1

  --- Logical volume ---
  LV Path                /dev/stray/home
  LV Name                home
  VG Name                stray
  LV UUID                zHYfVs-Dmo0-3xGz-n7yp-Dq0C-6ILH-c3Kgni
  LV Write Access        read/write
  LV Creation host, time stray, 2016-08-27 17:25:05 -0400
  LV Status              available
  # open                 1
  LV Size                128.07 GiB
  Current LE             32786
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:3

lvmdiskscan - scan for all devices LVM can see.

# lvmdiskscan
  /dev/stray/boot2 [       9.54 GiB]
  /dev/sda1        [     149.05 GiB] LVM physical volume
  /dev/stray/swap  [       1.91 GiB]
  /dev/stray/boot1 [       9.54 GiB]
  /dev/stray/home  [     128.07 GiB]
  2 disks
  2 partitions
  0 LVM physical volume whole disks
  1 LVM physical volume

This is very interesting. And the output on a non-LVM system is more illuminating than most of the LVM commands:

# lvmdiskscan
  /dev/loop0                         [     100.00 GiB]
  /dev/mapper/home_crypt             [     190.00 GiB]
  /dev/loop1                         [       2.00 GiB]
  /dev/sda1                          [       1.46 GiB]
  /dev/mapper/docker-8:8-803519-pool [     100.00 GiB]
  /dev/sda2                          [     173.75 GiB]
  /dev/sda3                          [      13.11 GiB]
  /dev/sda4                          [     190.00 GiB]
  2 disks
  6 partitions
  0 LVM physical volume whole disks
  0 LVM physical volumes

lvs - information about Logical Volumes

# lvs
  LV    VG    Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  boot1 stray -wi-a-----   9.54g
  boot2 stray -wi-ao----   9.54g
  home  stray -wi-ao---- 128.07g
  swap  stray -wi-a-----   1.91g

I have to admit I don't get this one at all - I'm going to assume it's an advanced tool I'd "get" if I had a more complex LVM system. I note that on my other LVM system, all LVs have '-wi-ao----' attributes ... This translates to "-writeable-inherited--active-open----," but that doesn't help me much.

lvscan - scan all the LVM-visible disks for Logical volumes:

# lvscan
  ACTIVE            '/dev/stray/boot1' [9.54 GiB] inherit
  ACTIVE            '/dev/stray/boot2' [9.54 GiB] inherit
  ACTIVE            '/dev/stray/swap' [1.91 GiB] inherit
  ACTIVE            '/dev/stray/home' [128.07 GiB] inherit

Resizing a Partition

To resize a LV/logical volume, the best thing is to boot to Knoppix (it's still the single best and easiest to use Linux utility disk!). The documentation I read said to run:

# vgchange -a y

I don't know why - but the process worked, so I'm taking this one on faith. (Yes, I looked at the man page for vgchange - I still don't know why.)

And now we have a step that technology should have eliminated by now, but has not [1]: if we want to reduce the size of the LV, we have to reduce the size of the file system inside it FIRST. If you don't, you'll mangle the FS and get yourself into all kinds of trouble. If you didn't take my advice to boot to Knoppix (or another live CD/DVD), then at the very least umount the LV in question.

# e2fsck -f /dev/stray/home
e2fsck 1.43.3 (04-Sep-2016)
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/stray/home: 3977/8396800 files (0.7% non-contiguous), 607121/33572864 blocks
# resize2fs /dev/stray/home 119G
resize2fs 1.43.3 (04-Sep-2016)
Resizing the filesystem on /dev/stray/home to 31195136 (4k) blocks.
The filesystem on /dev/stray/home is now 31195136 (4k) blocks long.

The fsck is REQUIRED ('-f' forces it even if the LV looks clean) or the resize will refuse to run. resize2fs /dev/stray/home 119G reduces the FS size: choose a number smaller than what you want (read all the instructions to find out why - you were going to read them first before you did anything, right?).

Next, resize the LV itself:

# lvreduce -L -8G /dev/stray/home
  WARNING: Failed to connect to lvmetad. Falling back to device scanning.
  WARNING: Reducing active logical volume to 120.07 GiB.
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce stray/home? [y/n]: y
  Size of logical volume stray/home changed from 128.07 GiB (32786 extents) to 120.07 GiB (30738 extents).
  Logical volume stray/home successfully resized.
# resize2fs /dev/stray/home
resize2fs 1.43.3 (04-Sep-2016)
Resizing the filesystem on /dev/stray/home to 31475712 (4k) blocks.
The filesystem on /dev/stray/home is now 31475712 (4k) blocks long.

lvreduce -L -8G /dev/stray/home reduces the size of the logical volume: '-L' says "by this amount" and the amount can be a target size like "800M" or an amount to reduce by like "-2T".

The final step is to run resize2fs /dev/stray/home - without a size parameter, it expands to use all available space in its resized home LV.

Reboot to your ordinary OS.

pvdisplay now shows "Free PE" of "2048" (previously 0) which makes more sense when you note "PE Size" is "4.00 MiB". vgdisplay shows this better with (partial output):

Alloc PE / Size       36108 / 141.05 GiB
Free  PE / Size       2048 / 8.00 GiB

We're now ready to create the new partition I was planning for:

# lvcreate -l 100%FREE -n boot3 stray

This says "use 100% of the free space to create a LV in the 'stray' VG, and call it 'boot3.'" You'll still need to format the new logical volume, but that's relatively easy.

[1]UPDATE: It occurred to me later that 'gparted' usually does all this in one easy-to-use graphical tool, but apparently it still can't look inside LVM Volume Groups to resize Logical Volumes, although it can resize the VG. Too bad.