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".