Shrinking an Ext4 File System on LVM in Linux

In Extending a Mounted Ext4 File System on LVM in Linux, we introduced how to extend a mounted ext4 filesystem on LVM Logical volume by adding a new physical volume. It is also common to shrink an ext4 file system as to spare some disk space. In this post, I will discuss how to shrink an ext file system on a LVM logical volume (LV).

After the file system and LV is shrunk, the disk space is returned to the volume group (VG) and you can allocate the disk space in the VG to other LVs. On the other hand, you may also delete a PV to remove a hard drive from the Linux box or shrink the underlining partition to spare some raw disk space. We will also introduce these 2 following actions.

The example we used for introduction here is that /dev/sdb is a hard drive with a partition /dev/sdb1 as a PV of VG vg, vg contains a LV named lv_data, and an ext4 file system on lv_data is created and mounted to /mnt/data.

First step: backup your data

Backup your data in /mnt/data first! Shrinking file systems and partitions are danger operations. Backup your data before any following operations.

Unmount the ext4 file system

Different from extending the file system, it is better to umount the file system first before shrinking it:

# umount /mnt/data

Extending a file system will give it more spare space where there is no data stored since the space is new. However, for shrinking a file system, the to be deleted space from the file system may have data stored there and it is more complex. To avoid possible data loss, please unmount the file system first.

Shrink the ext4 file system and the LVM LV

The suggested way to shrink the ext4 file system and the LVM LV is to use the lvresize command:

# lvresize --resizefs --size SIZE /dev/vg/vg_data

Here, SIZE is your intended new size for the LV and file system, such as 200G. --resizefs lets lvresize also resize underlying filesystem together with the logical volume. It is better than resize2fs + lvresize since it is not unlikely for an admin to accidently use inconsistent parameter for resize2fs and lvresize.

It will prints information like (may be different according to the versions of the tools on you system):

fsck from util-linux 2.21.2
/dev/mapper/vg_linux-lv_home: 15741/54419456 files (0.1% non-contiguous), 4781794/217677824 blocks
resize2fs 1.42.3 (14-May-2012)
Resizing the filesystem on /dev/mapper/vg_linux-lv_home to 26214400 (4k) blocks.

  Reducing logical volume lv_home to 100.00 GiB
  Logical volume lv_home successfully resized

Please note that this command may take much time for moving data to spare disk space. Only do this when you have sufficient time allowing the file system being kept unmounted.

After this command executes successfully, you can remount the file system again and check the file system size by df -hT.

Next steps

After the file system and LV is shrunk, the disk space is returned to the VG vg and you can allocate the space to other LVs. Here, we introduce 2 other possible following steps depending on your purpose of shrinking the file system and LV. You may check them only if you need them.

1. Removing the hard drive

You may want to remove the /dev/sdb from the box. Make sure you shrink the file system to small enough in the above lvresize command so that the spare space in the vg is larger than /dev/sdb1’s capacity.

To remove the hard drive, detailed tutorial can be found in How to delete a disk from a LVM group while keeping the data. Here, we only list the commands:

# pvmove /dev/sdb1
# vgreduce vg /dev/sdb1
# pvremove /dev/sdb1

Then, if there is no other partitions on /dev/sdb, you are free to remove the hard drive for /dev/sdb. Finding the physical hard drive for a device like /dev/sdb in Linux may be tricky (/dev/sdb is not always the 2nd disk on your box!), my suggested method is introduced in .

2. Shrinking the partitions

You may not want to remove /dev/sdb but to shrink /dev/sdb1 and spare some raw disk space for creating other partitions on /dev/sdb.

To achieve this, you need 2 steps: shrink the PV /dev/sdb1 and shrink the disk partition /dev/sdb1.

Shrink the PV

Now, you need pvresize:

# pvresize --setphysicalvolumesize SIZE /dev/sdb1

Here, ensure that the PV size SIZE is appropriate for your intended new partition size of /dev/sdb1.

Shrink the partition

Here, I suggest parted for resizing partition instead of the old method of shrinking partition using fdisk.

The resizepart subcommand in parted can move the END position of a partition:

2.4.10 resizepart
-----------------

 -- Command: resizepart NUMBER END

     Moves the END position of partition NUMBER.  Note that this does
     not modify any filesystem present in the partition.  If you wish to
     do this, you will need to use external tools, such as 'resize2fs'.

     When growing a partition you will want to grow the filesystem
     afterwards, but when shrinking, you need to shrink the filesystem
     before the partition.

An example of using the resizepart command in parted is as follows:

# parted /dev/sdb
GNU Parted 3.2
Using /dev/sdb
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: ATA ST31000528AS (scsi)
Disk /dev/sdb: 1000GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End    Size   Type     File system  Flags
 1      32.3kB  700GB  700GB  primary

(parted) resizepart
Partition number? 1
End?  [700GB]? 650GB
Warning: Shrinking a partition can cause data loss, are you sure you want to continue?
Yes/No? No
(parted) resizepart
Partition number? 1
End?  [650GB]? 680GB
(parted) quit
Information: You may need to update /etc/fstab.

Note that in this example, we select “No” for the warning parted printed out for safety and use a larger size instead.

Besides of parted, if you prefer a GUI program, the GPartd is a very handy tool for shrinking partitions.

Eric Ma

Eric is a systems guy. Eric is interested in building high-performance and scalable distributed systems and related technologies. The views or opinions expressed here are solely Eric's own and do not necessarily represent those of any third parties.

11 comments:

  1. Instead of
    “lvresize –resizefs –resize ”
    it should be
    “lvresize –resizefs –size “

  2. There’s an error in the resize command. –resize should be –size:
    # lvresize –resizefs –size SIZE /dev/vg/vg_data

    Otherwise lvresize throws an error.

  3. lvresize saved me a lot of pain , and is WAY MORE safer than lvreduce , esp on a prod server.

    Thanks, much appreciated.

  4. Thanks for your write up, definitely a lot less messier than manually shrinking fs then lv. And the backup bit up there before all the work is abolutely spot on.

    Cheers

Leave a Reply

Your email address will not be published. Required fields are marked *