* query a file/inode for a block/extent mapping to find out where its data is and how badly it's fragmented
* atomically relocate any extent to anywhere on disk
* mark a given section of the disk as not open for allocation
These three ioctl's together would seem to be more useful
The first one would accept an inode or an fd and return a listing of what extents are where. Useful for analyzing a file for fragmentation and/or planning an optimal relocation strategy.
The second one would do most of the grunt work. It would accept an inode or fd, a file offset, an extent size, and a disk offset, and use that to put the given chunk of said file on the disk at the directed spot. Of course we'd sanity check stuff to prevent overwriting of other files in use and whatnot, and maybe make it interruptible so that impatient admins don't have to panic, and wayward defrags don't lock up the system. We might even return a size_t indicating how much of the block in question was relocated (much like the read and write system calls)
The third one would prevent backfill into a part of the disk we're trying to clean up. This would keep normal disk allocation activity from polluting a zone we're trying to use to reassemble a file. Naturally this is easily abused so it might be best to restrict this to root, and of course it would probably only work on a per mount basis, and perhaps even restricting the "red zone" to one segment or so that occupies no more than half of the file system.
These three would allow fine tuned defragmentation and even allow norton style heuristics whereby active files are gapped for room to grow. Giving the userspace utility using these ioctls full control over them could optimize how well we defrag the filesystem.
The "donor inode" method doesn't seem quite as flexible as defragmentation could be.
Heck, the previous "defrag trifecta" could probably even be extended to work with filesystems in general such as ext3, btrfs, fat32, and others.