- Implement __RxWriteReleaseResources(), RxCommonWrite(), RxCompleteMdl(), RxGetTopIrpIfRdbssIrp(), RxLowIoWriteShell(), RxLowIoWriteShellCompletion()
- Finish implementation of RxCommonCleanup() so that it handles setting EOF on a file
- Finish implementation of RxCommonCreate() so that it handles sharing violations and attempts to scavenge open files

[RXCE]
- Implement RxpScavengeFobxs(), RxpTrackDereference(), RxpTrackReference(), RxPurgeFobx(), RxPurgeRelatedFobxs(), RxReinitializeContext(), RxSetFileSizeWithLock(), RxScavengeFobxsForNetRoot()
- Fix a bug in RxPrefixTableLookupName() where it was badly handling nodes in scavenger

This commits brings several improvments to the NFS driver.
First of all, now, the driver handles creating, extending and writing to files!
It also handles purging dormant opened files when a file opening fails because of a sharing violation
Finally, it also brings something to look at our references issues in RDBSS to help finding out why our FCB are never (or nearly) dereferenced

CORE-8204
CORE-11327
CORE-13581

svn path=/trunk/; revision=75398
This commit is contained in:
Pierre Schweitzer 2017-07-24 17:05:05 +00:00
parent 30a8a02f54
commit f8e1661549
7 changed files with 1922 additions and 17 deletions

View file

@ -296,6 +296,9 @@ typedef struct _SRV_OPEN
#define FOBX_FLAG_UNC_NAME 0x2000000
#define FOBX_FLAG_ENCLOSED_ALLOCATED 0x4000000
#define FOBX_FLAG_MARKED_AS_DORMANT 0x8000000
#ifdef __REACTOS__
#define FOBX_FLAG_DISABLE_COLLAPSING 0x20000000
#endif
typedef struct _FOBX
{
@ -349,6 +352,7 @@ typedef struct _FOBX
#define RDBSS_REF_TRACK_NETFCB 0x00000010
#define RDBSS_REF_TRACK_SRVOPEN 0x00000020
#define RX_PRINT_REF_TRACKING 0x40000000
#define RX_LOG_REF_TRACKING 0x80000000
extern ULONG RdbssReferenceTracingValue;
@ -367,12 +371,21 @@ RxpTrackDereference(
_In_ PVOID Instance);
#define REF_TRACING_ON(TraceMask) (TraceMask & RdbssReferenceTracingValue)
#ifndef __REACTOS__
#define PRINT_REF_COUNT(TYPE, Count) \
if (REF_TRACING_ON( RDBSS_REF_TRACK_ ## TYPE) && \
(RdbssReferenceTracingValue & RX_PRINT_REF_TRACKING)) \
{ \
DbgPrint("%ld\n", Count); \
}
#else
#define PRINT_REF_COUNT(TYPE, Count) \
if (REF_TRACING_ON( RDBSS_REF_TRACK_ ## TYPE) && \
(RdbssReferenceTracingValue & RX_PRINT_REF_TRACKING)) \
{ \
DbgPrint("(%s:%d) %s: %ld\n", __FILE__, __LINE__, #TYPE, Count); \
}
#endif
#define RxReferenceSrvCall(SrvCall) \
RxpTrackReference(RDBSS_REF_TRACK_SRVCALL, __FILE__, __LINE__, SrvCall); \
@ -500,6 +513,11 @@ RxFinalizeVNetRoot(
#define RxWaitForStableVNetRoot(V, R) RxWaitForStableCondition(&(V)->Condition, &(V)->TransitionWaitList, (R), NULL)
#define RxTransitionVNetRoot(V, C) RxUpdateCondition((C), &(V)->Condition, &(V)->TransitionWaitList)
VOID
RxSetFileSizeWithLock(
_Inout_ PFCB Fcb,
_In_ PLONGLONG FileSize);
VOID
RxGetFileSizeWithLock(
_In_ PFCB Fcb,

View file

@ -323,6 +323,8 @@ typedef struct _LOWIO_CONTEXT
#define LOWIO_CONTEXT_FLAG_CAN_COMPLETE_AT_DPC_LEVEL 0x08
#define LOWIO_READWRITEFLAG_PAGING_IO 0x01
#define LOWIO_READWRITEFLAG_EXTENDING_FILESIZE 0x02
#define LOWIO_READWRITEFLAG_EXTENDING_VDL 0x04
#define RDBSS_MANAGE_SRV_CALL_EXTENSION 0x01
#define RDBSS_MANAGE_NET_ROOT_EXTENSION 0x02

View file

@ -37,6 +37,10 @@ __RxInitializeTopLevelIrpContext(
#define RxInitializeTopLevelIrpContext(a,b,c) __RxInitializeTopLevelIrpContext(a,b,c,0)
PIRP
RxGetTopIrpIfRdbssIrp(
VOID);
PRDBSS_DEVICE_OBJECT
RxGetTopDeviceObjectIfRdbssIrp(
VOID);
@ -307,6 +311,14 @@ typedef enum
RX_CONTEXT_FLAG_MINIRDR_INITIATED = 0x80000000,
} RX_CONTEXT_FLAGS;
#define RX_CONTEXT_PRESERVED_FLAGS (RX_CONTEXT_FLAG_FROM_POOL | \
RX_CONTEXT_FLAG_MUST_SUCCEED_ALLOCATED | \
RX_CONTEXT_FLAG_IN_FSP)
#define RX_CONTEXT_INITIALIZATION_FLAGS (RX_CONTEXT_FLAG_WAIT | \
RX_CONTEXT_FLAG_MUST_SUCCEED | \
RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING)
typedef enum
{
RX_CONTEXT_CREATE_FLAG_UNC_NAME = 0x1,
@ -329,6 +341,23 @@ typedef enum {
RXCONTEXT_FLAG4LOWIO_LOCK_BUFFERED_ON_ENTRY = 0x200
} RX_CONTEXT_LOWIO_FLAGS;
#if DBG
#define RxSaveAndSetExceptionNoBreakpointFlag(R, F) \
{ \
F = FlagOn(R->Flags, RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT); \
SetFlag(R->Flags, RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT); \
}
#define RxRestoreExceptionNoBreakpointFlag(R, F) \
{ \
ClearFlag(R->Flags, RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT); \
SetFlag(R->Flags, F); \
}
#else
#define RxSaveAndSetExceptionNoBreakpointFlag(R, F)
#define RxRestoreExceptionNoBreakpointFlag(R, F)
#endif
#if DBG
VOID
__RxItsTheSameContext(
@ -470,6 +499,11 @@ NTAPI
RxDereferenceAndDeleteRxContext_Real(
_In_ PRX_CONTEXT RxContext);
VOID
NTAPI
RxReinitializeContext(
_Inout_ PRX_CONTEXT RxContext);
#if DBG
#define RxDereferenceAndDeleteRxContext(RXCONTEXT) \
{ \

View file

@ -222,6 +222,7 @@ RxTrackPagingIoResource(
} \
RxTrackPagingIoResource(Fcb, 1, __LINE__, __FILE__)
#ifndef __REACTOS__
#define RxAcquirePagingIoResourceShared(RxContext, Fcb, Flag) \
ExAcquireResourceSharedLite((Fcb)->Header.PagingIoResource, Flag); \
if (AcquiredFile) \
@ -232,6 +233,21 @@ RxTrackPagingIoResource(
} \
RxTrackPagingIoResource(Fcb, 2, __LINE__, __FILE__); \
}
#else
#define RxAcquirePagingIoResourceShared(RxContext, Fcb, Flag) \
{ \
BOOLEAN AcquiredFile; \
AcquiredFile = ExAcquireResourceSharedLite((Fcb)->Header.PagingIoResource, Flag); \
if (AcquiredFile) \
{ \
if (RxContext != NULL) \
{ \
((PRX_CONTEXT)RxContext)->FcbPagingIoResourceAcquired = TRUE; \
} \
RxTrackPagingIoResource(Fcb, 2, __LINE__, __FILE__); \
} \
}
#endif
#define RxReleasePagingIoResource(RxContext, Fcb) \
RxTrackPagingIoResource(Fcb, 3, __LINE__, __FILE__); \
@ -249,6 +265,26 @@ RxTrackPagingIoResource(
} \
ExReleaseResourceForThreadLite((Fcb)->Header.PagingIoResource, (Thread))
#ifdef __REACTOS__
VOID
__RxWriteReleaseResources(
PRX_CONTEXT RxContext,
BOOLEAN ResourceOwnerSet
#ifdef RDBSS_TRACKER
,
ULONG LineNumber,
PCSTR FileName,
ULONG SerialNumber
#endif
);
#ifdef RDBSS_TRACKER
#define RxWriteReleaseResources(R, B) __RxWriteReleaseResources((R), (B), __LINE__, __FILE__, 0)
#else
#define RxWriteReleaseResources(R, B) __RxWriteReleaseResources((R), (B))
#endif
#endif
BOOLEAN
NTAPI
RxAcquireFcbForLazyWrite(
@ -294,6 +330,7 @@ RxPrePostIrp(
_In_ PIRP Irp);
VOID
NTAPI
RxAddToWorkque(
_In_ PRX_CONTEXT RxContext,
_In_ PIRP Irp);
@ -574,6 +611,10 @@ NTSTATUS
RxPurgeFobxFromCache(
PFOBX FobxToBePurged);
BOOLEAN
RxPurgeFobx(
PFOBX pFobx);
VOID
RxUndoScavengerFinalizationMarking(
PVOID Instance);
@ -745,4 +786,10 @@ RxCancelRoutine(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp);
#ifdef __REACTOS__
#define RxWriteCacheingAllowed(F, S) ( \
BooleanFlagOn((F)->FcbState, FCB_STATE_WRITECACHING_ENABLED) && \
!BooleanFlagOn((S)->Flags, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING))
#endif
#endif

View file

@ -35,6 +35,16 @@ VOID
RxMarkFobxOnClose(
_In_ PFOBX Fobx);
NTSTATUS
RxPurgeRelatedFobxs(
PNET_ROOT NetRoot,
PRX_CONTEXT RxContext,
BOOLEAN AttemptFinalization,
PFCB PurgingFcb);
#define DONT_ATTEMPT_FINALIZE_ON_PURGE FALSE
#define ATTEMPT_FINALIZE_ON_PURGE TRUE
typedef enum _RDBSS_SCAVENGER_STATE
{
RDBSS_SCAVENGER_INACTIVE,
@ -116,6 +126,12 @@ BOOLEAN
RxScavengeRelatedFobxs(
_In_ PFCB Fcb);
VOID
RxScavengeFobxsForNetRoot(
PNET_ROOT NetRoot,
PFCB PurgingFcb,
BOOLEAN SynchronizeWithScavenger);
VOID
RxpMarkInstanceForScavengedFinalization(
PVOID Instance);

File diff suppressed because it is too large Load diff

View file

@ -121,7 +121,14 @@ BOOLEAN RxStopOnLoudCompletion = TRUE;
BOOLEAN RxSrvCallConstructionDispatcherActive = FALSE;
LIST_ENTRY RxSrvCalldownList;
RX_SPIN_LOCK RxStrucSupSpinLock;
ULONG RdbssReferenceTracingValue;
#if 0
ULONG RdbssReferenceTracingValue = (RDBSS_REF_TRACK_SRVCALL | RDBSS_REF_TRACK_NETROOT |
RDBSS_REF_TRACK_VNETROOT | RDBSS_REF_TRACK_NETFOBX |
RDBSS_REF_TRACK_NETFCB | RDBSS_REF_TRACK_SRVOPEN |
RX_PRINT_REF_TRACKING);
#else
ULONG RdbssReferenceTracingValue = 0;
#endif
LARGE_INTEGER RxWorkQueueWaitInterval[RxMaximumWorkQueue];
LARGE_INTEGER RxSpinUpDispatcherWaitInterval;
RX_DISPATCHER RxDispatcher;
@ -2906,7 +2913,7 @@ RxFinalizeNetRoot(
HashBucket = &FcbTable->HashBuckets[Bucket];
ListEntry = HashBucket->Flink;
while (ListEntry != HashBucket)
{
{
PFCB Fcb;
Fcb = CONTAINING_RECORD(ListEntry, FCB, FcbTableEntry.HashLinks);
@ -3866,7 +3873,7 @@ RxFinishFcbInitialization(
{
/* If our FCB newly points to a file, initiliaze everything related */
if (FileType == RDBSS_NTC_STORAGE_TYPE_FILE)
{
if (OldType != RDBSS_NTC_STORAGE_TYPE_FILE)
{
@ -6302,7 +6309,7 @@ RxPrefixTableLookupName(
{
NODE_TYPE_CODE Type;
Type = NodeType(Container);
Type = (NodeType(Container) & ~RX_SCAVENGER_MASK);
switch (Type)
{
case RDBSS_NTC_SRVCALL:
@ -6318,7 +6325,9 @@ RxPrefixTableLookupName(
break;
default:
DPRINT1("Invalid node type: %x\n", Type);
ASSERT(FALSE);
RxReference(Container);
break;
}
}
@ -6479,6 +6488,43 @@ RxProcessFcbChangeBufferingStateRequest(
UNIMPLEMENTED;
}
/*
* @implemented
*/
VOID
RxpScavengeFobxs(
PRDBSS_SCAVENGER Scavenger,
PLIST_ENTRY FobxToScavenge)
{
/* Explore the whole list of FOBX to scavenge */
while (!IsListEmpty(FobxToScavenge))
{
PFCB Fcb;
PFOBX Fobx;
PLIST_ENTRY Entry;
Entry = RemoveHeadList(FobxToScavenge);
Fobx = CONTAINING_RECORD(Entry, FOBX, ScavengerFinalizationList);
Fcb = (PFCB)Fobx->SrvOpen->pFcb;
/* Try to acquire the lock exclusively to perform finalization */
if (RxAcquireExclusiveFcb(NULL, Fcb) != STATUS_SUCCESS)
{
RxDereferenceNetRoot(Fobx, LHS_LockNotHeld);
}
else
{
RxReferenceNetFcb(Fcb);
RxDereferenceNetRoot(Fobx, LHS_ExclusiveLockHeld);
if (!RxDereferenceAndFinalizeNetFcb(Fcb, NULL, FALSE, FALSE))
{
RxReleaseFcb(NULL, Fcb);
}
}
}
}
BOOLEAN
RxpTrackDereference(
_In_ ULONG TraceType,
@ -6486,6 +6532,9 @@ RxpTrackDereference(
_In_ ULONG Line,
_In_ PVOID Instance)
{
PCSTR InstanceType;
ULONG ReferenceCount;
PAGED_CODE();
if (!BooleanFlagOn(RdbssReferenceTracingValue, TraceType))
@ -6493,7 +6542,53 @@ RxpTrackDereference(
return TRUE;
}
UNIMPLEMENTED;
switch (TraceType)
{
case RDBSS_REF_TRACK_SRVCALL:
InstanceType = "SrvCall";
ReferenceCount = ((PSRV_CALL)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_NETROOT:
InstanceType = "NetRoot";
ReferenceCount = ((PNET_ROOT)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_VNETROOT:
InstanceType = "VNetRoot";
ReferenceCount = ((PV_NET_ROOT)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_NETFOBX:
InstanceType = "NetFobx";
ReferenceCount = ((PFOBX)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_NETFCB:
InstanceType = "NetFcb";
ReferenceCount = ((PFCB)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_SRVOPEN:
InstanceType = "SrvOpen";
ReferenceCount = ((PSRV_OPEN)Instance)->NodeReferenceCount;
break;
default:
DPRINT1("Invalid node type!\n");
return TRUE;
}
if (BooleanFlagOn(RdbssReferenceTracingValue, RX_LOG_REF_TRACKING))
{
UNIMPLEMENTED;
}
if (BooleanFlagOn(RdbssReferenceTracingValue, RX_PRINT_REF_TRACKING))
{
DbgPrint("(%s:%d) %p (%s) dereferenced from %d\n", FileName, Line, Instance, InstanceType, ReferenceCount);
}
return TRUE;
}
@ -6504,12 +6599,60 @@ RxpTrackReference(
_In_ ULONG Line,
_In_ PVOID Instance)
{
PCSTR InstanceType;
ULONG ReferenceCount;
if (!BooleanFlagOn(RdbssReferenceTracingValue, TraceType))
{
return;
}
UNIMPLEMENTED;
switch (TraceType)
{
case RDBSS_REF_TRACK_SRVCALL:
InstanceType = "SrvCall";
ReferenceCount = ((PSRV_CALL)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_NETROOT:
InstanceType = "NetRoot";
ReferenceCount = ((PNET_ROOT)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_VNETROOT:
InstanceType = "VNetRoot";
ReferenceCount = ((PV_NET_ROOT)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_NETFOBX:
InstanceType = "NetFobx";
ReferenceCount = ((PFOBX)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_NETFCB:
InstanceType = "NetFcb";
ReferenceCount = ((PFCB)Instance)->NodeReferenceCount;
break;
case RDBSS_REF_TRACK_SRVOPEN:
InstanceType = "SrvOpen";
ReferenceCount = ((PSRV_OPEN)Instance)->NodeReferenceCount;
break;
default:
DPRINT1("Invalid node type!\n");
return;
}
if (BooleanFlagOn(RdbssReferenceTracingValue, RX_LOG_REF_TRACKING))
{
UNIMPLEMENTED;
}
if (BooleanFlagOn(RdbssReferenceTracingValue, RX_PRINT_REF_TRACKING))
{
DbgPrint("(%s:%d) %p (%s) referenced from %d\n", FileName, Line, Instance, InstanceType, ReferenceCount);
}
}
/*
@ -6698,6 +6841,42 @@ RxPurgeFcbInSystemCache(
return Status;
}
/*
* @implemented
*/
BOOLEAN
RxPurgeFobx(
PFOBX pFobx)
{
NTSTATUS Status;
PFCB FcbToBePurged;
PAGED_CODE();
/* Get the associated FCB */
FcbToBePurged = (PFCB)pFobx->pSrvOpen->pFcb;
Status = RxAcquireExclusiveFcb(NULL, FcbToBePurged);
ASSERT(Status == STATUS_SUCCESS);
/* Purge it */
Status = RxPurgeFcbInSystemCache(FcbToBePurged, NULL, 0, FALSE, TRUE);
if (Status != STATUS_SUCCESS)
{
DPRINT1("Purge failed for %p (%p)\n", FcbToBePurged, pFobx);
return FALSE;
}
/* And flush */
if (!MmFlushImageSection(&FcbToBePurged->NonPaged->SectionObjectPointers, MmFlushForWrite))
{
DPRINT1("Image section flush failed for %p (%p)\n", FcbToBePurged, pFobx);
return FALSE;
}
DPRINT("Purge OK for %p (%p)\n", FcbToBePurged, pFobx);
return TRUE;
}
/*
* @implemented
*/
@ -6744,6 +6923,155 @@ RxPurgeFobxFromCache(
return Status;
}
/*
* @implemented
*/
NTSTATUS
RxPurgeRelatedFobxs(
PNET_ROOT NetRoot,
PRX_CONTEXT RxContext,
BOOLEAN AttemptFinalization,
PFCB PurgingFcb)
{
PLIST_ENTRY Entry;
ULONG SuccessfullPurge;
PRDBSS_SCAVENGER Scavenger;
PRDBSS_DEVICE_OBJECT RxDeviceObject;
PPURGE_SYNCHRONIZATION_CONTEXT PurgeSyncCtx;
PAGED_CODE();
RxDeviceObject = RxContext->RxDeviceObject;
Scavenger = RxDeviceObject->pRdbssScavenger;
PurgeSyncCtx = &NetRoot->PurgeSyncronizationContext;
RxAcquireScavengerMutex();
/* If there's already a purge in progress */
if (PurgeSyncCtx->PurgeInProgress)
{
/* Add our RX_CONTEXT to the current run */
InsertTailList(&PurgeSyncCtx->ContextsAwaitingPurgeCompletion,
&RxContext->RxContextSerializationQLinks);
/* And wait until it's done */
RxReleaseScavengerMutex();
RxWaitSync(RxContext);
RxAcquireScavengerMutex();
}
/* Start the purge */
PurgeSyncCtx->PurgeInProgress = TRUE;
/* While the purge is still handling our NET_ROOT, do nothing but wait */
while (Scavenger->CurrentNetRootForClosePendingProcessing == NetRoot)
{
RxReleaseScavengerMutex();
KeWaitForSingleObject(&Scavenger->ClosePendingProcessingSyncEvent, Executive,
KernelMode, TRUE, NULL);
RxAcquireScavengerMutex();
}
/* Now, for all the entries */
SuccessfullPurge = 0;
Entry = Scavenger->ClosePendingFobxsList.Flink;
while (Entry != &Scavenger->ClosePendingFobxsList)
{
PFCB Fcb;
PFOBX Fobx;
BOOLEAN Success;
Fobx = CONTAINING_RECORD(Entry, FOBX, ClosePendingList);
DPRINT("Dealing with FOBX: %p\n", Fobx);
Entry = Entry->Flink;
/* If it's not matching our NET_ROOT, ignore */
if (Fobx->pSrvOpen == NULL ||
Fobx->pSrvOpen->pFcb == NULL ||
((PFCB)Fobx->pSrvOpen->pFcb)->VNetRoot == NULL ||
(PNET_ROOT)((PFCB)Fobx->pSrvOpen->pFcb)->VNetRoot->pNetRoot != NetRoot)
{
continue;
}
/* Determine if it matches our FCB */
Fcb = (PFCB)Fobx->pSrvOpen->pFcb;
if (PurgingFcb != NULL && NodeType(PurgingFcb) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY &&
PurgingFcb != Fcb)
{
NTSTATUS Status;
MINIRDR_CALL_THROUGH(Status, RxDeviceObject->Dispatch, MRxAreFilesAliased, (Fcb, PurgingFcb));
if (Status == STATUS_SUCCESS)
{
continue;
}
}
/* Matching, we'll purge it */
RemoveEntryList(&Fobx->ClosePendingList);
/* Reference it so that it doesn't disappear */
RxReferenceNetFobx(Fobx);
RxReleaseScavengerMutex();
/* And purge */
Success = RxPurgeFobx(Fobx);
if (Success)
{
++SuccessfullPurge;
}
/* If we don't have to finalize it (or if we cannot acquire lock exclusively
* Just normally dereference
*/
if ((AttemptFinalization == DONT_ATTEMPT_FINALIZE_ON_PURGE) ||
RxAcquireExclusiveFcb(NULL, Fcb) != STATUS_SUCCESS)
{
RxDereferenceNetFobx(Fobx, LHS_LockNotHeld);
}
/* Otherwise, finalize */
else
{
RxReferenceNetFcb(Fcb);
RxDereferenceNetFobx(Fobx, LHS_ExclusiveLockHeld);
if (!RxDereferenceAndFinalizeNetFcb(Fcb, NULL, FALSE, FALSE))
{
RxReleaseFcb(NULL, Fcb);
}
}
if (!Success)
{
DPRINT1("Failed purging %p (%p)\n", Fcb, Fobx);
}
RxAcquireScavengerMutex();
}
/* If no contexts left, purge is not running */
if (IsListEmpty(&PurgeSyncCtx->ContextsAwaitingPurgeCompletion))
{
PurgeSyncCtx->PurgeInProgress = FALSE;
}
/* Otherwise, notify a waiter it can start */
else
{
PRX_CONTEXT Context;
Entry = RemoveHeadList(&PurgeSyncCtx->ContextsAwaitingPurgeCompletion);
Context = CONTAINING_RECORD(Entry, RX_CONTEXT, RxContextSerializationQLinks);
RxSignalSynchronousWaiter(Context);
}
RxReleaseScavengerMutex();
return (SuccessfullPurge > 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
}
/*
* @implemented
*/
@ -6954,6 +7282,38 @@ RxReference(
RxReleaseScavengerMutex();
}
/*
* @implemented
*/
VOID
NTAPI
RxReinitializeContext(
IN OUT PRX_CONTEXT RxContext)
{
PIRP Irp;
PRDBSS_DEVICE_OBJECT RxDeviceObject;
ULONG InitialContextFlags, SavedFlags;
PAGED_CODE();
/* Backup a few flags */
Irp = RxContext->CurrentIrp;
RxDeviceObject = RxContext->RxDeviceObject;
SavedFlags = RxContext->Flags & RX_CONTEXT_PRESERVED_FLAGS;
InitialContextFlags = RxContext->Flags & RX_CONTEXT_INITIALIZATION_FLAGS;
/* Reset our context */
RxPrepareContextForReuse(RxContext);
/* Zero everything */
RtlZeroMemory(&RxContext->MajorFunction, sizeof(RX_CONTEXT) - FIELD_OFFSET(RX_CONTEXT, MajorFunction));
/* Restore saved flags */
RxContext->Flags = SavedFlags;
/* And reinit the context */
RxInitializeContext(Irp, RxDeviceObject, InitialContextFlags, RxContext);
}
/*
* @implemented
*/
@ -7106,6 +7466,110 @@ RxResumeBlockedOperations_Serially(
RxReleaseSerializationMutex();
}
/*
* @implemented
*/
VOID
RxSetFileSizeWithLock(
IN OUT PFCB Fcb,
IN PLONGLONG FileSize)
{
PAGED_CODE();
/* Set attribute and increase version */
Fcb->Header.FileSize.QuadPart = *FileSize;
++Fcb->ulFileSizeVersion;
}
/*
* @implemented
*/
VOID
RxScavengeFobxsForNetRoot(
PNET_ROOT NetRoot,
PFCB PurgingFcb,
BOOLEAN SynchronizeWithScavenger)
{
PRDBSS_SCAVENGER Scavenger;
PRDBSS_DEVICE_OBJECT RxDeviceObject;
PAGED_CODE();
RxDeviceObject = NetRoot->pSrvCall->RxDeviceObject;
Scavenger = RxDeviceObject->pRdbssScavenger;
/* Wait for the scavenger, if asked to */
if (SynchronizeWithScavenger)
{
KeWaitForSingleObject(&Scavenger->SyncEvent, Executive, KernelMode, FALSE, NULL);
}
RxAcquireScavengerMutex();
/* If there's nothing left to do... */
if (Scavenger->FobxsToBeFinalized <= 0)
{
RxReleaseScavengerMutex();
}
else
{
PLIST_ENTRY Entry;
LIST_ENTRY FobxToScavenge;
InitializeListHead(&FobxToScavenge);
/* Browse all the FOBXs to finalize */
Entry = Scavenger->FobxFinalizationList.Flink;
while (Entry != &Scavenger->FobxFinalizationList)
{
PFOBX Fobx;
Fobx = CONTAINING_RECORD(Entry, FOBX, ScavengerFinalizationList);
Entry = Entry->Flink;
if (Fobx->SrvOpen != NULL)
{
PFCB Fcb;
Fcb = (PFCB)Fobx->SrvOpen->pFcb;
/* If it matches our NET_ROOT */
if ((PNET_ROOT)Fcb->pNetRoot == NetRoot)
{
NTSTATUS Status;
/* Check whether it matches our FCB */
Status = STATUS_MORE_PROCESSING_REQUIRED;
if (PurgingFcb != NULL && PurgingFcb != Fcb)
{
MINIRDR_CALL_THROUGH(Status, RxDeviceObject->Dispatch, MRxAreFilesAliased, (Fcb, PurgingFcb));
}
/* If so, add it to the list of the FOBXs to scavenge */
if (Status != STATUS_SUCCESS)
{
RxReferenceNetFobx(Fobx);
ASSERT(NodeType(Fobx) == RDBSS_NTC_FOBX);
RemoveEntryList(&Fobx->ScavengerFinalizationList);
InsertTailList(&FobxToScavenge, &Fobx->ScavengerFinalizationList);
}
}
}
}
RxReleaseScavengerMutex();
/* Now, scavenge all the extracted FOBX */
RxpScavengeFobxs(Scavenger, &FobxToScavenge);
}
if (SynchronizeWithScavenger)
{
KeSetEvent(&Scavenger->SyncEvent, IO_NO_INCREMENT, FALSE);
}
}
/*
* @implemented
*/