XFS

How to Shrink XFS File System on Enterprise Linux 7.2

Why XFS File System Cannot be Shrunk Directly?

Why cannot we just lvreduce XFS file system? A quote from Red Hat official document talking about XFS space management may explain the whole thing.

XFS is a highly scalable, high-performance file system which was originally designed at Silicon Graphics, Inc. XFS is the default file system for Red Hat Enterprise Linux 7.

After an XFS file system is created, its size cannot be reduced. However, it can still be enlarged using the xfs_growfs command (refer to Section 6.4, “Increasing the Size of an XFS File System”).

lvreduce XFS?

It’s true, but the scalability of XFS is only for scaling up, not for scaling down. What if we need to shrink a mount point which was mis-allocated with too much space (I know this would rarely happen on most production environments). Can we just reclaim some space back? The answer is No and Yes.

The “No” is that we cannot reduce XFS logical volume (LV) directly just by handy lvreduce or something else. The “Yes” is that we can work around it, but the approach might be a little tricky.

If your file systems are formatted as any of legacy ext series, you may refer to the post below for resolutions: How to Reduce Logical Volume Size on Linux

Steps to Shrink XFS File System

Let’s start our tutorial.

1. Create a file for verifying after reducing XFS size

Log in server as a normal user, i.e. edchen in this case.

[edchen@test ~]$ pwd
/home/edchen
[edchen@test ~]$ vi Hello
Hello, world!
[edchen@test ~]$ ll
total 4
-rw-rw-r--. 1 edchen edchen 14 Mar 24 00:03 Hello
[edchen@test ~]$ exit

2. Check current status

Let’s see the space usage.
[root@test ~]# df -h | grep home
/dev/mapper/centos_example-home  188G   33M  188G   1% /home
[root@test ~]# vgs
  VG             #PV #LV #SN Attr   VSize   VFree
  centos_example   1   3   0 wz--n- 239.51g 64.00m
[root@test ~]# lvdisplay
...
  --- Logical volume ---
  LV Path                /dev/centos_example/home
  LV Name                home
  VG Name                centos_example
  LV UUID              
  LV Write Access        read/write
  LV Creation host, time test.com, 2016-03-21 08:27:22 -0400
  LV Status              available
  # open                 1
  LV Size                187.45 GiB
  Current LE             47986
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:2

You can see that /home is taking too much free space without using it. We need to shrink this XFS logical volume /dev/centos_example/home.

[root@test ~]# mount | grep home
/dev/mapper/centos_example-home on /home type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

See? It’s a XFS LV mounted. Since XFS does not allow to shrink its size, so we need a strategy to workaround this. Of course, we don’t want to reinstall OS. Here is my plan in short:

  1. Backup the data
  2. Remove current LV
  3. Create a smaller LV
  4. Restore the data

Let’s see how far we can go.

3. Install XFS backup utilities

The best tool to backup XFS file system is xfsdump. Since there’s no xfsdump in CentOS 7.2 minimal, so we have to install it by ourselves. First of all, let’s see what is xfsdump.

[root@test ~]# yum info xfsdump
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.ksu.edu.tw
 * epel: mirror01.idc.hinet.net
 * extras: ftp.ksu.edu.tw
 * updates: centos.cs.nctu.edu.tw
 * webtatic: sp.repo.webtatic.com
Available Packages
Name        : xfsdump
Arch        : x86_64
Version     : 3.1.4
Release     : 1.el7
Size        : 307 k
Repo        : base/7/x86_64
Summary     : Administrative utilities for the XFS filesystem
URL         : http://oss.sgi.com/projects/xfs/
License     : GPL+
Description : The xfsdump package contains xfsdump, xfsrestore and a number of
            : other utilities for administering XFS filesystems.
            :
            : xfsdump examines files in a filesystem, determines which need to
            : be backed up, and copies those files to a specified disk, tape or
            : other storage medium.         It uses XFS-specific directives for
            : optimizing the dump of an XFS filesystem, and also knows how to
            : backup XFS extended attributes.  Backups created with xfsdump are
            : "endian safe" and can thus be transfered between Linux machines of
            : different architectures and also between IRIX machines.
            :
            : xfsrestore performs the inverse function of xfsdump; it can
            : restore a full backup of a filesystem.  Subsequent incremental
            : backups can then be layered on top of the full backup.  Single
            : files and directory subtrees may be restored from full or partial
            : backups.

Install xfsdump package which also includes xfsrestore

[root@test ~]# yum -y install xfsdump
Loaded plugins: fastestmirror
base                                                     | 3.6 kB     00:00
epel/x86_64/metalink                                     | 5.2 kB     00:00
extras                                                   | 3.4 kB     00:00
mysql-connectors-community                               | 2.5 kB     00:00
mysql-tools-community                                    | 2.5 kB     00:00
mysql57-community                                        | 2.5 kB     00:00
updates                                                  | 3.4 kB     00:00
webtatic                                                 | 3.6 kB     00:00
updates/7/x86_64/primary_db                                | 3.2 MB   00:20
Loading mirror speeds from cached hostfile
 * base: ftp.ksu.edu.tw
 * epel: mirror01.idc.hinet.net
 * extras: ftp.ksu.edu.tw
 * updates: centos.cs.nctu.edu.tw
 * webtatic: us-east.repo.webtatic.com
Resolving Dependencies
--> Running transaction check
---> Package xfsdump.x86_64 0:3.1.4-1.el7 will be installed
--> Processing Dependency: attr >= 2.0.0 for package: xfsdump-3.1.4-1.el7.x86_64
--> Running transaction check
---> Package attr.x86_64 0:2.4.46-12.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package          Arch            Version                   Repository     Size
================================================================================
Installing:
 xfsdump          x86_64          3.1.4-1.el7               base          307 k
Installing for dependencies:
 attr             x86_64          2.4.46-12.el7             base           66 k

Transaction Summary
================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 373 k
Installed size: 1.1 M
Downloading packages:
(1/2): attr-2.4.46-12.el7.x86_64.rpm                       |  66 kB   00:00
(2/2): xfsdump-3.1.4-1.el7.x86_64.rpm                      | 307 kB   00:02
--------------------------------------------------------------------------------
Total                                              145 kB/s | 373 kB  00:02
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : attr-2.4.46-12.el7.x86_64                                    1/2
  Installing : xfsdump-3.1.4-1.el7.x86_64                                   2/2
  Verifying  : attr-2.4.46-12.el7.x86_64                                    1/2
  Verifying  : xfsdump-3.1.4-1.el7.x86_64                                   2/2

Installed:
  xfsdump.x86_64 0:3.1.4-1.el7

Dependency Installed:
  attr.x86_64 0:2.4.46-12.el7

Complete!

4. Backup the XFS file system

We backup the XFS file system to a regular file in the root directory / which will stay everything unchanged in this tutorial. The -l option specifies a dump level (0-9). To perform a full backup, use 0. The -f option specifies the destination of target and source, the format is:

-f <target file name> <source LV name>
[root@test ~]# xfsdump -l 0 -f /home.image /dev/centos_example/home
xfsdump: using file dump (drive_simple) strategy
xfsdump: version 3.1.4 (dump format 3.0) - type ^C for status and control

 ============================= dump label dialog ==============================

please enter label for this dump session (timeout in 300 sec)
 -> 20160324-dump
session label entered: "20160324-dump"

 --------------------------------- end dialog ---------------------------------

xfsdump: level 0 dump of test.com:/home
xfsdump: dump date: Thu Mar 24 00:06:49 2016
xfsdump: session id: 7fe1566a-de11-45f2-93c5-85a9b4725a27
xfsdump: session label: "20160324-dump"
xfsdump: ino map phase 1: constructing initial dump list
xfsdump: ino map phase 2: skipping (no pruning necessary)
xfsdump: ino map phase 3: skipping (only one dump stream)
xfsdump: ino map construction complete
xfsdump: estimated dump size: 20800 bytes
xfsdump: /var/lib/xfsdump/inventory created

 ============================= media label dialog =============================

please enter label for media in drive 0 (timeout in 300 sec)
 -> home-old
media label entered: "home-old"

 --------------------------------- end dialog ---------------------------------

xfsdump: creating dump session media file 0 (media 0, file 0)
xfsdump: dumping ino map
xfsdump: dumping directories
xfsdump: dumping non-directory files
xfsdump: ending media file
xfsdump: media file size 21352 bytes
xfsdump: dump size (non-dir files) : 0 bytes
xfsdump: dump complete: 20 seconds elapsed
xfsdump: Dump Summary:
xfsdump:   stream 0 /home.image OK (success)
xfsdump: Dump Status: SUCCESS

Let’s see the dump file.

[root@test ~]# ll /home.image
-rw-r--r--. 1 root root 21352 Mar 24 00:07 /home.image

5. Remove the source LV

We should umount the file system before doing anything on the LV.

[root@test ~]# umount /dev/centos_example/home

Use lvremove to delete the LV.

[root@test ~]# lvremove /dev/centos_example/home
Do you really want to remove active logical volume home? [y/n]: y
  Logical volume "home" successfully removed
[root@test ~]# vgs
  VG             #PV #LV #SN Attr   VSize   VFree
  centos_example   1   2   0 wz--n- 239.51g 187.51g

As you can see, the space is released.

6. Create a new LV

Use lvcreate to create a 10GB with the same name.

[root@test ~]# lvcreate -L 10G -n home centos_example
WARNING: xfs signature detected on /dev/centos_example/home at offset 0. Wipe it? [y/n]: y
  Wiping xfs signature on /dev/centos_example/home.
  Logical volume "home" created.

The signature is replaced with the new one. Let’s see the current status of VG and LV.

[root@test ~]# vgs
  VG             #PV #LV #SN Attr   VSize   VFree
  centos_example   1   3   0 wz--n- 239.51g 177.51g
[root@test ~]# lvdisplay
...
  --- Logical volume ---
  LV Path                /dev/centos_example/home
  LV Name                home
  VG Name                centos_example
  LV UUID              
  LV Write Access        read/write
  LV Creation host, time test.com, 2016-03-24 00:10:45 -0400
  LV Status              available
  # open                 0
  LV Size                10.00 GiB
  Current LE             2560
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:2

There’s a 10GB taken by the new LV. Now, we have to format the new LV in XFS by mkfs.xfs before actually mounting on /home.

[root@test ~]# mkfs.xfs /dev/centos_example/home
meta-data=/dev/centos_example/home isize=256    agcount=4, agsize=655360 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0
data     =                       bsize=4096   blocks=2621440, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

Mount the LV to /home.

[root@test ~]# mount /dev/centos_example/home /home

List the content of /home.

[root@test ~]# ll /home
total 0

Of course, nothing in the /home, because we have not restored the data yet.

7. Restore data back to the new and smaller XFS file system

[root@test ~]# xfsrestore -f /home.image /home
xfsrestore: using file dump (drive_simple) strategy
xfsrestore: version 3.1.4 (dump format 3.0) - type ^C for status and control
xfsrestore: searching media for dump
xfsrestore: examining media file 0
xfsrestore: dump description:
xfsrestore: hostname: test.com
xfsrestore: mount point: /home
xfsrestore: volume: /dev/mapper/centos_example-home
xfsrestore: session time: Thu Mar 24 00:06:49 2016
xfsrestore: level: 0
xfsrestore: session label: "20160324-dump"
xfsrestore: media label: "home-old"
xfsrestore: file system id: 091dc119-8bae-42ac-a725-4a79196398c9
xfsrestore: session id: 7fe1566a-de11-45f2-93c5-85a9b4725a27
xfsrestore: media id: d07cadad-8e5e-4767-bf52-e256dc060e5d
xfsrestore: using online session inventory
xfsrestore: searching media for directory dump
xfsrestore: reading directories
xfsrestore: 1 directories and 0 entries processed
xfsrestore: directory post-processing
xfsrestore: restore complete: 1 seconds elapsed
xfsrestore: Restore Summary:
xfsrestore:   stream 0 /home.image OK (success)
xfsrestore: Restore Status: SUCCESS

Check the /home.

[root@test ~]# ll /home
total 0
drwx------. 2 edchen edchen 71 Mar 24 00:01 edchen
[root@test ~]# df -h | grep home
/dev/mapper/centos_example-home   10G   33M   10G   1% /home
[root@test ~]# mount | grep home
/dev/mapper/centos_example-home on /home type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

So far so good, we have the content back to /home. But I have a question now: Can it survive through reboots? Let’s continue.

[root@test ~]# init 6

8. Verify the data after reducing XFS LV size

Log in server as edchen and verify the file.

[edchen@test ~]$ ll
total 4
-rw-rw-r--. 1 edchen edchen 14 Mar 24 00:03 Hello
[edchen@test ~]$ cat Hello
Hello, world!

We did it!

7 thoughts on “How to Shrink XFS File System on Enterprise Linux 7.2

  1. This is a perfect example of how to document something. Successfully resized /home and / on RHEL 8 with this. Thank you very much.

  2. Thanks, I had to resize a CentOS 7 partition to make it accessible from CentOS 6, and this guide was perfect 🙂

Leave a Reply

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