Разрыв оппортунистических блокировок
После
При предоставлении опортюнитивной блокировки система откладывает обработку запрашивающего IRP. При разрыве оплока запрос IRP ожидающего оплока завершается со статусом STATUS_SUCCESS. Для блокировок уровня 1, пакетных и фильтрационных блокировок элемент IoStatus.Information в IRP устанавливается для указания уровня, до которого снижается блокировка. Ниже приведены следующие уровни:
FILE_OPLOCK_BROKEN_TO_NONE: оплок был нарушен, и в потоке нет актуального оплока. Оплок, как говорят, будет "переведен в состояние None".
FILE_OPLOCK_BROKEN_TO_LEVEL_2: Текущий файло-перехват (уровень 1 или Batch) был преобразован в файло-перехват уровня 2. Фильтрация оплоков никогда не прерывается до уровня 2, они всегда разрываются на уровень None.
Для блокировок типа Read-Handle, Read-Write и Read-Write-Handle, уровень, на который прерывается блокировка, описывается как сочетание одного или нескольких флагов OPLOCK_LEVEL_CACHE_READ, OPLOCK_LEVEL_CACHE_HANDLE или OPLOCK_LEVEL_CACHE_WRITE в элементе NewOplockLevel структуры REQUEST_OPLOCK_OUTPUT_BUFFER, переданной в качестве параметра lpOutBuffer функции DeviceIoControl. Аналогичным образом FltFsControlFile и ZwFsControlFile можно использовать для запроса оплоков Windows 7 в режиме ядра. Дополнительные сведения см. в FSCTL_REQUEST_OPLOCK.
Если пакет oplock системы нарушает уровень 1, пакетную службу, фильтр, чтение и запись, чтение и дескриптор записи или при определенных обстоятельствах Read-Handle oplock:
- Пакет oplock завершает отложенный запрос oplock’а IRP.
- Операция, которая вызвала нарушение оплока, сама по себе задерживается.
Диспетчер ввода-вывода блокирует операцию, вместо возврата STATUS_PENDING, если операция:
- Выдается на синхронном обработчике.
- Это IRP_MJ_CREATE, который всегда синхронен.
Менеджер ввода-вывода ожидает подтверждения от владельца oplock, чтобы сообщить системе управления oplock, что они завершили обработку, и это безопасно для продолжения отложенной операции. Эта задержка позволяет владельцу oplock вернуть поток в согласованное состояние до продолжения текущей операции. Система будет ждать бесконечно, чтобы получить подтверждение, так как нет тайм-аута. Владелец оплока обязан своевременно признать нарушение. IRP отложенной операции переводится в состояние, допускающее отмену. Если приложение или драйвер, который ожидает, завершает свою работу, пакет oplock немедленно завершает IRP со статусом STATUS_CANCELLED.
IRP_MJ_CREATE IRP может указать параметр создания FILE_COMPLETE_IF_OPLOCKED, чтобы избежать блокировки в рамках подтверждения останова oplock. Этот параметр сообщает пакету oplock не блокировать создание IRP до получения подтверждения останова oplock. Вместо этого создание разрешено продолжить. Если успешное создание приводит к утрате оплока, возвращаемый код будет STATUS_OPLOCK_BREAK_IN_PROGRESS, а не STATUS_SUCCESS. Флаг FILE_COMPLETE_IF_OPLOCKED обычно используется для предотвращения взаимоблокировок. Например, если клиент владеет оплоком в потоке, а тот же клиент позже открывает тот же поток, клиент будет блокировать ожидание того, чтобы подтвердить разрыв оплока. В этом сценарии использование флага FILE_COMPLETE_IF_OPLOCKED позволяет избежать взаимоблокировки.
Файловая система NTFS инициирует разрывы блокировок oplock для Batch и Filter перед проверкой нарушений совместного доступа. Поэтому создание указанного FILE_COMPLETE_IF_OPLOCKED может завершиться сбоем STATUS_SHARING_VIOLATION, но по-прежнему приводит к прерыванию блокировки пакетной службы или фильтра. В этом случае для элемента сведений структуры IO_STATUS_BLOCK задано значение FILE_OPBATCH_BREAK_UNDERWAY, чтобы разрешить вызывающему объекту обнаруживать этот случай.
Для оплока Read-Handle и оплока чтенияWrite-Handle разрыв оплока инициируется после того, как NTFS проверяет и обнаруживает нарушение общего доступа. Эта последовательность дает владельцам oplock возможность закрыть свои дескрипторы и освободить место, тем самым позволяя избежать возвращения нарушения общего доступа пользователю. Это также позволяет избежать безоговорочного нарушения оплока в случаях, когда дескриптор, который кэширует оплок, не конфликтует с новым процессом создания.
Когда оплоки уровня 2 и чтения, а также в некоторых случаях Read-Handle, разрываются, система не ожидает подтверждения. Причина заключается в том, что в потоке не должно быть кэшированного состояния, которое необходимо восстановить в файле, прежде чем разрешить другим клиентам доступ к нему.
Существуют определенные операции файловой системы, которые проверяют текущее состояние оплока, чтобы определить, требуется ли сломать оплок. В следующих статьях, относящихся к операциям, описывается, что вызывает разрыв оплока, что определяет уровень, до которого происходит разрыв оплока, и требуется ли подтверждение разрыва.
- IRP_MJ_CREATE
- IRP_MJ_READ
- IRP_MJ_WRITE
- IRP_MJ_CLEANUP
- IRP_MJ_LOCK_CONTROL
- IRP_MJ_SET_INFORMATION
- IRP_MJ_FILE_SYSTEM_CONTROL
- FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION (синхронизация секции)
Для разрыва оплока Windows 7 требуется подтверждение, если флаг REQUEST_OPLOCK_OUTPUT_FLAG_ACK_REQUIRED установлен в элементе Flags структуры REQUEST_OPLOCK_OUTPUT_BUFFER, переданной в качестве выходного параметра DeviceIoControl(lpOutBuffer), FltFsControlFile(OutBuffer) или ZwFsControlFile(OutBuffer). Дополнительные сведения см. в FSCTL_REQUEST_OPLOCK.
Перечисленные статьи по каждой операции описывают сведения о том, когда нарушение оплок Read-Handle приводит к ожиданию выполнения операции, которая привела к этому нарушению. Например, статья IRP_MJ_CREATE содержит ассоциированные Read-Handle подробные сведения.