2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSCommSupport.cpp
38 #include "AFSCommon.h"
40 #define AFS_MAX_FCBS_TO_DROP 10
42 static AFSExtent *ExtentFor( PLIST_ENTRY le, ULONG SkipList );
43 static AFSExtent *NextExtent( AFSExtent *Extent, ULONG SkipList );
44 static ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
45 static VOID VerifyExtentsLists(AFSFcb *Fcb);
46 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le);
49 AFSEntryForOffset( IN AFSFcb *Fcb,
50 IN PLARGE_INTEGER Offset);
54 // Returns with Extents lock EX and no one using them.
58 AFSLockForExtentsTrim( IN AFSFcb *Fcb)
61 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
63 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
64 AFS_TRACE_LEVEL_VERBOSE,
65 "AFSLockForExtentsTrim Acuiring Fcb extents lock %08lX EXCL %08lX\n",
66 &pNPFcb->Specific.File.ExtentsResource,
67 PsGetCurrentThread());
69 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
75 // return FALSE *or* with Extents lock EX and noone using them
78 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
80 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
82 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
83 AFS_TRACE_LEVEL_VERBOSE,
84 "AFSLockForExtentsTrimNoWait Attempting to acquiring Fcb extent lock %08lX EXCL %08lX\n",
85 &pNPFcb->Specific.File.ExtentsResource,
86 PsGetCurrentThread());
88 if (!AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, FALSE ))
91 // Couldn't lock immediately
94 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
95 AFS_TRACE_LEVEL_VERBOSE,
96 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
97 &pNPFcb->Specific.File.ExtentsResource,
98 PsGetCurrentThread());
106 // Pull all the extents away from the FCB.
109 AFSTearDownFcbExtents( IN AFSFcb *Fcb )
111 BOOLEAN bFoundExtents = FALSE;
112 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
115 ULONG ulCount = 0, ulReleaseCount = 0, ulProcessCount = 0;
117 AFSReleaseExtentsCB *pRelease = NULL;
118 BOOLEAN locked = FALSE;
120 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
126 // Ensure that no one is working with the extents and grab the
130 AFSLockForExtentsTrim( Fcb );
134 if (0 == Fcb->Specific.File.ExtentCount)
136 try_return ( ntStatus = STATUS_SUCCESS);
140 // Release a max of 100 extents at a time
143 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
145 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
147 AFS_EXTENT_RELEASE_TAG);
148 if (NULL == pRelease)
151 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
154 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
156 ulCount = Fcb->Specific.File.ExtentCount;
158 while( ulReleaseCount < ulCount)
161 bFoundExtents = TRUE;
163 RtlZeroMemory( pRelease,
164 sizeof( AFSReleaseExtentsCB ) +
165 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
167 if( ulCount - ulReleaseCount <= AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
169 ulProcessCount = ulCount - ulReleaseCount;
173 ulProcessCount = AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
176 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
177 pRelease->ExtentCount = ulProcessCount;
180 // Update the metadata for this call
183 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
184 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
185 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
186 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
187 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
191 while (ulProcessCount < pRelease->ExtentCount)
193 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
195 pRelease->FileExtents[ulProcessCount].Flags = AFS_EXTENT_FLAG_RELEASE;
198 RtlCopyMemory( pRelease->FileExtents[ulProcessCount].MD5,
200 sizeof(pEntry->MD5));
202 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
205 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
208 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
211 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
216 AFSRemoveEntryDirtyList( Fcb,
219 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
221 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
223 ASSERT( dirtyCount >= 0);
226 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
229 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
230 AFS_TRACE_LEVEL_VERBOSE,
231 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
233 Fcb->ObjectInformation->FileId.Cell,
234 Fcb->ObjectInformation->FileId.Volume,
235 Fcb->ObjectInformation->FileId.Vnode,
236 Fcb->ObjectInformation->FileId.Unique,
237 pEntry->FileOffset.HighPart,
238 pEntry->FileOffset.LowPart,
241 pRelease->FileExtents[ulProcessCount].Length = pEntry->Size;
242 pRelease->FileExtents[ulProcessCount].DirtyLength = pEntry->Size;
243 pRelease->FileExtents[ulProcessCount].DirtyOffset = 0;
244 pRelease->FileExtents[ulProcessCount].CacheOffset = pEntry->CacheOffset;
245 pRelease->FileExtents[ulProcessCount].FileOffset = pEntry->FileOffset;
247 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pEntry->Size/1024)));
249 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pEntry->Size/1024)));
251 ASSERT( pEntry->ActiveCount == 0);
255 AFSExFreePool( pEntry);
257 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
259 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
262 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
269 // Send the request down. We cannot send this down
270 // asynchronously - if we did that we could request them
271 // back before the service got this request and then this
272 // request would be a corruption.
275 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
277 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
278 AFS_REQUEST_FLAG_SYNCHRONOUS,
281 &Fcb->ObjectInformation->FileId,
287 if( !NT_SUCCESS(ntStatus))
291 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
292 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
295 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
296 AFS_TRACE_LEVEL_ERROR,
297 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
298 Fcb->ObjectInformation->FileId.Cell,
299 Fcb->ObjectInformation->FileId.Volume,
300 Fcb->ObjectInformation->FileId.Vnode,
301 Fcb->ObjectInformation->FileId.Unique,
306 ulReleaseCount += ulProcessCount;
310 // Reinitialize the skip lists
313 ASSERT( Fcb->Specific.File.ExtentCount == 0);
315 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
317 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
321 // Reinitialize the dirty list as well
324 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
327 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
329 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
330 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
332 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
334 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
341 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
342 AFS_TRACE_LEVEL_VERBOSE,
343 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
344 &Fcb->NPFcb->Specific.File.ExtentsResource,
345 PsGetCurrentThread());
347 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
353 AFSExFreePool( pRelease);
357 return bFoundExtents;
361 ExtentForOffsetInList( IN AFSFcb *Fcb,
364 IN PLARGE_INTEGER Offset)
367 // Return the extent that maps the offset, that
368 // - Contains the offset
369 // - or is immediately ahead of the offset (in this list)
370 // - otherwise return NULL.
373 PLIST_ENTRY pLe = List;
374 AFSExtent *pPrevious = NULL;
376 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
378 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
382 entry = ExtentFor( pLe, ListNumber );
389 if (Offset->QuadPart < entry->FileOffset.QuadPart)
392 // Offset is ahead of entry. Return previous
397 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
400 // We start after this extent - carry on round
408 // Otherwise its a match
415 // Got to the end. Return Previous
421 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
427 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
428 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
433 // Return the extent that contains the offset
436 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
437 IN PLARGE_INTEGER Offset,
438 IN BOOLEAN ReturnPrevious,
441 AFSExtent *pPrevious = Hint;
445 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
447 #if AFS_VALIDATE_EXTENTS
448 VerifyExtentsLists(Fcb);
452 // So we will go across the skip lists until we find an
453 // appropriate entry (previous or direct match). If it's a match
454 // we are done, other wise we start on the next layer down
456 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
458 if (NULL == pPrevious)
461 // We haven't found anything in the previous layers
463 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
465 else if (NULL == pPrevious->Lists[i].Flink)
467 ASSERT(AFS_EXTENTS_LIST != i);
469 // The hint doesn't exist at this level, next one down
476 // take the previous into the next
478 pLe = &pPrevious->Lists[i];
481 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
483 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
486 // Found it immediately. Stop here
492 if (NULL == pPrevious || ReturnPrevious )
497 ASSERT( !AFSExtentContains(pPrevious, Offset) );
503 AFSEntryForOffset( IN AFSFcb *Fcb,
504 IN PLARGE_INTEGER Offset)
506 AFSExtent *pPrevious = NULL;
510 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
512 #if AFS_VALIDATE_EXTENTS
513 VerifyExtentsLists(Fcb);
517 // So we will go across the skip lists until we find an
518 // appropriate entry (previous or direct match). If it's a match
519 // we are done, other wise we start on the next layer down
521 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
523 if (NULL == pPrevious)
526 // We haven't found anything in the previous layers
528 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
530 else if (NULL == pPrevious->Lists[i].Flink)
532 ASSERT(AFS_EXTENTS_LIST != i);
534 // The hint doesn't exist at this level, next one down
541 // take the previous into the next
543 pLe = &pPrevious->Lists[i];
546 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
548 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
551 // Found it immediately. Stop here
561 AFSExtentForOffset( IN AFSFcb *Fcb,
562 IN PLARGE_INTEGER Offset,
563 IN BOOLEAN ReturnPrevious)
565 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
569 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
570 IN PLARGE_INTEGER Offset,
572 IN OUT AFSExtent **FirstExtent,
573 OUT AFSExtent **LastExtent)
576 // Return TRUE region is completely mapped. FALSE
577 // otherwise. If the region isn't mapped then the last
578 // extent to map part of the region is returned.
580 // *LastExtent as input is where to start looking.
581 // *LastExtent as output is either the extent which
582 // contains the Offset, or the last one which doesn't
586 BOOLEAN retVal = FALSE;
591 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
592 AFS_TRACE_LEVEL_VERBOSE,
593 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
594 &Fcb->NPFcb->Specific.File.ExtentsResource,
595 PsGetCurrentThread());
597 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
599 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
600 *FirstExtent = entry;
602 if (NULL == entry || !AFSExtentContains(entry, Offset))
604 try_return (retVal = FALSE);
607 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
611 if ((entry->FileOffset.QuadPart + entry->Size) >=
612 (Offset->QuadPart + Size))
615 // The end is inside the extent
617 try_return (retVal = TRUE);
620 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
623 // Run out of extents
625 try_return (retVal = FALSE);
628 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
630 if (newEntry->FileOffset.QuadPart !=
631 (entry->FileOffset.QuadPart + entry->Size))
636 try_return (retVal = FALSE);
644 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
645 AFS_TRACE_LEVEL_VERBOSE,
646 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
647 &Fcb->NPFcb->Specific.File.ExtentsResource,
648 PsGetCurrentThread());
650 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
659 // Given an FCB and an Offset we look to see whether there extents to
660 // Map them all. If there are then we return TRUE to fullymapped
661 // and *FirstExtent points to the first extent to map the extent.
662 // If not then we return FALSE, but we request the extents to be mapped.
663 // Further *FirstExtent (if non null) is the last extent which doesn't
666 // Finally on the way *in* if *FirstExtent is non null it is where we start looking
670 AFSRequestExtents( IN AFSFcb *Fcb,
671 IN PLARGE_INTEGER Offset,
673 OUT BOOLEAN *FullyMapped)
676 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
677 NTSTATUS ntStatus = STATUS_SUCCESS;
679 AFSRequestExtentsCB request;
680 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
681 AFSExtent *pFirstExtent;
682 LARGE_INTEGER liAlignedOffset;
683 ULONG ulAlignedLength = 0;
684 LARGE_INTEGER liTimeOut;
687 // Check our extents, then fire off a request if we need to.
688 // We start off knowing nothing about where we will go.
693 *FullyMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent );
698 ASSERT(AFSExtentContains(pFirstExtent, Offset));
699 LARGE_INTEGER end = *Offset;
700 end.QuadPart += (Size-1);
701 ASSERT(AFSExtentContains(pExtent, &end));
703 return STATUS_SUCCESS;
707 // So we need to queue a request. Since we will be clearing the
708 // ExtentsRequestComplete event we need to do with with the lock
712 liTimeOut.QuadPart = -(50000000);
716 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
720 // If this isn't the same process which caused the failure then try to request them again
723 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
725 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
730 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
733 ntStatus = KeWaitForSingleObject( &pNPFcb->Specific.File.ExtentsRequestComplete,
738 if (!NT_SUCCESS(ntStatus))
749 // Lock resource EX and look again
752 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
753 AFS_TRACE_LEVEL_VERBOSE,
754 "AFSRequestExtents Acquiring Fcb extent lock %08lX EXCL %08lX\n",
755 &pNPFcb->Specific.File.ExtentsResource,
756 PsGetCurrentThread());
758 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
760 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
764 // If this isn't the same process which caused the failure then try to request them again
767 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
769 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
771 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
772 AFS_TRACE_LEVEL_VERBOSE,
773 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
774 &pNPFcb->Specific.File.ExtentsResource,
775 PsGetCurrentThread());
777 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
782 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
785 if( KeReadStateEvent( &pNPFcb->Specific.File.ExtentsRequestComplete) ||
786 ntStatus == STATUS_TIMEOUT)
789 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
791 if( !NT_SUCCESS( ntStatus))
795 // If this isn't the same process which caused the failure then try to request them again
798 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
800 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
801 AFS_TRACE_LEVEL_VERBOSE,
802 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
803 &pNPFcb->Specific.File.ExtentsResource,
804 PsGetCurrentThread());
806 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
811 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
813 ntStatus = STATUS_SUCCESS;
820 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
821 AFS_TRACE_LEVEL_VERBOSE,
822 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
823 &pNPFcb->Specific.File.ExtentsResource,
824 PsGetCurrentThread());
826 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
829 if (!NT_SUCCESS(ntStatus))
838 // We have the lock Ex and there is no filling going on.
839 // Check again to see whether things have moved since we last
840 // checked. Since we haven't locked against pinning, we will
846 *FullyMapped = AFSDoExtentsMapRegion(Fcb, Offset, Size, &pFirstExtent, &pExtent);
851 ASSERT(AFSExtentContains(pFirstExtent, Offset));
852 LARGE_INTEGER end = *Offset;
853 end.QuadPart += (Size-1);
854 ASSERT(AFSExtentContains(pExtent, &end));
856 try_return (ntStatus = STATUS_SUCCESS);
859 RtlZeroMemory( &request,
860 sizeof( AFSRequestExtentsCB));
866 ulAlignedLength = Size;
868 liAlignedOffset = *Offset;
870 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
873 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
875 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
878 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
881 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
884 request.ByteOffset = liAlignedOffset;
885 request.Length = ulAlignedLength;
887 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
892 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
893 AFS_TRACE_LEVEL_VERBOSE,
894 "AFSRequestExtents Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
895 Fcb->ObjectInformation->FileId.Cell,
896 Fcb->ObjectInformation->FileId.Volume,
897 Fcb->ObjectInformation->FileId.Vnode,
898 Fcb->ObjectInformation->FileId.Unique,
899 request.ByteOffset.LowPart,
901 PsGetCurrentThread());
903 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
907 &Fcb->ObjectInformation->FileId,
909 sizeof( AFSRequestExtentsCB ),
913 if( NT_SUCCESS( ntStatus))
915 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
921 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
926 if (NT_SUCCESS( ntStatus ))
928 KeQueryTickCount( &Fcb->Specific.File.LastExtentAccess );
931 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
932 AFS_TRACE_LEVEL_VERBOSE,
933 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
934 &pNPFcb->Specific.File.ExtentsResource,
935 PsGetCurrentThread());
937 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
944 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
945 IN PLARGE_INTEGER Offset,
949 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
950 NTSTATUS ntStatus = STATUS_SUCCESS;
951 AFSExtent *pExtent = NULL;
952 AFSRequestExtentsCB request;
953 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
954 AFSExtent *pFirstExtent = NULL;
955 LARGE_INTEGER liAlignedOffset;
956 ULONG ulAlignedLength = 0;
957 BOOLEAN bRegionMapped = FALSE;
962 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
965 // If the service set a failure on the file since the last
966 // CreateFile was issued, return it now.
969 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
973 // If this isn't the same process which caused the failure then try to request them again
976 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
978 try_return( ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus);
981 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
985 // Check if we are already mapped
988 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
993 try_return( ntStatus = STATUS_SUCCESS);
997 // Align our request on extent size boundary
1000 ulAlignedLength = Size;
1002 liAlignedOffset = *Offset;
1004 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
1007 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
1009 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
1012 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
1015 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
1018 RtlZeroMemory( &request,
1019 sizeof( AFSRequestExtentsCB));
1021 request.ByteOffset = liAlignedOffset;
1022 request.Length = ulAlignedLength;
1024 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
1025 &request.ByteOffset,
1029 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1030 AFS_TRACE_LEVEL_VERBOSE,
1031 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
1032 Fcb->ObjectInformation->FileId.Cell,
1033 Fcb->ObjectInformation->FileId.Volume,
1034 Fcb->ObjectInformation->FileId.Vnode,
1035 Fcb->ObjectInformation->FileId.Unique,
1036 request.ByteOffset.LowPart,
1038 PsGetCurrentThread());
1040 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
1044 &Fcb->ObjectInformation->FileId,
1046 sizeof( AFSRequestExtentsCB ),
1050 if( NT_SUCCESS( ntStatus))
1053 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
1059 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
1071 AFSProcessExtentsResult( IN AFSFcb *Fcb,
1073 IN AFSFileExtentCB *Result)
1075 NTSTATUS ntStatus = STATUS_SUCCESS;
1076 AFSFileExtentCB *pFileExtents = Result;
1079 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
1080 ULONG fileExtentsUsed = 0;
1081 BOOLEAN bFoundExtent = FALSE;
1082 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
1083 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1086 // Grab the extents exclusive for the duration
1089 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1090 AFS_TRACE_LEVEL_VERBOSE,
1091 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
1092 &pNPFcb->Specific.File.ExtentsResource,
1093 PsGetCurrentThread());
1095 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
1101 // Find where to put the extents
1103 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1106 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
1109 le = pSkipEntries[AFS_EXTENTS_LIST];
1111 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1114 // No extents. Insert at head of list (which is where the skip lists point!)
1118 else if (0 != pFileExtents->FileOffset.QuadPart)
1121 // We want to find the best extents immediately *behind* this offset
1123 LARGE_INTEGER offset = pFileExtents->FileOffset;
1126 // Ask in the top skip list first, then work down
1128 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
1130 pExtent = ExtentForOffsetInList( Fcb,
1135 if (NULL == pExtent)
1138 // No dice. Header has to become the head of the list
1140 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1142 // And as a loop invariant we should never have found an extent
1144 ASSERT(!bFoundExtent);
1149 // pExtent is where to start to insert at this level
1151 pSkipEntries[i] = &pExtent->Lists[i];
1154 // And also where to start to look at the next level
1157 if (i > AFS_EXTENTS_LIST)
1159 pSkipEntries[i-1] = &pExtent->Lists[i-1];
1161 bFoundExtent = TRUE;
1165 if (NULL == pExtent)
1167 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1172 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
1178 // Looking at offset 0, so we must start at the beginning
1181 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1185 // And set up the skip lists
1188 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1190 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1194 while (fileExtentsUsed < Count)
1198 // Loop invariant - le points to where to insert after and
1199 // pExtent points to le->fLink
1202 ASSERT (NULL == pExtent ||
1203 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1205 if (NULL == pExtent ||
1206 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1209 // We need to insert a new extent at le. Start with
1210 // some sanity check on spanning
1212 if (NULL != pExtent &&
1213 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1214 pExtent->FileOffset.QuadPart))
1217 // File Extents overlaps pExtent
1219 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1220 pExtent->FileOffset.QuadPart);
1222 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1226 // File offset is entirely in front of this extent. Create
1227 // a new one (remember le is the previous list entry)
1229 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1232 if (NULL == pExtent)
1237 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1240 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1242 pExtent->FileOffset = pFileExtents->FileOffset;
1243 pExtent->CacheOffset = pFileExtents->CacheOffset;
1244 pExtent->Size = pFileExtents->Length;
1246 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1247 AFS_TRACE_LEVEL_VERBOSE,
1248 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1249 Fcb->ObjectInformation->FileId.Cell,
1250 Fcb->ObjectInformation->FileId.Volume,
1251 Fcb->ObjectInformation->FileId.Vnode,
1252 Fcb->ObjectInformation->FileId.Unique,
1253 pFileExtents->FileOffset.QuadPart,
1254 pFileExtents->CacheOffset.QuadPart,
1255 pFileExtents->Length);
1257 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1259 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1261 InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1263 if( InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount) == 1)
1266 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1272 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1273 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1274 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1277 // Do not move the cursor - we will do it next time
1281 // And into the (upper) skip lists - Again, do not move the cursor
1283 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1285 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1287 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1288 #if AFS_VALIDATE_EXTENTS
1289 VerifyExtentsLists(Fcb);
1294 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1297 if (pExtent->Size != pFileExtents->Length)
1300 ASSERT (pExtent->Size == pFileExtents->Length);
1302 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1306 // Move both cursors forward.
1308 // First the extent pointer
1311 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1314 // Then the skip lists cursors forward if needed
1316 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1318 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1321 // Check sanity before
1323 #if AFS_VALIDATE_EXTENTS
1324 VerifyExtentsLists(Fcb);
1328 // Skip list should point to us
1330 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1332 // Move forward cursor
1334 pSkipEntries[i] = pSkipEntries[i]->Flink;
1336 // Check sanity before
1338 #if AFS_VALIDATE_EXTENTS
1339 VerifyExtentsLists(Fcb);
1345 // And then the cursor in the supplied array
1351 // setup pExtent if there is one
1353 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1355 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1365 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1368 // Sanity check on spanning
1370 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1371 pFileExtents->FileOffset.QuadPart)
1374 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1375 pFileExtents->FileOffset.QuadPart);
1377 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1381 // Move le and pExtent forward
1383 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1387 // Then the check the skip lists cursors
1389 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1391 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1395 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1396 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1397 // - We are not the last on the list. In that case we have to be strictly less than
1399 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1401 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1402 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1409 // setup pExtent if there is one
1412 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1414 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1424 // All done, signal that we are done drop the lock, exit
1429 if( !NT_SUCCESS( ntStatus))
1433 // If we failed the service is going to drop all extents so trim away the
1437 AFSTrimSpecifiedExtents( Fcb,
1442 #if AFS_VALIDATE_EXTENTS
1443 VerifyExtentsLists(Fcb);
1446 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1450 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1451 AFS_TRACE_LEVEL_VERBOSE,
1452 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1453 &pNPFcb->Specific.File.ExtentsResource,
1454 PsGetCurrentThread());
1456 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1463 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1465 AFSFcb *pFcb = NULL;
1466 AFSVolumeCB *pVolumeCB = NULL;
1467 NTSTATUS ntStatus = STATUS_SUCCESS;
1468 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1469 ULONGLONG ullIndex = 0;
1470 AFSObjectInfoCB *pObjectInfo = NULL;
1475 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1476 AFS_TRACE_LEVEL_VERBOSE,
1477 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1478 &pDevExt->Specific.RDR.VolumeTreeLock,
1479 PsGetCurrentThread());
1481 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1483 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1484 AFS_TRACE_LEVEL_VERBOSE,
1485 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1486 SetExtents->FileId.Cell,
1487 SetExtents->FileId.Volume,
1488 SetExtents->FileId.Vnode,
1489 SetExtents->FileId.Unique);
1492 // Locate the volume node
1495 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1497 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1499 (AFSBTreeEntry **)&pVolumeCB);
1501 if( pVolumeCB != NULL)
1504 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1505 AFS_TRACE_LEVEL_VERBOSE,
1506 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1507 pVolumeCB->ObjectInfoTree.TreeLock,
1508 PsGetCurrentThread());
1510 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1513 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1515 if( !NT_SUCCESS( ntStatus) ||
1519 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1520 AFS_TRACE_LEVEL_ERROR,
1521 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1522 SetExtents->FileId.Cell,
1523 SetExtents->FileId.Volume,
1524 SetExtents->FileId.Vnode,
1525 SetExtents->FileId.Unique,
1528 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1531 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1534 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1537 // Now locate the Object in this volume
1540 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1542 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1544 (AFSBTreeEntry **)&pObjectInfo);
1546 if( pObjectInfo != NULL)
1550 // Reference the node so it won't be torn down
1553 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1555 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1556 AFS_TRACE_LEVEL_VERBOSE,
1557 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1559 pObjectInfo->ObjectReferenceCount);
1562 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1564 if( !NT_SUCCESS( ntStatus) ||
1565 pObjectInfo == NULL)
1568 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1569 AFS_TRACE_LEVEL_ERROR,
1570 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1572 SetExtents->FileId.Cell,
1573 SetExtents->FileId.Volume,
1574 SetExtents->FileId.Vnode,
1575 SetExtents->FileId.Unique,
1578 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1581 pFcb = pObjectInfo->Fcb;
1584 // If we have a result failure then don't bother trying to set the extents
1587 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1590 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1591 AFS_TRACE_LEVEL_ERROR,
1592 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1593 SetExtents->FileId.Cell,
1594 SetExtents->FileId.Volume,
1595 SetExtents->FileId.Vnode,
1596 SetExtents->FileId.Unique,
1597 SetExtents->ResultStatus);
1599 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1600 AFS_TRACE_LEVEL_VERBOSE,
1601 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1602 &pFcb->NPFcb->Specific.File.ExtentsResource,
1603 PsGetCurrentThread());
1605 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1608 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1610 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1614 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1615 AFS_TRACE_LEVEL_VERBOSE,
1616 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1617 &pFcb->NPFcb->Specific.File.ExtentsResource,
1618 PsGetCurrentThread());
1620 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1622 try_return( ntStatus);
1625 ntStatus = AFSProcessExtentsResult ( pFcb,
1626 SetExtents->ExtentCount,
1627 SetExtents->FileExtents );
1631 if( pObjectInfo != NULL)
1634 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1636 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1637 AFS_TRACE_LEVEL_VERBOSE,
1638 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1640 pObjectInfo->ObjectReferenceCount);
1648 // Helper fuctions for Usermode initiation of release of extents
1651 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1653 OUT AFSFileExtentCB *FileExtents,
1654 IN ULONG BufferSize,
1655 OUT ULONG *ExtentCount,
1656 OUT BOOLEAN *DirtyExtents)
1661 ULONG ulExtentCount = 0;
1662 NTSTATUS ntStatus = STATUS_SUCCESS;
1663 BOOLEAN bReleaseAll = FALSE;
1664 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1668 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1670 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1673 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1674 AFS_TRACE_LEVEL_VERBOSE,
1675 "AFSReleaseSpecifiedExtents Buffer too small\n");
1677 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1680 RtlZeroMemory( FileExtents, BufferSize);
1683 *DirtyExtents = FALSE;
1686 // iterate until we have dealt with all we were asked for or
1687 // are at the end of the list. Note that this deals (albeit
1688 // badly) with out of order extents
1691 pExtent = AFSExtentForOffset( Fcb,
1692 &Extents->FileExtents[0].FileOffset,
1695 if (NULL == pExtent)
1697 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1701 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1705 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1706 ( Extents->FileId.Cell == 0 &&
1707 Extents->FileId.Volume == 0 &&
1708 Extents->FileId.Vnode == 0 &&
1709 Extents->FileId.Unique == 0))
1715 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1716 ulExtentCount < Extents->ExtentCount)
1720 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1725 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1728 // Skip forward through the extent list until we get
1729 // to the one we want
1735 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1738 // We don't have the extent asked for so return UNKNOWN
1741 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1742 AFS_TRACE_LEVEL_VERBOSE,
1743 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1744 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1745 Extents->FileExtents[ulExtentCount].Length);
1747 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1749 FileExtents[*ExtentCount].Length = 0;
1750 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1751 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1753 *ExtentCount = (*ExtentCount) + 1;
1758 // Reset where we are looking
1761 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1765 else if( pExtent->ActiveCount > 0)
1768 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1769 AFS_TRACE_LEVEL_VERBOSE,
1770 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1771 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1772 Extents->FileExtents[ulExtentCount].Length);
1774 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1776 FileExtents[*ExtentCount].Length = 0;
1777 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1778 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1780 *ExtentCount = (*ExtentCount) + 1;
1785 // Reset where we are looking
1788 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1797 // If the extent is currently active then skip it
1800 if( pExtent->ActiveCount > 0)
1809 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1811 FileExtents[*ExtentCount].Length = pExtent->Size;
1812 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1813 FileExtents[*ExtentCount].DirtyOffset = 0;
1814 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1815 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1817 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1818 AFS_TRACE_LEVEL_VERBOSE,
1819 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1821 Fcb->ObjectInformation->FileId.Cell,
1822 Fcb->ObjectInformation->FileId.Volume,
1823 Fcb->ObjectInformation->FileId.Vnode,
1824 Fcb->ObjectInformation->FileId.Unique,
1825 FileExtents[*ExtentCount].FileOffset.QuadPart,
1826 FileExtents[*ExtentCount].Length);
1828 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1831 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1834 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1837 AFSRemoveEntryDirtyList( Fcb,
1840 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1842 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1844 *DirtyExtents = TRUE;
1847 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1851 // move forward all three cursors
1855 *ExtentCount = (*ExtentCount) + 1;
1860 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1862 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1864 RemoveEntryList( &pExtent->Lists[i] );
1868 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1870 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1875 AFSExFreePool( pExtent);
1877 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1879 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
1882 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1897 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1900 AFSFcb *pFcb = NULL;
1901 AFSVolumeCB *pVolumeCB = NULL;
1902 AFSDeviceExt *pRDRDeviceExt = NULL;
1903 AFSDeviceExt *pControlDeviceExt = NULL;
1904 BOOLEAN bLocatedEntry = FALSE;
1905 AFSObjectInfoCB *pCurrentObject = NULL;
1906 BOOLEAN bReleaseVolumeListLock = FALSE;
1908 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1909 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1911 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1912 AFS_TRACE_LEVEL_VERBOSE,
1913 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1914 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1915 PsGetCurrentThread());
1917 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1920 bReleaseVolumeListLock = TRUE;
1922 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1924 while( pVolumeCB != NULL)
1928 // The Volume list may move under our feet. Lock it.
1931 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1932 AFS_TRACE_LEVEL_VERBOSE,
1933 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1934 pVolumeCB->ObjectInfoTree.TreeLock,
1935 PsGetCurrentThread());
1937 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1939 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1941 bReleaseVolumeListLock = FALSE;
1943 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1946 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1948 if( NULL == LastFcb)
1951 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1956 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1961 while( pCurrentObject != NULL)
1964 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1967 // If the FCB is a candidate we try to lock it (but without waiting - which
1968 // means we are deadlock free
1972 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1978 AFSLockForExtentsTrim( pFcb);
1983 if( !AFSLockForExtentsTrimNoWait( pFcb))
1986 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1995 // Need to be sure there are no current flushes in the queue
1998 if( pFcb->Specific.File.ExtentCount == 0)
2001 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2002 AFS_TRACE_LEVEL_VERBOSE,
2003 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2004 &pFcb->NPFcb->Specific.File.ExtentsResource,
2005 PsGetCurrentThread());
2007 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
2009 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2016 if( pFcb->Specific.File.QueuedFlushCount > 0)
2019 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2020 AFS_TRACE_LEVEL_VERBOSE,
2021 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2022 &pFcb->NPFcb->Specific.File.ExtentsResource,
2023 PsGetCurrentThread());
2025 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
2029 AFSWaitOnQueuedFlushes( pFcb);
2034 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2042 if( pFcb->OpenHandleCount > 0)
2045 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2046 AFS_TRACE_LEVEL_VERBOSE,
2047 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2048 &pFcb->NPFcb->Specific.File.ExtentsResource,
2049 PsGetCurrentThread());
2051 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
2053 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2061 // A hit a very palpable hit. Pin it
2064 InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2066 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2067 AFS_TRACE_LEVEL_VERBOSE,
2068 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
2070 pCurrentObject->ObjectReferenceCount);
2072 bLocatedEntry = TRUE;
2077 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2082 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2089 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2092 bReleaseVolumeListLock = TRUE;
2094 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2097 if( bReleaseVolumeListLock)
2100 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2107 AFSProcessExtentFailure( PIRP Irp)
2109 AFSExtentFailureCB *pFailureCB = NULL;
2110 NTSTATUS ntStatus = STATUS_SUCCESS;
2111 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2112 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2113 AFSVolumeCB *pVolumeCB = NULL;
2114 ULONGLONG ullIndex = 0;
2115 AFSObjectInfoCB *pObjectInfo = NULL;
2119 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
2122 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2123 AFS_TRACE_LEVEL_ERROR,
2124 "AFSProcessExtentFailure Input buffer too small\n");
2126 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2129 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
2131 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2132 AFS_TRACE_LEVEL_ERROR,
2133 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2134 pFailureCB->FileId.Cell,
2135 pFailureCB->FileId.Volume,
2136 pFailureCB->FileId.Vnode,
2137 pFailureCB->FileId.Unique,
2138 pFailureCB->FailureStatus);
2140 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2143 // Locate the volume node
2146 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
2148 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2150 (AFSBTreeEntry **)&pVolumeCB);
2152 if( pVolumeCB != NULL)
2155 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2156 AFS_TRACE_LEVEL_VERBOSE,
2157 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2158 pVolumeCB->ObjectInfoTree.TreeLock,
2159 PsGetCurrentThread());
2161 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2164 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2166 if( !NT_SUCCESS( ntStatus) ||
2170 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2171 AFS_TRACE_LEVEL_ERROR,
2172 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
2173 ullIndex, ntStatus);
2175 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2178 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2181 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2184 // Now locate the Object in this volume
2187 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
2189 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2191 (AFSBTreeEntry **)&pObjectInfo);
2193 if( pObjectInfo != NULL &&
2194 pObjectInfo->Fcb != NULL)
2198 // Reference the node so it won't be torn down
2201 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2203 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2204 AFS_TRACE_LEVEL_VERBOSE,
2205 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2207 pObjectInfo->ObjectReferenceCount);
2210 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2212 if( !NT_SUCCESS( ntStatus) ||
2213 pObjectInfo == NULL ||
2214 pObjectInfo->Fcb == NULL)
2217 if( pObjectInfo == NULL)
2219 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2220 AFS_TRACE_LEVEL_ERROR,
2221 "AFSProcessExtentFailure Invalid file index %I64X\n",
2226 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2227 AFS_TRACE_LEVEL_ERROR,
2228 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2232 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2235 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2236 AFS_TRACE_LEVEL_VERBOSE,
2237 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2238 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2239 PsGetCurrentThread());
2241 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2244 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2246 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2250 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2251 AFS_TRACE_LEVEL_VERBOSE,
2252 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2253 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2254 PsGetCurrentThread());
2256 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2258 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2260 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2261 AFS_TRACE_LEVEL_VERBOSE,
2262 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2264 pObjectInfo->ObjectReferenceCount);
2275 AFSProcessReleaseFileExtents( IN PIRP Irp)
2277 NTSTATUS ntStatus = STATUS_SUCCESS;
2278 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2279 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2280 AFSFcb *pFcb = NULL;
2281 AFSVolumeCB *pVolumeCB = NULL;
2282 AFSDeviceExt *pDevExt;
2283 AFSReleaseFileExtentsCB *pExtents;
2284 AFSReleaseFileExtentsResultCB *pResult = NULL;
2285 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2287 ULONGLONG ullIndex = 0;
2288 AFSObjectInfoCB *pObjectInfo = NULL;
2289 BOOLEAN bLocked = FALSE;
2290 BOOLEAN bDirtyExtents = FALSE;
2295 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2297 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2299 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2300 sizeof( AFSReleaseFileExtentsCB))
2303 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2304 AFS_TRACE_LEVEL_ERROR,
2305 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2307 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2310 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2311 sizeof(AFSReleaseFileExtentsResultCB))
2314 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2315 AFS_TRACE_LEVEL_ERROR,
2316 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2319 // Must have space for one extent in one file
2322 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2325 if (pExtents->ExtentCount == 0)
2328 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2329 AFS_TRACE_LEVEL_ERROR,
2330 "AFSProcessReleaseFileExtents Extent count zero\n");
2332 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2335 if (pExtents->FileId.Cell != 0 ||
2336 pExtents->FileId.Volume != 0 ||
2337 pExtents->FileId.Vnode != 0 ||
2338 pExtents->FileId.Unique != 0)
2341 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2342 AFS_TRACE_LEVEL_VERBOSE,
2343 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2344 pExtents->FileId.Cell,
2345 pExtents->FileId.Volume,
2346 pExtents->FileId.Vnode,
2347 pExtents->FileId.Unique);
2349 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2350 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2351 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2352 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2353 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2356 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2357 AFS_TRACE_LEVEL_ERROR,
2358 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2359 pExtents->FileId.Cell,
2360 pExtents->FileId.Volume,
2361 pExtents->FileId.Vnode,
2362 pExtents->FileId.Unique);
2364 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2367 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2368 AFS_TRACE_LEVEL_VERBOSE,
2369 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2370 &pDevExt->Specific.RDR.VolumeTreeLock,
2371 PsGetCurrentThread());
2373 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2376 // Locate the volume node
2379 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2381 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2383 (AFSBTreeEntry **)&pVolumeCB);
2385 if( pVolumeCB != NULL)
2388 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2389 AFS_TRACE_LEVEL_VERBOSE,
2390 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2391 pVolumeCB->ObjectInfoTree.TreeLock,
2392 PsGetCurrentThread());
2394 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2397 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2399 if( !NT_SUCCESS( ntStatus) ||
2403 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2404 AFS_TRACE_LEVEL_ERROR,
2405 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2406 ullIndex, ntStatus);
2408 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2411 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2414 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2417 // Now locate the Object in this volume
2420 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2422 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2424 (AFSBTreeEntry **)&pObjectInfo);
2426 if( pObjectInfo != NULL)
2430 // Reference the node so it won't be torn down
2433 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2435 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2436 AFS_TRACE_LEVEL_VERBOSE,
2437 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2439 pObjectInfo->ObjectReferenceCount);
2442 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2444 if( !NT_SUCCESS( ntStatus) ||
2445 pObjectInfo == NULL)
2448 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2449 AFS_TRACE_LEVEL_ERROR,
2450 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2453 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2456 pFcb = pObjectInfo->Fcb;
2461 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2462 AFS_TRACE_LEVEL_ERROR,
2463 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2464 pExtents->FileId.Cell,
2465 pExtents->FileId.Volume,
2466 pExtents->FileId.Vnode,
2467 pExtents->FileId.Unique);
2469 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2472 AFSLockForExtentsTrim( pFcb );
2480 // Locate an Fcb to trim down
2483 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2484 AFS_TRACE_LEVEL_VERBOSE,
2485 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2487 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2492 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2498 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2499 AFS_TRACE_LEVEL_ERROR,
2500 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2502 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2505 pObjectInfo = pFcb->ObjectInformation;
2511 // Allocate a scratch buffer to move in the extent information
2514 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2515 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2517 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2519 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2520 AFS_TRACE_LEVEL_ERROR,
2521 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2523 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2526 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2528 AFS_EXTENTS_RESULT_TAG);
2529 if (NULL == pResult)
2532 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2533 AFS_TRACE_LEVEL_ERROR,
2534 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2536 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2540 // Set up the header (for an array of one)
2542 pResult->FileCount = 1;
2543 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2544 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2547 // Setup the first (and only) file
2549 pFile = pResult->Files;
2550 pFile->FileId = pObjectInfo->FileId;
2551 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2554 // Stash away the auth group
2557 RtlCopyMemory( &pFile->AuthGroup,
2562 // Update the metadata for this call
2565 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2566 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2567 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2568 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2569 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2571 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2573 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2577 &pFile->ExtentCount,
2580 if (!NT_SUCCESS(ntStatus))
2583 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2584 AFS_TRACE_LEVEL_ERROR,
2585 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2588 try_return( ntStatus );
2591 if( pExtents->ExtentCount == 0)
2594 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2595 AFS_TRACE_LEVEL_WARNING,
2596 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2599 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2601 if( pExtents->ExtentCount > 0)
2603 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2606 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2615 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2616 AFS_TRACE_LEVEL_VERBOSE,
2617 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2618 &pFcb->NPFcb->Specific.File.ExtentsResource,
2619 PsGetCurrentThread());
2621 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2624 if( NULL != pResult &&
2625 Irp->AssociatedIrp.SystemBuffer != pResult)
2628 AFSExFreePool(pResult);
2631 if (NT_SUCCESS(ntStatus))
2633 Irp->IoStatus.Information = ulSz;
2637 Irp->IoStatus.Information = 0;
2640 Irp->IoStatus.Status = ntStatus;
2642 if( pObjectInfo != NULL)
2645 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2647 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2648 AFS_TRACE_LEVEL_VERBOSE,
2649 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2651 pObjectInfo->ObjectReferenceCount);
2659 AFSWaitForExtentMapping( AFSFcb *Fcb )
2661 NTSTATUS ntStatus = STATUS_SUCCESS;
2662 LARGE_INTEGER liTimeOut;
2667 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2669 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2673 // If this isn't the same process which caused the failure then try to request them again
2676 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
2678 try_return( ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus);
2681 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2684 liTimeOut.QuadPart = -(50000000);
2686 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2692 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2696 // If this isn't the same process which caused the failure then try to request them again
2699 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
2701 try_return( ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus);
2704 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2707 if( ntStatus == STATUS_TIMEOUT)
2710 ntStatus = STATUS_SUCCESS;
2722 AFSFlushExtents( IN AFSFcb *Fcb)
2724 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2725 AFSExtent *pExtent, *pNextExtent;
2727 AFSReleaseExtentsCB *pRelease = NULL;
2729 ULONG initialDirtyCount = 0;
2730 BOOLEAN bExtentsLocked = FALSE;
2733 NTSTATUS ntStatus = STATUS_SUCCESS;
2734 LARGE_INTEGER liLastFlush;
2735 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2736 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2738 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2741 // Save, then reset the flush time
2744 liLastFlush = Fcb->Specific.File.LastServerFlush;
2746 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2752 // Lock extents while we count and set up the array to send to
2756 AFSLockForExtentsTrim( Fcb);
2758 bExtentsLocked = TRUE;
2760 InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2763 // Clear our queued flush event
2766 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2769 // Look for a start in the list to flush entries
2774 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2776 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2778 AFS_EXTENT_RELEASE_TAG);
2779 if( NULL == pRelease)
2782 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2785 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2787 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2790 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2792 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2795 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2799 // Update the metadata for this call
2802 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2803 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2804 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2805 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2806 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2810 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2813 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2815 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2818 if ( pExtent == NULL)
2824 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2826 if ( pExtent->ActiveCount > 0)
2828 pExtent = pNextExtent;
2832 AFSRemoveEntryDirtyList( Fcb, pExtent);
2834 pExtent->DirtyList.fLink = NULL;
2835 pExtent->DirtyList.bLink = NULL;
2837 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2840 // Clear the flag in advance of the write. If we do
2841 // things this was we know that the clear is
2842 // pessimistic (any write which happens from now on
2843 // will set the flag dirty again).
2846 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2848 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2850 pRelease->FileExtents[count].Length = pExtent->Size;
2851 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2852 pRelease->FileExtents[count].DirtyOffset = 0;
2853 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2854 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2857 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2859 sizeof(pExtent->MD5));
2861 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2864 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2865 AFS_TRACE_LEVEL_VERBOSE,
2866 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2868 Fcb->ObjectInformation->FileId.Cell,
2869 Fcb->ObjectInformation->FileId.Volume,
2870 Fcb->ObjectInformation->FileId.Vnode,
2871 Fcb->ObjectInformation->FileId.Unique,
2872 pExtent->FileOffset.QuadPart,
2875 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2878 // Need to pull this extent from the main list as well
2881 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2883 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2885 RemoveEntryList( &pExtent->Lists[i] );
2889 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2891 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2893 AFSExFreePool( pExtent);
2895 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2897 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
2900 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2907 pExtent = pNextExtent;
2910 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2913 // If we are done then get out
2919 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2920 AFS_TRACE_LEVEL_VERBOSE,
2921 "AFSFlushExtents No more dirty extents found\n");
2927 // Fire off the request synchronously
2930 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2932 pRelease->ExtentCount = count;
2934 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2935 AFS_TRACE_LEVEL_VERBOSE,
2936 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2937 &pNPFcb->Specific.File.ExtentsResource,
2938 PsGetCurrentThread());
2940 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2941 bExtentsLocked = FALSE;
2943 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2947 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2948 AFS_REQUEST_FLAG_SYNCHRONOUS,
2951 &Fcb->ObjectInformation->FileId,
2957 if( !NT_SUCCESS(ntStatus))
2961 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2962 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2965 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2966 AFS_TRACE_LEVEL_ERROR,
2967 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2968 Fcb->ObjectInformation->FileId.Cell,
2969 Fcb->ObjectInformation->FileId.Volume,
2970 Fcb->ObjectInformation->FileId.Vnode,
2971 Fcb->ObjectInformation->FileId.Unique,
2975 AFSLockForExtentsTrim( Fcb);
2977 bExtentsLocked = TRUE;
2982 if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
2985 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2990 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2997 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2998 AFS_TRACE_LEVEL_VERBOSE,
2999 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
3000 &pNPFcb->Specific.File.ExtentsResource,
3001 PsGetCurrentThread());
3003 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3008 AFSExFreePool( pRelease);
3016 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb)
3018 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3021 AFSReleaseExtentsCB *pRelease = NULL;
3023 ULONG initialDirtyCount = 0;
3024 BOOLEAN bExtentsLocked = FALSE;
3027 NTSTATUS ntStatus = STATUS_SUCCESS;
3028 LARGE_INTEGER liLastFlush;
3029 ULONG ulRemainingExtentLength = 0;
3030 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3032 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3035 // Save, then reset the flush time
3038 liLastFlush = Fcb->Specific.File.LastServerFlush;
3040 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3046 // Look for a start in the list to flush entries
3051 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3053 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3055 AFS_EXTENT_RELEASE_TAG);
3056 if( NULL == pRelease)
3059 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3062 if( Fcb->OpenHandleCount > 0)
3066 // Don't release everything ...
3070 // For now release everything
3073 //ulRemainingExtentLength = 1500;
3076 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3079 AFSLockForExtentsTrim( Fcb);
3081 bExtentsLocked = TRUE;
3083 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3086 // Update the metadata for this call
3089 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3090 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3091 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3092 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3093 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3097 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3099 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3100 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3103 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3107 if( pExtent->ActiveCount > 0)
3113 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3115 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3116 AFS_TRACE_LEVEL_VERBOSE,
3117 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3119 Fcb->ObjectInformation->FileId.Cell,
3120 Fcb->ObjectInformation->FileId.Volume,
3121 Fcb->ObjectInformation->FileId.Vnode,
3122 Fcb->ObjectInformation->FileId.Unique,
3123 pExtent->FileOffset.QuadPart,
3126 pRelease->FileExtents[count].Length = pExtent->Size;
3127 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3128 pRelease->FileExtents[count].DirtyOffset = 0;
3129 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3130 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3133 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3135 sizeof(pExtent->MD5));
3137 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3140 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3143 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3146 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3149 AFSRemoveEntryDirtyList( Fcb,
3152 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3154 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3157 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3161 // Need to pull this extent from the main list as well
3164 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3166 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3168 RemoveEntryList( &pExtent->Lists[i] );
3172 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3174 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3176 AFSExFreePool( pExtent);
3178 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3180 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3183 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3192 // If we are done then get out
3198 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3199 AFS_TRACE_LEVEL_VERBOSE,
3200 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3206 // Fire off the request synchronously
3209 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3211 pRelease->ExtentCount = count;
3214 // Drop the extents lock for the duration of the call to
3215 // the network. We have pinned the extents so, even
3216 // though we might get extents added during this period,
3217 // but none will be removed. Hence we can carry on from
3221 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3222 AFS_TRACE_LEVEL_VERBOSE,
3223 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3224 &pNPFcb->Specific.File.ExtentsResource,
3225 PsGetCurrentThread());
3227 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3228 bExtentsLocked = FALSE;
3230 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3231 AFS_REQUEST_FLAG_SYNCHRONOUS,
3234 &Fcb->ObjectInformation->FileId,
3240 if( !NT_SUCCESS(ntStatus))
3244 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3245 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3248 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3249 AFS_TRACE_LEVEL_ERROR,
3250 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3251 Fcb->ObjectInformation->FileId.Cell,
3252 Fcb->ObjectInformation->FileId.Volume,
3253 Fcb->ObjectInformation->FileId.Vnode,
3254 Fcb->ObjectInformation->FileId.Unique,
3264 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3265 AFS_TRACE_LEVEL_VERBOSE,
3266 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3267 &pNPFcb->Specific.File.ExtentsResource,
3268 PsGetCurrentThread());
3270 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3275 AFSExFreePool( pRelease);
3283 AFSMarkDirty( IN AFSFcb *Fcb,
3284 IN AFSExtent *StartExtent,
3285 IN ULONG ExtentsCount,
3286 IN LARGE_INTEGER *StartingByte)
3289 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3290 AFSExtent *pExtent = StartExtent;
3291 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3293 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3295 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3296 AFS_TRACE_LEVEL_VERBOSE,
3297 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3298 &Fcb->NPFcb->Specific.File.ExtentsResource,
3299 PsGetCurrentThread());
3301 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3303 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3307 // Find the insertion point
3310 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3315 else if( StartingByte->QuadPart == 0)
3323 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3325 while( pCurrentExtent != NULL)
3328 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3329 pCurrentExtent->DirtyList.fLink == NULL)
3335 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3339 while( ulCount < ExtentsCount)
3342 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3344 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3347 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3348 AFS_TRACE_LEVEL_VERBOSE,
3349 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3350 pExtent->FileOffset.QuadPart,
3353 pExtent->DirtyList.fLink = NULL;
3354 pExtent->DirtyList.bLink = NULL;
3359 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3361 pExtent->DirtyList.bLink = NULL;
3363 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3365 pNPFcb->Specific.File.DirtyListHead = pExtent;
3367 pCurrentExtent = pExtent;
3369 bInsertHead = FALSE;
3371 else if( bInsertTail)
3374 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3377 pNPFcb->Specific.File.DirtyListHead = pExtent;
3382 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3384 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3387 pNPFcb->Specific.File.DirtyListTail = pExtent;
3392 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3393 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3395 if( pExtent->DirtyList.fLink == NULL)
3398 pNPFcb->Specific.File.DirtyListTail = pExtent;
3403 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3406 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3408 pCurrentExtent = pExtent;
3411 pExtent->Flags |= AFS_EXTENT_DIRTY;
3414 // Up the dirty count
3417 InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3422 pCurrentExtent = pExtent;
3425 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3426 AFS_TRACE_LEVEL_VERBOSE,
3427 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3429 pExtent->ActiveCount);
3431 ASSERT( pExtent->ActiveCount > 0);
3433 InterlockedDecrement( &pExtent->ActiveCount);
3435 pExtent = pNextExtent;
3440 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3442 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3443 AFS_TRACE_LEVEL_VERBOSE,
3444 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3445 &Fcb->NPFcb->Specific.File.ExtentsResource,
3446 PsGetCurrentThread());
3448 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3457 static AFSExtent *ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3459 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3462 static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
3464 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3467 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3469 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3472 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3476 // Check the ordering of the extents lists
3478 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3480 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3482 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3484 LARGE_INTEGER lastOffset;
3486 lastOffset.QuadPart = 0;
3488 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3489 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3494 pExtent = ExtentFor(pLe, listNo);
3497 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3498 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3499 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3502 ASSERT(pLe->Flink->Blink == pLe);
3503 ASSERT(pLe->Blink->Flink == pLe);
3506 // Should follow on from previous
3508 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3509 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3512 // Should match alignment criteria
3514 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3517 // "lower" lists should be populated
3519 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3521 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3529 AFSTrimExtents( IN AFSFcb *Fcb,
3530 IN PLARGE_INTEGER FileSize)
3533 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3536 BOOLEAN locked = FALSE;
3537 NTSTATUS ntStatus = STATUS_SUCCESS;
3538 LARGE_INTEGER liAlignedOffset = {0,0};
3539 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3540 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3546 // Get an aligned offset
3549 if( FileSize != NULL)
3552 liAlignedOffset = *FileSize;
3555 if( liAlignedOffset.QuadPart > 0 &&
3556 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3560 // Align UP to the next cache block size
3563 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3567 // Ensure that no one is working with the extents and grab the
3571 AFSLockForExtentsTrim( Fcb);
3575 if( 0 == Fcb->Specific.File.ExtentCount)
3579 // Update the request extent status
3582 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3584 try_return( ntStatus = STATUS_SUCCESS);
3588 // We are truncating from a specific length in the file. If the offset
3589 // is non-zero then go find the first extent to remove
3592 if( 0 == FileSize->QuadPart)
3595 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3600 pExtent = AFSExtentForOffset( Fcb,
3604 if( NULL == pExtent)
3607 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3611 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3615 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3618 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3621 // Only trim down extents beyond the aligned offset
3626 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3629 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3632 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3635 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3639 AFSRemoveEntryDirtyList( Fcb,
3642 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3644 ASSERT(dirtyCount >= 0);
3647 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3650 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3652 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3654 RemoveEntryList( &pExtent->Lists[i] );
3658 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3659 AFS_TRACE_LEVEL_VERBOSE,
3660 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3662 Fcb->ObjectInformation->FileId.Cell,
3663 Fcb->ObjectInformation->FileId.Volume,
3664 Fcb->ObjectInformation->FileId.Vnode,
3665 Fcb->ObjectInformation->FileId.Unique,
3666 pExtent->FileOffset.QuadPart,
3669 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3671 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3673 ASSERT( pExtent->ActiveCount == 0);
3678 AFSExFreePool( pExtent);
3680 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3682 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3685 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3693 // Update the request extent status
3696 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3703 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3704 AFS_TRACE_LEVEL_VERBOSE,
3705 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3706 &Fcb->NPFcb->Specific.File.ExtentsResource,
3707 PsGetCurrentThread());
3709 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3717 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3719 IN AFSFileExtentCB *Result)
3722 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3725 AFSFileExtentCB *pFileExtents = Result;
3726 NTSTATUS ntStatus = STATUS_SUCCESS;
3727 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3728 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3733 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3735 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3739 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3742 // Only trim down extents beyond the aligned offset
3747 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3750 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3753 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3756 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3761 AFSRemoveEntryDirtyList( Fcb,
3764 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3766 ASSERT( dirtyCount >= 0);
3770 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3774 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3776 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3778 RemoveEntryList( &pExtent->Lists[i] );
3782 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3783 AFS_TRACE_LEVEL_VERBOSE,
3784 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3786 Fcb->ObjectInformation->FileId.Cell,
3787 Fcb->ObjectInformation->FileId.Volume,
3788 Fcb->ObjectInformation->FileId.Vnode,
3789 Fcb->ObjectInformation->FileId.Unique,
3790 pExtent->FileOffset.QuadPart,
3793 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3795 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3797 ASSERT( pExtent->ActiveCount == 0);
3802 AFSExFreePool( pExtent);
3804 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3806 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3809 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3815 // Next extent we are looking for
3825 // Update the request extent status
3828 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3835 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3836 IN ULONG ExtentsCount)
3839 AFSExtent *pExtent = StartExtent;
3840 AFSExtent *pNextExtent;
3843 while( ulCount < ExtentsCount)
3846 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3848 InterlockedIncrement( &pExtent->ActiveCount);
3850 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3851 AFS_TRACE_LEVEL_VERBOSE,
3852 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
3854 pExtent->ActiveCount);
3856 pExtent = pNextExtent;
3865 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
3866 IN ULONG ExtentsCount)
3869 AFSExtent *pExtent = StartExtent;
3870 AFSExtent *pNextExtent;
3873 while( ulCount < ExtentsCount)
3876 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3878 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3879 AFS_TRACE_LEVEL_VERBOSE,
3880 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
3882 pExtent->ActiveCount);
3884 ASSERT( pExtent->ActiveCount > 0);
3886 InterlockedDecrement( &pExtent->ActiveCount);
3888 pExtent = pNextExtent;
3897 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
3898 IN AFSExtent *Extent)
3901 if( Extent->DirtyList.fLink == NULL)
3904 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
3906 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
3909 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
3915 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
3918 if( Extent->DirtyList.bLink == NULL)
3921 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
3923 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
3926 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
3932 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
3941 AFSSetupMD5Hash( IN AFSFcb *Fcb,
3942 IN AFSExtent *StartExtent,
3943 IN ULONG ExtentsCount,
3944 IN void *SystemBuffer,
3945 IN LARGE_INTEGER *ByteOffset,
3949 NTSTATUS ntStatus = STATUS_SUCCESS;
3950 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3951 AFSExtent *pExtent = StartExtent;
3952 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3954 char *pCurrentBuffer = (char *)SystemBuffer;
3955 char *pMD5Buffer = NULL;
3956 ULONG ulCurrentLen = 0;
3957 void *pExtentBuffer = NULL;
3958 LARGE_INTEGER liByteOffset;
3959 ULONG ulBytesRead = 0;
3964 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3965 AFS_TRACE_LEVEL_VERBOSE,
3966 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3967 &Fcb->NPFcb->Specific.File.ExtentsResource,
3968 PsGetCurrentThread());
3970 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3972 liByteOffset.QuadPart = ByteOffset->QuadPart;
3974 while( ulCount < ExtentsCount)
3977 RtlZeroMemory( pExtent->MD5,
3978 sizeof( pExtent->MD5));
3980 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3982 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
3983 ByteCount < pExtent->Size)
3986 if( pExtentBuffer == NULL)
3989 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
3991 AFS_GENERIC_MEMORY_9_TAG);
3993 if( pExtentBuffer == NULL)
4000 RtlZeroMemory( pExtentBuffer,
4003 RtlCopyMemory( pExtentBuffer,
4007 pMD5Buffer = (char *)pExtentBuffer;
4009 ulCurrentLen = ByteCount;
4011 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4014 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4016 AFS_GENERIC_MEMORY_10_TAG);
4018 if( pExtentBuffer == NULL)
4024 RtlZeroMemory( pExtentBuffer,
4027 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4031 RtlCopyMemory( pExtentBuffer,
4032 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4035 ASSERT( pExtent->CacheOffset.HighPart == 0);
4036 RtlCopyMemory( pExtentBuffer,
4037 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4041 ulBytesRead = pExtent->Size;
4046 ntStatus = AFSReadCacheFile( pExtentBuffer,
4047 &pExtent->CacheOffset,
4051 if( !NT_SUCCESS( ntStatus))
4057 pMD5Buffer = (char *)pExtentBuffer;
4059 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4061 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4068 ulCurrentLen = pExtent->Size;
4070 pMD5Buffer = pCurrentBuffer;
4073 AFSGenerateMD5( pMD5Buffer,
4077 pExtent = pNextExtent;
4081 ByteCount -= ulCurrentLen;
4083 pCurrentBuffer += ulCurrentLen;
4085 liByteOffset.QuadPart += ulCurrentLen;
4088 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4089 AFS_TRACE_LEVEL_VERBOSE,
4090 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4091 &Fcb->NPFcb->Specific.File.ExtentsResource,
4092 PsGetCurrentThread());
4094 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4096 if( pExtentBuffer != NULL)
4099 AFSExFreePool( pExtentBuffer);