支持 BypassIO 操作
从 Windows 11 开始,所有微型筛选器都应添加对 BypassIO 操作的支持。 通过调用 FltFsControlFile 或 ZwFsControlFile 来请求 BypassIO 操作:
- FSCTL_MANAGE_BYPASS_IO控件代码。
- InputBuffer 参数指向FS_BPIO_INPUT结构中的请求特定信息。
- 由 OutputBuffer 参数指向的调用方分配FS_BPIO_OUTPUT结构,其中系统返回操作的结果。
本页提供了每个 BypassIO 操作的详细信息。 操作请求在 FS_BPIO_INPUT 的操作成员中指定为FS_BPIO_OPERATIONS值。
有关 BypassIO 的详细信息,请参阅 有关筛选器的 BypassIO。
FS_BPIO_OP_ENABLE请求
此请求可能来自用户或内核模式。 目前不支持对非缓存 写入 的 BypassIO。
FS_BPIO_OP_ENABLE 系统为给定文件启用 BypassIO 的请求,这意味着驱动程序可能不会看到该文件的所有非缓存读取。
BypassIO 是每个文件开放的概念;也就是说, FS_BPIO_OP_ENABLE 请求仅影响与启用请求关联的文件对象,并且不会更改同一文件或流上其他打开的行为。 如果发送对同一文件对象的多个启用请求,则只有第一个请求有意义,并且将忽略所有后续请求。
在驱动程序的预操作回调中:
如果驱动程序可以支持给定文件的 BypassIO,则应将请求转发到堆栈中。
如果驱动程序不支持给定文件的 BypassIO,则应使用以下信息调用 FltVetoBypassIo:
- 驱动程序的名称,该名称位于 FltObjects 参数指向的FLT_RELATED_OBJECTS结构中。
- NTSTATUS 错误代码,描述在 OperationStatus 参数中否决启用请求的原因。
- 一个唯一的描述性字符串,其中包含有关在 FailureReason 参数中否决启用请求的原因的详细信息。
FltVetoBypassIo 编写驱动程序名称、错误代码和字符串,描述微型筛选器在FS_BPIO_OUTPUT结构中否决启用请求的原因,并将状态、筛选器提供的原因和筛选器名称的 ETW 事件写入事件日志。
如果 FltVetoBypassIo 成功,小筛选器应使用 STATUS_SUCCESS 完成FSCTL_MANAGE_BYPASS_IO;否则,它应返回 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_DISABLE FSCTL_MANAGE_BYPASS_IO操作发送到文件系统堆栈的顶部。 出现此情况的一个示例是收到加密此文件的请求的加密驱动程序。
如果驱动程序收到 FS_BPIO_OP_DISABLE但 当前未启用 BypassIO,则它应忽略请求。 如果在当前未启用 BypassIO 的文件上发送此操作,则应将其忽略。
此操作不应失败。
FS_BPIO_OP_QUERY请求
此请求可能来自用户或内核模式。
筛选器应处理类似于FS_BPIO_OP_ENABLE操作的FS_BPIO_OP_QUERY请求,调用 FltVetoBypassIo 以适当方式使用与前面所述的相应参数中所述的诊断信息一样否决。 主要区别在于驱动程序在 QUERY 期间未进入 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_PAUSE FSCTL_MANAGE_BYPASS_IO操作发送到卷堆栈顶部,以通知文件系统停止在此卷的卷和存储堆栈上执行 BypassIO。 文件系统从此卷中清空所有活动的 BypassIO 操作,然后返回。 然后,卷堆栈驱动程序可以处理外部请求。
所有已启用 BypassIO 的活动文件随后停止执行存储堆栈级 BypassIO 操作。 此操作请求:
- 可以在卷句柄或给定卷的任何文件句柄上发送。
- 可以多次发送到同一卷。
- 如果卷上没有启用了 BypassIO 的文件,则可以发送。
BypassIO 继续在文件系统堆栈上运行。
此操作不应失败。
卷堆栈暂停示例
BitLocker 是需要对卷启用加密时使用该操作的组件的示例。
另一个示例是以下方案:假设 Volsnap 允许在没有活动卷快照的卷上启用 BypassIO。 后来,发出了创建卷快照的请求。 Volsnap 在继续操作之前执行以下操作:
- 将 FS_BPIO_OP_VOLUME_STACK_PAUSE 操作发送到堆栈顶部,请求系统禁用卷堆栈上的 BypassIO。 每次创建新快照时,都会执行此操作。 成功返回后,现在禁用 BypassIO 并在给定卷上清空。
- 处理快照创建请求
然后,Volsnap 必须否决此卷上所有未来的 BPIO_OP_ENABLE 和 BPIO_OP_QUERY 请求。
FS_BPIO_OP_VOLUME_STACK_RESUME请求
卷堆栈驱动程序将此 FSCTL 操作发送到文件系统,以恢复给定卷上的 BypassIO 处理。 当导致驱动程序发送FS_BPIO_OP_VOLUME_STACK_PAUSE不再处于活动状态的方案时,它会发送此操作。 即使当前未启用或暂停 BypassIO,也可以发送此操作。
此请求可能来自用户或内核模式。
此操作不应失败。
卷堆栈恢复示例
使用前面所述的卷堆栈暂停方案,假设该卷不再具有任何活动快照。 只有在最后一个快照消失后,Volsnap 才会发送 FS_BPIO_OP_VOLUME_STACK_RESUME 。
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请求
此请求可能来自用户或内核模式。 文件系统返回有关 FS_BPIO_INFO 结构中卷的 BypassIO 的信息。