4

I am trying to defrag a heavily fragmented XFS file-system on a CentOS 6.6 machine:

[root@server opt]# xfs_db -c frag -r /dev/md3
actual 598, ideal 215, fragmentation factor 64.05%

However, when I attempt to launch the xfs_fsr utility, it exits with the message No improvement will be made (skipping):

[root@server opt]# xfs_fsr -t 25200 /dev/md3 -v
/opt start inode=0
ino=536871105
No improvement will be made (skipping): ino=536871105

How can I get this to defrag?

Chris
  • 1,137
  • 4
  • 14
  • 25

1 Answers1

4

Update

After checking xfs_fsr's source code I found this section:

/* Check if the temporary file has fewer extents */
new_nextents = getnextents(tfd);
if (dflag)
    fsrprintf(_("Temporary file has %d extents (%d in original)\n"), new_nextents, cur_nextents);
if (cur_nextents <= new_nextents) {
    if (vflag)
        fsrprintf(_("No improvement will be made (skipping): %s\n"), fname);
    free(fbuf);
    close(tfd);
    return 1; /* no change/no error */
}

I re-run the command with the -d (debug flag) and it returned the following:

xfs_fsr /dev/md1 -v -d
/mnt/disk1 start inode=0
ino=133
ino=133 extents=4 can_save=3 tmp=/mnt/disk1/.fsr/ag0/tmp23917
DEBUG: fsize=30364684107 blsz_dio=16773120 d_min=512 d_max=2147483136 pgsz=4096
Temporary file has 4 extents (4 in original)
No improvement will be made (skipping): ino=133

This means the original file consists of 4 file parts across the HDD platters and creating a new defragmented file would still consist of 4 file parts so this file has been skipped. But why isn't it able to merge them? I don't know so I asked at kernel.org bugzilla.

Update 2

I received an answer. As my XFS filesystem (and probably yours) has a block size of 4KB, the maximum size of a file part can not be bigger than 8GB as stated in the XFS docs:

If a file is zero bytes long, it will have no extents, di_nblocks and di_nexents will be zero. Any file with data will have at least one extent, and each extent can use from 1 to over 2 million blocks (221) on the filesystem. For a default 4KB block size filesystem, a single extent can be up to 8GB in length.

So "No improvement will be made" means "No improvement possible" ;)

Original Answer

I'm having the same problem and found out that there are many cases where xfs_fsr skips the defragmentation:

 * mandatory locks are present
 * file is marked immutable, append-only, or nodefrag
 * filesystem is shut down
 * change/modify times have been altered since defrag started
 * original file is mmapped

If you use -v, xfs_fsr returns the inode numbers of the files that where skipped:

xfs_fsr /dev/md1 -v
/mnt/disk1 start inode=0
ino=133
No improvement will be made (skipping): ino=133
ino=135
No improvement will be made (skipping): ino=135
....

With this inode number you are able to check the attributes of the file with the bmap -a command of xfs_db:

xfs_db -r /dev/md3
xfs_db> inode 133
xfs_db> bmap -a
xfs_db> bmap -d
data offset 0 startblock 1314074773 (4/240332949) count 2097151 flag 0
data offset 2097151 startblock 1316171924 (4/242430100) count 2097151 flag 0
data offset 4194302 startblock 1318269075 (4/244527251) count 2097151 flag 0
data offset 6291453 startblock 1320366226 (4/246624402) count 1121800 flag 0
xfs_db> quit

As you can see it returns in my case an empty value as there are no attribute flags present.

So I tried to check as next thing the lock status. At first we obtain the file name of the inode as follows:

find /mnt/disk1 -xdev -inum 133
/mnt/disk1/foo/bar.dat

And then we try to get the lock status:

lsof /mnt/disk1/foo/bar.dat

As the result is empty, nothing seems to lock this file.

Now lets check if the file has been changed since the last defrag try:

ls -l /mnt/disk1/foo/bar.dat
-rw-rw-rw- 1 nobody users 30364684107 Nov 18  2019 /mnt/disk1/foo/bar.dat

Nope, looks still "old".

mgutt
  • 377
  • 2
  • 16