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!
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.
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