Windows XP、fat32 システム ボリューム上のファイルの最適化に問題があります。デフラグ ツールを作成しているわけではありませんが、ソリューションの一部では、特定のファイル セットをディスク上に連続的に配置する必要があります。これを確実にするために、FSCTL_MOVE_FILE ioctl を使用して、ファイル エクステントをボリューム上の十分なサイズの単一の空き領域エクステントに移動しています。プロセスは次のようになります。
1) ファイルを作成します。
return m_file.Create(path,
GENERIC_READ | GENERIC_WRITE,
0, NULL,
CREATE_ALWAYS,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH |
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
NULL);
2) ファイルをゼロで埋めます。
3) ファイルが断片化されていることを確認します。断片化されている場合は、FSCTL_GET_VOLUME_BITMAP を使用してボリューム ビットマップを取得し、十分なサイズの空きクラスター チェーンを見つけます。
4) FSCTL_MOVE_FILE を使用して、ファイルを見つかったエクステントに最適化します。
MOVE_FILE_DATA input;
input.FileHandle = fileHandle;
input.StartingVcn.QuadPart = 0;
input.StartingLcn.QuadPart = freeExtent.lcn;
input.ClusterCount = totalFileClusters;
DWORD bytesReturned = 0; // unused
::DeviceIoControl(
volumeHandle,
FSCTL_MOVE_FILE,
&input,
sizeof(input),
NULL,
0,
&bytesReturned,
NULL);
この最後の呼び出しは、NTFS システムと通常のボリュームで正常に機能します。XP の非システム ボリュームも問題ありません。ただし、XP の FAT32 システム ボリュームでは、ほぼ常に INVALID_ARGUMENT (87) エラーが発生します。ファイルはかなり大きく、約 700MB です。ボリュームには約 10GB の空き容量があります。fsctl が失敗した後、エラーが発生する前にファイルの一部が実際に移動されたことがわかります。何度か挑戦しましたが、今のところ50回すべて失敗しています。この方法で大きなファイルを移動すると、以前に解放されていたクラスターがボリューム上の別の何かによって占有されるために失敗する可能性があることを認識しています。しかし、カーネルが存在しない場合、これを軽減する方法がわかりません。私が間違っていること、および/またはどうすれば改善できますか?