mirror of
https://github.com/reactos/reactos.git
synced 2025-05-30 22:49:12 +00:00
[RDBSS]
- 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:
parent
30a8a02f54
commit
f8e1661549
7 changed files with 1922 additions and 17 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
{ \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue