#define AFS_MAX_FCBS_TO_DROP 10
-static AFSExtent *ExtentFor( PLIST_ENTRY le, ULONG SkipList );
-static AFSExtent *NextExtent( AFSExtent *Extent, ULONG SkipList );
static ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
static VOID VerifyExtentsLists(AFSFcb *Fcb);
static AFSExtent *DirtyExtentFor(PLIST_ENTRY le);
VOID
AFSLockForExtentsTrim( IN AFSFcb *Fcb)
{
- NTSTATUS ntStatus;
- AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
- "AFSLockForExtentsTrim Acuiring Fcb extents lock %08lX EXCL %08lX\n",
- &pNPFcb->Specific.File.ExtentsResource,
+ "AFSLockForExtentsTrim Acquiring Fcb extents lock %08lX EXCL %08lX\n",
+ &Fcb->NPFcb->Specific.File.ExtentsResource,
PsGetCurrentThread());
- AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
+ AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
return;
}
BOOLEAN
AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
{
- AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
- "AFSLockForExtentsTrimNoWait Attempting to acquiring Fcb extent lock %08lX EXCL %08lX\n",
- &pNPFcb->Specific.File.ExtentsResource,
+ "AFSLockForExtentsTrimNoWait Attempting to acquire Fcb extent lock %08lX EXCL %08lX\n",
+ &Fcb->NPFcb->Specific.File.ExtentsResource,
PsGetCurrentThread());
- if (!AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, FALSE ))
+ if (!AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, FALSE ))
{
//
// Couldn't lock immediately
AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
"AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
- &pNPFcb->Specific.File.ExtentsResource,
+ &Fcb->NPFcb->Specific.File.ExtentsResource,
PsGetCurrentThread());
return FALSE;
return TRUE;
}
+
+static VOID
+AFSFreeExtent( IN AFSFcb *Fcb,
+ IN AFSExtent *pExtent)
+{
+ AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
+ LONG lCount;
+
+ for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
+ {
+ if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
+ {
+ RemoveEntryList( &pExtent->Lists[i] );
+ }
+ }
+
+ InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
+
+ InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
+
+ lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+
+ lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
+
+ if( lCount == 0)
+ {
+
+ KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
+ 0,
+ FALSE);
+ }
+
+ AFSExFreePoolWithTag( pExtent, AFS_EXTENT_TAG);
+}
+
//
-// Pull all the extents away from the FCB.
+// AFSTearDownFcbExtents was originally written to
+// remove all of the extents from an FCB. For that to happen
+// it must be an invariant that the extent list cannot change
+// from the moment the caller decides to execute AFSTearDownFcbExtents
+// until it returns. This invariant does not hold because the
+// the decision to call AFSTearDownFcbExtents is made without
+// holding the ExtentsResource and it is possible that extents
+// are in active use. Therefore, AFSTearDownFcbExtents now releases
+// as many non-active extents as it can.
//
-BOOLEAN
+VOID
AFSTearDownFcbExtents( IN AFSFcb *Fcb,
IN GUID *AuthGroup)
{
- BOOLEAN bFoundExtents = FALSE;
AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
- LIST_ENTRY *le;
+ LIST_ENTRY *le, *leNext;
AFSExtent *pEntry;
- ULONG ulCount = 0, ulReleaseCount = 0, ulProcessCount = 0;
+ LONG lExtentCount = 0, lProcessCount = 0;
+ ULONG ulReleaseCount = 0;
size_t sz;
AFSReleaseExtentsCB *pRelease = NULL;
BOOLEAN locked = FALSE;
try_return ( ntStatus = STATUS_SUCCESS);
}
- //
- // Release a max of 100 extents at a time
- //
-
sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
}
- le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
-
- ulCount = Fcb->Specific.File.ExtentCount;
+ AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
+ TRUE);
- while( ulReleaseCount < ulCount)
+ for( le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink,
+ lExtentCount = 0;
+ lExtentCount < Fcb->Specific.File.ExtentCount;
+ lExtentCount += lProcessCount)
{
- bFoundExtents = TRUE;
-
RtlZeroMemory( pRelease,
sizeof( AFSReleaseExtentsCB ) +
(AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
- if( ulCount - ulReleaseCount <= AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
- {
- ulProcessCount = ulCount - ulReleaseCount;
- }
- else
+ for( lProcessCount = 0, ulReleaseCount = 0;
+ !IsListEmpty( le) &&
+ ulReleaseCount < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
+ lExtentCount + lProcessCount < Fcb->Specific.File.ExtentCount;
+ lProcessCount++, le = leNext)
{
- ulProcessCount = AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
- }
-
- pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
- pRelease->ExtentCount = ulProcessCount;
- //
- // Update the metadata for this call
- //
-
- pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
- pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
- pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
- pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
- pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
-
- ulProcessCount = 0;
+ leNext = le->Flink;
- while (ulProcessCount < pRelease->ExtentCount)
- {
pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
- pRelease->FileExtents[ulProcessCount].Flags = AFS_EXTENT_FLAG_RELEASE;
+ if( pEntry->ActiveCount == 0)
+ {
+
+ pRelease->FileExtents[ulReleaseCount].Flags = AFS_EXTENT_FLAG_RELEASE;
#if GEN_MD5
- RtlCopyMemory( pRelease->FileExtents[ulProcessCount].MD5,
- pEntry->MD5,
- sizeof(pEntry->MD5));
+ RtlCopyMemory( pRelease->FileExtents[ulReleaseCount].MD5,
+ pEntry->MD5,
+ sizeof(pEntry->MD5));
- pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
+ pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
#endif
- if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
- {
-
- AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
- TRUE);
-
if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
{
AFSRemoveEntryDirtyList( Fcb,
pEntry);
- pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
+ pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
ASSERT( dirtyCount >= 0);
}
- AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
+ AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
+ pEntry,
+ Fcb->ObjectInformation->FileId.Cell,
+ Fcb->ObjectInformation->FileId.Volume,
+ Fcb->ObjectInformation->FileId.Vnode,
+ Fcb->ObjectInformation->FileId.Unique,
+ pEntry->FileOffset.HighPart,
+ pEntry->FileOffset.LowPart,
+ pEntry->Size);
+
+ pRelease->FileExtents[ulReleaseCount].Length = pEntry->Size;
+ pRelease->FileExtents[ulReleaseCount].DirtyLength = pEntry->Size;
+ pRelease->FileExtents[ulReleaseCount].DirtyOffset = 0;
+ pRelease->FileExtents[ulReleaseCount].CacheOffset = pEntry->CacheOffset;
+ pRelease->FileExtents[ulReleaseCount].FileOffset = pEntry->FileOffset;
+
+ ulReleaseCount++;
+
+ AFSFreeExtent( Fcb,
+ pEntry);
}
+ }
- AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
- AFS_TRACE_LEVEL_VERBOSE,
- "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
- pEntry,
- Fcb->ObjectInformation->FileId.Cell,
- Fcb->ObjectInformation->FileId.Volume,
- Fcb->ObjectInformation->FileId.Vnode,
- Fcb->ObjectInformation->FileId.Unique,
- pEntry->FileOffset.HighPart,
- pEntry->FileOffset.LowPart,
- pEntry->Size);
+ if ( ulReleaseCount > 0)
+ {
- pRelease->FileExtents[ulProcessCount].Length = pEntry->Size;
- pRelease->FileExtents[ulProcessCount].DirtyLength = pEntry->Size;
- pRelease->FileExtents[ulProcessCount].DirtyOffset = 0;
- pRelease->FileExtents[ulProcessCount].CacheOffset = pEntry->CacheOffset;
- pRelease->FileExtents[ulProcessCount].FileOffset = pEntry->FileOffset;
+ pRelease->ExtentCount = ulReleaseCount;
- InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pEntry->Size/1024)));
+ pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
- InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pEntry->Size/1024)));
+ //
+ // Update the metadata for this call
+ //
- ASSERT( pEntry->ActiveCount == 0);
+ pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
+ pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
+ pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
+ pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
+ pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
- ulProcessCount ++;
- le = le->Flink;
- AFSExFreePool( pEntry);
+ //
+ // Send the request down. We cannot send this down
+ // asynchronously - if we did that we could request them
+ // back before the service got this request and then this
+ // request would be a corruption.
+ //
- lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+ sz = sizeof( AFSReleaseExtentsCB ) + (lProcessCount * sizeof ( AFSFileExtentCB ));
- lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
+ ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
+ AFS_REQUEST_FLAG_SYNCHRONOUS,
+ pAuthGroup,
+ NULL,
+ &Fcb->ObjectInformation->FileId,
+ pRelease,
+ sz,
+ NULL,
+ NULL);
- if( lCount == 0)
+ if( !NT_SUCCESS(ntStatus))
{
- KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
- 0,
- FALSE);
- }
- }
-
- //
- // Send the request down. We cannot send this down
- // asynchronously - if we did that we could request them
- // back before the service got this request and then this
- // request would be a corruption.
- //
-
- sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
-
- ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
- AFS_REQUEST_FLAG_SYNCHRONOUS,
- pAuthGroup,
- NULL,
- &Fcb->ObjectInformation->FileId,
- pRelease,
- sz,
- NULL,
- NULL);
-
- if( !NT_SUCCESS(ntStatus))
- {
-
- //
- // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
- // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
- //
+ //
+ // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
+ // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
+ //
- AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
- AFS_TRACE_LEVEL_ERROR,
- "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
- Fcb->ObjectInformation->FileId.Cell,
- Fcb->ObjectInformation->FileId.Volume,
- Fcb->ObjectInformation->FileId.Vnode,
- Fcb->ObjectInformation->FileId.Unique,
- ntStatus);
+ AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
+ AFS_TRACE_LEVEL_ERROR,
+ "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+ Fcb->ObjectInformation->FileId.Cell,
+ Fcb->ObjectInformation->FileId.Volume,
+ Fcb->ObjectInformation->FileId.Vnode,
+ Fcb->ObjectInformation->FileId.Unique,
+ ntStatus);
+ }
}
-
- ulReleaseCount += ulProcessCount;
}
+ AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
+
//
- // Reinitialize the skip lists
+ // if all extents have been released, reinitialize the skip lists
//
- ASSERT( Fcb->Specific.File.ExtentCount == 0);
-
- for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
+ if( Fcb->Specific.File.ExtentCount == 0)
{
- InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
- }
- //
- // Reinitialize the dirty list as well
- //
+ for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
+ {
+ InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
+ }
- AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
- TRUE);
+ //
+ // Reinitialize the dirty list as well
+ //
- ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
+ AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
+ TRUE);
- Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
- Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
+ ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
- AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
+ Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
+ Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
+
+ AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
+ }
Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
if (pRelease)
{
- AFSExFreePool( pRelease);
+ AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
}
}
-
- return bFoundExtents;
}
static PAFSExtent
__Enter
{
- AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
- AFS_TRACE_LEVEL_VERBOSE,
- "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
- &Fcb->NPFcb->Specific.File.ExtentsResource,
- PsGetCurrentThread());
-
- AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
+ ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
- entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
- *FirstExtent = entry;
-
- if (NULL == entry || !AFSExtentContains(entry, Offset))
- {
- try_return (retVal = FALSE);
- }
-
- ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
-
- while (TRUE)
+ __try
{
- if ((entry->FileOffset.QuadPart + entry->Size) >=
- (Offset->QuadPart + Size))
- {
- //
- // The end is inside the extent
- //
- try_return (retVal = TRUE);
- }
+ entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
+ *FirstExtent = entry;
- if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
+ if (NULL == entry || !AFSExtentContains(entry, Offset))
{
- //
- // Run out of extents
- //
try_return (retVal = FALSE);
}
- newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
+ ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
- if (newEntry->FileOffset.QuadPart !=
- (entry->FileOffset.QuadPart + entry->Size))
+ while (TRUE)
{
- //
- // Gap
- //
- try_return (retVal = FALSE);
- }
+ if ((entry->FileOffset.QuadPart + entry->Size) >=
+ (Offset->QuadPart + Size))
+ {
+ //
+ // The end is inside the extent
+ //
+ try_return (retVal = TRUE);
+ }
+
+ if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
+ {
+ //
+ // Run out of extents
+ //
+ try_return (retVal = FALSE);
+ }
- entry = newEntry;
+ newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
+
+ if (newEntry->FileOffset.QuadPart !=
+ (entry->FileOffset.QuadPart + entry->Size))
+ {
+ //
+ // Gap
+ //
+ try_return (retVal = FALSE);
+ }
+
+ entry = newEntry;
+ }
}
+ __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
+ {
-try_exit:
+ AFSDbgLogMsg( 0,
+ 0,
+ "EXCEPTION - AFSDoExtentsMapRegion\n");
- AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
- AFS_TRACE_LEVEL_VERBOSE,
- "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
- &Fcb->NPFcb->Specific.File.ExtentsResource,
- PsGetCurrentThread());
+ AFSDumpTraceFilesFnc();
+ }
- AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
+try_exit:
*LastExtent = entry;
}
// Check if we are already mapped
//
+ AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSRequestExtentsAsync Acquiring Fcb extents lock %08lX SHARED %08lX\n",
+ &pNPFcb->Specific.File.ExtentsResource,
+ PsGetCurrentThread());
+
+ AFSAcquireShared( &pNPFcb->Specific.File.ExtentsResource, TRUE );
+
bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
if( bRegionMapped)
{
+ KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
+ }
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSRequestExtentsAsync Releasing Fcb extents lock %08lX SHARED %08lX\n",
+ &pNPFcb->Specific.File.ExtentsResource,
+ PsGetCurrentThread());
+
+ AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
+
+ if ( bRegionMapped)
+ {
+
try_return( ntStatus = STATUS_SUCCESS);
}
request.Length))
{
+ KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
+
AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
"AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
}
}
- if( NT_SUCCESS( ntStatus))
+ if( !NT_SUCCESS( ntStatus))
{
- KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
+ KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
+ 0,
+ FALSE);
}
}
- else
- {
-
- KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
- }
try_exit:
if (NULL == pExtent)
{
- ASSERT( FALSE);
-
try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
}
// Reference the node so it won't be torn down
//
- lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
+ lCount = AFSObjectInfoIncrement( pObjectInfo);
AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
AFS_TRACE_LEVEL_VERBOSE,
if( pObjectInfo != NULL)
{
- lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
+ lCount = AFSObjectInfoDecrement( pObjectInfo);
AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
AFS_TRACE_LEVEL_VERBOSE,
ulExtentCount ++;
*ExtentCount = (*ExtentCount) + 1;
- //
- // And unpick
- //
- for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
- {
- if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
- {
- RemoveEntryList( &pExtent->Lists[i] );
- }
- }
-
- InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
-
- InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
-
- //
- // and free
- //
- AFSExFreePool( pExtent);
-
- lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
-
- lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
-
- if( lCount == 0)
- {
-
- KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
- 0,
- FALSE);
- }
+ AFSFreeExtent( Fcb,
+ pExtent);
}
try_exit:
// A hit a very palpable hit. Pin it
//
- lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
+ lCount = AFSObjectInfoIncrement( pCurrentObject);
AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
AFS_TRACE_LEVEL_VERBOSE,
// Reference the node so it won't be torn down
//
- lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
+ lCount = AFSObjectInfoIncrement( pObjectInfo);
AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
AFS_TRACE_LEVEL_VERBOSE,
AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
- lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
+ lCount = AFSObjectInfoDecrement( pObjectInfo);
AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
AFS_TRACE_LEVEL_VERBOSE,
// Reference the node so it won't be torn down
//
- lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
+ lCount = AFSObjectInfoIncrement( pObjectInfo);
AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
AFS_TRACE_LEVEL_VERBOSE,
Irp->AssociatedIrp.SystemBuffer != pResult)
{
- AFSExFreePool(pResult);
+ AFSExFreePoolWithTag(pResult, AFS_EXTENTS_RESULT_TAG);
}
if (NT_SUCCESS(ntStatus))
if( pObjectInfo != NULL)
{
- lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
+ lCount = AFSObjectInfoDecrement( pObjectInfo);
AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
AFS_TRACE_LEVEL_VERBOSE,
__Enter
{
+ lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
+
if( pAuthGroup == NULL ||
RtlCompareMemory( pAuthGroup,
&Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
bExtentsLocked = TRUE;
- lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
-
//
// Clear our queued flush event
//
pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
- //
- // Need to pull this extent from the main list as well
- //
-
- for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
- {
- if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
- {
- RemoveEntryList( &pExtent->Lists[i] );
- }
- }
-
- InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
-
- InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
-
- AFSExFreePool( pExtent);
-
- lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
-
- lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
-
- if( lCount == 0)
- {
-
- KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
- 0,
- FALSE);
- }
+ AFSFreeExtent( Fcb,
+ pExtent);
count ++;
lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
+ ASSERT( lCount >= 0);
+
if( lCount == 0)
{
if (pRelease)
{
- AFSExFreePool( pRelease);
+ AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
}
}
NTSTATUS
AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
- IN GUID *AuthGroup)
+ IN GUID *AuthGroup,
+ IN BOOLEAN bReleaseAll)
{
AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
AFSExtent *pExtent;
try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
}
- if( Fcb->OpenHandleCount > 0)
+ if( Fcb->OpenHandleCount > 0 &&
+ !bReleaseAll)
{
//
// Don't release everything ...
//
- //
- // For now release everything
- //
-
- //ulRemainingExtentLength = 1500;
+ ulRemainingExtentLength = 1024;
}
while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
}
+ AFSFreeExtent( Fcb,
+ pExtent);
+
+ count ++;
+ }
+
+ //
+ // If we are done then get out
+ //
+
+ if( count == 0)
+ {
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSReleaseExtentsWithFlush No more dirty extents found\n");
+
+ break;
+ }
+
+ //
+ // Fire off the request synchronously
+ //
+
+ sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
+
+ pRelease->ExtentCount = count;
+
+ //
+ // Drop the extents lock for the duration of the call to
+ // the network. We have pinned the extents so, even
+ // though we might get extents added during this period,
+ // but none will be removed. Hence we can carry on from
+ // le.
+ //
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
+ &pNPFcb->Specific.File.ExtentsResource,
+ PsGetCurrentThread());
+
+ AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
+ bExtentsLocked = FALSE;
+
+ ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
+ AFS_REQUEST_FLAG_SYNCHRONOUS,
+ pAuthGroup,
+ NULL,
+ &Fcb->ObjectInformation->FileId,
+ pRelease,
+ sz,
+ NULL,
+ NULL);
+
+ if( !NT_SUCCESS(ntStatus))
+ {
+
//
- // Need to pull this extent from the main list as well
+ // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
+ // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
//
- for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
- {
- if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
- {
- RemoveEntryList( &pExtent->Lists[i] );
- }
- }
+ AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
+ AFS_TRACE_LEVEL_ERROR,
+ "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+ Fcb->ObjectInformation->FileId.Cell,
+ Fcb->ObjectInformation->FileId.Volume,
+ Fcb->ObjectInformation->FileId.Vnode,
+ Fcb->ObjectInformation->FileId.Unique,
+ ntStatus);
+ }
+ }
- InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
+try_exit:
+
+ if (bExtentsLocked)
+ {
- InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
+ AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
+ &pNPFcb->Specific.File.ExtentsResource,
+ PsGetCurrentThread());
- AFSExFreePool( pExtent);
+ AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
+ }
- lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+ if (pRelease)
+ {
+ AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
+ }
+ }
- lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
+ return ntStatus;
+}
- if( lCount == 0)
- {
+NTSTATUS
+AFSReleaseCleanExtents( IN AFSFcb *Fcb,
+ IN GUID *AuthGroup)
+{
+ AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
+ AFSExtent *pExtent;
+ LIST_ENTRY *le;
+ AFSReleaseExtentsCB *pRelease = NULL;
+ ULONG count = 0;
+ ULONG initialDirtyCount = 0;
+ BOOLEAN bExtentsLocked = FALSE;
+ ULONG total = 0;
+ ULONG sz = 0;
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ LARGE_INTEGER liLastFlush;
+ ULONG ulRemainingExtentLength = 0;
+ AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
+ GUID *pAuthGroup = AuthGroup;
+ GUID stAuthGroup;
+
+ ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
+
+ //
+ // Save, then reset the flush time
+ //
- KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
- 0,
- FALSE);
+ liLastFlush = Fcb->Specific.File.LastServerFlush;
+
+ KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
+
+ __Enter
+ {
+
+ if( pAuthGroup == NULL ||
+ RtlCompareMemory( pAuthGroup,
+ &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
+ sizeof( GUID)) == sizeof( GUID))
+ {
+
+ RtlZeroMemory( &stAuthGroup,
+ sizeof( GUID));
+
+ ntStatus = AFSRetrieveValidAuthGroup( Fcb,
+ NULL,
+ TRUE,
+ &stAuthGroup);
+
+ if( !NT_SUCCESS( ntStatus))
+ {
+ try_return( ntStatus);
+ }
+
+ pAuthGroup = &stAuthGroup;
+ }
+
+ //
+ // Look for a start in the list to flush entries
+ //
+
+ total = count;
+
+ sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
+
+ pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
+ sz,
+ AFS_EXTENT_RELEASE_TAG);
+ if( NULL == pRelease)
+ {
+
+ try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
+ }
+
+ while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
+ {
+
+ AFSLockForExtentsTrim( Fcb);
+
+ bExtentsLocked = TRUE;
+
+ pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
+
+ //
+ // Update the metadata for this call
+ //
+
+ pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
+ pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
+ pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
+ pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
+ pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
+
+ count = 0;
+
+ le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
+
+ while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
+ le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
+ {
+
+ pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
+
+ le = le->Flink;
+
+ if( pExtent->ActiveCount > 0 ||
+ BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
+ {
+ continue;
}
+ pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
+ pExtent,
+ Fcb->ObjectInformation->FileId.Cell,
+ Fcb->ObjectInformation->FileId.Volume,
+ Fcb->ObjectInformation->FileId.Vnode,
+ Fcb->ObjectInformation->FileId.Unique,
+ pExtent->FileOffset.QuadPart,
+ pExtent->Size);
+
+ pRelease->FileExtents[count].Length = pExtent->Size;
+ pRelease->FileExtents[count].DirtyLength = pExtent->Size;
+ pRelease->FileExtents[count].DirtyOffset = 0;
+ pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
+ pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
+
+#if GEN_MD5
+ RtlCopyMemory( pRelease->FileExtents[count].MD5,
+ pExtent->MD5,
+ sizeof(pExtent->MD5));
+
+ pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
+#endif
+
+ AFSFreeExtent( Fcb,
+ pExtent);
+
count ++;
}
AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
- "AFSReleaseExtentsWithFlush No more dirty extents found\n");
+ "AFSReleaseCleanExtents No more dirty extents found\n");
break;
}
AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
- "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
+ "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
&pNPFcb->Specific.File.ExtentsResource,
PsGetCurrentThread());
AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
AFS_TRACE_LEVEL_ERROR,
- "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+ "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
Fcb->ObjectInformation->FileId.Cell,
Fcb->ObjectInformation->FileId.Volume,
Fcb->ObjectInformation->FileId.Vnode,
AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
- "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
+ "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
&pNPFcb->Specific.File.ExtentsResource,
PsGetCurrentThread());
if (pRelease)
{
- AFSExFreePool( pRelease);
+ AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
}
}
AFSMarkDirty( IN AFSFcb *Fcb,
IN AFSExtent *StartExtent,
IN ULONG ExtentsCount,
- IN LARGE_INTEGER *StartingByte)
+ IN LARGE_INTEGER *StartingByte,
+ IN BOOLEAN DerefExtents)
{
AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
ULONG ulCount = 0;
BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
LONG lCount;
+ BOOLEAN bLocked = FALSE;
AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
&Fcb->NPFcb->Specific.File.ExtentsResource,
PsGetCurrentThread());
- AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
+ if( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource))
+ {
+ AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
+ bLocked = TRUE;
+ }
AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
TRUE);
- //
- // Find the insertion point
- //
-
- if( pNPFcb->Specific.File.DirtyListHead == NULL)
- {
-
- bInsertTail = TRUE;
- }
- else if( StartingByte->QuadPart == 0)
+ __try
{
+ //
+ // Find the insertion point
+ //
- bInsertHead = TRUE;
- }
- else
- {
+ if( pNPFcb->Specific.File.DirtyListHead == NULL)
+ {
- pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
+ bInsertTail = TRUE;
+ }
+ else if( StartingByte->QuadPart == 0)
+ {
- while( pCurrentExtent != NULL)
+ bInsertHead = TRUE;
+ }
+ else
{
- if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
- pCurrentExtent->DirtyList.fLink == NULL)
- {
+ pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
- break;
- }
+ while( pCurrentExtent != NULL)
+ {
- pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
- }
- }
+ if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
+ pCurrentExtent->DirtyList.fLink == NULL)
+ {
- while( ulCount < ExtentsCount)
- {
+ break;
+ }
- pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
+ pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
+ }
+ }
- if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
+ while( ulCount < ExtentsCount)
{
- AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
- AFS_TRACE_LEVEL_VERBOSE,
- "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
- pExtent->FileOffset.QuadPart,
- pExtent->Size);
-
- pExtent->DirtyList.fLink = NULL;
- pExtent->DirtyList.bLink = NULL;
+ pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
- if( bInsertHead)
+ if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
{
- pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
+ AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
+ pExtent->FileOffset.QuadPart,
+ pExtent->Size);
+ pExtent->DirtyList.fLink = NULL;
pExtent->DirtyList.bLink = NULL;
- pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
+ if( bInsertHead)
+ {
- pNPFcb->Specific.File.DirtyListHead = pExtent;
+ pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
- pCurrentExtent = pExtent;
+ pExtent->DirtyList.bLink = NULL;
- bInsertHead = FALSE;
- }
- else if( bInsertTail)
- {
-
- if( pNPFcb->Specific.File.DirtyListHead == NULL)
- {
+ pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
pNPFcb->Specific.File.DirtyListHead = pExtent;
- }
- else
- {
- pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
+ pCurrentExtent = pExtent;
- pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
+ bInsertHead = FALSE;
}
+ else if( bInsertTail)
+ {
- pNPFcb->Specific.File.DirtyListTail = pExtent;
- }
- else
- {
+ if( pNPFcb->Specific.File.DirtyListHead == NULL)
+ {
- pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
- pExtent->DirtyList.bLink = (void *)pCurrentExtent;
+ pNPFcb->Specific.File.DirtyListHead = pExtent;
+ }
+ else
+ {
- if( pExtent->DirtyList.fLink == NULL)
- {
+ pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
+
+ pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
+ }
pNPFcb->Specific.File.DirtyListTail = pExtent;
}
else
{
- ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
+ pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
+
+ pExtent->DirtyList.bLink = (void *)pCurrentExtent;
+
+ if( pExtent->DirtyList.fLink == NULL)
+ {
+
+ pNPFcb->Specific.File.DirtyListTail = pExtent;
+ }
+ else
+ {
+
+ ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
+ }
+
+ pCurrentExtent->DirtyList.fLink = (void *)pExtent;
+
+ pCurrentExtent = pExtent;
}
- pCurrentExtent->DirtyList.fLink = (void *)pExtent;
+ pExtent->Flags |= AFS_EXTENT_DIRTY;
+
+ //
+ // Up the dirty count
+ //
+
+ lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
+ }
+ else
+ {
pCurrentExtent = pExtent;
}
- pExtent->Flags |= AFS_EXTENT_DIRTY;
+ AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
+ pExtent,
+ pExtent->ActiveCount);
- //
- // Up the dirty count
- //
+ if( DerefExtents)
+ {
+ ASSERT( pExtent->ActiveCount > 0);
+ lCount = InterlockedDecrement( &pExtent->ActiveCount);
+ }
- lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
- }
- else
- {
+ pExtent = pNextExtent;
- pCurrentExtent = pExtent;
+ ulCount++;
}
+ }
+ __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
+ {
- AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
- AFS_TRACE_LEVEL_VERBOSE,
- "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
- pExtent,
- pExtent->ActiveCount);
-
- ASSERT( pExtent->ActiveCount > 0);
-
- lCount = InterlockedDecrement( &pExtent->ActiveCount);
+ AFSDbgLogMsg( 0,
+ 0,
+ "EXCEPTION - AFSMarkDirty\n");
- pExtent = pNextExtent;
-
- ulCount++;
+ AFSDumpTraceFilesFnc();
}
AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
&Fcb->NPFcb->Specific.File.ExtentsResource,
PsGetCurrentThread());
- AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
+ if( bLocked)
+ {
+ AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
+ }
return;
}
// Helper functions
//
-static AFSExtent *ExtentFor(PLIST_ENTRY le, ULONG SkipList)
+AFSExtent *
+ExtentFor(PLIST_ENTRY le, ULONG SkipList)
{
+
return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
}
-static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
+AFSExtent *
+NextExtent(AFSExtent *Extent, ULONG SkipList)
{
+
return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
}
static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
{
+
return CONTAINING_RECORD( le, AFSExtent, DirtyList );
}
AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
}
- for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
- {
- if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
- {
- RemoveEntryList( &pExtent->Lists[i] );
- }
- }
-
AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
"AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
pExtent->FileOffset.QuadPart,
pExtent->Size);
- InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
-
- InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
-
ASSERT( pExtent->ActiveCount == 0);
- //
- // and free
- //
- AFSExFreePool( pExtent);
-
- lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
-
- lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
-
- if( lCount == 0)
- {
-
- KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
- 0,
- FALSE);
- }
+ AFSFreeExtent( Fcb,
+ pExtent);
}
}
}
- for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
- {
- if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
- {
- RemoveEntryList( &pExtent->Lists[i] );
- }
- }
-
AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
"AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
pExtent->FileOffset.QuadPart,
pExtent->Size);
- InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
-
- InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
-
ASSERT( pExtent->ActiveCount == 0);
- //
- // and free
- //
- AFSExFreePool( pExtent);
-
- lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
-
- lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
-
- if( lCount == 0)
- {
-
- KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
- 0,
- FALSE);
- }
+ AFSFreeExtent( Fcb,
+ pExtent);
//
// Next extent we are looking for
return;
}
+ULONG
+AFSConstructCleanByteRangeList( AFSFcb * pFcb,
+ AFSByteRange ** pByteRangeList)
+{
+
+ ULONG ulByteRangeMax;
+ ULONG ulByteRangeCount = 0;
+ AFSByteRange *ByteRangeList;
+ AFSExtent *pExtent, *pNextExtent;
+
+ AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
+
+ ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
+
+ ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
+ ulByteRangeMax * sizeof( AFSByteRange),
+ AFS_BYTERANGE_TAG);
+
+ if ( ByteRangeList == NULL)
+ {
+
+ (*pByteRangeList) = NULL;
+
+ try_return( ulByteRangeCount = DWORD_MAX);
+ }
+
+ RtlZeroMemory( ByteRangeList,
+ ulByteRangeMax * sizeof( AFSByteRange));
+
+ //
+ // The for loop populates the ByteRangeList entries with values that are
+ // the gaps in the DirtyList. In other words, if a range is not present
+ // in the DirtyList it will be represented in the ByteRangeList array.
+ //
+
+ for ( ulByteRangeCount = 0,
+ pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
+ ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
+ pExtent = pNextExtent)
+ {
+
+ pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
+
+ //
+ // The first time the for() is entered the ulByteRangeCount will be zero and
+ // ByteRangeList[0] FileOffset and Length will both be zero. If the first
+ // extent is not for offset zero, the ByteRangeList[0] Length is set to the
+ // FileOffset of the Extent.
+ //
+ // Future passes through the loop behave in a similar fashion but
+ // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
+ //
+
+ if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
+ {
+
+ ByteRangeList[ulByteRangeCount].Length.QuadPart =
+ pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
+
+ ulByteRangeCount++;
+ }
+
+ //
+ // Having processed the current dirty extent, the following while loop
+ // searches for the next clean gap between dirty extents.
+ //
+
+ while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
+ {
+
+ pExtent = pNextExtent;
+
+ pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
+ }
+
+ //
+ // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
+ // The Length is left at zero and will be assigned either when the for loop continues or
+ // when the for loop exits.
+ //
+
+ ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
+ }
+
+ //
+ // Assign the Length of the final clean range to match the file length.
+ //
+
+ ByteRangeList[ulByteRangeCount].Length.QuadPart =
+ pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
+
+ (*pByteRangeList) = ByteRangeList;
+
+ try_exit:
+
+ AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
+
+ return ulByteRangeCount;
+}
+
#if GEN_MD5
void
AFSSetupMD5Hash( IN AFSFcb *Fcb,
AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
- liByteOffset.QuadPart = ByteOffset->QuadPart;
-
- while( ulCount < ExtentsCount)
+ __try
{
+ liByteOffset.QuadPart = ByteOffset->QuadPart;
- RtlZeroMemory( pExtent->MD5,
- sizeof( pExtent->MD5));
+ while( ulCount < ExtentsCount)
+ {
- pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
+ RtlZeroMemory( pExtent->MD5,
+ sizeof( pExtent->MD5));
- if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
- ByteCount < pExtent->Size)
- {
+ pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
- if( pExtentBuffer == NULL)
+ if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
+ ByteCount < pExtent->Size)
{
- pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
- pExtent->Size,
- AFS_GENERIC_MEMORY_9_TAG);
-
if( pExtentBuffer == NULL)
{
- break;
- }
- }
+ pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
+ pExtent->Size,
+ AFS_GENERIC_MEMORY_9_TAG);
- RtlZeroMemory( pExtentBuffer,
- pExtent->Size);
+ if( pExtentBuffer == NULL)
+ {
- RtlCopyMemory( pExtentBuffer,
- pCurrentBuffer,
- ByteCount);
+ break;
+ }
+ }
- pMD5Buffer = (char *)pExtentBuffer;
+ RtlZeroMemory( pExtentBuffer,
+ pExtent->Size);
- ulCurrentLen = ByteCount;
- }
- else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
- {
+ RtlCopyMemory( pExtentBuffer,
+ pCurrentBuffer,
+ ByteCount);
- pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
- pExtent->Size,
- AFS_GENERIC_MEMORY_10_TAG);
+ pMD5Buffer = (char *)pExtentBuffer;
- if( pExtentBuffer == NULL)
+ ulCurrentLen = ByteCount;
+ }
+ else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
{
- break;
- }
+ pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
+ pExtent->Size,
+ AFS_GENERIC_MEMORY_10_TAG);
+
+ if( pExtentBuffer == NULL)
+ {
- RtlZeroMemory( pExtentBuffer,
- pExtent->Size);
+ break;
+ }
- if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
- {
+ RtlZeroMemory( pExtentBuffer,
+ pExtent->Size);
+
+ if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
+ {
#ifdef AMD64
- RtlCopyMemory( pExtentBuffer,
- ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
- pExtent->Size);
+ RtlCopyMemory( pExtentBuffer,
+ ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
+ pExtent->Size);
#else
- ASSERT( pExtent->CacheOffset.HighPart == 0);
- RtlCopyMemory( pExtentBuffer,
- ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
- pExtent->Size);
+ ASSERT( pExtent->CacheOffset.HighPart == 0);
+ RtlCopyMemory( pExtentBuffer,
+ ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
+ pExtent->Size);
#endif
- ulBytesRead = pExtent->Size;
+ ulBytesRead = pExtent->Size;
+ }
+ else
+ {
+
+ ntStatus = AFSReadCacheFile( pExtentBuffer,
+ &pExtent->CacheOffset,
+ pExtent->Size,
+ &ulBytesRead);
+
+ if( !NT_SUCCESS( ntStatus))
+ {
+
+ break;
+ }
+ }
+
+ pMD5Buffer = (char *)pExtentBuffer;
+
+ ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
+
+ RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
+ pCurrentBuffer,
+ ulCurrentLen);
}
else
{
- ntStatus = AFSReadCacheFile( pExtentBuffer,
- &pExtent->CacheOffset,
- pExtent->Size,
- &ulBytesRead);
+ ulCurrentLen = pExtent->Size;
- if( !NT_SUCCESS( ntStatus))
- {
- break;
- }
+ pMD5Buffer = pCurrentBuffer;
}
- pMD5Buffer = (char *)pExtentBuffer;
+ AFSGenerateMD5( pMD5Buffer,
+ pExtent->Size,
+ pExtent->MD5);
- ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
-
- RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
- pCurrentBuffer,
- ulCurrentLen);
- }
- else
- {
+ pExtent = pNextExtent;
- ulCurrentLen = pExtent->Size;
+ ulCount++;
- pMD5Buffer = pCurrentBuffer;
- }
+ ByteCount -= ulCurrentLen;
- AFSGenerateMD5( pMD5Buffer,
- pExtent->Size,
- pExtent->MD5);
+ pCurrentBuffer += ulCurrentLen;
- pExtent = pNextExtent;
+ liByteOffset.QuadPart += ulCurrentLen;
+ }
- ulCount++;
+ AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
+ &Fcb->NPFcb->Specific.File.ExtentsResource,
+ PsGetCurrentThread());
- ByteCount -= ulCurrentLen;
+ }
+ __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
+ {
- pCurrentBuffer += ulCurrentLen;
+ AFSDbgLogMsg( 0,
+ 0,
+ "EXCEPTION - AFSSetupMD5Hash\n");
- liByteOffset.QuadPart += ulCurrentLen;
+ AFSDumpTraceFilesFnc();
}
- AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
- AFS_TRACE_LEVEL_VERBOSE,
- "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
- &Fcb->NPFcb->Specific.File.ExtentsResource,
- PsGetCurrentThread());
-
AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
if( pExtentBuffer != NULL)
{
- AFSExFreePool( pExtentBuffer);
+ AFSExFreePoolWithTag( pExtentBuffer, AFS_GENERIC_MEMORY_9_TAG);
}
}