Compartir a través de


Control de solicitudes de paginación de PnP

Un controlador de filtro de almacenamiento debe controlar las solicitudes de paginación de PnP (IRP_MJ_PNP con IRP_MN_DEVICE_USAGE_NOTIFICATION y Parameters.UsageNotification.Type establecido en DeviceUsageTypePaging) si el controlador de función que está filtrando controla este IRP.

Los siguientes elementos se deben agregar a deviceExtension del do de filtro:

ULONG PagingCount;

KEVENT PagingCountEvent;

Al recibir solicitudes de paginación de PnP, un controlador de filtro de almacenamiento debe actualizar pagingCount y la configuración del bit de DO_POWER_PAGABLE en filter DO. El tiempo de la actualización del bit de DO_POWER_PAGABLE depende de si el bit se establece o se borra. Si el IRP indica que se debe establecer el bit, el controlador de filtro debe establecerlo antes de reenviar el IRP a la pila del controlador. Pero si el IRP indica que se debe borrar el bit, el controlador de filtro no debe borrar el bit inmediatamente. Primero debe reenviar el IRP y esperar a que los controladores inferiores devuelvan su estado y borren el bit solo si los controladores inferiores devuelven STATUS_SUCCESS.

A continuación se realiza un seguimiento del flujo de acciones realizadas por el controlador de filtro de almacenamiento. Consulte el ejemplo de pseudocódigo inmediatamente debajo del esquema para ver una representación de este esquema en el código C:

A. Compruebe que se ha iniciado el dispositivo. Si no es así, se produce un error con STATUS_DEVICE_NOT_READY.

B. Sincronice en PagingCountEvent (KeWaitForSingleObject( PagingCountEvent, ...)).

C. Si quita el último dispositivo de paginación ( (! Parameters.UsageNotification.InPath && (PagingCount == 1) ) then

  1. Establezca un valor booleano local en TRUE y

  2. Si el bit de DO_POWER_INRUSH no se establece en filter DO, establezca el bit de DO_POWER_PAGABLE .

    A continuación se explica por qué el bit de DO_POWER_PAGABLE debe establecerse en el camino hacia abajo y no hacia arriba:

    Los requisitos de energía establecen que, si algún objeto de dispositivo inferior establece el bit de DO_POWER_PAGABLE , todos los controladores de nivel superior deben hacer lo mismo. Si el controlador de filtro no puede establecer el bit de DO_POWER_PAGABLE antes de enviar el IRP de solicitud de paginación a la pila, podría infringir esta condición de la siguiente manera:

    Supongamos que el controlador de filtro no establece el bit de DO_POWER_PAGABLE en su do de filtro antes de reenviar el IRP de solicitud de paginación a los controladores debajo de él en la pila de controladores. A continuación, supongamos que un controlador inferior establece el bit de DO_POWER_PAGABLE en su propio DO. Por último, supongamos que antes de la finalización del IRP por el controlador de filtro se produce un IRP de alimentación. En ese momento, el bit de DO_POWER_PAGABLE se borraría en filter DO, pero se establecería en el DO del controlador de nivel inferior, lo que provocaría un bloqueo del sistema.

    Es seguro establecer el DO_POWER_PAGABLE bit antes de reenviar una solicitud de paginación a la pila, ya que ya no hay un archivo de paginación activo en el dispositivo del controlador de filtro y, por lo tanto, no se producirá más E/S de paginación en él. Si la solicitud para quitar este archivo de paginación se realiza correctamente, se realizará el controlador de filtro. Si se produce un error en la solicitud, el controlador de filtro puede restaurar el estado original de sus marcas simplemente borrando el DO_POWER_PAGABLE bit antes de completar el IRP. Dado que las solicitudes de archivo de paginación se serializan, no hay peligro de que algún otro subproceso haya modificado este bit desde que el controlador de filtro lo modificó por última vez.

D. Reenvía sincrónicamente el IRP a los controladores inferiores.

E. Si el IRP se completa correctamente, entonces

  1. Llame a IoAdjustPagingPathCount(&PagingCount, Parameters.UsageNotification.InPath) para incrementar o disminuir pagingCount. IoAdjustPagingPathCount realiza un InterlockedIncrement o InterlockedDecrement de PagingCount según el valor de Parameters.UsageNotification.InPath. Un valor de TRUE indica que se está agregando un archivo de paginación, por lo que incrementa PagingCount; Un valor false indica que se está quitando un archivo de paginación, por lo que disminuye la PaginaciónCount.

  2. Si Parameters.UsageNotification.InPath es TRUE, se agrega un archivo de paginación, por lo que se borra el bit de DO_POWER_PAGABLE .

F. De lo contrario, si se produce un error en el IRP, entonces

  1. Compruebe el valor booleano local para ver si DO_POWER_PAGABLE se estableció en filter DO al bajar.

  2. Si DO_POWER_PAGABLE se estableció en el camino hacia abajo, ápeselo.

G. Sincronización de finalización (KeSetEvent(PagingCountEvent, ...)).

Ejemplo de pseudocódigo

Las secciones marcadas por letras (//A, //B, etc.) en el ejemplo de código siguiente se asignan a las letras del esquema anterior.

case DeviceUsageTypePaging: { 
    BOOLEAN setPageable = FALSE; 
    BOOLEAN addPageFile = irpStack -> 
                          Parameters.UsageNotification.InPath; 
 
 // A 
    if((addPageFile) && 
        (extension -> CurrentPnpState != 
        IRP_MN_START_DEVICE)) { 
            status = STATUS_DEVICE_NOT_READY; 
            break; 
        } 
 // B 
    KeWaitForSingleObject(&commonExtension -> PagingCountEvent, 
                                    Executive, KernelMode, 
                                    FALSE, NULL); 
 // C 
    if (!addPageFile && commonExtension -> PagingCount == 1 ) { 
        // The last paging file is no longer active.
        // Set the DO_POWER_PAGABLE bit before 
        // forwarding the paging request down the 
        // stack.
        if (!(DeviceObject->Flags & DO_POWER_INRUSH)) { 
            DeviceObject->Flags |=             DO_POWER_PAGABLE; 
            setPageable = TRUE; 
        ) 
    ) 
 // D 
        status = ForwardIrpSynchronous(commonExtension, Irp); 
 // E
        if (NT_SUCCESS(status)) { 
            IoAdjustPagingPathCount(&commonExtension -> PagingCount, 
                                    addPageFile); 
        if (addPageFile && commonExtension -> PagingCount == 1) { 
            // Once the lower device objects have 
            // succeeded the addition of the paging 
            // file, it is illegal to fail the 
            // request. It is also the time to 
            // clear the Filter DO's 
            //DO_POWER_PAGABLE flag.
 
            DeviceObject->Flags &= ~DO_POWER_PAGABLE; 
            } 
        } else { 
 // F 
        if (setPageable == TRUE) { 
            DeviceObject->Flags &= ~DO_POWER_PAGABLE; 
            setPageable = FALSE; 
        } 
    } 
 // G 
        KeSetEvent(&commonExtension->PagingCountEvent, 
                                    IO_NO_INCREMENT, FALSE); 
                                    break;
    } *Do not use or delete the last paragraph mark. It maintains the template setup and formats.