Shrinking partitions using LVM

August 1, 2013

In one of the projects we had a number of virtual machines that were servicing the same content. The content was duplicated in each of them in the local filesystem. The storage space that was used for the VM infrastructure was getting full, therefore we were asked politely from the VM infrastructure provider if we could do something about it.

The first step was easily decided and we set up a VM that had all the content and was sharing it through NFS with the other web servers. The next part was to resize the disks of the VMs so that the exceeded space could be free. One of the possible ways was to attach a second disk, transfer everything there, change the configuration for the VM and it should work. However, this sounded a good idea to try a few things with LVM. This is a small step by step guide on how to do it.

The layout of the disks is one 300GB disk with one volume group (named vgroup) and on top of it 3 differente logical volumes, the root, the swap and the data. The only other partition existing is a small /boot partition. The data logical volume is mounted on /data directory and the home directories together with the web content reside there.

  1. Backup the necessary files and remove the partiotion
    We could shrink the /data filesystem using resize2fs, and then resize the logical volume, but we decided that we could easily just recreate it. So we backed up the necessary data and then we recreated a smaller lvm partition:

    1. umount /data
    2. lvremove /dev/vgroup/data
    3. lvcreate -L2G -n data vgroup
    4. mkfs.ext4 /dev/vgroup/data
  2. Transfer the logical volumes to the beginning of the disk (optional)
    Using the commands lvdisplay -m we can easily see that there is a gap on the physical allocation because of the recreation. So we had to transfer the logical volumes to use the beginning blocks. This can be easily done using pvmove. From the lvdisplay -m output we note the Current LE size and physical extents to see which we have to transfer and where. The pvmove syntax is the following
    pvmove /dev/vda5:oldstart-oldfinish /dev/vda5:newstart-newfinish –alloc anywhere
    It is important to use the newfinish and the –alloc anywhere parameters, since if you omit them pvmove will fail with a strange error message.
  3. Resize the physical partition
    pvresize /dev/vda5 –setphysicalvolumesize 40G
  4. Update the partition table
    This part is needed, since we have to also inform the partition table of the changes that we just made. The tool used will be gnu parted, and we will use the sector output since it doesn’t have the issued of G vs GB etc. 😉

    1. parted /dev/vda unit s print

      Model: Virtio Block Device (virtblk)
      Disk /dev/vda: 614400000s
      Sector size (logical/physical): 512B/512B
      Partition Table: msdos

      Number Start End Size Type File system Flags
      1 2048s 499711s 497664s primary ext2 boot
      2 501758s 614397951s 613896194s extended
      5 501760s 614397951s 613896192s logical lvm

      We note the start sector and the partitions we exist.

    2. lvm pvs –units s

      PV VG Fmt Attr PSize PFree
      /dev/vda5 vgroup lvm2 a- 83877888S 29360128S

      We note the PSize in sectors. So we now know how many sectors the partition should be.

    3. We calculate the end sector from using the start sector of partition 5 and the size in sectors from lvm pvs. In this example the end sector is 501760+83877888 = 84379648.
    4. parted /dev/vda unit s mkpart extended 501758 84379648
    5. parted /dev/vda unit s mkpart logical 501760 84379648
    6. parted /dev/vda set 5 lvm on
    7. parted is messing with the partition table, and doesn’t touch the data, but in any case if something goes off .. the data are lost. So be careful. After the reboot we have the smaller partition needed.

  5. shrink the file from the host machine
    This is not something that we did, but our friendly upstream administrator, using a simple dd command.
    dd if=disk0 count=84379648 size=512
    The count number is the number of the last sector used. The configuration of the VM was updated to use the new disk image

After this procedure the VM was booted and the check to see if everything was back to normal was done using a simple find on each mounted partition command:
find / -xdev -type f -exec cat {} > /dev/null \;


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: