Solicitud y concesión de bloqueos oportunistas
Cuando el redirector de red accede a archivos en servidores remotos, solicita el oplock del servidor remoto. Las aplicaciones cliente solicitan directamente los oplocks únicamente cuando el bloqueo está destinado a un archivo en el servidor local.
Los Bloqueos oportunistas se solicitan a través de FSCTL. Las siguientes FSCTL se utilizan para los distintos tipos de bloqueo oportunista, que pueden emitir tanto las aplicaciones en modo usuario como los controladores en modo kernel.
- Para solicitar bloqueos oportunistas de Windows 7:
- Para solicitar bloqueos oportunistas heredados:
Para solicitar un bloqueo oportunista de Windows 7 en modo usuario, llame a DeviceIoControl:
- Establezca dwIoControlCode en FSCTL_REQUEST_OPLOCK.
- Pase un puntero a una estructura REQUEST_OPLOCK_INPUT_BUFFER en el parámetro lpInBuffer.
- Consulte la documentación de esa estructura para obtener información sobre cómo formatear la solicitud de oplock.
- Pase un puntero a una estructura REQUEST_OPLOCK_OUTPUT_BUFFER en el parámetro lpOutBuffer.
Para obtener más información, consulte FSCTL_REQUEST_OPLOCK.
Si se puede conceder el bloqueo oportunista solicitado, DeviceIoControl devuelve FALSE y GetLastError devuelve ERROR_IO_PENDING. Por esta razón, nunca se conceden bloqueos oportunistas para E/S sincrónica. La operación solapada no se completa hasta que se rompe el bloqueo oportunista. Una vez completada la operación, el REQUEST_OPLOCK_OUTPUT_BUFFER contendrá información sobre la rotura del bloqueo oportunista.
Si no se puede conceder el bloqueo oportunista, el sistema de archivos devuelve un código de error apropiado. Los códigos de error devueltos con más frecuencia son ERROR_OPLOCK_NOT_GRANTED y ERROR_INVALID_PARAMETER.
Para solicitar bloqueos oportunistas de Windows 7 en modo kernel:
Un minifiltro de sistema de ficheros debe utilizar FltAllocateCallbackData y rellenar el campo FLT_CALLBACK_DATA así:
- Establece su campo Iopb->MajorFunction en IRP_MJ_FILE_SYSETM_CONTROL.
- Establece su campo Iopb->MinorFunction en IRP_MN_USER_FS_REQUEST.
- Establece su miembro Iopb->Parameters.FileSystemControl.Buffered.FsControlCode a FSCTL_REQUEST_OPLOCK.
- Asignar un búfer cuyo tamaño sea igual al mayor de REQUEST_OPLOCK_INPUT_BUFFER o REQUEST_OPLOCK_OUTPUT_BUFFER.
- Establece el miembro > del FLT_CALLBACK_DATA asignado para que apunte a ese búfer.
- Establezca los campos > y > de FLT_CALLBACK_DATA asignados al tamaño de ese búfer.
Consulte la documentación de la estructura REQUEST_OPLOCK_INPUT_BUFFER para obtener información sobre cómo dar formato a la solicitud de bloqueo oportunista.
A continuación, el minifiltro del sistema de ficheros debe llamar a FltPerformAsynchronousIo, pasando el FLT_CALLBACK_DATA asignado como parámetro CallbackData.
Si se puede conceder el bloqueo oportunista solicitado, la llamada FltPerformAsynchronousIo devuelve STATUS_PENDING. Por esta razón, nunca se conceden bloqueos oportunistas para E/S sincrónica. La operación no se completa hasta que se rompe el bloqueo oportunista. Una vez completada la operación, el REQUEST_OPLOCK_OUTPUT_BUFFER contendrá información sobre la rotura del bloqueo oportunista.
Si no se puede conceder el bloqueo oportunista, el sistema de archivos devuelve un código de error apropiado. Los códigos de error devueltos con más frecuencia son STATUS_OPLOCK_NOT_GRANTED y STATUS_INVALID_PARAMETER.
Otros tipos de controladores pueden llamar a ZwFsControlFile:
- Establece FsControlCode a FSCTL_REQUEST_OPLOCK.
- Pase un puntero a una estructura REQUEST_OPLOCK_INPUT_BUFFER en el parámetro InputBuffer y establezca el parámetro InputBufferLength en el tamaño de ese búfer.
- Pasa un puntero a una estructura REQUEST_OPLOCK_OUTPUT_BUFFER en el parámetro OutputBuffer y establece el parámetro OutputBufferLength al tamaño de ese buffer.
Consulte la documentación de la estructura REQUEST_OPLOCK_INPUT_BUFFER para obtener información sobre cómo dar formato a la solicitud de bloqueo oportunista.
Si se puede conceder el bloqueo oportunista solicitado, la llamada ZwFsControlFile devuelve STATUS_PENDING. Por esta razón, nunca se conceden bloqueos oportunistas para E/S sincrónica. La operación no se completa hasta que se rompe el bloqueo oportunista. Una vez completada la operación, el REQUEST_OPLOCK_OUTPUT_BUFFER contendrá información sobre la rotura del bloqueo oportunista.
Si no se puede conceder el bloqueo oportunista, el sistema de archivos devuelve un código de error apropiado. Los códigos de error devueltos con más frecuencia son STATUS_OPLOCK_NOT_GRANTED y STATUS_INVALID_PARAMETER.
Atomic create-with-oplock no es un tipo de bloqueo oportunista. En su lugar, es un procedimiento que permite que las operaciones abiertas eviten provocar infracciones del modo de uso compartido en el intervalo de tiempo entre abrir un archivo y recibir un bloqueo oportunista. Con los bloqueos oportunistas heredados, se requieren bloqueos oportunistas de filtro y apertura de dos identificadores. Con los bloqueos oportunistas de Windows 7, una aplicación o controlador puede solicitar cualquier tipo de bloqueo oportunista utilizando este procedimiento y solo necesita abrir un identificador.
Para realizar el procedimiento atomic create-with-oplock, debe:
- Usar FltCreateFileEx2 o ZwCreateFile, según corresponda, para abrir el archivo. En el parámetro CreateOptions pasar la marca FILE_OPEN_REQUIRING_OPLOCK. Puede establecer los parámetros DesiredAccess y ShareAccess según sea necesario. Por ejemplo, en el parámetro DesiredAccess establezca GENERIC_READ para que pueda leer el archivo, y en el parámetro ShareAccess, establezca las banderas FILE_SHARE_READ | FILE_SHARE_DELETE para permitir que otros usuarios lean, cambien el nombre o marquen el archivo para su eliminación mientras lo tiene abierto.
- Use el código de control FSCTL_REQUEST_OPLOCK para solicitar un interbloqueo en el objeto o identificador de archivo resultante, como se describe en Solicitud de un interbloqueo en modo kernel.
No realice ninguna operación del sistema de archivos en el archivo entre los pasos 1 y 2. Si lo hace, puede provocar interbloqueos.
El bloqueo oportunista más común para solicitar usando este procedimiento es el tipo Read-Handle. Esto le permite permitir a otros llamadores tanto acceso concurrente como sea posible, mientras que todavía le permite ser notificado si necesita cerrar su identificador para evitar causar una violación de compartición a un open en conflicto.
El bloqueo de filtro heredado también permite a una aplicación "retirarse" cuando otras aplicaciones/clientes intentan acceder al mismo flujo, pero es menos flexible que el método atómico de creación con bloqueo. Este mecanismo permite que una aplicación acceda a un flujo sin provocar que otros accesores del flujo reciban violaciones de uso compartido al intentar abrir el flujo. Para evitar violaciones de compartición, se debe utilizar el siguiente procedimiento de tres pasos para solicitar un bloqueo de filtro:
Abra el archivo con un acceso requerido de FILE_READ_ATTRIBUTES y un modo compartido de FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE. El identificador abierto en este paso no hará que otras aplicaciones reciban infracciones de uso compartido porque solo está abierto para el acceso a atributos (FILE_READ_ATTRIBUTES) y no para el acceso a datos (FILE_READ_DATA). Este identificador es adecuado para solicitar el bloqueo de filtro, pero no para realizar E/S en el flujo de datos.
Solicite un bloqueo oportunista de filtro (FSCTL_REQUEST_FILTER_OPLOCK) en el identificador del paso 1. El bloqueo oportunista concedido en este paso permite al poseedor del bloqueo oportunista «salir del paso» sin causar una violación de compartición a otra aplicación que intente acceder al flujo.
Vuelva a abrir el archivo para el acceso de lectura. El identificador abierto en este paso permite al poseedor del bloqueo oportunista realizar E/S en el flujo.
El sistema de archivos NTFS proporciona una optimización para este procedimiento a través de la opción de creación FILE_RESERVE_OPFILTER. Si esta marca se especifica en el paso 1 del procedimiento anterior, permite que el sistema de archivos rechace la solicitud de creación con STATUS_OPLOCK_NOT_GRANTED si el sistema de archivos puede determinar que el paso 2 fallará. Si el paso 1 se realiza correctamente, no hay ninguna garantía de que el paso 2 vaya a realizar correctamente, aunque se haya especificado FILE_RESERVE_OPFILTER para la solicitud de creación.
La siguiente tabla identifica las condiciones necesarias para conceder un bloqueo oportunista.
Tipo de solicitud | Condiciones |
---|---|
Nivel 1 Filtro Batch |
Solo se concede si se cumplen todas las condiciones siguientes:
Si el estado actual del bloqueo oportunista es:
|
Nivel 2 |
Solo se concede si se cumplen todas las condiciones siguientes:
Si el estado actual del bloqueo oportunista es:
|
Leer |
Solo se concede si se cumplen todas las condiciones siguientes:
Si el estado actual del bloqueo oportunista es:
|
Read-Handle |
Solo se concede si se cumplen todas las condiciones siguientes:
Si el estado actual del bloqueo oportunista es:
|
Lectura y escritura |
Solo se concede si se cumplen todas las condiciones siguientes:
Si el estado actual del bloqueo oportunista es:
|
Read-Write-Handle |
Solo se concede si se cumple lo siguiente:
Si el estado actual del bloqueo oportunista es:
|
Nota
Los bloqueos oportunistas de Read y Nivel 2 pueden coexistir en el mismo flujo, y los bloqueos oportunistas de Read y Read-Handle pueden coexistir, pero los bloqueos oportunistas de Nivel 2 y Read-Handle no pueden coexistir.