Interrupción de bloqueos oportunistas
Una vez solicitado y concedido un bloqueo oportunista, el propietario de ese bloqueo oportunista tiene acceso al flujo en función del tipo de bloqueo oportunista que se haya solicitado. Si la operación recibida no es compatible con el interbloqueo actual, el sistema interrumpe el interbloqueo.
Cuando se concede un bloqueo oportunista, el sistema pone en espera el IRP solicitante. Cuando se interrumpe un bloqueo oportunista, el IRP de la solicitud del bloqueo oportunista pendiente se completa con STATUS_SUCCESS. En el caso de los bloqueos oportunistas de nivel 1, lote y filtro, el miembro IoStatus.Information del IRP se establece para indicar el nivel en el que se interrumpe el bloqueo oportunista. Estos niveles son:
FILE_OPLOCK_BROKEN_TO_NONE: el bloqueo oportunista se ha interrumpido y no hay ningún bloqueo oportunista actual en la secuencia. Se dice que el bloqueo oportunista se ha "interrumpido en Ninguno".
FILE_OPLOCK_BROKEN_TO_LEVEL_2: el bloqueo oportunista actual (nivel 1 o lote) se convirtió en un bloqueo oportunista de nivel 2. Los bloqueos oportunistas de filtro nunca se interrumpen en el nivel 2, siempre se interrumpen en Ninguno.
En el caso de los bloqueos oportunistas Read-Handle, Read-Write y Read-Write-Handle, el nivel en el que se interrumpe el bloqueo oportunista se describe como una combinación de cero o más de las marcas OPLOCK_LEVEL_CACHE_READ, OPLOCK_LEVEL_CACHE_HANDLE u OPLOCK_LEVEL_CACHE_WRITE en el miembro NewOplockLevel de la estructura REQUEST_OPLOCK_OUTPUT_BUFFER pasada como el parámetro lpOutBuffer de DeviceIoControl. De forma similar, FltFsControlFile y ZwFsControlFile se pueden usar para solicitar bloqueos oportunistas de Windows 7 desde el modo kernel. Para obtener más información, consulte FSCTL_REQUEST_OPLOCK.
Cuando el paquete de bloqueos oportunistas del sistema interrumpe un bloqueo oportunista de Nivel 1, Lote, Filtro, Read-Write, Read-Write-Handle o, bajo ciertas circunstancias, Read-Handle:
- El paquete de bloqueos oportunistas completa el IRP de solicitud de bloqueo oportunista pendiente.
- La operación que provocó la interrupción del bloqueo oportunista queda pendiente.
El administrador de E/S hace que la operación se bloquee, en lugar de devolver STATUS_PENDING, si la operación:
- Se emite en un identificador sincrónico.
- Es un IRP_MJ_CREATE, que siempre es sincrónico.
El administrador de E/S espera una confirmación del propietario del bloqueo oportunista para notificar al paquete de bloqueos oportunistas que ha terminado su procesamiento y es seguro que la operación pendiente continúe. Este retraso permite al propietario del bloqueo oportunista volver a colocar la secuencia en un estado coherente antes de que continúe la operación actual. El sistema esperaría para siempre recibir la confirmación, ya que no hay tiempo de espera. Por lo tanto, es necesario que el propietario del bloqueo oportunista confirme la interrupción de forma oportuna. El IRP de la operación pendiente se establece en un estado cancelable. Si la aplicación o el controlador que realiza la espera finaliza, el paquete de bloqueos oportunistas completa inmediatamente el IRP con STATUS_CANCELLED.
Un IRP_MJ_CREATE IRP puede especificar la opción de creación FILE_COMPLETE_IF_OPLOCKED para evitar que se bloquee como parte de la confirmación de interrupción del bloqueo oportunista. Esta opción indica al paquete de bloqueos oportunistas que no bloquee el IRP de creación hasta que se reciba la confirmación de interrupción del bloqueo oportunista. En su lugar, se permite que la creación prosiga. Si una creación exitosa da como resultado una interrupción de oplock, el código devuelto es STATUS_OPLOCK_BREAK_IN_PROGRESS, en lugar de STATUS_SUCCESS. La bandera FILE_COMPLETE_IF_OPLOCKED se utiliza generalmente para prevenir bloqueos. Por ejemplo, si un cliente posee un bloqueo oportunista en una secuencia y el mismo cliente abre posteriormente la misma secuencia, el cliente bloquearía la espera para confirmar la interrupción del bloqueo oportunista. En este escenario, el uso del indicador FILE_COMPLETE_IF_OPLOCKED evita el interbloqueo.
El sistema de archivos NTFS inicia interrupciones de bloqueo oportunista para bloqueos oportunistas de lote y filtro antes de comprobar si hay infracciones de uso compartido. Por lo tanto, es posible que una operación de creación que especifique FILE_COMPLETE_IF_OPLOCKED falle con STATUS_SHARING_VIOLATION pero aún así provoque la interrupción de un bloqueo oportunista de lote o filtro. En este caso, el miembro de información de la estructura IO_STATUS_BLOCK se establece en FILE_OPBATCH_BREAK_UNDERWAY para permitir que el autor de la llamada detecte este caso.
Para los bloqueos oportunistas Read-Handle y Read-Write-Handle, la interrupción del bloqueo oportunista se inicia después de que NTFS compruebe y detecte una infracción de uso compartido. Esta secuencia ofrece a los propietarios del bloqueo oportunista una oportunidad para cerrar sus identificadores y salir, lo que permite no devolver la infracción de uso compartido al usuario. También evita interrumpir el bloqueo oportunista incondicionalmente en los casos en que el identificador que almacena en caché el bloqueo oportunista no entra en conflicto con la nueva creación.
Cuando se interrumpen bloqueos oportunistas de nivel 2, lectura y, en determinadas circunstancias, Read-Handle, el sistema no espera una confirmación. El motivo es que no debe haber ningún estado almacenado en caché en la secuencia que debe restaurarse en el archivo antes de permitir que otros clientes accedan a él.
Hay ciertas operaciones del sistema de archivos que comprueban el estado actual del bloqueo oportunista para determinar si es necesario interrumpirlo. En los siguientes artículos específicos de la operación se describe lo que desencadena una interrupción de bloqueo oportunista, lo que determina el nivel en el que se interrumpe el bloqueo oportunista y si se requiere una confirmación de la interrupción:
- 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
Una interrupción de un bloqueo oportunista de Windows 7 requiere una confirmación si el indicador REQUEST_OPLOCK_OUTPUT_FLAG_ACK_REQUIRED está establecido en el miembro Flags de la estructura REQUEST_OPLOCK_OUTPUT_BUFFER pasada como parámetro de salida de DeviceIoControl(lpOutBuffer), FltFsControlFile(OutBuffer) o ZwFsControlFile(OutBuffer). Para obtener más información, consulte FSCTL_REQUEST_OPLOCK.
En los artículos enumerados por operación se describen los detalles de cuándo una interrupción de un bloqueo oportunista Read-Handle da como resultado que la operación que interrumpió el bloqueo oportunista quede pendiente. Por ejemplo, el artículo IRP_MJ_CREATE contiene los detalles asociados de Read-Handle.