From 69fd1ebd6c985667ffd01a72e704ef06024f34ad Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Sat, 23 Jan 2016 14:01:53 -0800 Subject: [PATCH] sys: store FileInfo in FileNode's --- inc/winfsp/fsctl.h | 1 + src/sys/create.c | 6 +++ src/sys/device.c | 2 +- src/sys/driver.h | 17 +++++++ src/sys/file.c | 107 ++++++++++++++++++++++++++++++++++++++++++++- src/sys/ioq.c | 2 +- src/sys/volume.c | 2 +- 7 files changed, 133 insertions(+), 4 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 4bfb1a5d..80e1c8e8 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -106,6 +106,7 @@ typedef struct UINT32 TransactTimeout; /* milliseconds; values between 1 sec and 10 sec */ UINT32 IrpTimeout; /* milliseconds; values between 1 min and 10 min */ UINT32 IrpCapacity; /* maximum number of pending IRP's */ + UINT32 FileInfoTimeout; /* milliseconds */ UINT32 EaSupported:1; /* supports extended attributes (unimplemented; set to 0) */ UINT32 FileNameRequired:1; /* FileName required for all operations (not just Create) */ WCHAR Prefix[64]; /* UNC prefix to recognize (\\server\path format, 0-term) */ diff --git a/src/sys/create.c b/src/sys/create.c index a6073bee..7e3e37aa 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -372,6 +372,7 @@ NTSTATUS FspFsvolCreatePrepare( if (NT_SUCCESS(Result)) { /* SUCCESS! */ + FspFileNodeSetFileInfo(FileNode, &FileDesc->State.FileInfo); FspIopRequestContext(Request, RequestFileDesc) = 0; Irp->IoStatus.Information = FILE_OPENED; Result = STATUS_SUCCESS; @@ -549,7 +550,9 @@ VOID FspFsvolCreateComplete( FileNode->Header.AllocationSize.QuadPart = Response->Rsp.Create.Opened.FileInfo.AllocationSize; FileNode->Header.FileSize.QuadPart = Response->Rsp.Create.Opened.FileInfo.FileSize; FileNode->UserContext = Response->Rsp.Create.Opened.UserContext; + FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber; FileDesc->UserContext2 = Response->Rsp.Create.Opened.UserContext2; + FileDesc->State.FileInfo = Response->Rsp.Create.Opened.FileInfo; DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE); @@ -602,6 +605,7 @@ VOID FspFsvolCreateComplete( } /* SUCCESS! */ + FspFileNodeSetFileInfo(FileNode, &FileDesc->State.FileInfo); FspIopRequestContext(Request, RequestFileDesc) = 0; Irp->IoStatus.Information = (ULONG_PTR)Response->IoStatus.Information; Result = STATUS_SUCCESS; @@ -656,6 +660,7 @@ VOID FspFsvolCreateComplete( else { /* SUCCESS! */ + FspFileNodeSetFileInfo(FileNode, &FileDesc->State.FileInfo); FspIopRequestContext(Request, RequestFileDesc) = 0; Irp->IoStatus.Information = (ULONG_PTR)Response->IoStatus.Information; Result = STATUS_SUCCESS; @@ -684,6 +689,7 @@ VOID FspFsvolCreateComplete( FspFileNodeRelease(FileNode, Both); /* SUCCESS! */ + FspFileNodeSetFileInfo(FileNode, &Response->Rsp.Overwrite.FileInfo); FspIopRequestContext(Request, RequestFileDesc) = 0; Irp->IoStatus.Information = Request->Req.Overwrite.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN; Result = STATUS_SUCCESS; diff --git a/src/sys/device.c b/src/sys/device.c index b2e07552..4e639f94 100644 --- a/src/sys/device.c +++ b/src/sys/device.c @@ -281,7 +281,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject) FsvolDeviceExtension->InitDoneDelRsc = 1; /* create our Ioq */ - IrpTimeout.QuadPart = FsvolDeviceExtension->VolumeParams.IrpTimeout * 10000; + IrpTimeout.QuadPart = FsvolDeviceExtension->VolumeParams.IrpTimeout * 10000ULL; /* convert millis to nanos */ Result = FspIoqCreate( FsvolDeviceExtension->VolumeParams.IrpCapacity, &IrpTimeout, FspIopCompleteCanceledIrp, diff --git a/src/sys/driver.h b/src/sys/driver.h index 24f8facf..a1faac33 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -534,6 +534,15 @@ typedef struct ERESOURCE PagingIoResource; FAST_MUTEX HeaderFastMutex; SECTION_OBJECT_POINTERS SectionObjectPointers; + /* FileInfo */ + KSPIN_LOCK InfoSpinLock; + UINT64 InfoExpirationTime; + UINT32 FileAttributes; + UINT32 ReparseTag; + UINT64 CreationTime; + UINT64 LastAccessTime; + UINT64 LastWriteTime; + UINT64 ChangeTime; } FSP_FILE_NODE_NONPAGED; typedef struct { @@ -552,6 +561,7 @@ typedef struct /* read-only after creation (and insertion in the ContextTable) */ PDEVICE_OBJECT FsvolDeviceObject; UINT64 UserContext; + UINT64 IndexNumber; FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage; UNICODE_STRING FileName; WCHAR FileNameBuf[]; @@ -560,6 +570,10 @@ typedef struct { FSP_FILE_NODE *FileNode; UINT64 UserContext2; + union + { + FSP_FSCTL_FILE_INFO FileInfo; /* create time only */ + } State; } FSP_FILE_DESC; NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, ULONG ExtraSize, FSP_FILE_NODE **PFileNode); @@ -585,6 +599,9 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, UINT32 GrantedAccess, UINT32 ShareAccess, BOOLEAN DeleteOnClose, NTSTATUS *PResult); VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PBOOLEAN PDeletePending); +VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); +BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); +VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, const FSP_FSCTL_FILE_INFO *FileInfo); NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); #define FspFileNodeAcquireShared(N,F) FspFileNodeAcquireShared(N, FspFileNodeAcquire ## F) diff --git a/src/sys/file.c b/src/sys/file.c index 192df9d6..042b949e 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -24,7 +24,9 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, UINT32 GrantedAccess, UINT32 ShareAccess, BOOLEAN DeleteOnClose, NTSTATUS *PResult); VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PBOOLEAN PDeletePending); - +VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); +BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); +VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, const FSP_FSCTL_FILE_INFO *FileInfo); NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); @@ -38,6 +40,9 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); #pragma alloc_text(PAGE, FspFileNodeRelease) #pragma alloc_text(PAGE, FspFileNodeOpen) #pragma alloc_text(PAGE, FspFileNodeClose) +#pragma alloc_text(PAGE, FspFileNodeGetFileInfo) +#pragma alloc_text(PAGE, FspFileNodeTryGetFileInfo) +#pragma alloc_text(PAGE, FspFileNodeSetFileInfo) #pragma alloc_text(PAGE, FspFileDescCreate) #pragma alloc_text(PAGE, FspFileDescDelete) #endif @@ -64,6 +69,7 @@ NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, ExInitializeResourceLite(&NonPaged->Resource); ExInitializeResourceLite(&NonPaged->PagingIoResource); ExInitializeFastMutex(&NonPaged->HeaderFastMutex); + KeInitializeSpinLock(&NonPaged->InfoSpinLock); RtlZeroMemory(FileNode, sizeof *FileNode + ExtraSize); FileNode->Header.NodeTypeCode = FspFileNodeFileKind; @@ -312,6 +318,105 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, *PDeletePending = Deleted && DeletePending; } +static VOID FspFileNodeGetFileInfoNp(FSP_FILE_NODE_NONPAGED *FileNodeNp, FSP_FSCTL_FILE_INFO *FileInfoNp) +{ + // !PAGED_CODE(); + + KIRQL Irql; + + KeAcquireSpinLock(&FileNodeNp->InfoSpinLock, &Irql); + FileInfoNp->FileAttributes = FileNodeNp->FileAttributes; + FileInfoNp->ReparseTag = FileNodeNp->ReparseTag; + FileInfoNp->CreationTime = FileNodeNp->CreationTime; + FileInfoNp->LastAccessTime = FileNodeNp->LastAccessTime; + FileInfoNp->LastWriteTime = FileNodeNp->LastWriteTime; + FileInfoNp->ChangeTime = FileNodeNp->ChangeTime; + KeReleaseSpinLock(&FileNodeNp->InfoSpinLock, Irql); +} + +static BOOLEAN FspFileNodeTryGetFileInfoNp(FSP_FILE_NODE_NONPAGED *FileNodeNp, + FSP_FSCTL_FILE_INFO *FileInfoNp) +{ + // !PAGED_CODE(); + + KIRQL Irql; + BOOLEAN Result; + + KeAcquireSpinLock(&FileNodeNp->InfoSpinLock, &Irql); + if (0 < FileNodeNp->InfoExpirationTime && FileNodeNp->InfoExpirationTime < KeQueryInterruptTime()) + { + FileInfoNp->FileAttributes = FileNodeNp->FileAttributes; + FileInfoNp->ReparseTag = FileNodeNp->ReparseTag; + FileInfoNp->CreationTime = FileNodeNp->CreationTime; + FileInfoNp->LastAccessTime = FileNodeNp->LastAccessTime; + FileInfoNp->LastWriteTime = FileNodeNp->LastWriteTime; + FileInfoNp->ChangeTime = FileNodeNp->ChangeTime; + Result = TRUE; + } + else + Result = FALSE; + KeReleaseSpinLock(&FileNodeNp->InfoSpinLock, Irql); + + return Result; +} + +static VOID FspFileNodeSetFileInfoNp(FSP_FILE_NODE_NONPAGED *FileNodeNp, + const FSP_FSCTL_FILE_INFO *FileInfoNp, UINT64 FileInfoTimeout) +{ + // !PAGED_CODE(); + + KIRQL Irql; + + KeAcquireSpinLock(&FileNodeNp->InfoSpinLock, &Irql); + FileNodeNp->FileAttributes = FileInfoNp->FileAttributes; + FileNodeNp->ReparseTag = FileInfoNp->ReparseTag; + FileNodeNp->CreationTime = FileInfoNp->CreationTime; + FileNodeNp->LastAccessTime = FileInfoNp->LastAccessTime; + FileNodeNp->LastWriteTime = FileInfoNp->LastWriteTime; + FileNodeNp->ChangeTime = FileInfoNp->ChangeTime; + FileNodeNp->InfoExpirationTime = 0 != FileInfoTimeout ? + KeQueryInterruptTime() + FileInfoTimeout : 0; + KeReleaseSpinLock(&FileNodeNp->InfoSpinLock, Irql); +} + +VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo) +{ + PAGED_CODE(); + + FSP_FILE_NODE_NONPAGED *FileNodeNp = FileNode->NonPaged; + FSP_FSCTL_FILE_INFO FileInfoNp; + + FspFileNodeGetFileInfoNp(FileNodeNp, &FileInfoNp); + + *FileInfo = FileInfoNp; +} + +BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo) +{ + PAGED_CODE(); + + FSP_FILE_NODE_NONPAGED *FileNodeNp = FileNode->NonPaged; + FSP_FSCTL_FILE_INFO FileInfoNp; + + if (!FspFileNodeTryGetFileInfoNp(FileNodeNp, &FileInfoNp)) + return FALSE; + + *FileInfo = FileInfoNp; + return TRUE; +} + +VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, const FSP_FSCTL_FILE_INFO *FileInfo) +{ + PAGED_CODE(); + + UINT64 FileInfoTimeout = FspFsvolDeviceExtension(FileNode->FsvolDeviceObject)-> + VolumeParams.FileInfoTimeout * 10000ULL; + FSP_FILE_NODE_NONPAGED *FileNodeNp = FileNode->NonPaged; + FSP_FSCTL_FILE_INFO FileInfoNp = *FileInfo; + + FspFileNodeSetFileInfoNp(FileNodeNp, &FileInfoNp, FileInfoTimeout); +} + NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc) { PAGED_CODE(); diff --git a/src/sys/ioq.c b/src/sys/ioq.c index b46465fa..9f9ead91 100644 --- a/src/sys/ioq.c +++ b/src/sys/ioq.c @@ -111,7 +111,7 @@ static PIRP FspCsqRemoveNextIrp(PIO_CSQ Csq, PVOID PeekContext) #define FspCsqRemoveNextIrp(Q, C) IoCsqRemoveNextIrp(Q, C) #endif -#define InterruptTimeToSecFactor 10000000 +#define InterruptTimeToSecFactor 10000000ULL #define ConvertInterruptTimeToSec(Time) ((ULONG)((Time) / InterruptTimeToSecFactor)) #define QueryInterruptTimeInSec() ConvertInterruptTimeToSec(KeQueryInterruptTime()) diff --git a/src/sys/volume.c b/src/sys/volume.c index 5ed9154c..cbb969a7 100644 --- a/src/sys/volume.c +++ b/src/sys/volume.c @@ -546,7 +546,7 @@ NTSTATUS FspVolumeTransact( /* wait for an IRP to arrive */ KeQuerySystemTime(&Timeout); - Timeout.QuadPart += FsvolDeviceExtension->VolumeParams.TransactTimeout * 10000; + Timeout.QuadPart += FsvolDeviceExtension->VolumeParams.TransactTimeout * 10000ULL; /* convert millis to nanos and add to absolute time */ while (0 == (PendingIrp = FspIoqNextPendingIrp(FsvolDeviceExtension->Ioq, 0, &Timeout))) {