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 ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
43 static VOID VerifyExtentsLists(AFSFcb *Fcb);
44 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le);
47 AFSEntryForOffset( IN AFSFcb *Fcb,
48 IN PLARGE_INTEGER Offset);
52 // Returns with Extents lock EX and no one using them.
56 AFSLockForExtentsTrim( IN AFSFcb *Fcb)
59 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
60 AFS_TRACE_LEVEL_VERBOSE,
61 "AFSLockForExtentsTrim Acquiring Fcb extents lock %08lX EXCL %08lX\n",
62 &Fcb->NPFcb->Specific.File.ExtentsResource,
63 PsGetCurrentThread());
65 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
71 // return FALSE *or* with Extents lock EX and noone using them
74 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
77 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
78 AFS_TRACE_LEVEL_VERBOSE,
79 "AFSLockForExtentsTrimNoWait Attempting to acquire Fcb extent lock %08lX EXCL %08lX\n",
80 &Fcb->NPFcb->Specific.File.ExtentsResource,
81 PsGetCurrentThread());
83 if (!AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, FALSE ))
86 // Couldn't lock immediately
89 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
90 AFS_TRACE_LEVEL_VERBOSE,
91 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
92 &Fcb->NPFcb->Specific.File.ExtentsResource,
93 PsGetCurrentThread());
102 AFSFreeExtent( IN AFSFcb *Fcb,
103 IN AFSExtent *pExtent)
105 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
108 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
110 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
112 RemoveEntryList( &pExtent->Lists[i] );
116 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
118 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
120 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
122 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
127 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
132 AFSExFreePoolWithTag( pExtent, AFS_EXTENT_TAG);
136 // AFSTearDownFcbExtents was originally written to
137 // remove all of the extents from an FCB. For that to happen
138 // it must be an invariant that the extent list cannot change
139 // from the moment the caller decides to execute AFSTearDownFcbExtents
140 // until it returns. This invariant does not hold because the
141 // the decision to call AFSTearDownFcbExtents is made without
142 // holding the ExtentsResource and it is possible that extents
143 // are in active use. Therefore, AFSTearDownFcbExtents now releases
144 // as many non-active extents as it can.
147 AFSTearDownFcbExtents( IN AFSFcb *Fcb,
150 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
151 LIST_ENTRY *le, *leNext;
153 LONG lExtentCount = 0, lProcessCount = 0;
154 ULONG ulReleaseCount = 0;
156 AFSReleaseExtentsCB *pRelease = NULL;
157 BOOLEAN locked = FALSE;
159 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
160 GUID *pAuthGroup = AuthGroup;
167 if( pAuthGroup == NULL ||
168 RtlCompareMemory( pAuthGroup,
169 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
170 sizeof( GUID)) == sizeof( GUID))
173 RtlZeroMemory( &stAuthGroup,
176 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
181 if( !NT_SUCCESS( ntStatus))
183 try_return( ntStatus);
186 pAuthGroup = &stAuthGroup;
190 // Ensure that no one is working with the extents and grab the
194 AFSLockForExtentsTrim( Fcb );
198 if (0 == Fcb->Specific.File.ExtentCount)
200 try_return ( ntStatus = STATUS_SUCCESS);
203 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
205 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
207 AFS_EXTENT_RELEASE_TAG);
208 if (NULL == pRelease)
211 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
214 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
217 for( le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink,
219 lExtentCount < Fcb->Specific.File.ExtentCount;
220 lExtentCount += lProcessCount)
223 RtlZeroMemory( pRelease,
224 sizeof( AFSReleaseExtentsCB ) +
225 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
227 for( lProcessCount = 0, ulReleaseCount = 0;
229 ulReleaseCount < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
230 lExtentCount + lProcessCount < Fcb->Specific.File.ExtentCount;
231 lProcessCount++, le = leNext)
236 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
238 if( pEntry->ActiveCount == 0)
241 pRelease->FileExtents[ulReleaseCount].Flags = AFS_EXTENT_FLAG_RELEASE;
244 RtlCopyMemory( pRelease->FileExtents[ulReleaseCount].MD5,
246 sizeof(pEntry->MD5));
248 pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
251 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
256 AFSRemoveEntryDirtyList( Fcb,
259 pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
261 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
263 ASSERT( dirtyCount >= 0);
266 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
267 AFS_TRACE_LEVEL_VERBOSE,
268 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
270 Fcb->ObjectInformation->FileId.Cell,
271 Fcb->ObjectInformation->FileId.Volume,
272 Fcb->ObjectInformation->FileId.Vnode,
273 Fcb->ObjectInformation->FileId.Unique,
274 pEntry->FileOffset.HighPart,
275 pEntry->FileOffset.LowPart,
278 pRelease->FileExtents[ulReleaseCount].Length = pEntry->Size;
279 pRelease->FileExtents[ulReleaseCount].DirtyLength = pEntry->Size;
280 pRelease->FileExtents[ulReleaseCount].DirtyOffset = 0;
281 pRelease->FileExtents[ulReleaseCount].CacheOffset = pEntry->CacheOffset;
282 pRelease->FileExtents[ulReleaseCount].FileOffset = pEntry->FileOffset;
291 if ( ulReleaseCount > 0)
294 pRelease->ExtentCount = ulReleaseCount;
296 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
299 // Update the metadata for this call
302 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
303 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
304 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
305 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
306 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
309 // Send the request down. We cannot send this down
310 // asynchronously - if we did that we could request them
311 // back before the service got this request and then this
312 // request would be a corruption.
315 sz = sizeof( AFSReleaseExtentsCB ) + (lProcessCount * sizeof ( AFSFileExtentCB ));
317 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
318 AFS_REQUEST_FLAG_SYNCHRONOUS,
321 &Fcb->ObjectInformation->FileId,
327 if( !NT_SUCCESS(ntStatus))
331 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
332 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
335 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
336 AFS_TRACE_LEVEL_ERROR,
337 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
338 Fcb->ObjectInformation->FileId.Cell,
339 Fcb->ObjectInformation->FileId.Volume,
340 Fcb->ObjectInformation->FileId.Vnode,
341 Fcb->ObjectInformation->FileId.Unique,
348 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
351 // if all extents have been released, reinitialize the skip lists
354 if( Fcb->Specific.File.ExtentCount == 0)
357 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
359 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
363 // Reinitialize the dirty list as well
366 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
369 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
371 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
372 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
374 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
377 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
384 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
385 AFS_TRACE_LEVEL_VERBOSE,
386 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
387 &Fcb->NPFcb->Specific.File.ExtentsResource,
388 PsGetCurrentThread());
390 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
396 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
402 ExtentForOffsetInList( IN AFSFcb *Fcb,
405 IN PLARGE_INTEGER Offset)
408 // Return the extent that maps the offset, that
409 // - Contains the offset
410 // - or is immediately ahead of the offset (in this list)
411 // - otherwise return NULL.
414 PLIST_ENTRY pLe = List;
415 AFSExtent *pPrevious = NULL;
417 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
419 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
423 entry = ExtentFor( pLe, ListNumber );
430 if (Offset->QuadPart < entry->FileOffset.QuadPart)
433 // Offset is ahead of entry. Return previous
438 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
441 // We start after this extent - carry on round
449 // Otherwise its a match
456 // Got to the end. Return Previous
462 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
468 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
469 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
474 // Return the extent that contains the offset
477 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
478 IN PLARGE_INTEGER Offset,
479 IN BOOLEAN ReturnPrevious,
482 AFSExtent *pPrevious = Hint;
486 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
488 #if AFS_VALIDATE_EXTENTS
489 VerifyExtentsLists(Fcb);
493 // So we will go across the skip lists until we find an
494 // appropriate entry (previous or direct match). If it's a match
495 // we are done, other wise we start on the next layer down
497 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
499 if (NULL == pPrevious)
502 // We haven't found anything in the previous layers
504 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
506 else if (NULL == pPrevious->Lists[i].Flink)
508 ASSERT(AFS_EXTENTS_LIST != i);
510 // The hint doesn't exist at this level, next one down
517 // take the previous into the next
519 pLe = &pPrevious->Lists[i];
522 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
524 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
527 // Found it immediately. Stop here
533 if (NULL == pPrevious || ReturnPrevious )
538 ASSERT( !AFSExtentContains(pPrevious, Offset) );
544 AFSEntryForOffset( IN AFSFcb *Fcb,
545 IN PLARGE_INTEGER Offset)
547 AFSExtent *pPrevious = NULL;
551 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
553 #if AFS_VALIDATE_EXTENTS
554 VerifyExtentsLists(Fcb);
558 // So we will go across the skip lists until we find an
559 // appropriate entry (previous or direct match). If it's a match
560 // we are done, other wise we start on the next layer down
562 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
564 if (NULL == pPrevious)
567 // We haven't found anything in the previous layers
569 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
571 else if (NULL == pPrevious->Lists[i].Flink)
573 ASSERT(AFS_EXTENTS_LIST != i);
575 // The hint doesn't exist at this level, next one down
582 // take the previous into the next
584 pLe = &pPrevious->Lists[i];
587 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
589 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
592 // Found it immediately. Stop here
602 AFSExtentForOffset( IN AFSFcb *Fcb,
603 IN PLARGE_INTEGER Offset,
604 IN BOOLEAN ReturnPrevious)
606 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
610 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
611 IN PLARGE_INTEGER Offset,
613 IN OUT AFSExtent **FirstExtent,
614 OUT AFSExtent **LastExtent)
617 // Return TRUE region is completely mapped. FALSE
618 // otherwise. If the region isn't mapped then the last
619 // extent to map part of the region is returned.
621 // *LastExtent as input is where to start looking.
622 // *LastExtent as output is either the extent which
623 // contains the Offset, or the last one which doesn't
627 BOOLEAN retVal = FALSE;
632 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
636 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
637 *FirstExtent = entry;
639 if (NULL == entry || !AFSExtentContains(entry, Offset))
641 try_return (retVal = FALSE);
644 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
648 if ((entry->FileOffset.QuadPart + entry->Size) >=
649 (Offset->QuadPart + Size))
652 // The end is inside the extent
654 try_return (retVal = TRUE);
657 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
660 // Run out of extents
662 try_return (retVal = FALSE);
665 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
667 if (newEntry->FileOffset.QuadPart !=
668 (entry->FileOffset.QuadPart + entry->Size))
673 try_return (retVal = FALSE);
679 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
684 "EXCEPTION - AFSDoExtentsMapRegion\n");
686 AFSDumpTraceFilesFnc();
698 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
700 IN PLARGE_INTEGER Offset,
704 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
705 NTSTATUS ntStatus = STATUS_SUCCESS;
706 AFSExtent *pExtent = NULL;
707 AFSRequestExtentsCB request;
708 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
709 AFSExtent *pFirstExtent = NULL;
710 LARGE_INTEGER liAlignedOffset;
711 ULONG ulAlignedLength = 0;
712 BOOLEAN bRegionMapped = FALSE;
713 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
718 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
721 // If the service set a failure on the file since the last
722 // CreateFile was issued, return it now.
725 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
729 // If this isn't the same authgroup which caused the failure
730 // then try to request them again
733 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
735 sizeof( GUID)) == sizeof( GUID))
738 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
740 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
742 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
745 try_return( ntStatus);
750 // Check if we are already mapped
753 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
754 AFS_TRACE_LEVEL_VERBOSE,
755 "AFSRequestExtentsAsync Acquiring Fcb extents lock %08lX SHARED %08lX\n",
756 &pNPFcb->Specific.File.ExtentsResource,
757 PsGetCurrentThread());
759 AFSAcquireShared( &pNPFcb->Specific.File.ExtentsResource, TRUE );
761 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
766 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
769 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
770 AFS_TRACE_LEVEL_VERBOSE,
771 "AFSRequestExtentsAsync Releasing Fcb extents lock %08lX SHARED %08lX\n",
772 &pNPFcb->Specific.File.ExtentsResource,
773 PsGetCurrentThread());
775 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
780 try_return( ntStatus = STATUS_SUCCESS);
784 // Align our request on extent size boundary
787 ulAlignedLength = Size;
789 liAlignedOffset = *Offset;
791 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
794 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
796 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
799 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
802 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
805 RtlZeroMemory( &request,
806 sizeof( AFSRequestExtentsCB));
808 request.ByteOffset = liAlignedOffset;
809 request.Length = ulAlignedLength;
811 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
816 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
817 AFS_TRACE_LEVEL_VERBOSE,
818 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
819 Fcb->ObjectInformation->FileId.Cell,
820 Fcb->ObjectInformation->FileId.Volume,
821 Fcb->ObjectInformation->FileId.Vnode,
822 Fcb->ObjectInformation->FileId.Unique,
823 request.ByteOffset.LowPart,
825 PsGetCurrentThread());
827 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
831 &Fcb->ObjectInformation->FileId,
833 sizeof( AFSRequestExtentsCB ),
837 if ( ntStatus == STATUS_ACCESS_DENIED)
842 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
847 if ( NT_SUCCESS( ntStatus2) &&
848 RtlCompareMemory( &stAuthGroup,
850 sizeof( GUID)) != sizeof( GUID))
853 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
857 &Fcb->ObjectInformation->FileId,
859 sizeof( AFSRequestExtentsCB ),
865 if( NT_SUCCESS( ntStatus))
868 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
874 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
886 AFSProcessExtentsResult( IN AFSFcb *Fcb,
888 IN AFSFileExtentCB *Result)
890 NTSTATUS ntStatus = STATUS_SUCCESS;
891 AFSFileExtentCB *pFileExtents = Result;
894 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
895 ULONG fileExtentsUsed = 0;
896 BOOLEAN bFoundExtent = FALSE;
897 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
898 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
902 // Grab the extents exclusive for the duration
905 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
906 AFS_TRACE_LEVEL_VERBOSE,
907 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
908 &pNPFcb->Specific.File.ExtentsResource,
909 PsGetCurrentThread());
911 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
917 // Find where to put the extents
919 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
922 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
925 le = pSkipEntries[AFS_EXTENTS_LIST];
927 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
930 // No extents. Insert at head of list (which is where the skip lists point!)
934 else if (0 != pFileExtents->FileOffset.QuadPart)
937 // We want to find the best extents immediately *behind* this offset
939 LARGE_INTEGER offset = pFileExtents->FileOffset;
942 // Ask in the top skip list first, then work down
944 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
946 pExtent = ExtentForOffsetInList( Fcb,
954 // No dice. Header has to become the head of the list
956 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
958 // And as a loop invariant we should never have found an extent
960 ASSERT(!bFoundExtent);
965 // pExtent is where to start to insert at this level
967 pSkipEntries[i] = &pExtent->Lists[i];
970 // And also where to start to look at the next level
973 if (i > AFS_EXTENTS_LIST)
975 pSkipEntries[i-1] = &pExtent->Lists[i-1];
983 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
988 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
994 // Looking at offset 0, so we must start at the beginning
997 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1001 // And set up the skip lists
1004 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1006 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1010 while (fileExtentsUsed < Count)
1014 // Loop invariant - le points to where to insert after and
1015 // pExtent points to le->fLink
1018 ASSERT (NULL == pExtent ||
1019 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1021 if (NULL == pExtent ||
1022 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1025 // We need to insert a new extent at le. Start with
1026 // some sanity check on spanning
1028 if (NULL != pExtent &&
1029 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1030 pExtent->FileOffset.QuadPart))
1033 // File Extents overlaps pExtent
1035 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1036 pExtent->FileOffset.QuadPart);
1038 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1042 // File offset is entirely in front of this extent. Create
1043 // a new one (remember le is the previous list entry)
1045 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1048 if (NULL == pExtent)
1051 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1054 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1056 pExtent->FileOffset = pFileExtents->FileOffset;
1057 pExtent->CacheOffset = pFileExtents->CacheOffset;
1058 pExtent->Size = pFileExtents->Length;
1060 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1061 AFS_TRACE_LEVEL_VERBOSE,
1062 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1063 Fcb->ObjectInformation->FileId.Cell,
1064 Fcb->ObjectInformation->FileId.Volume,
1065 Fcb->ObjectInformation->FileId.Vnode,
1066 Fcb->ObjectInformation->FileId.Unique,
1067 pFileExtents->FileOffset.QuadPart,
1068 pFileExtents->CacheOffset.QuadPart,
1069 pFileExtents->Length);
1071 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1073 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1075 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1077 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1082 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1088 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1089 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1090 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1093 // Do not move the cursor - we will do it next time
1097 // And into the (upper) skip lists - Again, do not move the cursor
1099 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1101 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1103 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1104 #if AFS_VALIDATE_EXTENTS
1105 VerifyExtentsLists(Fcb);
1110 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1113 if (pExtent->Size != pFileExtents->Length)
1116 ASSERT (pExtent->Size == pFileExtents->Length);
1118 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1122 // Move both cursors forward.
1124 // First the extent pointer
1127 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1130 // Then the skip lists cursors forward if needed
1132 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1134 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1137 // Check sanity before
1139 #if AFS_VALIDATE_EXTENTS
1140 VerifyExtentsLists(Fcb);
1144 // Skip list should point to us
1146 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1148 // Move forward cursor
1150 pSkipEntries[i] = pSkipEntries[i]->Flink;
1152 // Check sanity before
1154 #if AFS_VALIDATE_EXTENTS
1155 VerifyExtentsLists(Fcb);
1161 // And then the cursor in the supplied array
1167 // setup pExtent if there is one
1169 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1171 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1181 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1184 // Sanity check on spanning
1186 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1187 pFileExtents->FileOffset.QuadPart)
1190 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1191 pFileExtents->FileOffset.QuadPart);
1193 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1197 // Move le and pExtent forward
1199 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1203 // Then the check the skip lists cursors
1205 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1207 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1211 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1212 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1213 // - We are not the last on the list. In that case we have to be strictly less than
1215 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1217 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1218 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1225 // setup pExtent if there is one
1228 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1230 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1240 // All done, signal that we are done drop the lock, exit
1245 if( !NT_SUCCESS( ntStatus))
1249 // If we failed the service is going to drop all extents so trim away the
1253 AFSTrimSpecifiedExtents( Fcb,
1258 #if AFS_VALIDATE_EXTENTS
1259 VerifyExtentsLists(Fcb);
1262 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1266 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1267 AFS_TRACE_LEVEL_VERBOSE,
1268 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1269 &pNPFcb->Specific.File.ExtentsResource,
1270 PsGetCurrentThread());
1272 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1279 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1281 AFSFcb *pFcb = NULL;
1282 AFSVolumeCB *pVolumeCB = NULL;
1283 NTSTATUS ntStatus = STATUS_SUCCESS;
1284 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1285 ULONGLONG ullIndex = 0;
1286 AFSObjectInfoCB *pObjectInfo = NULL;
1292 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1293 AFS_TRACE_LEVEL_VERBOSE,
1294 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1295 &pDevExt->Specific.RDR.VolumeTreeLock,
1296 PsGetCurrentThread());
1298 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1300 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1301 AFS_TRACE_LEVEL_VERBOSE,
1302 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1303 SetExtents->FileId.Cell,
1304 SetExtents->FileId.Volume,
1305 SetExtents->FileId.Vnode,
1306 SetExtents->FileId.Unique);
1309 // Locate the volume node
1312 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1314 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1316 (AFSBTreeEntry **)&pVolumeCB);
1318 if( pVolumeCB != NULL)
1321 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1322 AFS_TRACE_LEVEL_VERBOSE,
1323 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1324 pVolumeCB->ObjectInfoTree.TreeLock,
1325 PsGetCurrentThread());
1327 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1330 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1332 if( !NT_SUCCESS( ntStatus) ||
1336 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1337 AFS_TRACE_LEVEL_ERROR,
1338 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1339 SetExtents->FileId.Cell,
1340 SetExtents->FileId.Volume,
1341 SetExtents->FileId.Vnode,
1342 SetExtents->FileId.Unique,
1345 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1348 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1351 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1354 // Now locate the Object in this volume
1357 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1359 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1361 (AFSBTreeEntry **)&pObjectInfo);
1363 if( pObjectInfo != NULL)
1367 // Reference the node so it won't be torn down
1370 lCount = AFSObjectInfoIncrement( pObjectInfo);
1372 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1373 AFS_TRACE_LEVEL_VERBOSE,
1374 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1379 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1381 if( !NT_SUCCESS( ntStatus) ||
1382 pObjectInfo == NULL)
1385 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1386 AFS_TRACE_LEVEL_ERROR,
1387 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1389 SetExtents->FileId.Cell,
1390 SetExtents->FileId.Volume,
1391 SetExtents->FileId.Vnode,
1392 SetExtents->FileId.Unique,
1395 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1398 pFcb = pObjectInfo->Fcb;
1401 // If we have a result failure then don't bother trying to set the extents
1404 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1407 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1408 AFS_TRACE_LEVEL_ERROR,
1409 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1410 SetExtents->FileId.Cell,
1411 SetExtents->FileId.Volume,
1412 SetExtents->FileId.Vnode,
1413 SetExtents->FileId.Unique,
1414 SetExtents->ResultStatus);
1416 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1417 AFS_TRACE_LEVEL_VERBOSE,
1418 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1419 &pFcb->NPFcb->Specific.File.ExtentsResource,
1420 PsGetCurrentThread());
1422 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1425 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1427 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1431 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1432 AFS_TRACE_LEVEL_VERBOSE,
1433 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1434 &pFcb->NPFcb->Specific.File.ExtentsResource,
1435 PsGetCurrentThread());
1437 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1439 try_return( ntStatus);
1442 ntStatus = AFSProcessExtentsResult ( pFcb,
1443 SetExtents->ExtentCount,
1444 SetExtents->FileExtents );
1448 if( pObjectInfo != NULL)
1451 lCount = AFSObjectInfoDecrement( pObjectInfo);
1453 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1454 AFS_TRACE_LEVEL_VERBOSE,
1455 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1465 // Helper fuctions for Usermode initiation of release of extents
1468 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1470 OUT AFSFileExtentCB *FileExtents,
1471 IN ULONG BufferSize,
1472 OUT ULONG *ExtentCount,
1473 OUT BOOLEAN *DirtyExtents)
1478 ULONG ulExtentCount = 0;
1479 NTSTATUS ntStatus = STATUS_SUCCESS;
1480 BOOLEAN bReleaseAll = FALSE;
1481 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1486 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1488 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1491 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1492 AFS_TRACE_LEVEL_VERBOSE,
1493 "AFSReleaseSpecifiedExtents Buffer too small\n");
1495 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1498 RtlZeroMemory( FileExtents, BufferSize);
1501 *DirtyExtents = FALSE;
1504 // iterate until we have dealt with all we were asked for or
1505 // are at the end of the list. Note that this deals (albeit
1506 // badly) with out of order extents
1509 pExtent = AFSExtentForOffset( Fcb,
1510 &Extents->FileExtents[0].FileOffset,
1513 if (NULL == pExtent)
1515 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1519 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1523 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1524 ( Extents->FileId.Cell == 0 &&
1525 Extents->FileId.Volume == 0 &&
1526 Extents->FileId.Vnode == 0 &&
1527 Extents->FileId.Unique == 0))
1533 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1534 ulExtentCount < Extents->ExtentCount)
1538 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1543 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1546 // Skip forward through the extent list until we get
1547 // to the one we want
1553 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1556 // We don't have the extent asked for so return UNKNOWN
1559 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1560 AFS_TRACE_LEVEL_VERBOSE,
1561 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1562 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1563 Extents->FileExtents[ulExtentCount].Length);
1565 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1567 FileExtents[*ExtentCount].Length = 0;
1568 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1569 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1571 *ExtentCount = (*ExtentCount) + 1;
1576 // Reset where we are looking
1579 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1583 else if( pExtent->ActiveCount > 0)
1586 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1587 AFS_TRACE_LEVEL_VERBOSE,
1588 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1589 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1590 Extents->FileExtents[ulExtentCount].Length);
1592 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1594 FileExtents[*ExtentCount].Length = 0;
1595 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1596 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1598 *ExtentCount = (*ExtentCount) + 1;
1603 // Reset where we are looking
1606 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1615 // If the extent is currently active then skip it
1618 if( pExtent->ActiveCount > 0)
1627 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1629 FileExtents[*ExtentCount].Length = pExtent->Size;
1630 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1631 FileExtents[*ExtentCount].DirtyOffset = 0;
1632 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1633 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1635 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1636 AFS_TRACE_LEVEL_VERBOSE,
1637 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1639 Fcb->ObjectInformation->FileId.Cell,
1640 Fcb->ObjectInformation->FileId.Volume,
1641 Fcb->ObjectInformation->FileId.Vnode,
1642 Fcb->ObjectInformation->FileId.Unique,
1643 FileExtents[*ExtentCount].FileOffset.QuadPart,
1644 FileExtents[*ExtentCount].Length);
1646 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1649 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1652 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1655 AFSRemoveEntryDirtyList( Fcb,
1658 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1660 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1662 *DirtyExtents = TRUE;
1665 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1669 // move forward all three cursors
1673 *ExtentCount = (*ExtentCount) + 1;
1688 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1691 AFSFcb *pFcb = NULL;
1692 AFSVolumeCB *pVolumeCB = NULL;
1693 AFSDeviceExt *pRDRDeviceExt = NULL;
1694 AFSDeviceExt *pControlDeviceExt = NULL;
1695 BOOLEAN bLocatedEntry = FALSE;
1696 AFSObjectInfoCB *pCurrentObject = NULL;
1697 BOOLEAN bReleaseVolumeListLock = FALSE;
1700 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1701 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1703 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1704 AFS_TRACE_LEVEL_VERBOSE,
1705 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1706 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1707 PsGetCurrentThread());
1709 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1712 bReleaseVolumeListLock = TRUE;
1714 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1716 while( pVolumeCB != NULL)
1720 // The Volume list may move under our feet. Lock it.
1723 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1724 AFS_TRACE_LEVEL_VERBOSE,
1725 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1726 pVolumeCB->ObjectInfoTree.TreeLock,
1727 PsGetCurrentThread());
1729 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1731 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1733 bReleaseVolumeListLock = FALSE;
1735 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1738 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1740 if( NULL == LastFcb)
1743 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1748 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1753 while( pCurrentObject != NULL)
1756 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1759 // If the FCB is a candidate we try to lock it (but without waiting - which
1760 // means we are deadlock free
1764 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1770 AFSLockForExtentsTrim( pFcb);
1775 if( !AFSLockForExtentsTrimNoWait( pFcb))
1778 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1787 // Need to be sure there are no current flushes in the queue
1790 if( pFcb->Specific.File.ExtentCount == 0)
1793 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1794 AFS_TRACE_LEVEL_VERBOSE,
1795 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1796 &pFcb->NPFcb->Specific.File.ExtentsResource,
1797 PsGetCurrentThread());
1799 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1801 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1808 if( pFcb->Specific.File.QueuedFlushCount > 0)
1811 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1812 AFS_TRACE_LEVEL_VERBOSE,
1813 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1814 &pFcb->NPFcb->Specific.File.ExtentsResource,
1815 PsGetCurrentThread());
1817 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1821 AFSWaitOnQueuedFlushes( pFcb);
1826 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1834 if( pFcb->OpenHandleCount > 0)
1837 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1838 AFS_TRACE_LEVEL_VERBOSE,
1839 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1840 &pFcb->NPFcb->Specific.File.ExtentsResource,
1841 PsGetCurrentThread());
1843 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1845 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1853 // A hit a very palpable hit. Pin it
1856 lCount = AFSObjectInfoIncrement( pCurrentObject);
1858 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1859 AFS_TRACE_LEVEL_VERBOSE,
1860 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1864 bLocatedEntry = TRUE;
1869 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1874 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1881 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1884 bReleaseVolumeListLock = TRUE;
1886 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1889 if( bReleaseVolumeListLock)
1892 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1899 AFSProcessExtentFailure( PIRP Irp)
1901 AFSExtentFailureCB *pFailureCB = NULL;
1902 NTSTATUS ntStatus = STATUS_SUCCESS;
1903 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1904 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1905 AFSVolumeCB *pVolumeCB = NULL;
1906 ULONGLONG ullIndex = 0;
1907 AFSObjectInfoCB *pObjectInfo = NULL;
1912 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1915 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1916 AFS_TRACE_LEVEL_ERROR,
1917 "AFSProcessExtentFailure Input buffer too small\n");
1919 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1922 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1924 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1925 AFS_TRACE_LEVEL_ERROR,
1926 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1927 pFailureCB->FileId.Cell,
1928 pFailureCB->FileId.Volume,
1929 pFailureCB->FileId.Vnode,
1930 pFailureCB->FileId.Unique,
1931 pFailureCB->FailureStatus);
1933 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1936 // Locate the volume node
1939 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1941 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1943 (AFSBTreeEntry **)&pVolumeCB);
1945 if( pVolumeCB != NULL)
1948 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1949 AFS_TRACE_LEVEL_VERBOSE,
1950 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1951 pVolumeCB->ObjectInfoTree.TreeLock,
1952 PsGetCurrentThread());
1954 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1957 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1959 if( !NT_SUCCESS( ntStatus) ||
1963 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1964 AFS_TRACE_LEVEL_ERROR,
1965 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1966 ullIndex, ntStatus);
1968 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1971 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1974 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1977 // Now locate the Object in this volume
1980 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1982 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1984 (AFSBTreeEntry **)&pObjectInfo);
1986 if( pObjectInfo != NULL &&
1987 pObjectInfo->Fcb != NULL)
1991 // Reference the node so it won't be torn down
1994 lCount = AFSObjectInfoIncrement( pObjectInfo);
1996 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1997 AFS_TRACE_LEVEL_VERBOSE,
1998 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2003 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2005 if( !NT_SUCCESS( ntStatus) ||
2006 pObjectInfo == NULL ||
2007 pObjectInfo->Fcb == NULL)
2010 if( pObjectInfo == NULL)
2012 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2013 AFS_TRACE_LEVEL_ERROR,
2014 "AFSProcessExtentFailure Invalid file index %I64X\n",
2019 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2020 AFS_TRACE_LEVEL_ERROR,
2021 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2025 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2028 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2029 AFS_TRACE_LEVEL_VERBOSE,
2030 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2031 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2032 PsGetCurrentThread());
2034 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2037 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2039 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2040 &pFailureCB->AuthGroup,
2043 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2047 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2048 AFS_TRACE_LEVEL_VERBOSE,
2049 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2050 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2051 PsGetCurrentThread());
2053 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2055 lCount = AFSObjectInfoDecrement( pObjectInfo);
2057 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2058 AFS_TRACE_LEVEL_VERBOSE,
2059 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2072 AFSProcessReleaseFileExtents( IN PIRP Irp)
2074 NTSTATUS ntStatus = STATUS_SUCCESS;
2075 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2076 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2077 AFSFcb *pFcb = NULL;
2078 AFSVolumeCB *pVolumeCB = NULL;
2079 AFSDeviceExt *pDevExt;
2080 AFSReleaseFileExtentsCB *pExtents;
2081 AFSReleaseFileExtentsResultCB *pResult = NULL;
2082 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2084 ULONGLONG ullIndex = 0;
2085 AFSObjectInfoCB *pObjectInfo = NULL;
2086 BOOLEAN bLocked = FALSE;
2087 BOOLEAN bDirtyExtents = FALSE;
2094 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2096 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2098 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2099 sizeof( AFSReleaseFileExtentsCB))
2102 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2103 AFS_TRACE_LEVEL_ERROR,
2104 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2106 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2109 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2110 sizeof(AFSReleaseFileExtentsResultCB))
2113 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2114 AFS_TRACE_LEVEL_ERROR,
2115 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2118 // Must have space for one extent in one file
2121 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2124 if (pExtents->ExtentCount == 0)
2127 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2128 AFS_TRACE_LEVEL_ERROR,
2129 "AFSProcessReleaseFileExtents Extent count zero\n");
2131 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2134 if (pExtents->FileId.Cell != 0 ||
2135 pExtents->FileId.Volume != 0 ||
2136 pExtents->FileId.Vnode != 0 ||
2137 pExtents->FileId.Unique != 0)
2140 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2141 AFS_TRACE_LEVEL_VERBOSE,
2142 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2143 pExtents->FileId.Cell,
2144 pExtents->FileId.Volume,
2145 pExtents->FileId.Vnode,
2146 pExtents->FileId.Unique);
2148 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2149 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2150 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2151 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2152 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2155 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2156 AFS_TRACE_LEVEL_ERROR,
2157 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2158 pExtents->FileId.Cell,
2159 pExtents->FileId.Volume,
2160 pExtents->FileId.Vnode,
2161 pExtents->FileId.Unique);
2163 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2166 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2167 AFS_TRACE_LEVEL_VERBOSE,
2168 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2169 &pDevExt->Specific.RDR.VolumeTreeLock,
2170 PsGetCurrentThread());
2172 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2175 // Locate the volume node
2178 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2180 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2182 (AFSBTreeEntry **)&pVolumeCB);
2184 if( pVolumeCB != NULL)
2187 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2188 AFS_TRACE_LEVEL_VERBOSE,
2189 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2190 pVolumeCB->ObjectInfoTree.TreeLock,
2191 PsGetCurrentThread());
2193 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2196 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2198 if( !NT_SUCCESS( ntStatus) ||
2202 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2203 AFS_TRACE_LEVEL_ERROR,
2204 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2205 ullIndex, ntStatus);
2207 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2210 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2213 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2216 // Now locate the Object in this volume
2219 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2221 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2223 (AFSBTreeEntry **)&pObjectInfo);
2225 if( pObjectInfo != NULL)
2229 // Reference the node so it won't be torn down
2232 lCount = AFSObjectInfoIncrement( pObjectInfo);
2234 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2235 AFS_TRACE_LEVEL_VERBOSE,
2236 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2241 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2243 if( !NT_SUCCESS( ntStatus) ||
2244 pObjectInfo == NULL)
2247 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2248 AFS_TRACE_LEVEL_ERROR,
2249 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2252 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2255 pFcb = pObjectInfo->Fcb;
2260 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2261 AFS_TRACE_LEVEL_ERROR,
2262 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2263 pExtents->FileId.Cell,
2264 pExtents->FileId.Volume,
2265 pExtents->FileId.Vnode,
2266 pExtents->FileId.Unique);
2268 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2271 AFSLockForExtentsTrim( pFcb );
2279 // Locate an Fcb to trim down
2282 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2283 AFS_TRACE_LEVEL_VERBOSE,
2284 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2286 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2291 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2297 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2298 AFS_TRACE_LEVEL_ERROR,
2299 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2301 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2304 pObjectInfo = pFcb->ObjectInformation;
2310 // Allocate a scratch buffer to move in the extent information
2313 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2314 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2316 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2318 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2319 AFS_TRACE_LEVEL_ERROR,
2320 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2322 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2325 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2327 AFS_EXTENTS_RESULT_TAG);
2328 if (NULL == pResult)
2331 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2332 AFS_TRACE_LEVEL_ERROR,
2333 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2335 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2339 // Set up the header (for an array of one)
2341 pResult->FileCount = 1;
2342 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2343 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2346 // Setup the first (and only) file
2348 pFile = pResult->Files;
2349 pFile->FileId = pObjectInfo->FileId;
2350 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2353 // Stash away the auth group
2356 RtlZeroMemory( &stAuthGroup,
2359 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2364 if( !NT_SUCCESS( ntStatus))
2366 try_return( ntStatus);
2369 RtlCopyMemory( &pFile->AuthGroup,
2374 // Update the metadata for this call
2377 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2378 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2379 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2380 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2381 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2383 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2385 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2389 &pFile->ExtentCount,
2392 if (!NT_SUCCESS(ntStatus))
2395 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2396 AFS_TRACE_LEVEL_ERROR,
2397 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2400 try_return( ntStatus );
2403 if( pExtents->ExtentCount == 0)
2406 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2407 AFS_TRACE_LEVEL_WARNING,
2408 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2411 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2413 if( pExtents->ExtentCount > 0)
2415 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2418 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2427 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2428 AFS_TRACE_LEVEL_VERBOSE,
2429 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2430 &pFcb->NPFcb->Specific.File.ExtentsResource,
2431 PsGetCurrentThread());
2433 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2436 if( NULL != pResult &&
2437 Irp->AssociatedIrp.SystemBuffer != pResult)
2440 AFSExFreePoolWithTag(pResult, AFS_EXTENTS_RESULT_TAG);
2443 if (NT_SUCCESS(ntStatus))
2445 Irp->IoStatus.Information = ulSz;
2449 Irp->IoStatus.Information = 0;
2452 Irp->IoStatus.Status = ntStatus;
2454 if( pObjectInfo != NULL)
2457 lCount = AFSObjectInfoDecrement( pObjectInfo);
2459 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2460 AFS_TRACE_LEVEL_VERBOSE,
2461 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2471 AFSWaitForExtentMapping( AFSFcb *Fcb,
2474 NTSTATUS ntStatus = STATUS_SUCCESS;
2475 LARGE_INTEGER liTimeOut;
2476 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2481 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2483 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2487 // If this isn't the same authgroup which caused the failure
2488 // then try to request them again
2491 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2493 sizeof( GUID)) == sizeof( GUID))
2496 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2498 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2500 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2503 try_return( ntStatus);
2507 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2509 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2515 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2519 // If this isn't the same authgroup which caused the failure
2520 // or the System Process,
2521 // then try to request the extents again
2524 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2526 sizeof( GUID)) == sizeof( GUID) ||
2527 ullProcessId == (ULONGLONG)AFSSysProcess)
2530 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2532 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2534 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2537 try_return( ntStatus);
2541 if( ntStatus == STATUS_TIMEOUT)
2544 ntStatus = STATUS_SUCCESS;
2556 AFSFlushExtents( IN AFSFcb *Fcb,
2559 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2560 AFSExtent *pExtent, *pNextExtent;
2562 AFSReleaseExtentsCB *pRelease = NULL;
2564 ULONG initialDirtyCount = 0;
2565 BOOLEAN bExtentsLocked = FALSE;
2568 NTSTATUS ntStatus = STATUS_SUCCESS;
2569 LARGE_INTEGER liLastFlush;
2570 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2571 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2572 GUID *pAuthGroup = AuthGroup;
2576 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2579 // Save, then reset the flush time
2582 liLastFlush = Fcb->Specific.File.LastServerFlush;
2584 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2589 if( pAuthGroup == NULL ||
2590 RtlCompareMemory( pAuthGroup,
2591 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2592 sizeof( GUID)) == sizeof( GUID))
2595 RtlZeroMemory( &stAuthGroup,
2598 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2603 if( !NT_SUCCESS( ntStatus))
2605 try_return( ntStatus);
2608 pAuthGroup = &stAuthGroup;
2612 // Lock extents while we count and set up the array to send to
2616 AFSLockForExtentsTrim( Fcb);
2618 bExtentsLocked = TRUE;
2620 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2623 // Clear our queued flush event
2626 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2629 // Look for a start in the list to flush entries
2634 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2636 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2638 AFS_EXTENT_RELEASE_TAG);
2639 if( NULL == pRelease)
2642 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2645 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2647 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2650 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2652 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2655 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2659 // Update the metadata for this call
2662 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2663 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2664 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2665 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2666 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2670 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2673 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2675 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2678 if ( pExtent == NULL)
2684 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2686 if ( pExtent->ActiveCount > 0)
2688 pExtent = pNextExtent;
2692 AFSRemoveEntryDirtyList( Fcb, pExtent);
2694 pExtent->DirtyList.fLink = NULL;
2695 pExtent->DirtyList.bLink = NULL;
2697 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2700 // Clear the flag in advance of the write. If we do
2701 // things this was we know that the clear is
2702 // pessimistic (any write which happens from now on
2703 // will set the flag dirty again).
2706 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2708 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2710 pRelease->FileExtents[count].Length = pExtent->Size;
2711 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2712 pRelease->FileExtents[count].DirtyOffset = 0;
2713 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2714 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2717 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2719 sizeof(pExtent->MD5));
2721 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2724 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2725 AFS_TRACE_LEVEL_VERBOSE,
2726 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2728 Fcb->ObjectInformation->FileId.Cell,
2729 Fcb->ObjectInformation->FileId.Volume,
2730 Fcb->ObjectInformation->FileId.Vnode,
2731 Fcb->ObjectInformation->FileId.Unique,
2732 pExtent->FileOffset.QuadPart,
2735 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2742 pExtent = pNextExtent;
2745 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2748 // If we are done then get out
2754 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2755 AFS_TRACE_LEVEL_VERBOSE,
2756 "AFSFlushExtents No more dirty extents found\n");
2762 // Fire off the request synchronously
2765 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2767 pRelease->ExtentCount = count;
2769 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2770 AFS_TRACE_LEVEL_VERBOSE,
2771 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2772 &pNPFcb->Specific.File.ExtentsResource,
2773 PsGetCurrentThread());
2775 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2776 bExtentsLocked = FALSE;
2778 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2782 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2783 AFS_REQUEST_FLAG_SYNCHRONOUS,
2786 &Fcb->ObjectInformation->FileId,
2792 if( !NT_SUCCESS(ntStatus))
2796 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2797 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2800 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2801 AFS_TRACE_LEVEL_ERROR,
2802 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2803 Fcb->ObjectInformation->FileId.Cell,
2804 Fcb->ObjectInformation->FileId.Volume,
2805 Fcb->ObjectInformation->FileId.Vnode,
2806 Fcb->ObjectInformation->FileId.Unique,
2810 AFSLockForExtentsTrim( Fcb);
2812 bExtentsLocked = TRUE;
2817 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2822 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2827 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2834 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2835 AFS_TRACE_LEVEL_VERBOSE,
2836 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2837 &pNPFcb->Specific.File.ExtentsResource,
2838 PsGetCurrentThread());
2840 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2845 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
2853 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2855 IN BOOLEAN bReleaseAll)
2857 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2860 AFSReleaseExtentsCB *pRelease = NULL;
2862 ULONG initialDirtyCount = 0;
2863 BOOLEAN bExtentsLocked = FALSE;
2866 NTSTATUS ntStatus = STATUS_SUCCESS;
2867 LARGE_INTEGER liLastFlush;
2868 ULONG ulRemainingExtentLength = 0;
2869 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2870 GUID *pAuthGroup = AuthGroup;
2874 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2877 // Save, then reset the flush time
2880 liLastFlush = Fcb->Specific.File.LastServerFlush;
2882 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2887 if( pAuthGroup == NULL ||
2888 RtlCompareMemory( pAuthGroup,
2889 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2890 sizeof( GUID)) == sizeof( GUID))
2893 RtlZeroMemory( &stAuthGroup,
2896 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2901 if( !NT_SUCCESS( ntStatus))
2903 try_return( ntStatus);
2906 pAuthGroup = &stAuthGroup;
2910 // Look for a start in the list to flush entries
2915 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2917 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2919 AFS_EXTENT_RELEASE_TAG);
2920 if( NULL == pRelease)
2923 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2926 if( Fcb->OpenHandleCount > 0 &&
2931 // Don't release everything ...
2934 ulRemainingExtentLength = 1024;
2937 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2940 AFSLockForExtentsTrim( Fcb);
2942 bExtentsLocked = TRUE;
2944 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2947 // Update the metadata for this call
2950 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2951 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2952 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2953 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2954 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2958 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2960 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2961 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
2964 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
2968 if( pExtent->ActiveCount > 0)
2974 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
2976 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2977 AFS_TRACE_LEVEL_VERBOSE,
2978 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2980 Fcb->ObjectInformation->FileId.Cell,
2981 Fcb->ObjectInformation->FileId.Volume,
2982 Fcb->ObjectInformation->FileId.Vnode,
2983 Fcb->ObjectInformation->FileId.Unique,
2984 pExtent->FileOffset.QuadPart,
2987 pRelease->FileExtents[count].Length = pExtent->Size;
2988 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2989 pRelease->FileExtents[count].DirtyOffset = 0;
2990 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2991 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2994 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2996 sizeof(pExtent->MD5));
2998 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3001 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3004 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3007 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3010 AFSRemoveEntryDirtyList( Fcb,
3013 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3015 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3018 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3028 // If we are done then get out
3034 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3035 AFS_TRACE_LEVEL_VERBOSE,
3036 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3042 // Fire off the request synchronously
3045 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3047 pRelease->ExtentCount = count;
3050 // Drop the extents lock for the duration of the call to
3051 // the network. We have pinned the extents so, even
3052 // though we might get extents added during this period,
3053 // but none will be removed. Hence we can carry on from
3057 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3058 AFS_TRACE_LEVEL_VERBOSE,
3059 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3060 &pNPFcb->Specific.File.ExtentsResource,
3061 PsGetCurrentThread());
3063 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3064 bExtentsLocked = FALSE;
3066 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3067 AFS_REQUEST_FLAG_SYNCHRONOUS,
3070 &Fcb->ObjectInformation->FileId,
3076 if( !NT_SUCCESS(ntStatus))
3080 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3081 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3084 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3085 AFS_TRACE_LEVEL_ERROR,
3086 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3087 Fcb->ObjectInformation->FileId.Cell,
3088 Fcb->ObjectInformation->FileId.Volume,
3089 Fcb->ObjectInformation->FileId.Vnode,
3090 Fcb->ObjectInformation->FileId.Unique,
3100 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3101 AFS_TRACE_LEVEL_VERBOSE,
3102 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3103 &pNPFcb->Specific.File.ExtentsResource,
3104 PsGetCurrentThread());
3106 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3111 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3119 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3122 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3125 AFSReleaseExtentsCB *pRelease = NULL;
3127 ULONG initialDirtyCount = 0;
3128 BOOLEAN bExtentsLocked = FALSE;
3131 NTSTATUS ntStatus = STATUS_SUCCESS;
3132 LARGE_INTEGER liLastFlush;
3133 ULONG ulRemainingExtentLength = 0;
3134 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3135 GUID *pAuthGroup = AuthGroup;
3138 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3141 // Save, then reset the flush time
3144 liLastFlush = Fcb->Specific.File.LastServerFlush;
3146 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3151 if( pAuthGroup == NULL ||
3152 RtlCompareMemory( pAuthGroup,
3153 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3154 sizeof( GUID)) == sizeof( GUID))
3157 RtlZeroMemory( &stAuthGroup,
3160 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3165 if( !NT_SUCCESS( ntStatus))
3167 try_return( ntStatus);
3170 pAuthGroup = &stAuthGroup;
3174 // Look for a start in the list to flush entries
3179 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3181 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3183 AFS_EXTENT_RELEASE_TAG);
3184 if( NULL == pRelease)
3187 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3190 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3193 AFSLockForExtentsTrim( Fcb);
3195 bExtentsLocked = TRUE;
3197 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3200 // Update the metadata for this call
3203 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3204 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3205 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3206 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3207 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3211 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3213 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3214 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3217 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3221 if( pExtent->ActiveCount > 0 ||
3222 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3227 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3229 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3230 AFS_TRACE_LEVEL_VERBOSE,
3231 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3233 Fcb->ObjectInformation->FileId.Cell,
3234 Fcb->ObjectInformation->FileId.Volume,
3235 Fcb->ObjectInformation->FileId.Vnode,
3236 Fcb->ObjectInformation->FileId.Unique,
3237 pExtent->FileOffset.QuadPart,
3240 pRelease->FileExtents[count].Length = pExtent->Size;
3241 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3242 pRelease->FileExtents[count].DirtyOffset = 0;
3243 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3244 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3247 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3249 sizeof(pExtent->MD5));
3251 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3261 // If we are done then get out
3267 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3268 AFS_TRACE_LEVEL_VERBOSE,
3269 "AFSReleaseCleanExtents No more dirty extents found\n");
3275 // Fire off the request synchronously
3278 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3280 pRelease->ExtentCount = count;
3283 // Drop the extents lock for the duration of the call to
3284 // the network. We have pinned the extents so, even
3285 // though we might get extents added during this period,
3286 // but none will be removed. Hence we can carry on from
3290 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3291 AFS_TRACE_LEVEL_VERBOSE,
3292 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3293 &pNPFcb->Specific.File.ExtentsResource,
3294 PsGetCurrentThread());
3296 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3297 bExtentsLocked = FALSE;
3299 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3300 AFS_REQUEST_FLAG_SYNCHRONOUS,
3303 &Fcb->ObjectInformation->FileId,
3309 if( !NT_SUCCESS(ntStatus))
3313 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3314 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3317 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3318 AFS_TRACE_LEVEL_ERROR,
3319 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3320 Fcb->ObjectInformation->FileId.Cell,
3321 Fcb->ObjectInformation->FileId.Volume,
3322 Fcb->ObjectInformation->FileId.Vnode,
3323 Fcb->ObjectInformation->FileId.Unique,
3333 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3334 AFS_TRACE_LEVEL_VERBOSE,
3335 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3336 &pNPFcb->Specific.File.ExtentsResource,
3337 PsGetCurrentThread());
3339 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3344 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3352 AFSMarkDirty( IN AFSFcb *Fcb,
3353 IN AFSExtent *StartExtent,
3354 IN ULONG ExtentsCount,
3355 IN LARGE_INTEGER *StartingByte,
3356 IN BOOLEAN DerefExtents)
3359 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3360 AFSExtent *pExtent = StartExtent;
3361 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3363 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3365 BOOLEAN bLocked = FALSE;
3367 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3368 AFS_TRACE_LEVEL_VERBOSE,
3369 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3370 &Fcb->NPFcb->Specific.File.ExtentsResource,
3371 PsGetCurrentThread());
3373 if( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource))
3375 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3379 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3385 // Find the insertion point
3388 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3393 else if( StartingByte->QuadPart == 0)
3401 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3403 while( pCurrentExtent != NULL)
3406 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3407 pCurrentExtent->DirtyList.fLink == NULL)
3413 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3417 while( ulCount < ExtentsCount)
3420 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3422 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3425 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3426 AFS_TRACE_LEVEL_VERBOSE,
3427 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3428 pExtent->FileOffset.QuadPart,
3431 pExtent->DirtyList.fLink = NULL;
3432 pExtent->DirtyList.bLink = NULL;
3437 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3439 pExtent->DirtyList.bLink = NULL;
3441 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3443 pNPFcb->Specific.File.DirtyListHead = pExtent;
3445 pCurrentExtent = pExtent;
3447 bInsertHead = FALSE;
3449 else if( bInsertTail)
3452 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3455 pNPFcb->Specific.File.DirtyListHead = pExtent;
3460 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3462 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3465 pNPFcb->Specific.File.DirtyListTail = pExtent;
3470 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3472 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3474 if( pExtent->DirtyList.fLink == NULL)
3477 pNPFcb->Specific.File.DirtyListTail = pExtent;
3482 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3485 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3487 pCurrentExtent = pExtent;
3490 pExtent->Flags |= AFS_EXTENT_DIRTY;
3493 // Up the dirty count
3496 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3501 pCurrentExtent = pExtent;
3504 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3505 AFS_TRACE_LEVEL_VERBOSE,
3506 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3508 pExtent->ActiveCount);
3512 ASSERT( pExtent->ActiveCount > 0);
3513 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3516 pExtent = pNextExtent;
3521 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
3526 "EXCEPTION - AFSMarkDirty\n");
3528 AFSDumpTraceFilesFnc();
3531 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3533 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3534 AFS_TRACE_LEVEL_VERBOSE,
3535 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3536 &Fcb->NPFcb->Specific.File.ExtentsResource,
3537 PsGetCurrentThread());
3541 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3552 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3555 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3559 NextExtent(AFSExtent *Extent, ULONG SkipList)
3562 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3565 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3568 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3571 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3575 // Check the ordering of the extents lists
3577 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3579 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3581 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3583 LARGE_INTEGER lastOffset;
3585 lastOffset.QuadPart = 0;
3587 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3588 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3593 pExtent = ExtentFor(pLe, listNo);
3596 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3597 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3598 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3601 ASSERT(pLe->Flink->Blink == pLe);
3602 ASSERT(pLe->Blink->Flink == pLe);
3605 // Should follow on from previous
3607 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3608 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3611 // Should match alignment criteria
3613 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3616 // "lower" lists should be populated
3618 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3620 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3628 AFSTrimExtents( IN AFSFcb *Fcb,
3629 IN PLARGE_INTEGER FileSize)
3632 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3635 BOOLEAN locked = FALSE;
3636 NTSTATUS ntStatus = STATUS_SUCCESS;
3637 LARGE_INTEGER liAlignedOffset = {0,0};
3638 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3639 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3646 // Get an aligned offset
3649 if( FileSize != NULL)
3652 liAlignedOffset = *FileSize;
3655 if( liAlignedOffset.QuadPart > 0 &&
3656 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3660 // Align UP to the next cache block size
3663 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3667 // Ensure that no one is working with the extents and grab the
3671 AFSLockForExtentsTrim( Fcb);
3675 if( 0 == Fcb->Specific.File.ExtentCount)
3679 // Update the request extent status
3682 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3684 try_return( ntStatus = STATUS_SUCCESS);
3688 // We are truncating from a specific length in the file. If the offset
3689 // is non-zero then go find the first extent to remove
3692 if( 0 == FileSize->QuadPart)
3695 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3700 pExtent = AFSExtentForOffset( Fcb,
3704 if( NULL == pExtent)
3707 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3711 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3715 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3718 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3721 // Only trim down extents beyond the aligned offset
3726 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3729 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3732 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3735 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3739 AFSRemoveEntryDirtyList( Fcb,
3742 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3744 ASSERT(dirtyCount >= 0);
3747 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3750 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3751 AFS_TRACE_LEVEL_VERBOSE,
3752 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3754 Fcb->ObjectInformation->FileId.Cell,
3755 Fcb->ObjectInformation->FileId.Volume,
3756 Fcb->ObjectInformation->FileId.Vnode,
3757 Fcb->ObjectInformation->FileId.Unique,
3758 pExtent->FileOffset.QuadPart,
3761 ASSERT( pExtent->ActiveCount == 0);
3769 // Update the request extent status
3772 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3779 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3780 AFS_TRACE_LEVEL_VERBOSE,
3781 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3782 &Fcb->NPFcb->Specific.File.ExtentsResource,
3783 PsGetCurrentThread());
3785 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3793 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3795 IN AFSFileExtentCB *Result)
3798 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3801 AFSFileExtentCB *pFileExtents = Result;
3802 NTSTATUS ntStatus = STATUS_SUCCESS;
3803 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3804 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3810 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3812 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3816 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3819 // Only trim down extents beyond the aligned offset
3824 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3827 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3830 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3833 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3838 AFSRemoveEntryDirtyList( Fcb,
3841 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3843 ASSERT( dirtyCount >= 0);
3847 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3851 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3852 AFS_TRACE_LEVEL_VERBOSE,
3853 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3855 Fcb->ObjectInformation->FileId.Cell,
3856 Fcb->ObjectInformation->FileId.Volume,
3857 Fcb->ObjectInformation->FileId.Vnode,
3858 Fcb->ObjectInformation->FileId.Unique,
3859 pExtent->FileOffset.QuadPart,
3862 ASSERT( pExtent->ActiveCount == 0);
3868 // Next extent we are looking for
3878 // Update the request extent status
3881 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3888 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3889 IN ULONG ExtentsCount)
3892 AFSExtent *pExtent = StartExtent;
3893 AFSExtent *pNextExtent;
3897 while( ulCount < ExtentsCount)
3900 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3902 lCount = InterlockedIncrement( &pExtent->ActiveCount);
3904 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3905 AFS_TRACE_LEVEL_VERBOSE,
3906 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
3910 pExtent = pNextExtent;
3919 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
3920 IN ULONG ExtentsCount)
3923 AFSExtent *pExtent = StartExtent;
3924 AFSExtent *pNextExtent;
3928 while( ulCount < ExtentsCount)
3931 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3933 ASSERT( pExtent->ActiveCount > 0);
3935 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3937 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3938 AFS_TRACE_LEVEL_VERBOSE,
3939 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
3943 pExtent = pNextExtent;
3952 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
3953 IN AFSExtent *Extent)
3956 if( Extent->DirtyList.fLink == NULL)
3959 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
3961 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
3964 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
3970 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
3973 if( Extent->DirtyList.bLink == NULL)
3976 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
3978 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
3981 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
3987 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
3995 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
3996 AFSByteRange ** pByteRangeList)
3999 ULONG ulByteRangeMax;
4000 ULONG ulByteRangeCount = 0;
4001 AFSByteRange *ByteRangeList;
4002 AFSExtent *pExtent, *pNextExtent;
4004 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
4006 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
4008 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
4009 ulByteRangeMax * sizeof( AFSByteRange),
4012 if ( ByteRangeList == NULL)
4015 (*pByteRangeList) = NULL;
4017 try_return( ulByteRangeCount = DWORD_MAX);
4020 RtlZeroMemory( ByteRangeList,
4021 ulByteRangeMax * sizeof( AFSByteRange));
4024 // The for loop populates the ByteRangeList entries with values that are
4025 // the gaps in the DirtyList. In other words, if a range is not present
4026 // in the DirtyList it will be represented in the ByteRangeList array.
4029 for ( ulByteRangeCount = 0,
4030 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4031 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4032 pExtent = pNextExtent)
4035 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4038 // The first time the for() is entered the ulByteRangeCount will be zero and
4039 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4040 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4041 // FileOffset of the Extent.
4043 // Future passes through the loop behave in a similar fashion but
4044 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4047 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4050 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4051 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4057 // Having processed the current dirty extent, the following while loop
4058 // searches for the next clean gap between dirty extents.
4061 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4064 pExtent = pNextExtent;
4066 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4070 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4071 // The Length is left at zero and will be assigned either when the for loop continues or
4072 // when the for loop exits.
4075 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4079 // Assign the Length of the final clean range to match the file length.
4082 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4083 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4085 (*pByteRangeList) = ByteRangeList;
4089 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4091 return ulByteRangeCount;
4096 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4097 IN AFSExtent *StartExtent,
4098 IN ULONG ExtentsCount,
4099 IN void *SystemBuffer,
4100 IN LARGE_INTEGER *ByteOffset,
4104 NTSTATUS ntStatus = STATUS_SUCCESS;
4105 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4106 AFSExtent *pExtent = StartExtent;
4107 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4109 char *pCurrentBuffer = (char *)SystemBuffer;
4110 char *pMD5Buffer = NULL;
4111 ULONG ulCurrentLen = 0;
4112 void *pExtentBuffer = NULL;
4113 LARGE_INTEGER liByteOffset;
4114 ULONG ulBytesRead = 0;
4119 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4120 AFS_TRACE_LEVEL_VERBOSE,
4121 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4122 &Fcb->NPFcb->Specific.File.ExtentsResource,
4123 PsGetCurrentThread());
4125 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4129 liByteOffset.QuadPart = ByteOffset->QuadPart;
4131 while( ulCount < ExtentsCount)
4134 RtlZeroMemory( pExtent->MD5,
4135 sizeof( pExtent->MD5));
4137 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4139 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4140 ByteCount < pExtent->Size)
4143 if( pExtentBuffer == NULL)
4146 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4148 AFS_GENERIC_MEMORY_9_TAG);
4150 if( pExtentBuffer == NULL)
4157 RtlZeroMemory( pExtentBuffer,
4160 RtlCopyMemory( pExtentBuffer,
4164 pMD5Buffer = (char *)pExtentBuffer;
4166 ulCurrentLen = ByteCount;
4168 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4171 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4173 AFS_GENERIC_MEMORY_10_TAG);
4175 if( pExtentBuffer == NULL)
4181 RtlZeroMemory( pExtentBuffer,
4184 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4188 RtlCopyMemory( pExtentBuffer,
4189 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4192 ASSERT( pExtent->CacheOffset.HighPart == 0);
4193 RtlCopyMemory( pExtentBuffer,
4194 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4198 ulBytesRead = pExtent->Size;
4203 ntStatus = AFSReadCacheFile( pExtentBuffer,
4204 &pExtent->CacheOffset,
4208 if( !NT_SUCCESS( ntStatus))
4215 pMD5Buffer = (char *)pExtentBuffer;
4217 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4219 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4226 ulCurrentLen = pExtent->Size;
4228 pMD5Buffer = pCurrentBuffer;
4231 AFSGenerateMD5( pMD5Buffer,
4235 pExtent = pNextExtent;
4239 ByteCount -= ulCurrentLen;
4241 pCurrentBuffer += ulCurrentLen;
4243 liByteOffset.QuadPart += ulCurrentLen;
4246 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4247 AFS_TRACE_LEVEL_VERBOSE,
4248 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4249 &Fcb->NPFcb->Specific.File.ExtentsResource,
4250 PsGetCurrentThread());
4253 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
4258 "EXCEPTION - AFSSetupMD5Hash\n");
4260 AFSDumpTraceFilesFnc();
4263 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4265 if( pExtentBuffer != NULL)
4268 AFSExFreePoolWithTag( pExtentBuffer, AFS_GENERIC_MEMORY_9_TAG);