Остановить выполнение DeviceIoControl
От: Аноним  
Дата: 04.05.06 12:07
Оценка:
Есть Thread, в котором реализована некоторая процедура, в которой используется API функция
DeviceIoControl (Handle, FSCTL_MOVE_FILE, ...);
Как прервать выполнение данной функции(DeviceIoControl)? Делаю следующее
private
lSync: OVERLAPPED;
....
constructor TmyThread.Create;
...
FillChar(lSync, SizeOf(TOverlapped), 0);
lSync.hEvent := CreateEvent(nil, true, FALSE, #0);
.....

unction UnNormilizeDrive(const ADrivePath: string): string;
begin
Result := '//./' + Copy(ADrivePath, 1, Pos('\', ADrivePath) — 1)
end;

DeviceHandle := CreateFile(PAnsiChar(UnNormilizeDrive(DriveName)), GENERIC_READ,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
...

MoveParams.FileHandle := CreateFile(PAnsiChar(AFile.FileName), ; FILE_READ_ATTRIBUTES, FILE_SHAR E_READ OR FILE_SHARE_WRITE OR FILE_SHARE_DELETE, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

if (MoveParams.FileHandle = INVALID_HANDLE_VALUE) then
MoveParams.FileHandle := CreateFile(PAnsiChar(AFile.FileName), GENERIC_READ,
FILE_SHARE_READ OR FILE_SHARE_WRITE OR FILE_SHARE_DELETE,
nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
....

AResult := DeviceIoControl(DeviceHandle, FSCTL_MOVE_FILE, @MoveParams, sizeof(MoveParams), nil, 0, w, @lSync);
if (not AResult) then
begin
....
end;

//По идее сюда должно быть передано управление сразу же. Однако управление не предается, а ждет окончания выполнения функции
//DeviceIoControl.. Что сделано не так? Как добиться того, чтобы можно было прервать операцию...
//Далее идет код, который и должен прервать операцию

procedure TmyThread.StopProc;
begin
SetEvent(lSync.hEvent);
end;
Re: Остановить выполнение DeviceIoControl
От: Alter_ Украина http://alter.org.ua
Дата: 04.05.06 19:30
Оценка:
Здравствуйте, Аноним, Вы писали:

По всей видимости в обработчике вашего IOCTL не предусмотрена асинхронная обработка. Поэтому управление и не возвращается.
--
Alter, http://alter.org.ua
Re[2]: Остановить выполнение DeviceIoControl
От: Аноним  
Дата: 05.05.06 07:17
Оценка:
A_>По всей видимости в обработчике вашего IOCTL не предусмотрена асинхронная обработка. Поэтому управление и не возвращается
Это как? У кого-то возвращается управление, а у кого-то нет. Просто на этом же компьютере работает программа дефрагментации диска и она умеет прерывать операцию. Насколько мне известно, перемещать файлы без фрагментации можно только DeviceIoControl и NtFsControlFile.
Re[3]: Остановить выполнение DeviceIoControl
От: Alter_ Украина http://alter.org.ua
Дата: 05.05.06 09:06
Оценка:
Здравствуйте, Аноним, Вы писали:

A_>>По всей видимости в обработчике вашего IOCTL не предусмотрена асинхронная обработка. Поэтому управление и не возвращается

А>Это как? У кого-то возвращается управление, а у кого-то нет. Просто на этом же компьютере работает программа дефрагментации диска и она умеет прерывать операцию. Насколько мне известно, перемещать файлы без фрагментации можно только DeviceIoControl и NtFsControlFile.

FSCTL_MOVE_FILE синхронен by design. Можете в сорцы FAT в DDK/IFS посмотреть.
Вынесите запрос в отдельный поток.
--
Alter, http://alter.org.ua
Re[3]: Остановить выполнение DeviceIoControl
От: MShura  
Дата: 05.05.06 11:34
Оценка:
A_>>По всей видимости в обработчике вашего IOCTL не предусмотрена асинхронная обработка. Поэтому управление и не возвращается
А>Это как? У кого-то возвращается управление, а у кого-то нет. Просто на этом же компьютере работает программа дефрагментации диска и она умеет прерывать операцию. Насколько мне известно, перемещать файлы без фрагментации можно только DeviceIoControl и NtFsControlFile.

Попробуйте перемещать файл не за раз, а более мелкими кусочками, тогда время реакции на прерывание будет адекватным.
Re[4]: Остановить выполнение DeviceIoControl
От: Аноним  
Дата: 10.05.06 12:59
Оценка:
MS>Попробуйте перемещать файл не за раз, а более мелкими кусочками, тогда время реакции на прерывание будет адекватным.

Это как? Там ведь в функции DeviceIoControl задаются параметры StartingVcn, StartingLcn и ClusterCount. Если укажешь занятые кластера или кластеров будет меньше чем нужно, то процесс переноса завершится неудачей.
Re[5]: Остановить выполнение DeviceIoControl
От: MShura  
Дата: 10.05.06 13:47
Оценка:
MS>>Попробуйте перемещать файл не за раз, а более мелкими кусочками, тогда время реакции на прерывание будет адекватным.

А>Это как? Там ведь в функции DeviceIoControl задаются параметры StartingVcn, StartingLcn и ClusterCount. Если укажешь занятые кластера или кластеров будет меньше чем нужно, то процесс переноса завершится неудачей.


Можно двигать только часть файла.
StartingVcn — это и есть смещение этой части относительно начала файла.

Пусть файл занимает 13 кластеров.
Указываешь StartingVcn = 0, ClusterCount = 5. Двигаешь в свободное место
Указываешь StartingVcn = 5, ClusterCount = 5. Двигаешь в свободное место
Указываешь StartingVcn = 10, ClusterCount = 3. Двигаешь в свободное место


Если том не залочен, то всегда есть шанс, что в указанном диапазоне [StartingLcn,StartingLcn+ClusterCount) часть кластеров окажутся занятыми, даже если за секунду до этого этот диапазон был свободен. Это надо учитывать.
Re[6]: Остановить выполнение DeviceIoControl
От: StrangerOk  
Дата: 01.04.07 09:54
Оценка:
Здравствуйте, MShura, Вы писали:

MS>>>Попробуйте перемещать файл не за раз, а более мелкими кусочками, тогда время реакции на прерывание будет адекватным.


А>>Это как? Там ведь в функции DeviceIoControl задаются параметры StartingVcn, StartingLcn и ClusterCount. Если укажешь занятые кластера или кластеров будет меньше чем нужно, то процесс переноса завершится неудачей.


MS>Можно двигать только часть файла.

MS>StartingVcn — это и есть смещение этой части относительно начала файла.

MS>Пусть файл занимает 13 кластеров.

MS>Указываешь StartingVcn = 0, ClusterCount = 5. Двигаешь в свободное место
MS>Указываешь StartingVcn = 5, ClusterCount = 5. Двигаешь в свободное место
MS>Указываешь StartingVcn = 10, ClusterCount = 3. Двигаешь в свободное место


MS>Если том не залочен, то всегда есть шанс, что в указанном диапазоне [StartingLcn,StartingLcn+ClusterCount) часть кластеров окажутся занятыми, даже если за секунду до этого этот диапазон был свободен. Это надо учитывать.




я тут читал и у меня появилося вопрос:
-а если файл который мы перемещаем большой и все кластеры раскиданы по винту групами, то как их перемещать? как узнать сколько кластеров в групе?
имея:
2*number of extents array — the vcn and the lcn as pairs
Re[7]: Остановить выполнение DeviceIoControl
От: MShura  
Дата: 01.04.07 18:51
Оценка:
MS>>Можно двигать только часть файла.
MS>>StartingVcn — это и есть смещение этой части относительно начала файла.

MS>>Пусть файл занимает 13 кластеров.

MS>>Указываешь StartingVcn = 0, ClusterCount = 5. Двигаешь в свободное место
MS>>Указываешь StartingVcn = 5, ClusterCount = 5. Двигаешь в свободное место
MS>>Указываешь StartingVcn = 10, ClusterCount = 3. Двигаешь в свободное место

SO>я тут читал и у меня появилося вопрос:

SO>-а если файл который мы перемещаем большой и все кластеры раскиданы по винту групами, то как их перемещать? как узнать сколько кластеров в групе?
SO> имея:
SO>2*number of extents array — the vcn and the lcn as pairs

На приведенном выше примере все 13 кластеров могут быть в одной группе. А с помощью FSCTL_MOVE_FILE мы эту группу можем частями перенести в другое место. Нет никакой необходимости работать целиком с группой.

Посмотрите MSDN к FSCTL_GET_RETRIEVAL_POINTERS
Если вам вернули три группы


ExtentCount = 3;
StartingVcn = AAA;
//             NextVcn  Lcn
Extents[0]  = { BBB,    666 }
Extents[1]  = { CCC,    777 }
Extents[2]  = { EEE,    888 }


То группы кластеров на диске это

- [666, 666+BBB-AAA)
- [777, 777+ССС-BBB)
- [888, 888+EEE-CCC)
Re[8]: Остановить выполнение DeviceIoControl
От: StrangerOk  
Дата: 02.04.07 09:06
Оценка:
Здравствуйте, MShura, Вы писали:

MS>На приведенном выше примере все 13 кластеров могут быть в одной группе. А с помощью FSCTL_MOVE_FILE мы эту группу можем частями перенести в другое место. Нет никакой необходимости работать целиком с группой.


MS>Посмотрите MSDN к FSCTL_GET_RETRIEVAL_POINTERS

MS>Если вам вернули три группы


MS>
MS>ExtentCount = 3;
MS>StartingVcn = AAA;
MS>//             NextVcn  Lcn
MS>Extents[0]  = { BBB,    666 }
MS>Extents[1]  = { CCC,    777 }
MS>Extents[2]  = { EEE,    888 }
MS>


MS>То группы кластеров на диске это


MS>
MS>- [666, 666+BBB-AAA)
MS>- [777, 777+ССС-BBB)
MS>- [888, 888+EEE-CCC)
MS>



Дело в том что мне не возвращают StartingVcn а возвращает только таблицу
NextVcn Lcn
{ AAA, 666 }
{ BBB, 777 }
{ CCC, 888 }
а как мне с нее найти мой StartingVcn или сразу число кластеров в групе или ещо как...

в програме я использовал вырезку кода из одной статьи :http://blogs.msdn.com/jeffrey_wall/archive/2004/09/13/229137.aspx может посмотря на нее вы мне чемто поможете?
Re[9]: Остановить выполнение DeviceIoControl
От: MShura  
Дата: 02.04.07 09:52
Оценка:
SO>Дело в том что мне не возвращают StartingVcn а возвращает только таблицу
SO> NextVcn Lcn
SO>{ AAA, 666 }
SO>{ BBB, 777 }
SO>{ CCC, 888 }
SO>а как мне с нее найти мой StartingVcn или сразу число кластеров в групе или ещо как...

SO>в програме я использовал вырезку кода из одной статьи :http://blogs.msdn.com/jeffrey_wall/archive/2004/09/13/229137.aspx может посмотря на нее вы мне чемто поможете?



По указанной ссылке если все точки не поместятся в буффер размером 64Мгб, то будет ошибка.
В принципе 64Мгб достаточно большое число. В такой буффер поместится описание примерно 4 млн фрагментов.
В худшем случае для этого требуется файл размером более 4 млн кластеров >= 2Гб (кластер 512 байт).
В случае сжатого файла этот размер становится в два раза меньше.
В реальности кластер наверняка будет 4К и фрагменты более одного кластера, так что в буффер 64 Мгб поместится описание фргаментов подавляющего большинства файлов.

В данном случае StartingVcn всегда равен 0.


P.S.
По-моему такой подход (использование мега буффера) неправильный, потому как можно иметь достаточно небольшой буффер для retieval points и получать описание фрагментов порциями.
Re[10]: Остановить выполнение DeviceIoControl
От: StrangerOk  
Дата: 02.04.07 20:10
Оценка:
Здравствуйте, MShura, Вы писали:

MS>По указанной ссылке если все точки не поместятся в буффер размером 64Мгб, то будет ошибка.

MS>В принципе 64Мгб достаточно большое число. В такой буффер поместится описание примерно 4 млн фрагментов.
MS>В худшем случае для этого требуется файл размером более 4 млн кластеров >= 2Гб (кластер 512 байт).
MS>В случае сжатого файла этот размер становится в два раза меньше.
MS>В реальности кластер наверняка будет 4К и фрагменты более одного кластера, так что в буффер 64 Мгб поместится описание фргаментов подавляющего большинства файлов.

MS>В данном случае StartingVcn всегда равен 0.



MS>P.S.

MS>По-моему такой подход (использование мега буффера) неправильный, потому как можно иметь достаточно небольшой буффер для retieval points и получать описание фрагментов порциями.




а что вы можете мне посоветовать в решении моей проблемы, либо что мне передать в ClusterCount используя даный код, либо что вы мне посоветуете переделать или дописать в даном коде (что был в ссылке)?
Re[11]: Остановить выполнение DeviceIoControl
От: MShura  
Дата: 03.04.07 06:50
Оценка:
MS>>P.S.
MS>>По-моему такой подход (использование мега буффера) неправильный, потому как можно иметь достаточно небольшой буффер для retieval points и получать описание фрагментов порциями.


SO>а что вы можете мне посоветовать в решении моей проблемы, либо что мне передать в ClusterCount используя даный код, либо что вы мне посоветуете переделать или дописать в даном коде (что был в ссылке)?


Честно говоря нет никакого желания изучать код по ссылке.

Перемещать можно порциями кратными 16 кластерам:
— Больше шансов отработать FSCTL_MOVE_FILE успешно (ведь с момента, когда вы нашли свободный фрагмент до момента когда начнет отрабатывать FSCTL_MOVE_FILE этот фрагмент может уже перестать быть свободным, а чем больше размер перемещаемого фрагмента, тем больше шансов на такой случай)
Однако если вам удалось залочить том, то можете двигать любыми порциями, однако помните о том, что если вы синхронно ждете завершения операции, то время отклика (на Cancel) может стать неприлично большим.
— Работает и на сжатых файлах
— Если при запросе retieval points StartingVcn кратен 16, то в выходном буффере точки будут начинаться именно с заданного Vcn (Если StartingVcn не кратно 16, то в выходном буффере возможно округление вниз StartingVcn до кратности 16 или 8)
— Можете вообще не пользоваться FSCTL_GET_RETRIEVAL_POINTERS, а пользоваться FSCTL_GET_NTFS_FILE_RECORD и парсить retieval points вручную (так делает dfrgntfs, входящий в состав Windows 2000).

Итого:
Используя мега буффер алгоритм обработки retrieval points упрощается.
Если ваша программа не предназначена для серверов, то решение вполне уместное.
Re[12]: Остановить выполнение DeviceIoControl
От: latemic Украина  
Дата: 14.12.07 07:26
Оценка:
Здравствуйте, MShura, Вы писали:

MS>Перемещать можно порциями кратными 16 кластерам:


Не совсем так

[msdn]If the file to be moved is a sparse or compressed file, the granularity of the move is 16 clusters; otherwise, the granularity is one cluster.
[/msdn]

По поводу кода по сылке, то он не представляет особого интереса. Это всего лишь .NET обвёртка для Defrag API. Автор верно заметил, что он не гарантирует работу этого кода
"Если нельзя, но очень хочется... то можно"
Re[13]: Остановить выполнение DeviceIoControl
От: MShura  
Дата: 14.12.07 12:09
Оценка:
MS>>Перемещать можно порциями кратными 16 кластерам:

L>Не совсем так


L>[msdn]If the file to be moved is a sparse or compressed file, the granularity of the move is 16 clusters; otherwise, the granularity is one cluster.

L>[/msdn]

Я же не писал, что порции обязаны быть кратным 16.
Было написано, что с кратностью 16 будет работать и на сжатых (т.е. на любых) файлах.
sparse — это частный случай compressed за одним маленьким исключением: его кратность помимо 16 может быть 2,4,8 кластеров.
Re[14]: Остановить выполнение DeviceIoControl
От: Аноним  
Дата: 14.12.07 12:38
Оценка:
Здравствуйте, MShura, Вы писали:

MS>>>Перемещать можно порциями кратными 16 кластерам:


L>>Не совсем так


L>>[msdn]If the file to be moved is a sparse or compressed file, the granularity of the move is 16 clusters; otherwise, the granularity is one cluster.

L>>[/msdn]

MS>Я же не писал, что порции обязаны быть кратным 16.

MS>Было написано, что с кратностью 16 будет работать и на сжатых (т.е. на любых) файлах.
MS>sparse — это частный случай compressed за одним маленьким исключением: его кратность помимо 16 может быть 2,4,8 кластеров.
Это не совсем очевидно из контекста, поэтому я и сделал ремарку. Ни в коем случае не хотел сказать что вы этого не знаете, посто уточнить для людей которые будуть пользоваться этой информацией.
Например, здесь автор утверждает совершенно уверенно что кратность перемещаемых фрагментов должна быть 16 кластеров.
Re[3]: Остановить выполнение DeviceIoControl
От: Maxim S. Shatskih Россия  
Дата: 14.12.07 17:43
Оценка:
А>Это как? У кого-то возвращается управление, а у кого-то нет. Просто на этом же компьютере работает программа дефрагментации диска и она умеет прерывать операцию.

она делает много мелких FSCTL_MOVE_FILE, и прервать можно только между ними.
Занимайтесь LoveCraftом, а не WarCraftом!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.