mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: ioq: now supports IRP expiration
This commit is contained in:
		| @@ -392,7 +392,7 @@ VOID FspFsvolCreateComplete( | |||||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); |     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||||
|     PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject; |     PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject; | ||||||
|     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject); |     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject); | ||||||
|     FSP_FSCTL_TRANSACT_REQ *Request = FspIopRequest(Irp); |     FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); | ||||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; |     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||||
|     PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; |     PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; | ||||||
|     ULONG CreateOptions = IrpSp->Parameters.Create.Options; |     ULONG CreateOptions = IrpSp->Parameters.Create.Options; | ||||||
| @@ -672,7 +672,7 @@ static VOID FspFsvolCreateCleanupClose( | |||||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); |     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||||
|     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = |     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = | ||||||
|         FspFsvrtDeviceExtension(FsvolDeviceExtension->FsvrtDeviceObject); |         FspFsvrtDeviceExtension(FsvolDeviceExtension->FsvrtDeviceObject); | ||||||
|     FSP_FSCTL_TRANSACT_REQ *OriginalRequest = FspIopRequest(Irp); |     FSP_FSCTL_TRANSACT_REQ *OriginalRequest = FspIrpRequest(Irp); | ||||||
|     FSP_FILE_CONTEXT *FsContext = FspIopRequestContext(OriginalRequest, RequestFsContext); |     FSP_FILE_CONTEXT *FsContext = FspIopRequestContext(OriginalRequest, RequestFsContext); | ||||||
|     UINT64 UserContext = Response->Rsp.Create.Opened.UserContext; |     UINT64 UserContext = Response->Rsp.Create.Opened.UserContext; | ||||||
|     UINT64 UserContext2 = Response->Rsp.Create.Opened.UserContext2; |     UINT64 UserContext2 = Response->Rsp.Create.Opened.UserContext2; | ||||||
|   | |||||||
| @@ -245,6 +245,13 @@ FAST_IO_RELEASE_FOR_MOD_WRITE FspReleaseForModWrite; | |||||||
| FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush; | FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush; | ||||||
| FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush; | FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush; | ||||||
|  |  | ||||||
|  | /* IRP context */ | ||||||
|  | #define FspIrpTimestamp(Irp)            \ | ||||||
|  |     (*(ULONGLONG *)&(Irp)->Tail.Overlay.DriverContext[0]) | ||||||
|  |     /* FspIrpTimestamp() uses up DriverContext[0] and [1] in 32-bit builds */ | ||||||
|  | #define FspIrpRequest(Irp)              \ | ||||||
|  |     (*(FSP_FSCTL_TRANSACT_REQ **)&(Irp)->Tail.Overlay.DriverContext[2]) | ||||||
|  |  | ||||||
| /* I/O queue */ | /* I/O queue */ | ||||||
| #define FspIoqTimeout                   ((PIRP)1) | #define FspIoqTimeout                   ((PIRP)1) | ||||||
| typedef struct | typedef struct | ||||||
| @@ -258,6 +265,7 @@ typedef struct | |||||||
| VOID FspIoqInitialize(FSP_IOQ *Ioq); | VOID FspIoqInitialize(FSP_IOQ *Ioq); | ||||||
| VOID FspIoqStop(FSP_IOQ *Ioq); | VOID FspIoqStop(FSP_IOQ *Ioq); | ||||||
| BOOLEAN FspIoqStopped(FSP_IOQ *Ioq); | BOOLEAN FspIoqStopped(FSP_IOQ *Ioq); | ||||||
|  | VOID FspIoqRemoveExpired(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout); | ||||||
| BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp); | BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp); | ||||||
| PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout); | PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout); | ||||||
| BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp); | BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp); | ||||||
| @@ -266,8 +274,6 @@ PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint); | |||||||
| /* I/O processing */ | /* I/O processing */ | ||||||
| #define FSP_FSCTL_WORK                  \ | #define FSP_FSCTL_WORK                  \ | ||||||
|     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'W', METHOD_NEITHER, FILE_ANY_ACCESS) |     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'W', METHOD_NEITHER, FILE_ANY_ACCESS) | ||||||
| #define FspIopRequest(Irp)              \ |  | ||||||
|     (*(FSP_FSCTL_TRANSACT_REQ **)&(Irp)->Tail.Overlay.DriverContext[0]) |  | ||||||
| #define FspIopRequestContext(Request, I)\ | #define FspIopRequestContext(Request, I)\ | ||||||
|     (*FspIopRequestContextAddress(Request, I)) |     (*FspIopRequestContextAddress(Request, I)) | ||||||
| #define FspIopCreateRequest(I, F, E, P) FspIopCreateRequestEx(I, F, E, 0, P) | #define FspIopCreateRequest(I, F, E, P) FspIopCreateRequestEx(I, F, E, 0, P) | ||||||
|   | |||||||
| @@ -473,7 +473,7 @@ static NTSTATUS FspFsvrtTransact( | |||||||
|     ASSERT(FspFsctlTransactCanProduceRequest(Request, SystemBufferEnd)); |     ASSERT(FspFsctlTransactCanProduceRequest(Request, SystemBufferEnd)); | ||||||
|     for (;;) |     for (;;) | ||||||
|     { |     { | ||||||
|         PendingIrpRequest = FspIopRequest(PendingIrp); |         PendingIrpRequest = FspIrpRequest(PendingIrp); | ||||||
|  |  | ||||||
|         Result = FspIopDispatchPrepare(PendingIrp, PendingIrpRequest); |         Result = FspIopDispatchPrepare(PendingIrp, PendingIrpRequest); | ||||||
|         if (!NT_SUCCESS(Result)) |         if (!NT_SUCCESS(Result)) | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ static NTSTATUS FspFsvolInternalDeviceControl( | |||||||
|  |  | ||||||
|                 /* associate the passed Request with our Irp; acquire ownership of the Request */ |                 /* associate the passed Request with our Irp; acquire ownership of the Request */ | ||||||
|                 Request->Hint = (UINT_PTR)Irp; |                 Request->Hint = (UINT_PTR)Irp; | ||||||
|                 FspIopRequest(Irp) = Request; |                 FspIrpRequest(Irp) = Request; | ||||||
|  |  | ||||||
|                 /* |                 /* | ||||||
|                  * Post the IRP to our Ioq; we do this here instead of at IRP_LEAVE_MJ time, |                  * Post the IRP to our Ioq; we do this here instead of at IRP_LEAVE_MJ time, | ||||||
| @@ -55,7 +55,7 @@ static NTSTATUS FspFsvolInternalDeviceControl( | |||||||
|                     ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq)); |                     ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq)); | ||||||
|  |  | ||||||
|                     Request->Hint = 0; |                     Request->Hint = 0; | ||||||
|                     FspIopRequest(Irp) = 0; |                     FspIrpRequest(Irp) = 0; | ||||||
|  |  | ||||||
|                     Result = STATUS_CANCELLED; |                     Result = STATUS_CANCELLED; | ||||||
|                     goto exit; |                     goto exit; | ||||||
|   | |||||||
| @@ -71,7 +71,7 @@ NTSTATUS FspIopCreateRequestEx( | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (0 != Irp) |     if (0 != Irp) | ||||||
|         FspIopRequest(Irp) = Request; |         FspIrpRequest(Irp) = Request; | ||||||
|     *PRequest = Request; |     *PRequest = Request; | ||||||
|  |  | ||||||
|     return STATUS_SUCCESS; |     return STATUS_SUCCESS; | ||||||
| @@ -152,10 +152,10 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease) | |||||||
|  |  | ||||||
|     ASSERT(STATUS_PENDING != Result); |     ASSERT(STATUS_PENDING != Result); | ||||||
|  |  | ||||||
|     if (0 != FspIopRequest(Irp)) |     if (0 != FspIrpRequest(Irp)) | ||||||
|     { |     { | ||||||
|         FspIopDeleteRequest(FspIopRequest(Irp)); |         FspIopDeleteRequest(FspIrpRequest(Irp)); | ||||||
|         FspIopRequest(Irp) = 0; |         FspIrpRequest(Irp) = 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* get the device object out of the IRP before completion */ |     /* get the device object out of the IRP before completion */ | ||||||
|   | |||||||
| @@ -55,6 +55,12 @@ | |||||||
|  * queue is not empty. |  * queue is not empty. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |     PVOID IrpHint; | ||||||
|  |     ULONGLONG ExpirationTime; | ||||||
|  | } FSP_IOQ_PEEK_CONTEXT; | ||||||
|  |  | ||||||
| static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext) | static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext) | ||||||
| { | { | ||||||
|     FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq); |     FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq); | ||||||
| @@ -81,6 +87,20 @@ static PIRP FspIoqPendingPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext) | |||||||
|         return 0; |         return 0; | ||||||
|     PLIST_ENTRY Head = &Ioq->PendingIrpList; |     PLIST_ENTRY Head = &Ioq->PendingIrpList; | ||||||
|     PLIST_ENTRY Entry = 0 == Irp ? Head->Flink : Irp->Tail.Overlay.ListEntry.Flink; |     PLIST_ENTRY Entry = 0 == Irp ? Head->Flink : Irp->Tail.Overlay.ListEntry.Flink; | ||||||
|  |     if (!PeekContext) | ||||||
|  |         return Head != Entry ? CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry) : 0; | ||||||
|  |     PVOID IrpHint = ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->IrpHint; | ||||||
|  |     if (0 == IrpHint) | ||||||
|  |     { | ||||||
|  |         if (Head != Entry) | ||||||
|  |         { | ||||||
|  |             Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); | ||||||
|  |             if (FspIrpTimestamp(Irp) <= ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->ExpirationTime) | ||||||
|  |                 /* IRP has expired; return it */ | ||||||
|  |                 return Irp; | ||||||
|  |         } | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|     return Head != Entry ? CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry) : 0; |     return Head != Entry ? CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry) : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -126,10 +146,22 @@ static PIRP FspIoqProcessPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext) | |||||||
|     PLIST_ENTRY Entry = 0 == Irp ? Head->Flink : Irp->Tail.Overlay.ListEntry.Flink; |     PLIST_ENTRY Entry = 0 == Irp ? Head->Flink : Irp->Tail.Overlay.ListEntry.Flink; | ||||||
|     if (!PeekContext) |     if (!PeekContext) | ||||||
|         return Head != Entry ? CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry) : 0; |         return Head != Entry ? CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry) : 0; | ||||||
|  |     PVOID IrpHint = ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->IrpHint; | ||||||
|  |     if (0 == IrpHint) | ||||||
|  |     { | ||||||
|  |         if (Head != Entry) | ||||||
|  |         { | ||||||
|  |             Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); | ||||||
|  |             if (FspIrpTimestamp(Irp) <= ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->ExpirationTime) | ||||||
|  |                 /* IRP has expired; return it */ | ||||||
|  |                 return Irp; | ||||||
|  |         } | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|     for (; Head != Entry; Entry = Entry->Flink) |     for (; Head != Entry; Entry = Entry->Flink) | ||||||
|     { |     { | ||||||
|         Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); |         Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); | ||||||
|         if (Irp == PeekContext) |         if (Irp == IrpHint) | ||||||
|             return Irp; |             return Irp; | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
| @@ -202,9 +234,22 @@ BOOLEAN FspIoqStopped(FSP_IOQ *Ioq) | |||||||
|     return Result; |     return Result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | VOID FspIoqRemoveExpired(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout) | ||||||
|  | { | ||||||
|  |     FSP_IOQ_PEEK_CONTEXT PeekContext; | ||||||
|  |     PeekContext.IrpHint = 0; | ||||||
|  |     PeekContext.ExpirationTime = KeQueryInterruptTime() - Timeout->QuadPart; | ||||||
|  |     PIRP Irp; | ||||||
|  |     while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, &PeekContext))) | ||||||
|  |         FspIoqPendingCompleteCanceledIrp(&Ioq->PendingIoCsq, Irp); | ||||||
|  |     while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, &PeekContext))) | ||||||
|  |         FspIoqProcessCompleteCanceledIrp(&Ioq->ProcessIoCsq, Irp); | ||||||
|  | } | ||||||
|  |  | ||||||
| BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp) | BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp) | ||||||
| { | { | ||||||
|     NTSTATUS Result; |     NTSTATUS Result; | ||||||
|  |     FspIrpTimestamp(Irp) = KeQueryInterruptTime(); | ||||||
|     Result = IoCsqInsertIrpEx(&Ioq->PendingIoCsq, Irp, 0, 0); |     Result = IoCsqInsertIrpEx(&Ioq->PendingIoCsq, Irp, 0, 0); | ||||||
|     return NT_SUCCESS(Result); |     return NT_SUCCESS(Result); | ||||||
| } | } | ||||||
| @@ -221,12 +266,16 @@ PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout) | |||||||
|         if (STATUS_TIMEOUT == Result) |         if (STATUS_TIMEOUT == Result) | ||||||
|             return FspIoqTimeout; |             return FspIoqTimeout; | ||||||
|     } |     } | ||||||
|     return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)1); |     FSP_IOQ_PEEK_CONTEXT PeekContext; | ||||||
|  |     PeekContext.IrpHint = (PVOID)1; | ||||||
|  |     PeekContext.ExpirationTime = 0; | ||||||
|  |     return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, &PeekContext); | ||||||
| } | } | ||||||
|  |  | ||||||
| BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp) | BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp) | ||||||
| { | { | ||||||
|     NTSTATUS Result; |     NTSTATUS Result; | ||||||
|  |     FspIrpTimestamp(Irp) = KeQueryInterruptTime(); | ||||||
|     Result = IoCsqInsertIrpEx(&Ioq->ProcessIoCsq, Irp, 0, 0); |     Result = IoCsqInsertIrpEx(&Ioq->ProcessIoCsq, Irp, 0, 0); | ||||||
|     return NT_SUCCESS(Result); |     return NT_SUCCESS(Result); | ||||||
| } | } | ||||||
| @@ -235,5 +284,8 @@ PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint) | |||||||
| { | { | ||||||
|     if (0 == IrpHint) |     if (0 == IrpHint) | ||||||
|         return 0; |         return 0; | ||||||
|     return IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, (PVOID)IrpHint); |     FSP_IOQ_PEEK_CONTEXT PeekContext; | ||||||
|  |     PeekContext.IrpHint = (PVOID)IrpHint; | ||||||
|  |     PeekContext.ExpirationTime = 0; | ||||||
|  |     return IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, &PeekContext); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user