You are currently viewing Shrinking an LVM Physical Volume

Shrinking an LVM Physical Volume

I have a Fedora installation that has been running on a local machine acting as a home server for several years.  Hacking my way through the system and through several distribution upgrades, it’s no longer a very clean system, and I tend to run into issues when trying to do something new.  I’m ready to start with a clean OS installation, however, I’ve allocated my entire 2 TB hard drive to an LVM volume group.  Instead of starting fresh, I would like to shrink the volume group, as I want to keep my existing data for a period of time.  To do so, I need to boot a live CD, as file systems that are in use cannot be resized.  I’ve chosen a Fedora Workstation 28 live CD, because that’s what I have available.  As an exercise, I’ve sandboxed this in a virtual machine representative of my environment, before I modify my home server.  Below, I’ll walk you through the necessary steps.

As with most any operation, it is critical you back up any data that is important to you before beginning.  Although you may desire to keep your existing partitions, errors are always possible.  Also, if you’re not familiar with any command below, I encourage you to visit the man page to learn more about it.

Activate the Logical Volumes

First, I need to activate the logical volumes (which may have already been done on boot).  Without this, I won’t be able to perform operations on the volume group.

# vgchange -a y
  3 logical volume(s) in volume group "fedora" now active

Before I get started, I need to identify which volume(s) I would like to shrink.  I can identify them with the lvdisplay command.

# lvdisplay
  --- Logical volume ---
  LV Path                /dev/fedora/root
  LV Name                root
  VG Name                fedora
  LV UUID                5SM1Dn-bZD2-t0hr-FYHY-w1Kl-dLPJ-CdV2Jm
  LV Write Access        read/write
  LV Creation host, time localhost-live, 2018-06-10 00:30:44 -0400
  LV Status              available
  # open                 0
  LV Size                20.00 GiB
  Current LE             5120
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:2
   
  --- Logical volume ---
  LV Path                /dev/fedora/home
  LV Name                home
  VG Name                fedora
  LV UUID                3aB0hK-uHZF-aaik-fV96-to7n-FBfH-PNYUdX
  LV Write Access        read/write
  LV Creation host, time localhost-live, 2018-06-10 00:30:49 -0400
  LV Status              available
  # open                 0
  LV Size                56.92 GiB
  Current LE             14572
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:3
   
  --- Logical volume ---
  LV Path                /dev/fedora/swap
  LV Name                swap
  VG Name                fedora
  LV UUID                H5ZCKf-2w5N-MfeA-iaha-Lzkt-vVLp-AfePZf
  LV Write Access        read/write
  LV Creation host, time localhost-live, 2018-06-10 00:30:55 -0400
  LV Status              available
  # open                 2
  LV Size                2.07 GiB
  Current LE             531
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:4

 

Resizing a Logical Volume

The Verbose Method

I must shrink the file system before the logical volume, otherwise I could corrupt the file system and data.  Before I can shrink our file system, I need to run a check on the file systems that we will be shrinking.  If I attempt to shrink a file system that is in an inconsistent state, data may be corrupted.  For this reason, the resize command enforces this step.  In my case, I want to reclaim space from my fedora-home volume.

# e2fsck -fy /dev/fedora/home

Once this completes, I can shrink the file system.  Currently, fedora-home has 1.5 TB allocated, but I want to reduce this to 600 GB (with my file system mounted, df -h shows I am using 489 GB).  Just to be safe, I’m going to shrink my file system a little bit more, and expand it after shrinking my logical volume.  If I shrink the logical volume beyond, I will likely have a corrupt file system.  For the sake of this example, I’ll simplify this to 20 GB, shrinking my actual file system to 19 GB.

# resize2fs /dev/fedora/home 19G

Now I am ready to shrink the logical volume.  I’m going to shrink mine to 20 GB.

# lvreduce -L 20G /dev/fedora/home

After reducing the size of the logical volume, I am ready to grow the file system to fill the remaining free space by omitting the size parameter.

# resize2fs /dev/fedora/home

 

The Easy Method

For simplicity, the above commands can be simplified into a single command that performs all three operations at once.

# lvresize --resizefs -L 20G /dev/fedora/home

 

Resizing a Physical Volume

The next step is to shrink the size of the physical volume on the hard disk, which is part of the larger volume group.  I will display information about our physical volume.

# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               fedora
  PV Size               <79.00 GiB / not usable 3.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              20223
  Free PE               9452
  Allocated PE          10771
  PV UUID               srcoWA-5puD-D3Yr-OM7p-D1Hd-CttO-wnrKeM

I want to resize the volume to the number of extents allocated.  The resize command does not take extents as a parameter, so some quick math tells me that I want a volume size of 43,084 MB.  For some reason, this gives us 10770 extents, so I will add 4 MB to this value.

# pvresize --setphysicalvolumesize 43088M /dev/sda2
/dev/sda2: Requested size <42.08 GiB is less than real size <79.00 GiB. Proceed?  [y/n]: y
  WARNING: /dev/sda2: Pretending size is 88244224 not 165672960 sectors.
  /dev/sda2: cannot resize to 10771 extents as later ones are allocated.
  0 physical volume(s) resized / 1 physical volume(s) not resized

The physical volume cannot be resized, because the 9452 free extents are in the middle of the volume, since I resized the second of three logical volumes.  I will want to display detailed information about the segments in the physical volume.

# pvs -v --segments /dev/sda2
    Wiping internal VG cache
    Wiping cache of LVM-capable devices
  PV         VG     Fmt  Attr PSize   PFree  Start SSize LV   Start Type   PE Ranges            
  /dev/sda2  fedora lvm2 a--  <79.00g 36.92g     0  5120 root     0 linear /dev/sda2:0-5119     
  /dev/sda2  fedora lvm2 a--  <79.00g 36.92g  5120  5120 home     0 linear /dev/sda2:5120-10239 
  /dev/sda2  fedora lvm2 a--  <79.00g 36.92g 10240  9452          0 free                        
  /dev/sda2  fedora lvm2 a--  <79.00g 36.92g 19692   531 swap     0 linear /dev/sda2:19692-20222

I can see that there is free space between the home and swap logical volumes.  Before I can move the swap logical volume, I need to make sure we don’t have it mounted.

# swapoff -a

I want to move the swap volume to start at extent 10240.  Since the source and destination are on the same disk, I will specify the anywhere allocation policy.  I won’t specify a destination, causing the logical volume to relocate to the beginning of free space where it has room.

# pvmove --alloc anywhere /dev/sda2:19692-20222

This may take some time depending on the size of the volume being moved.  After the operation has completed, I will query the segments again.

# pvs -v --segments /dev/sda2
    Wiping internal VG cache
    Wiping cache of LVM-capable devices
  PV         VG     Fmt  Attr PSize   PFree  Start SSize LV   Start Type   PE Ranges            
  /dev/sda2  fedora lvm2 a--  <79.00g 36.92g     0  5120 root     0 linear /dev/sda2:0-5119     
  /dev/sda2  fedora lvm2 a--  <79.00g 36.92g  5120  5120 home     0 linear /dev/sda2:5120-10239 
  /dev/sda2  fedora lvm2 a--  <79.00g 36.92g 10240   531 swap     0 linear /dev/sda2:10240-10770
  /dev/sda2  fedora lvm2 a--  <79.00g 36.92g 10771  9452          0 free

Now that the physical volume is no longer fragmented, I will attempt the same resize command.

# pvresize --setphysicalvolumesize 43088M /dev/sda2
/dev/sda2: Requested size <42.08 GiB is less than real size <79.00 GiB. Proceed?  [y/n]: y
  WARNING: /dev/sda2: Pretending size is 88244224 not 165672960 sectors.
  Physical volume "/dev/sda2" changed
  1 physical volume(s) resized / 0 physical volume(s) not resized

 

Resizing the LVM Partition

I have resized the logical volume, and subsequently the physical volume.  However, the LVM partition still occupies the free space on the hard disk.

# fdisk -l
Disk /dev/sda: 80 GiB, 85899345920 bytes, 167772160 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xb0fe5325

Device     Boot   Start       End   Sectors Size Id Type
/dev/sda1  *       2048   2099199   2097152   1G 83 Linux
/dev/sda2       2099200 167772159 165672960  79G 8e Linux LVM

Before I resize the partition, it is critical to make a backup of the partition table.  In this example, I am just dumping it to the current directory.  It is highly recommended to copy this to persistent storage, elsewhere than the LVM storage or disk I am modifying.  I recommend using scp to copy this file somewhere on the network, or copying it to external storage.

# sfdisk -d /dev/sda > sda.dump

Again, back the partition table up before proceeding.  The sfdisk command can be used with this file to restore the partition table.  See the man page for details.

Now that the partition is backed up, I can safely continue.  I can see precisely the number of sectors our physical volume occupies.

# pvs --units s
  PV         VG     Fmt  Attr PSize     PFree
  /dev/sda2  fedora lvm2 a--  88236032S    0S

Take note this is less than the number of sectors, by 8192.  This is 4M with 512 byte sectors.  Something is using this overhead, so I will use the larger sector size of 88244224 to be safe.  Start parted and begin.

# parted /dev/sda
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted)

Typing help provides a listing of what each command does.  For the sake of this article, I’ve provided an abbreviated list for the commands I will be using.

(parted) help
  help [COMMAND]                           print general help, or help on
        COMMAND
  print [devices|free|list,all|NUMBER]     display the partition table,
        available devices, free space, all found partitions, or a particular
        partition
  quit                                     exit program
  resizepart NUMBER END                    resize partition NUMBER
  unit UNIT                                set the default unit to UNIT

By default, parted will operate with human-readable units, using MB (1000 KB) and GB (1000 MB) as preferred units (as opposed to MiB or GiB).  I will change this to sectors to reduce any ambiguity.

(parted) unit s

I can print the partition table, producing output very similar to fdisk.

(parted) print                                                            
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sda: 167772160s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start     End         Size        Type     File system  Flags
 1      2048s     2099199s    2097152s    primary  ext4         boot
 2      2099200s  167772159s  165672960s  primary               lvm

I had previously decided on resizing partition 2 to 88244224 sectors.  Adding that value to the start sector of 2099200 and subtracting 1, I get an end sector of 90343423.

(parted) resizepart 2 90343423                                            
Warning: Shrinking a partition can cause data loss, are you sure you want to
continue?
Yes/No? Yes

I will print the partition table once more to see if anything happened.

(parted) print                                                            
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sda: 167772160s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start     End        Size       Type     File system  Flags
 1      2048s     2099199s   2097152s   primary  ext4         boot
 2      2099200s  90343423s  88244224s  primary               lvm

This looks promising!  Next, I will quit, and return to bash.

(parted) quit                                                             
Information: You may need to update /etc/fstab.

This informational message can be disregarded, since I haven’t populated /etc/fstab.  I should however do a disk check, to ensure the logical volumes are still in good shape.

# e2fsck -fy /dev/fedora/root
# e2fsck -fy /dev/fedora/home
# e2fsck -fy /dev/fedora/swap

No errors!  After rebooting, I am able to verify the Fedora installation is working on the smaller partition.  Additionally, the install media is able to detect and use free space on the disk.

Let me know your experiences below, and please share this if you’ve found it helpful!

This Post Has 2 Comments

  1. Fabio

    I tried your method step by step but something went wrong and the EFI partition got corrupted. So I had to reinstall and ditched LVM.

  2. Steve

    I originally installed Ubuntu 20 LTS using the automatic install, and then wanted to install Fedora alongside.
    The Ubuntu installer created a vol group and logical volumes from the disk.

    I followed everything in your procedures. The only thing I saw that didn’t match your experience was when I ran `# e2fsck -fy /dev//swap` I got:

    ext2fs_open2: Bad magic number in super-block
    e2fsck: Superblock invalid, trying backup blocks…
    e2fsck: Bad magic number in super-block while trying to open /dev//swap

    The superblock could not be read or does not describe a valid ext2/ext3/ext4
    filesystem. If the device is valid and it really contains an ext2/ext3/ext4
    filesystem (and not swap or ufs or something else), then the superblock
    is corrupt, and you might try running e2fsck with an alternate superblock:
    e2fsck -b 8193
    or
    e2fsck -b 32768

    /dev//swap contains a swap file system

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.