Saturday, June 10, 2017

Freeing Space at Beginning of LVM Partition

I ran into a situation on an old computer where I had two partitions:
  • /sda1 = /boot
  • /sda2 = lvm
Unfortunately, the size of /boot was less than 200 MB, so it wasn't big enough for newer kernels and extras.  What I wanted to do was slightly shrink my lvm and give the space to /boot.  Unfortunately, after using pvmove to free some physical extents at the beginning of the partition, I found that pvresize was unable to free space at the beginning of a partition.  I tried using gparted to do the job, but it gave me error messages. 

So I decided to do the job manually.  It turns out that you can absolutely resize an LVM partition without pvresize; you just need to use vgcfgbackup and vgcfgrestore.

Obviously you should backup your data before doing anything.  From there:

  1. Make a backup of the current configuration.
    vgcfgbackup --file /tmp/my_vg_cfg VolumeGroupName
  2. Disable the logical volumes by unmounting everything and running
    vgchange -an VolumeGroupName
  3. Edit /tmp/my_vg_cfg (maybe make a backup) and do the following:
    • Know how many Physical Extents (PEs) you are going to reduce by. In my case, one PE was 16 MB (32768 x 512 byte sectors).
    • Increment seqno for good housekeeping
    • Reduce dev_size by the number of PEs 
    • Reduce pe_count by the number of PEs
    • Under each of the logical_volumes, under each segment, reduce the number inside stripes by the number of PEs.  Note that you shouldn't need to touch the start_extent number, even if it's non-zero.
  4. Use parted to delete the partition and recreate it to the right, keeping the same ending location.  I used sectors as the units to make it easy, since one PE is 32768 sectors in my case. 
  5. Now recreate the physical volume.  You can find the physical volume UUID inside the /tmp/my_vg_cfg.  Replace sda2 with whatever your partition is.
    pvcreate --uuid PV_UUID --restorefile /tmp/my_vg_cfg /dev/sda2
  6. Now we need to "restore" the lvm using our modified file:
    vgcfgrestore --file /tmp/my_vg_cfg VolumeGroupName
  7. That's it.  You should be able to use vgchange -ay to re-enable the logical volumes and then run fsck to make sure everything took.
I'm kind of surprised I couldn't find this solution with a quick Google search.