sys: IRP_MJ_CREATE refactoring

This commit is contained in:
Bill Zissimopoulos 2016-01-12 12:16:33 -08:00
parent e885905c77
commit 26e2bf506b
3 changed files with 68 additions and 52 deletions

View File

@ -46,7 +46,7 @@ enum
{ {
FspFsctlTransactUnknownKind = 0, FspFsctlTransactUnknownKind = 0,
FspFsctlTransactCreateKind, FspFsctlTransactCreateKind,
FspFsctlTransactCreate2Kind, FspFsctlTransactOverwriteKind,
FspFsctlTransactCleanupKind, FspFsctlTransactCleanupKind,
FspFsctlTransactCloseKind, FspFsctlTransactCloseKind,
FspFsctlTransactReadKind, FspFsctlTransactReadKind,
@ -124,10 +124,9 @@ typedef struct
{ {
UINT64 UserContext; UINT64 UserContext;
UINT64 UserContext2; UINT64 UserContext2;
UINT32 CloseStatus; /* if non-0 close the file (and do NOT overwrite!) */
UINT32 FileAttributes; /* FILE_ATTRIBUTE_{NORMAL,DIRECTORY,etc.} */ UINT32 FileAttributes; /* FILE_ATTRIBUTE_{NORMAL,DIRECTORY,etc.} */
UINT32 Supersede:1; /* 0: FILE_OVERWRITE operation, 1: FILE_SUPERSEDE operation */ UINT32 Supersede:1; /* 0: FILE_OVERWRITE operation, 1: FILE_SUPERSEDE operation */
} Create2; } Overwrite;
struct struct
{ {
UINT64 UserContext; UINT64 UserContext;
@ -167,7 +166,7 @@ typedef struct
struct struct
{ {
UINT64 UserContext; /* open file user context (unique file id) */ 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 AllocationSize; /* file allocation size */
UINT64 FileSize; /* file size */ UINT64 FileSize; /* file size */
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */ UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
@ -180,11 +179,9 @@ typedef struct
} Create; } Create;
struct 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 AllocationSize; /* file allocation size */
UINT64 FileSize; /* file size */ UINT64 FileSize; /* file size */
} Create2; } Overwrite;
} Rsp; } Rsp;
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[]; FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
} FSP_FSCTL_TRANSACT_RSP; } FSP_FSCTL_TRANSACT_RSP;

View File

@ -15,8 +15,9 @@ static NTSTATUS FspFsvolCreate(
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
static VOID FspFsvolCreatePostClose( 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 FspFsvolCreateRequestFini;
static FSP_IOP_REQUEST_FINI FspFsvolCreateOverwriteRequestFini;
FSP_DRIVER_DISPATCH FspCreate; FSP_DRIVER_DISPATCH FspCreate;
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
@ -27,6 +28,7 @@ FSP_DRIVER_DISPATCH FspCreate;
#pragma alloc_text(PAGE, FspFsvolCreateComplete) #pragma alloc_text(PAGE, FspFsvolCreateComplete)
#pragma alloc_text(PAGE, FspFsvolCreatePostClose) #pragma alloc_text(PAGE, FspFsvolCreatePostClose)
#pragma alloc_text(PAGE, FspFsvolCreateRequestFini) #pragma alloc_text(PAGE, FspFsvolCreateRequestFini)
#pragma alloc_text(PAGE, FspFsvolCreateOverwriteRequestFini)
#pragma alloc_text(PAGE, FspCreate) #pragma alloc_text(PAGE, FspCreate)
#endif #endif
@ -35,9 +37,13 @@ FSP_DRIVER_DISPATCH FspCreate;
enum enum
{ {
/* CreateRequest */
RequestFsContext = 0, RequestFsContext = 0,
RequestAccessToken, RequestAccessToken = 1,
RequestProcess, RequestProcess = 2,
/* OverwriteRequest */
//RequestFsContext = 0,
RequestFileObject = 1,
}; };
static NTSTATUS FspFsctlCreate( static NTSTATUS FspFsctlCreate(
@ -302,6 +308,7 @@ NTSTATUS FspFsvolCreatePrepare(
HANDLE UserModeAccessToken; HANDLE UserModeAccessToken;
PEPROCESS Process; PEPROCESS Process;
FSP_FILE_CONTEXT *FsContext; FSP_FILE_CONTEXT *FsContext;
PFILE_OBJECT FileObject;
if (FspFsctlTransactCreateKind == Request->Kind) if (FspFsctlTransactCreateKind == Request->Kind)
{ {
@ -324,9 +331,10 @@ NTSTATUS FspFsvolCreatePrepare(
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
else if (FspFsctlTransactCreate2Kind == Request->Kind) else if (FspFsctlTransactOverwriteKind == Request->Kind)
{ {
FsContext = FspIopRequestContext(Request, RequestFsContext); FsContext = FspIopRequestContext(Request, RequestFsContext);
FileObject = FspIopRequestContext(Request, RequestFileObject);
/* lock the FsContext for Paging IO */ /* lock the FsContext for Paging IO */
Success = FspFileContextPgioLockExclusive(FsContext, FALSE); Success = FspFileContextPgioLockExclusive(FsContext, FALSE);
@ -340,15 +348,19 @@ NTSTATUS FspFsvolCreatePrepare(
return Result; return Result;
} }
FspIopRequestContext(Request, RequestFileObject) = 0;
/* see what the MM thinks about all this */ /* see what the MM thinks about all this */
LARGE_INTEGER Zero = { 0 }; LARGE_INTEGER Zero = { 0 };
Success = MmCanFileBeTruncated(&FsContext->NonPaged->SectionObjectPointers, &Zero); Success = MmCanFileBeTruncated(&FsContext->NonPaged->SectionObjectPointers, &Zero);
if (!Success) if (!Success)
{ {
/* cannot truncate; tell user mode that we are closing the file */
FspFileContextPgioUnlock(FsContext); 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 */ /* purge any caches on this file */
@ -458,10 +470,9 @@ VOID FspFsvolCreateComplete(
&Result); &Result);
if (0 == OpenedFsContext) if (0 == OpenedFsContext)
{ {
/* unable to open the FsContext; post a close Create2 request */ /* unable to open the FsContext; post a Close request */
FspFsvolCreatePostClose(FsContext, FspFsvolCreatePostClose(FsContext,
Response->Rsp.Create.Opened.UserContext2, Response->Rsp.Create.Opened.UserContext2);
Result);
FSP_RETURN(); FSP_RETURN();
} }
@ -497,10 +508,8 @@ VOID FspFsvolCreateComplete(
Result = DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; Result = DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
FspFileContextClose(FsContext, FileObject); FspFileContextClose(FsContext, FileObject);
FspFsvolCreatePostClose(FsContext, FspFsvolCreatePostClose(FsContext,
Response->Rsp.Create.Opened.UserContext2, Response->Rsp.Create.Opened.UserContext2);
Result);
FSP_RETURN(); FSP_RETURN();
} }
@ -523,26 +532,24 @@ VOID FspFsvolCreateComplete(
FspIopDeleteRequest(Request); FspIopDeleteRequest(Request);
/* create the Create2 request; MustSucceed because we must either overwrite or close */ /* create the Create2 request; MustSucceed because we must either overwrite or close */
FspIopCreateRequestMustSucceed(Irp, FspIopCreateRequestFunnel(Irp,
FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FsContext->FileName : 0, 0, FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FsContext->FileName : 0, 0,
FspFsvolCreateOverwriteRequestFini, TRUE,
&Request); &Request);
/* associate the FsContext with the Create2 request */ /* associate the FsContext with the Create2 request */
FspIopRequestContext(Request, RequestFsContext) = FsContext; FspIopRequestContext(Request, RequestFsContext) = FsContext;
/* populate the Create2 request */ /* populate the Create2 request */
Request->Kind = FspFsctlTransactCreate2Kind; Request->Kind = FspFsctlTransactOverwriteKind;
Request->Req.Create2.UserContext = FsContext->UserContext; Request->Req.Overwrite.UserContext = FsContext->UserContext;
Request->Req.Create2.UserContext2 = (UINT_PTR)FileObject->FsContext2; Request->Req.Overwrite.UserContext2 = (UINT_PTR)FileObject->FsContext2;
Request->Req.Create2.FileAttributes = IrpSp->Parameters.Create.FileAttributes; Request->Req.Overwrite.FileAttributes = IrpSp->Parameters.Create.FileAttributes;
Request->Req.Create2.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information; Request->Req.Overwrite.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information;
Request->Req.Create2.CloseStatus = STATUS_SUCCESS;
/* /*
* Note that it is still possible for this request to not be delivered, * 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 * if the volume device Ioq is stopped or if the IRP is canceled.
* from our perspective, because they mean that the file system is going
* away and should correctly tear things down.
*/ */
if (FspIoqPostIrpBestEffort(FsvolDeviceExtension->Ioq, Irp, &Result)) if (FspIoqPostIrpBestEffort(FsvolDeviceExtension->Ioq, Irp, &Result))
@ -555,25 +562,18 @@ VOID FspFsvolCreateComplete(
Result = STATUS_SUCCESS; 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. * 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? */ /* did the user-mode file system sent us a failure code? */
if (!NT_SUCCESS(Response->IoStatus.Status)) if (!NT_SUCCESS(Response->IoStatus.Status))
{ {
FspFileContextPgioUnlock(FsContext); FspFileContextPgioUnlock(FsContext);
FspFileContextClose(FsContext, FileObject); FspFileContextClose(FsContext, FileObject);
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
@ -588,11 +588,11 @@ VOID FspFsvolCreateComplete(
FspFileContextPgioUnlock(FsContext); FspFileContextPgioUnlock(FsContext);
/* disassociate the FsContext from the Create2 request */ /* disassociate the FsContext from the Overwrite request */
FspIopRequestContext(Request, RequestFsContext) = 0; FspIopRequestContext(Request, RequestFsContext) = 0;
/* SUCCESS! */ /* 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; Result = STATUS_SUCCESS;
} }
else else
@ -604,12 +604,10 @@ VOID FspFsvolCreateComplete(
} }
static VOID FspFsvolCreatePostClose( static VOID FspFsvolCreatePostClose(
FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2, NTSTATUS CloseStatus) FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2)
{ {
PAGED_CODE(); PAGED_CODE();
ASSERT(STATUS_SUCCESS != CloseStatus);
PDEVICE_OBJECT FsvolDeviceObject = FsContext->FsvolDeviceObject; PDEVICE_OBJECT FsvolDeviceObject = FsContext->FsvolDeviceObject;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
FSP_FSCTL_TRANSACT_REQ *Request; FSP_FSCTL_TRANSACT_REQ *Request;
@ -619,11 +617,10 @@ static VOID FspFsvolCreatePostClose(
FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FsContext->FileName : 0, FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FsContext->FileName : 0,
0, &Request); 0, &Request);
/* populate the Create2 request */ /* populate the Close request */
Request->Kind = FspFsctlTransactCreate2Kind; Request->Kind = FspFsctlTransactCloseKind;
Request->Req.Create2.UserContext = FsContext->UserContext; Request->Req.Close.UserContext = FsContext->UserContext;
Request->Req.Create2.UserContext2 = UserContext2; Request->Req.Close.UserContext2 = UserContext2;
Request->Req.Create2.CloseStatus = CloseStatus;
/* /*
* Post as a BestEffort work request. This allows us to complete our own IRP * 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( NTSTATUS FspCreate(
PDEVICE_OBJECT DeviceObject, PIRP Irp) PDEVICE_OBJECT DeviceObject, PIRP Irp)
{ {

View File

@ -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. * opening a prior FsContext that we found in the table.
* *
* First check and update the share access. If successful then retain the * 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); ASSERT(OpenedFsContext != FsContext);