Linux XFS Defragmentation

There is a lot of debate over whether or not one should defragment file systems on Linux. Frankly, in most cases fragmentation of Linux file systems is probably not a problem. However, in a very few cases fragmentation might be a problem. When such a scenario has arisen is up to the reader of this article to decide. Recently here at ERACC we experienced access / speed degradation of the XFS file system on a heavily used /home partition. Part of the problem was that the file system was over 90% full. Another part of the problem was when we checked it with xfs_db the file system was roughly 20% fragmented. Besides cleaning up the file system by deleting and archiving old data from user's directories, we came up with a defragmenation strategy for the entire server. This script is the result:

#!/bin/bash
#
# Bash script by Gene Alexander (http://www.eracc.com/contact)
# of ERA Computers & Consulting (www.eracc.com, blog.eracc.com, shopping.eracc.com)
# Written using vim, the BEST plain text file editor in all of Creation.
#
# Teach yourself bash scripting: http://tldp.org/LDP/abs/html/index.html
#
# Purpose: To check fragmentation on XFS with xfs_db and run xfs_fsr on XFS mount points that
# are above a specific fragmentation threshold.
#
# What is xfs_db? Use 'man xfs_db' to find out.
# What is xfs_fsr? Use 'man xfs_fsr' to find out.
#
# Any busy files, such as open logs on /var/log, will be skipped. To defragment logs one should
# wrap this script with another script to stop and restart logging. Or, even better, write
# one's own script just for defragmentation of the logs.
#
# Warranty: NONE. Use at your own discretion and be aware that data loss is on your head if
# you choose to use this script.
#
# License: GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.html
#
# Suggested Usage: crontab file for root
# 0 0 * * * /root/bin/chkxfsfrag # Run at midnight
#
# Original Release: 2011 December 15 (Merry Christmas!)
# DO NOT ALTER HEADER FROM THIS LINE UP.
#
e='/bin/echo -e'                                # Use the echo command, not built-in.
xfsfsr=/sbin/xfs_fsr                            # Set variable with the path to xfs_fsr.
xfsdb=/sbin/xfs_db                              # Set variable with the path to xfs_db.
pctmax=0                                        # Set maxiumum frag percent needed for defrag.
                                                # This is zero here for testing purposes only
                                                # a higher number should be used in production.
array=`df -T|grep xfs|cut -f 1 --delim=" "`     # Array of all XFS file systems.
for i in ${array[@]};
do
        percentage=`$xfsdb -c frag -r ${i}|cut -f 7 --delim=" "`
        percent2=`$e $percentage|cut -f 1 --delim=.`
        if [ "$percent2" -gt "$pctmax" ]
        then
                $e "${i} is $percentage fragmented. Running defragment on ${i}."
                # Only uncomment one of the following two lines.
                #$xfsfsr -v ${i}        # Uncomment for verbose defrag.
                #$xfsfsr ${i}           # Uncomment for quiet defrag.
        else
                $e "${i}\t$percent2 is not above fragmentation threshold of $pctmax."
        fi
done
exit 0

To run this from cron it should be made executable with at least 700 permission:

chmod 700 /root/bin/chkxfsfrag

We received this message requesting more information from our contact page:

Hi I spotted your post on LXer.com. It is cool you came up with a script to 
defragment XFS. I am really interested to find out how it worked out for you. 
You state the initial percentage of fragmentation and disk usage, could you 
please enlighten us dear readers on the outcome?

Cheers,

Gregory P.

Glad to Gregory. The /home file system in question is a separate 206 GB partition that was a bit over 90% full. After cleaning off the old files it was showing about 10% fragmentation. It had 99.1 GB free as of 15 December 2011 (The date of this article.). After the second nightly run of our XFS defragment script, which was at 00:00 on 15 December 2011, this is the level of fragmentation on that partition:

# /sbin/xfs_db -c frag -r /dev/sda10
actual 194744, ideal 194051, fragmentation factor 0.36%

Our script here uses the quiet option and is set to only defrag if a file system is more than 5% fragmented.

Edit on Mon Dec 19 11:07:39 CST 2011: Add the -e switch to the echo variable. (What does the -e switch do? Perhaps 'man echo' would reveal a clue.) Include a horizontal tab and the percentage of fragmentation in the report under "else".

Edit Sat Dec 24 22:09:10 CST 2011: Change $percentage to $percent2 for uniformity in the reporting of fragmentation.