FSCTL_MOVE_FILE в Windows XP, системный том, FAT32

У меня проблема с дефрагментацией файлов на системном томе 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 также не представляют проблемы. Однако на системных томах FAT32 на XP я почти всегда получаю сообщение об ошибке INVALID_ARGUMENT (87). Файлы довольно большие, около 700 МБ. Том имеет около 10 ГБ свободного места. После сбоя fsctl видно, что часть файла была фактически перемещена до возникновения ошибки. Я пробовал несколько попыток, но пока все 50 из них не увенчались успехом. Я знаю, что перемещение большого файла таким образом может завершиться неудачей из-за того, что ранее свободный кластер, находящийся дальше по дороге, будет занят чем-то другим на томе, особенно если том имеет большую активность (как это обычно бывает с системными томами). Но я понятия не имею, как смягчить это, учитывая, что у меня нет ядра. Что я делаю неправильно и/или как я могу сделать лучше?


person Inso Reiges    schedule 12.12.2012    source источник


Ответы (2)


Короткий ответ: нет, вы не можете попасть туда из пользовательского режима. Вы всегда будете соревноваться с остальными процессами приложений/операционной системы, которые манипулируют файловой системой.

Если вы действительно хотите пойти по этому пути, вам потребуется написать довольно сложный драйвер ядра (минифильтр файловой системы), чтобы помочь с синхронизацией этой операции. Это может быть непросто, особенно при перемещении томов, на которых размещены файлы страниц/подкачки.

Удачи!

person Bukes    schedule 12.12.2012

Две проблемы. Во-первых, в действующей системе вы всегда соревнуетесь с другими действиями (как предложил предыдущий ответчик). Например, после извлечения растрового изображения тома оно может быть уже устаревшим из-за операций в других процессах, которые вы не видите.

Во-вторых, вероятно, в FAT32 есть ограничение на то, сколько вы можете перемещать за раз. Возможно, вам следует подумать о перемещении файлов кусками по 256 КБ (т. е. размером представления отображения диспетчера кеша). Если вы столкнулись с ошибкой, такой как нажатие пробела, который раньше был свободен, у вас будет гораздо меньше работы для размышлений.

Наконец, если у вас есть файл размером 700 МБ, если он существует в 700 фрагментах по 1 МБ, я сомневаюсь, что вы увидите какие-либо значительные улучшения производительности по сравнению с одним фрагментом размером 700 МБ.

person MJZ    schedule 13.12.2012