From 26e2bf506b1b4ff702d7359a34a7e3316315aeac Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 12 Jan 2016 12:16:33 -0800 Subject: [PATCH] sys: IRP_MJ_CREATE refactoring --- inc/winfsp/fsctl.h | 11 ++--- src/sys/create.c | 107 ++++++++++++++++++++++++++------------------- src/sys/filectx.c | 2 +- 3 files changed, 68 insertions(+), 52 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index a3c37efc..1aa5f931 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -46,7 +46,7 @@ enum { FspFsctlTransactUnknownKind = 0, FspFsctlTransactCreateKind, - FspFsctlTransactCreate2Kind, + FspFsctlTransactOverwriteKind, FspFsctlTransactCleanupKind, FspFsctlTransactCloseKind, FspFsctlTransactReadKind, @@ -124,10 +124,9 @@ typedef struct { UINT64 UserContext; UINT64 UserContext2; - UINT32 CloseStatus; /* if non-0 close the file (and do NOT overwrite!) */ UINT32 FileAttributes; /* FILE_ATTRIBUTE_{NORMAL,DIRECTORY,etc.} */ UINT32 Supersede:1; /* 0: FILE_OVERWRITE operation, 1: FILE_SUPERSEDE operation */ - } Create2; + } Overwrite; struct { UINT64 UserContext; @@ -167,7 +166,7 @@ typedef struct struct { UINT64 UserContext; /* open file user context (unique file id) */ - UINT64 UserContext2; /* kernel file object user context (only low 32 bits valid) */ + UINT64 UserContext2; /* kernel file object user context (stores as many bits as a pointer) */ UINT64 AllocationSize; /* file allocation size */ UINT64 FileSize; /* file size */ UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */ @@ -180,11 +179,9 @@ typedef struct } Create; struct { - UINT64 UserContext; /* open file user context (unique file id) */ - UINT64 UserContext2; /* kernel file object user context (only low 32 bits valid) */ UINT64 AllocationSize; /* file allocation size */ UINT64 FileSize; /* file size */ - } Create2; + } Overwrite; } Rsp; FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[]; } FSP_FSCTL_TRANSACT_RSP; diff --git a/src/sys/create.c b/src/sys/create.c index 6874336f..23c15f7d 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -15,8 +15,9 @@ static NTSTATUS FspFsvolCreate( FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; static VOID FspFsvolCreatePostClose( - FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2, NTSTATUS CloseStatus); + FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2); static FSP_IOP_REQUEST_FINI FspFsvolCreateRequestFini; +static FSP_IOP_REQUEST_FINI FspFsvolCreateOverwriteRequestFini; FSP_DRIVER_DISPATCH FspCreate; #ifdef ALLOC_PRAGMA @@ -27,6 +28,7 @@ FSP_DRIVER_DISPATCH FspCreate; #pragma alloc_text(PAGE, FspFsvolCreateComplete) #pragma alloc_text(PAGE, FspFsvolCreatePostClose) #pragma alloc_text(PAGE, FspFsvolCreateRequestFini) +#pragma alloc_text(PAGE, FspFsvolCreateOverwriteRequestFini) #pragma alloc_text(PAGE, FspCreate) #endif @@ -35,9 +37,13 @@ FSP_DRIVER_DISPATCH FspCreate; enum { - RequestFsContext = 0, - RequestAccessToken, - RequestProcess, + /* CreateRequest */ + RequestFsContext = 0, + RequestAccessToken = 1, + RequestProcess = 2, + /* OverwriteRequest */ + //RequestFsContext = 0, + RequestFileObject = 1, }; static NTSTATUS FspFsctlCreate( @@ -302,6 +308,7 @@ NTSTATUS FspFsvolCreatePrepare( HANDLE UserModeAccessToken; PEPROCESS Process; FSP_FILE_CONTEXT *FsContext; + PFILE_OBJECT FileObject; if (FspFsctlTransactCreateKind == Request->Kind) { @@ -324,9 +331,10 @@ NTSTATUS FspFsvolCreatePrepare( return STATUS_SUCCESS; } - else if (FspFsctlTransactCreate2Kind == Request->Kind) + else if (FspFsctlTransactOverwriteKind == Request->Kind) { FsContext = FspIopRequestContext(Request, RequestFsContext); + FileObject = FspIopRequestContext(Request, RequestFileObject); /* lock the FsContext for Paging IO */ Success = FspFileContextPgioLockExclusive(FsContext, FALSE); @@ -340,15 +348,19 @@ NTSTATUS FspFsvolCreatePrepare( return Result; } + FspIopRequestContext(Request, RequestFileObject) = 0; + /* see what the MM thinks about all this */ LARGE_INTEGER Zero = { 0 }; Success = MmCanFileBeTruncated(&FsContext->NonPaged->SectionObjectPointers, &Zero); if (!Success) { - /* cannot truncate; tell user mode that we are closing the file */ FspFileContextPgioUnlock(FsContext); - Request->Req.Create2.CloseStatus = (UINT32)STATUS_USER_MAPPED_FILE; - return STATUS_SUCCESS; + + FspFileContextClose(FsContext, FileObject); + FspFsvolCreatePostClose(FsContext, (UINT_PTR)FileObject->FsContext2); + + return STATUS_USER_MAPPED_FILE; } /* purge any caches on this file */ @@ -458,10 +470,9 @@ VOID FspFsvolCreateComplete( &Result); if (0 == OpenedFsContext) { - /* unable to open the FsContext; post a close Create2 request */ + /* unable to open the FsContext; post a Close request */ FspFsvolCreatePostClose(FsContext, - Response->Rsp.Create.Opened.UserContext2, - Result); + Response->Rsp.Create.Opened.UserContext2); FSP_RETURN(); } @@ -497,10 +508,8 @@ VOID FspFsvolCreateComplete( Result = DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; FspFileContextClose(FsContext, FileObject); - FspFsvolCreatePostClose(FsContext, - Response->Rsp.Create.Opened.UserContext2, - Result); + Response->Rsp.Create.Opened.UserContext2); FSP_RETURN(); } @@ -523,26 +532,24 @@ VOID FspFsvolCreateComplete( FspIopDeleteRequest(Request); /* create the Create2 request; MustSucceed because we must either overwrite or close */ - FspIopCreateRequestMustSucceed(Irp, + FspIopCreateRequestFunnel(Irp, FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FsContext->FileName : 0, 0, + FspFsvolCreateOverwriteRequestFini, TRUE, &Request); /* associate the FsContext with the Create2 request */ FspIopRequestContext(Request, RequestFsContext) = FsContext; /* populate the Create2 request */ - Request->Kind = FspFsctlTransactCreate2Kind; - Request->Req.Create2.UserContext = FsContext->UserContext; - Request->Req.Create2.UserContext2 = (UINT_PTR)FileObject->FsContext2; - Request->Req.Create2.FileAttributes = IrpSp->Parameters.Create.FileAttributes; - Request->Req.Create2.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information; - Request->Req.Create2.CloseStatus = STATUS_SUCCESS; + Request->Kind = FspFsctlTransactOverwriteKind; + Request->Req.Overwrite.UserContext = FsContext->UserContext; + Request->Req.Overwrite.UserContext2 = (UINT_PTR)FileObject->FsContext2; + Request->Req.Overwrite.FileAttributes = IrpSp->Parameters.Create.FileAttributes; + Request->Req.Overwrite.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information; /* * Note that it is still possible for this request to not be delivered, - * if the volume device Ioq is stopped. But such failures are benign - * from our perspective, because they mean that the file system is going - * away and should correctly tear things down. + * if the volume device Ioq is stopped or if the IRP is canceled. */ if (FspIoqPostIrpBestEffort(FsvolDeviceExtension->Ioq, Irp, &Result)) @@ -555,25 +562,18 @@ VOID FspFsvolCreateComplete( Result = STATUS_SUCCESS; } } - else if (FspFsctlTransactCreate2Kind == Request->Kind) + else if (FspFsctlTransactOverwriteKind == Request->Kind) { /* - * A Create2 request will either succeed or else fail and close the corresponding file. + * An Overwrite request will either succeed or else fail and close the corresponding file. * There is no need to reach out to user-mode again and ask them to close the file. */ - /* was this a close request? */ - if (STATUS_SUCCESS != Request->Req.Create2.CloseStatus) - { - Irp->IoStatus.Information = 0; - Result = STATUS_SUCCESS != Request->Req.Create2.CloseStatus; - FSP_RETURN(); - } - /* did the user-mode file system sent us a failure code? */ if (!NT_SUCCESS(Response->IoStatus.Status)) { FspFileContextPgioUnlock(FsContext); + FspFileContextClose(FsContext, FileObject); Irp->IoStatus.Information = 0; @@ -588,11 +588,11 @@ VOID FspFsvolCreateComplete( FspFileContextPgioUnlock(FsContext); - /* disassociate the FsContext from the Create2 request */ + /* disassociate the FsContext from the Overwrite request */ FspIopRequestContext(Request, RequestFsContext) = 0; /* SUCCESS! */ - Irp->IoStatus.Information = Request->Req.Create2.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN; + Irp->IoStatus.Information = Request->Req.Overwrite.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN; Result = STATUS_SUCCESS; } else @@ -604,12 +604,10 @@ VOID FspFsvolCreateComplete( } static VOID FspFsvolCreatePostClose( - FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2, NTSTATUS CloseStatus) + FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2) { PAGED_CODE(); - ASSERT(STATUS_SUCCESS != CloseStatus); - PDEVICE_OBJECT FsvolDeviceObject = FsContext->FsvolDeviceObject; FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); FSP_FSCTL_TRANSACT_REQ *Request; @@ -619,11 +617,10 @@ static VOID FspFsvolCreatePostClose( FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FsContext->FileName : 0, 0, &Request); - /* populate the Create2 request */ - Request->Kind = FspFsctlTransactCreate2Kind; - Request->Req.Create2.UserContext = FsContext->UserContext; - Request->Req.Create2.UserContext2 = UserContext2; - Request->Req.Create2.CloseStatus = CloseStatus; + /* populate the Close request */ + Request->Kind = FspFsctlTransactCloseKind; + Request->Req.Close.UserContext = FsContext->UserContext; + Request->Req.Close.UserContext2 = UserContext2; /* * Post as a BestEffort work request. This allows us to complete our own IRP @@ -678,6 +675,28 @@ static VOID FspFsvolCreateRequestFini(PVOID Context[3]) } } +static VOID FspFsvolCreateOverwriteRequestFini(PVOID Context[3]) +{ + PAGED_CODE(); + + if (0 != Context[RequestFsContext]) + { + FSP_FILE_CONTEXT *FsContext = Context[RequestFsContext]; + PFILE_OBJECT FileObject = Context[RequestFileObject]; + + if (0 != FileObject) + { + FspFsvolCreatePostClose(FsContext, (UINT_PTR)FileObject->FsContext2); + FspFileContextClose(FsContext, FileObject); + } + + FspFileContextRelease(FsContext); + + Context[RequestFileObject] = 0; + Context[RequestFsContext] = 0; + } +} + NTSTATUS FspCreate( PDEVICE_OBJECT DeviceObject, PIRP Irp) { diff --git a/src/sys/filectx.c b/src/sys/filectx.c index a1b7392c..6ffc1081 100644 --- a/src/sys/filectx.c +++ b/src/sys/filectx.c @@ -112,7 +112,7 @@ FSP_FILE_CONTEXT *FspFileContextOpen(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT F * opening a prior FsContext that we found in the table. * * First check and update the share access. If successful then retain the - * prior FsContext for our caller. + * opened FsContext for our caller. */ ASSERT(OpenedFsContext != FsContext);