Reduce a filesystem, a logical volume and even a physical disk
Imagine that your linux system is running on a 1To drive. At one point you needed 1To but nowaday you only use 70Go on it. You may want to transfer your system to a smaller drive either to :
- Reuse this 1To physical drive in another system
- Free up some space on your host if this 1To drive is a thick provisioned virtual hard drive
As a reminder, if this 1To drive is a virtual thin provisioned hard drive, you can reclaim the space by ensuring that your hypervisor is correctly configured to support discard on this drive, then run the fstrim
command in the linux VM. The discard option in fstab would trim automatically
In the following example, the system is a debian VM using LVM and the hard drive will be changed from 32G to 10G.
My filesystem type on the root partition I’ll shrink is ext4 and I boot using UEFI
Before starting be sure you have a backup of your data. You could loose all your data if something goes wrong.
To be able to perform this operation, your filesystem should not be mounted.
In my case I’m shrinking the root filesystem so I’ll boot on a debian system installed on a second disk.
Another option would be to boot in the debian installation media and choose Advanced -> Rescue mode in the installer to get a shell and perform the commands. If you do so, ensure to answer “do not use a root file system” when the installer will ask what partition to use a the root filesystem.
Let’s start by identifying the drives and filesystem to reduce
root@debian:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 7G 0 disk
├─sda1 8:1 0 512M 0 part /boot/efi
├─sda2 8:2 0 5.5G 0 part /
└─sda3 8:3 0 976M 0 part [SWAP]
sdb 8:16 0 32G 0 disk
├─sdb1 8:17 0 512M 0 part
├─sdb2 8:18 0 488M 0 part
└─sdb3 8:19 0 31G 0 part
├─debian--vg-root 254:0 0 30.1G 0 lvm
└─debian--vg-swap_1 254:1 0 976M 0 lvm
sdc 8:32 0 10G 0 disk
root@debian:~# fdisk -l /dev/sdb
Disk /dev/sdb: 32 GiB, 34359738368 bytes, 67108864 sectors
Disk model: QEMU HARDDISK
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: gpt
Disk identifier: 0C445618-2828-451C-BBD8-3105C88F2D06
Device Start End Sectors Size Type
/dev/sdb1 2048 1050623 1048576 512M EFI System
/dev/sdb2 1050624 2050047 999424 488M Linux filesystem
/dev/sdb3 2050048 67106815 65056768 31G Linux LVM
In my case the original hard drive is sdb and target is sdc.
sdb have 3 parition, sdb1 is the EFI parition, sdb2 is the boot partition and sdb3 is the LVM partition where my root and swap partition is located.
We will shrink “debian–vg-root” and move everything from sdb to sdc
Let’s see/confirm the current root filesystem size.
root@debian:~# mount /dev/debian-vg/root /mnt
root@debian:~# df -h | grep root
/dev/mapper/debian--vg-root 30G 1.7G 27G 6% /mnt
root@debian:~# umount /dev/debian-vg/root
To be able to reduce the logical volume root of the debian-vg volume group we must start be reducing the filesystem size.
We start by a forced fsck check on the filesystem
root@debian:~# e2fsck -f /dev/debian-vg/root
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/debian-vg/root: 38223/1970416 files (0.2% non-contiguous), 590657/7879680 blocks
Then reduce your filesystem with the resize2fs
command. The -M option will reduce as much as possible. This command could be very long to execute depending to the size of the filesystem
root@debian:~# resize2fs -M /dev/debian-vg/root
resize2fs 1.47.0 (5-Feb-2023)
resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on /dev/debian-vg/root to 784869 (4k) blocks.
The filesystem on /dev/debian-vg/root is now 784869 (4k) blocks long.
Check the result
root@debian:~# mount /dev/debian-vg/root /mnt
root@debian:~# df -h | grep root
/dev/mapper/debian--vg-root 2.8G 1.7G 1.1G 62% /mnt
root@debian:~# umount /dev/debian-vg/root
Now let’s resize the LVM logical volume. Stay safe between the filesystem size and the lv size. A lv smaller than the filesystem will destroy it. Add at least ~1G to be safe. Here I resize to 6G as i want to keep enough free space on the root filesystem
root@debian:~# lvresize -L 6G /dev/debian-vg/root
WARNING: Reducing active logical volume to 6.00 GiB.
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce debian-vg/root? [y/n]: y
Size of logical volume debian-vg/root changed from <30.06 GiB (7695 extents) to 6.00 GiB (1536 extents).
Logical volume debian-vg/root successfully resized.
You can extend the filesystem to 100% of the logical volume if you want
root@debian:~# e2fsck -f /dev/debian-vg/root
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/debian-vg/root: 38223/196224 files (0.2% non-contiguous), 474182/784869 blocks
root@debian:~# resize2fs /dev/debian-vg/root
resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on /dev/debian-vg/root to 1572864 (4k) blocks.
The filesystem on /dev/debian-vg/root is now 1572864 (4k) blocks long.
root@debian:~# mount /dev/debian-vg/root /mnt
root@debian:~# df -h | grep root
/dev/mapper/debian--vg-root 5.8G 1.7G 3.9G 30% /mnt
root@debian:~# umount /mnt
Let’s run lsblk
again
root@debian:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 7G 0 disk
├─sda1 8:1 0 512M 0 part /boot/efi
├─sda2 8:2 0 5.5G 0 part /
└─sda3 8:3 0 976M 0 part [SWAP]
sdb 8:16 0 32G 0 disk
├─sdb1 8:17 0 512M 0 part
├─sdb2 8:18 0 488M 0 part
└─sdb3 8:19 0 31G 0 part
├─debian--vg-root 254:0 0 6G 0 lvm
└─debian--vg-swap_1 254:1 0 976M 0 lvm
sdc 8:32 0 10G 0 disk
The sdb3 parition is still 31G but it’s content is only 6G+976M + 512M of sdb1 + 488M of sdb2 = ~8G. It will fit in sdc. We can start to move our data to the new disk.
Let’s see again the partition table of sdb
root@debian:~# fdisk -l /dev/sdb
Disk /dev/sdb: 32 GiB, 34359738368 bytes, 67108864 sectors
Disk model: QEMU HARDDISK
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: gpt
Disk identifier: 0C445618-2828-451C-BBD8-3105C88F2D06
Device Start End Sectors Size Type
/dev/sdb1 2048 1050623 1048576 512M EFI System
/dev/sdb2 1050624 2050047 999424 488M Linux filesystem
/dev/sdb3 2050048 67106815 65056768 31G Linux LVM
Then we need to replicate this on sdc. Of course the LVM partition will be smaller.
I start by creating a GPT disklabel (as I’m using EFI boot. If you are using “Legacy bios” you need to create a MBR disklabel with o instead of g and making the new system bootable will require extra step not explained here)
root@debian:~# fdisk /dev/sdc
Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS (MBR) disklabel with disk identifier 0x9cf3f81a.
Command (m for help): g
Created a new GPT disklabel (GUID: 3D38E71C-613D-5345-AA1B-8979A377E738).
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
Now we will replicate the partition table of sdb to sdc.
root@debian:~# fdisk /dev/sdc
Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n
Partition number (1-128, default 1):
First sector (2048-20971486, default 2048): 2048
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-20971486, default 20969471): +1048576
Created a new partition 1 of type 'Linux filesystem' and of size 512 MiB.
Command (m for help): t
Selected partition 1
Partition type or alias (type L to list all): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.
Command (m for help): n
Partition number (2-128, default 2): 2
First sector (1050625-20971486, default 1052672): 1052672
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1052672-20971486, default 20969471): +999424
Created a new partition 2 of type 'Linux filesystem' and of size 488 MiB.
Command (m for help): n
Partition number (3-128, default 3): 3
First sector (1050625-20971486, default 2054144): 2054144
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2054144-20971486, default 20969471):
Created a new partition 3 of type 'Linux filesystem' and of size 9 GiB.
Command (m for help): t
Partition number (1-3, default 3): 3
Partition type or alias (type L to list all): lvm
Changed type of partition 'Linux filesystem' to 'Linux LVM'.
Command (m for help): p
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
Disk model: QEMU HARDDISK
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: gpt
Disk identifier: 3D38E71C-613D-5345-AA1B-8979A377E738
Device Start End Sectors Size Type
/dev/sdc1 2048 1050624 1048577 512M EFI System
/dev/sdc2 1052672 2052096 999425 488M Linux filesystem
/dev/sdc3 2054144 20969471 18915328 9G Linux LVM
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
Let’s copy sdb1 to sdc1 and sdb2 to sdc2 (EFI and boot partition)
root@debian:~# dd if=/dev/sdb1 of=/dev/sdc1 bs=4k
131072+0 records in
131072+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 3.80218 s, 141 MB/s
root@debian:~# dd if=/dev/sdb2 of=/dev/sdc2 bs=4k
124928+0 records in
124928+0 records out
511705088 bytes (512 MB, 488 MiB) copied, 4.3996 s, 116 MB/s
We will now extend the lvm physical volume
root@debian:~# vgextend debian-vg /dev/sdc3
Physical volume "/dev/sdc3" successfully created.
Volume group "debian-vg" successfully extended
Then move the volume group from sdb3 to sdc3.
root@debian:~# pvmove -v /dev/sdb3 /dev/sdc3
Executing: /sbin/modprobe dm-mirror
Creating logical volume pvmove0
activation/volume_list configuration setting not defined: Checking only host tags for debian-vg/root.
Moving 1536 extents of logical volume debian-vg/root.
activation/volume_list configuration setting not defined: Checking only host tags for debian-vg/swap_1.
Moving 244 extents of logical volume debian-vg/swap_1.
activation/volume_list configuration setting not defined: Checking only host tags for debian-vg/root.
activation/volume_list configuration setting not defined: Checking only host tags for debian-vg/swap_1.
Archiving volume group "debian-vg" metadata (seqno 5).
Creating debian--vg-pvmove0
Loading table for debian--vg-pvmove0 (254:2).
Loading table for debian--vg-root (254:0).
Loading table for debian--vg-swap_1 (254:1).
Suspending debian--vg-root (254:0) with device flush
Suspending debian--vg-swap_1 (254:1) with device flush
Resuming debian--vg-pvmove0 (254:2).
Resuming debian--vg-root (254:0).
Resuming debian--vg-swap_1 (254:1).
activation/volume_list configuration setting not defined: Checking only host tags for debian-vg/pvmove0.
Creating volume group backup "/etc/lvm/backup/debian-vg" (seqno 6).
Checking progress before waiting every 15 seconds.
/dev/sdb3: Moved: 0.39%
/dev/sdb3: Moved: 52.36%
/dev/sdb3: Moved: 86.29%
/dev/sdb3: Moved: 100.00%
Polling finished successfully.
The last step is to remove sdb3 from the volume group
root@debian:~# pvs
PV VG Fmt Attr PSize PFree
/dev/sdb3 debian-vg lvm2 a-- <31.02g <31.02g
/dev/sdc3 debian-vg lvm2 a-- <9.02g 2.06g
root@debian:~# vgreduce debian-vg /dev/sdb3
Removed "/dev/sdb3" from volume group "debian-vg"
root@debian:~# pvs
PV VG Fmt Attr PSize PFree
/dev/sdb3 lvm2 --- 31.02g 31.02g
/dev/sdc3 debian-vg lvm2 a-- <9.02g 2.06g
You can now halt the system, remove the sdb disk and boot on the new disk.
Depending on your OS and the UEFI, you may need to tell the EFI to boot on the right file on the new disk. For example, you use debian and proxmox, you will need to create a new boot entry
Recent Comments