How to shrink a physical volume

lvm

I have a physical volume on a partition which extends across the whole disk, say /dev/sda1 using 100% of /dev/sda. Now I need to shrink it to create /dev/sda2. A logical volume actually uses ~50% of the PV, so theoretically there's plenty of room available, but it's all allocated withing the single PV. Is there a safe way to shrink the physical volume (and the underlying disk partition), to create some extra room for the second partition? Unfortunately, my configuration excludes possibility to temporarily pvmove the physical volume to another device.

Of course, I know that I can do it on a file level (like backing up the contents, repartitioning the disk drive and recreating the LVM configuration), but I would prefer to do the job without the need to configure LV from scratch.

Thank you upfront.

Best Answer

If you just need another separate filesystem, you don't have to create a new partition: you can create another LVM logical volume within the existing volume group using the unallocated space in the PV. But if you specifically need a new partition, then you must do as you originally planned.

GParted is a GUI tool that can do the entire PV + partition resizing operation for you. You'll most likely find it in your distribution's package collection.

But if you cannot or don't want to use it for some reason, read on...

Reducing a LVM physical volume that has unallocated space in it is pretty simple. For example, to reduce the size of /dev/sda1 to 40 GiB:

# pvresize --setphysicalvolumesize 40G /dev/sda1

This command is safe, as it will refuse to do anything if the part of the PV it would cut away contains allocated extents.

But that's just the first step. The second step will be to reduce the size of the partition itself.

To be safe, it is recommended that you initially shrink the PV a bit more than you plan to actually shrink the partition, so that after shrinking the partition you can explicitly extend the PV to cover the full size of the partition. If the extend operation fails, you'll immediately know that something went wrong in resizing the partition and won't be leaving hidden errors to trap you or someone else in the future.

You can shrink a partition using a plain Linux fdisk command, but you must keep in mind a few things:

  • When using fdisk to resize a partition, make sure to set it to display all partition sizes and starting locations in sectors first. During the history of Linux fdisk, its behavior has varied here: modern versions do it by default, older versions may need a -u or -u=sectors option to do so.
  • When resizing an existing partition, you cannot move the starting point of the partition. (If you move the starting point, it will no longer be a simple resize operation, but a more complex partition move operation.)

When using fdisk, any changes are written to the disk only when you use the w command. So I would suggest proceeding like this:

  • use sfdisk -d /dev/sda > /safe/location/partition_table_backup.dump to backup the existing partition table.
  • start fdisk /dev/sda in interactive mode
  • use the p command to view the current partition table and verify the "start" and "end" values are displayed as sectors. Make a note of the "start" value.
  • use the d command to delete the current partition entry for sda1.
  • use the n command to recreate the primary partition entry 1 for sda1 in desired size, taking care to specify the location of the first sector exactly as it was (i.e. the same number as was displayed in the "start" value of the p command).
  • use the t command to set the type of the partition 1 to "Linux LVM".
  • double-check your work
  • use the w command to write the updated partition table and exit fdisk.

Pay attention to the message displayed by fdiskat the end. If it says "The kernel still uses the old table", something is blocking the on-line partition table update. You can try partprobe /dev/sda to tell the kernel to reread the partition table (using a newer interface than some older versions of fdisk use, so it might help and certainly won't hurt) and then look at cat /proc/partitions to see if the partition is now recognized by the kernel at the expected size.

If the partition resize is successful, you can now run pvresize /dev/sda1. If you followed my advice and resized the PV initially a bit smaller than the desired new size of the partition, it should now successfully extend the PV a bit to fully cover the resized partition automatically. If this command reports an error, you've probablu made a mistake in specifying the new size and should use sfdisk /dev/sda < /safe/location/partition_table_backup.dump to restore the partition table to what it initially was, and then try again.

(On very old systems, you might actually have to deactivate the VG before running partprobe or even reboot to allow the system re-read the updated partition table.)

Once the resizing operation is complete, you can now use fdisk again to create the second partition you needed. Yes, you could also do it together while resizing the partition, but doing just one thing at a time is safer and ensures you can easily roll back your changes if needed.

Related Question