Поделиться через


Поддержка операций BypassIO

Начиная с Windows 11, все минифильтры должны добавлять поддержку операций BypassIO. Операции BypassIO запрашиваются путем вызова FltFsControlFile или ZwFsControlFile с помощью:

На этой странице содержатся сведения о каждой операции BypassIO. Запрос операции указывается в качестве значения FS_BPIO_OPERATIONS в элементе ОперацииFS_BPIO_INPUT.

Дополнительные сведения о BypassIO см. в разделе BypassIO для фильтров.

запрос FS_BPIO_OP_ENABLE

Этот запрос может поступать из пользовательского режима или режима ядра. BypassIO для операций без кэширования записи в настоящее время не поддерживается.

FS_BPIO_OP_ENABLE запрашивает, чтобы система включила BypassIO для данного файла, что означает, что драйвер может не видеть все несеченные операции чтения для этого файла.

BypassIO — это концепция для каждого открытия файла; то есть запрос FS_BPIO_OP_ENABLE влияет только на объект файла, связанный с запросом на включение, и не изменяет поведение других открытий в том же файле или потоке. Если к одному и тому же объекту файла отправляется несколько запросов на включение, то имеет смысл только первый запрос, а все последующие запросы игнорируются.

В обратном вызове драйвера до операции:

  • Если драйвер может поддерживать BypassIO для заданного файла, он должен перенаправить запрос вниз по стеку.

  • Если драйвер не поддерживает BypassIO для данного файла, он должен вызвать FltVetoBypassIo со следующими сведениями:

    • Имя драйвера, которое находится в структуре FLT_RELATED_OBJECTS , на которую указывает параметр FltObjects .
    • Код ошибки NTSTATUS, описывающий причину наложения вето на запрос на включение в параметре OperationStatus .
    • Уникальная описательная строка с подробными сведениями о том, почему вы нажали вето на запрос на включение в параметре FailureReason .

    FltVetoBypassIo записывает имя драйвера, код ошибки и строку, описывающую, почему минифильтр нажал вето на запрос на включение в структуре FS_BPIO_OUTPUT и записывает событие трассировки событий Windows с состоянием, причиной, предоставленной фильтром, и именем фильтра в журнал событий.

Минифильтр должен завершить FSCTL_MANAGE_BYPASS_IO с STATUS_SUCCESS, если FltVetoBypassIo успешно выполняется; В противном случае он должен вернуть ошибку, возвращенную FltVetoBypassIo .

Во время после операции драйвер может увидеть, способны ли все драйверы под ним поддерживать BypassIO. Если да, драйвер должен сохранить любое необходимое состояние для файла и продолжить обработку завершения. Фильтр и файловая система отвечают за поддержание состояния для правильной обработки запросов, которые могут быть несовместимы с состоянием с поддержкой BypassIO.

Примечание

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

Файловая система автоматически наволяет вето на запрос на включение BypassIO для следующих типов файлов:

  • Каталоги (альтернативные потоки данных в каталоге могут использовать BypassIO)
  • Тома (открывается DASD)
  • Файлы со сжатием NTFS
  • Файлы с расширением NTFS
  • Разреженные файлы
  • Файлы подкачки
  • Все файлы на томах DAX

Большинству фильтров не требуется поддерживать состояние, включающее BypassIO в определенном потоке. Вместо этого эти сведения можно запросить, вызвав FsRtlGetBypassIoOpenCount.

FS_BPIO_OP_ENABLE пример: фильтр шифрования

Когда фильтр шифрования получает FS_BPIO_OP_ENABLE операцию с файлом:

  • Если файл уже зашифрован, фильтр должен вызвать FltVetoBypassIo , чтобы наказать вето на операцию BypassIO, указав соответствующее состояние и диагностическое сообщение, например:

    • OpStatus = STATUS_NOT_SUPPORTED_WITH_ENCRYPTION
    • FailureReason = "Зашифрованный файл не поддерживается"
  • Если файл в настоящее время не зашифрован, фильтр должен разрешить BypassIO. При последующем запросе на шифрование этого файла фильтр может использовать операцию FS_BPIO_OP_STREAM_PAUSE для отключения BypassIO.

запрос FS_BPIO_OP_DISABLE

Этот запрос может поступать из пользовательского режима или режима ядра. Это позволяет драйверу очистить любое связанное состояние BypassIO.

Если драйвер ранее разрешал включение BypassIO для этого файла и теперь должен отключить поддержку BypassIO для файла, он должен отправить операцию FS_BPIO_OP_DISABLEFSCTL_MANAGE_BYPASS_IO в верхнюю часть стека файловой системы с помощью связанного дескриптора. Примером возникновения этого условия является драйвер шифрования, который получил запрос на шифрование этого файла.

Если драйвер получает FS_BPIO_OP_DISABLE но в настоящее время не включает BypassIO, он должен игнорировать запрос. Если эта операция отправляется в файл, для которых в настоящее время не включено BypassIO, ее следует игнорировать.

Эта операция не должна завершаться сбоем.

запрос FS_BPIO_OP_QUERY

Этот запрос может поступать из пользовательского режима или режима ядра.

Фильтр должен обрабатывать запрос FS_BPIO_OP_QUERY аналогично операции FS_BPIO_OP_ENABLE , вызывая FltVetoBypassIo , чтобы налагать вето соответствующим образом с теми же диагностическими сведениями, которые описаны ранее в соответствующих параметрах. Основное отличие заключается в том, что драйвер не переходит в состояние BypassIO ENABLE во время запроса.

Операция FS_BPIO_OP_QUERY может быть отправлена в дескрипторах каталога и тома ( запрос FS_BPIO_OP_ENABLE не может быть отправлен в дескрипторах каталога или тома).

Пример запроса: фильтр шифрования

Когда фильтр шифрования получает FS_BPIO_OP_QUERY операцию с файлом:

  • Если файл уже зашифрован, фильтр должен вызвать FltVetoBypassIo , чтобы наказать вето на операцию BypassIO, предоставляя соответствующее состояние и диагностическое сообщение, например:

    • OpStatus = STATUS_NOT_SUPPORTED_WITH_ENCRYPTION
    • FailureReason = "Зашифрованный файл не поддерживается"
  • Если файл в настоящее время не зашифрован, фильтр должен успешно выполнить запрос.

запрос FS_BPIO_OP_VOLUME_STACK_PAUSE

Этот запрос может поступать из пользовательского режима или режима ядра.

Если драйвер стека тома ранее разрешал включение BypassIO на томе и теперь должен остановить BypassIO (например, из-за какого-то внешнего запроса), драйвер должен отправить FS_BPIO_OP_VOLUME_STACK_PAUSEFSCTL_MANAGE_BYPASS_IO операцию в верхнюю часть стека томов, чтобы уведомить файловую систему о прекращении выполнения BypassIO в стеках тома и хранилища. Файловая система истощает все активные операции BypassIO из этого тома, а затем возвращает . Затем драйвер стека томов может обработать внешний запрос.

После этого все активные файлы с поддержкой BypassIO прекратят выполнение операций BypassIO уровня стека хранилища. Этот запрос операции:

  • Может быть отправлено на дескриптор тома или любой дескриптор файла для заданного тома.
  • Может быть отправлено несколько раз на один том.
  • Можно отправить, если на томе нет файлов с поддержкой BypassIO.

BypassIO продолжает работать в стеке файловой системы.

Эта операция не должна завершаться сбоем.

Пример приостановки стека томов

BitLocker — это пример компонента, который использует эту операцию, когда ему нужно включить шифрование на томе.

Другим примером является следующий сценарий: предположим, что Volsnap разрешил включить BypassIO на томе без активных моментальных снимков тома. Позже был сделан запрос на создание тома snapshot. Перед продолжением Volsnap выполняет следующие действия:

  • Отправляет операцию FS_BPIO_OP_VOLUME_STACK_PAUSE в верхнюю часть стека с запросом на отключение BypassIO в стеке томов. Это происходит при каждом создании нового snapshot. После успешного возврата BypassIO отключается и истощается на заданном томе.
  • Обрабатывает запрос на создание snapshot

Затем Volsnap должен наказать вето на все будущие BPIO_OP_ENABLE и BPIO_OP_QUERY запросы на этот том.

запрос FS_BPIO_OP_VOLUME_STACK_RESUME

Драйвер стека томов отправляет эту операцию FSCTL в файловую систему, чтобы возобновить обработку BypassIO на заданном томе. Она отправляет эту операцию, когда сценарий, который вызвал отправку драйвером FS_BPIO_OP_VOLUME_STACK_PAUSE , больше не активен. Эта операция может быть отправлена, даже если BypassIO в настоящее время не включена или приостановлена.

Этот запрос может поступать из пользовательского режима или режима ядра.

Эта операция не должна завершаться сбоем.

Пример возобновления стека томов

Используя описанный выше сценарий приостановки стека томов, предположим, что в томе больше нет активных моментальных снимков. Вольснап отправит FS_BPIO_OP_VOLUME_STACK_RESUME только после того, как уйдет последний snapshot.

запрос FS_BPIO_OP_STREAM_PAUSE

Фильтр может отправить операцию FS_BPIO_OP_STREAM_PAUSE для приостановки BypassIO в потоке. Этот запрос может поступать из пользовательского режима или режима ядра. Все активные файлы с поддержкой BypassIO перестают выполнять операции BypassIO.

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

Перед возвратом файловой системы она приостанавливает все открытые в потоке дескрипторы BypassIO и завершает все активные операции BypassIO в потоке. Эти действия гарантируют, что при возврате фильтр может выполнить операцию с файлом, которую он должен выполнить.

Эту операцию можно отправить несколько раз в один поток. Файловая система игнорирует его, если он отправляется в поток, который в настоящее время не поддерживает BypassIO.

Если фильтр выполняет операцию приостановки потока, BypassIO продолжает работу в стеке тома и хранилища.

Эта операция не должна завершаться сбоем.

Пример приостановки потока: фильтр шифрования

Предположим, что фильтр шифрования позволяет включить BypassIO в потоке, который затем не был зашифрован, но позже получил запрос на шифрование этого потока.

Перед продолжением работы фильтра шифрования он должен вызвать FsRtlGetBypassIoOpenCount , чтобы определить, активен ли BypassIO в этом потоке. Если да, фильтр шифрования отправляет FS_BPIO_OP_STREAM_PAUSE операцию с запросом на отключение BypassIO. После успешного возвращения BypassIO отключается и очищается, поэтому фильтр может безопасно выполнять запрос шифрования. Чтобы исключить возможные условия гонки, фильтр должен наказать вето на все будущие FS_BPIO_OP_ENABLE и FS_BPIO_OP_QUERY запросы в этом зашифрованном потоке.

запрос FS_BPIO_OP_STREAM_RESUME

Если сценарий, который привел к отправке фильтром операции FS_BPIO_OP_STREAM_PAUSE , больше не существует, фильтр отправляет FS_BPIO_OP_STREAM_RESUME операцию в файловую систему, чтобы возобновить обработку BypassIO данного потока. Этот запрос может поступать из пользовательского режима или режима ядра.

Если эта операция отправляется, когда BypassIO не включена или приостановлена, она игнорируется.

Приостановка и возобновление не учитываются. Вместо этого в резюме файловая система отправляет запрос FS_BPIO_OP_QUERY в верхнюю часть стека файловой системы, чтобы определить, блокируются ли все оставшиеся фильтры. Файловая система возобновляет BypassIO, только если все фильтры в стеке не блокируют BypassIO.

Эта операция не должна завершаться сбоем.

Пример возобновления потока: фильтр шифрования

Используя описанный выше сценарий FS_BPIO_OP_STREAM_PAUSE , предположим, что файл, который ранее был зашифрован после вызова FS_BPIO_OP_STREAM_PAUSE , больше не зашифрован. Затем фильтр должен отправить операцию FS_BPIO_OP_STREAM_RESUME , чтобы разрешить BypassIO возобновить работу в этом потоке.

запрос FS_BPIO_OP_GET_INFO

Этот запрос может поступать из пользовательского режима или режима ядра. Файловая система возвращает сведения о BypassIO для тома в структуре FS_BPIO_INFO .