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 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
818 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
819 AFS_TRACE_LEVEL_VERBOSE,
820 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
821 Fcb->ObjectInformation->FileId.Cell,
822 Fcb->ObjectInformation->FileId.Volume,
823 Fcb->ObjectInformation->FileId.Vnode,
824 Fcb->ObjectInformation->FileId.Unique,
825 request.ByteOffset.LowPart,
827 PsGetCurrentThread());
829 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
833 &Fcb->ObjectInformation->FileId,
835 sizeof( AFSRequestExtentsCB ),
839 if ( ntStatus == STATUS_ACCESS_DENIED)
844 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
849 if ( NT_SUCCESS( ntStatus2) &&
850 RtlCompareMemory( &stAuthGroup,
852 sizeof( GUID)) != sizeof( GUID))
855 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
859 &Fcb->ObjectInformation->FileId,
861 sizeof( AFSRequestExtentsCB ),
867 if( !NT_SUCCESS( ntStatus))
870 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
885 AFSProcessExtentsResult( IN AFSFcb *Fcb,
887 IN AFSFileExtentCB *Result)
889 NTSTATUS ntStatus = STATUS_SUCCESS;
890 AFSFileExtentCB *pFileExtents = Result;
893 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
894 ULONG fileExtentsUsed = 0;
895 BOOLEAN bFoundExtent = FALSE;
896 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
897 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
901 // Grab the extents exclusive for the duration
904 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
905 AFS_TRACE_LEVEL_VERBOSE,
906 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
907 &pNPFcb->Specific.File.ExtentsResource,
908 PsGetCurrentThread());
910 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
916 // Find where to put the extents
918 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
921 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
924 le = pSkipEntries[AFS_EXTENTS_LIST];
926 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
929 // No extents. Insert at head of list (which is where the skip lists point!)
933 else if (0 != pFileExtents->FileOffset.QuadPart)
936 // We want to find the best extents immediately *behind* this offset
938 LARGE_INTEGER offset = pFileExtents->FileOffset;
941 // Ask in the top skip list first, then work down
943 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
945 pExtent = ExtentForOffsetInList( Fcb,
953 // No dice. Header has to become the head of the list
955 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
957 // And as a loop invariant we should never have found an extent
959 ASSERT(!bFoundExtent);
964 // pExtent is where to start to insert at this level
966 pSkipEntries[i] = &pExtent->Lists[i];
969 // And also where to start to look at the next level
972 if (i > AFS_EXTENTS_LIST)
974 pSkipEntries[i-1] = &pExtent->Lists[i-1];
982 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
987 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
993 // Looking at offset 0, so we must start at the beginning
996 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1000 // And set up the skip lists
1003 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1005 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1009 while (fileExtentsUsed < Count)
1013 // Loop invariant - le points to where to insert after and
1014 // pExtent points to le->fLink
1017 ASSERT (NULL == pExtent ||
1018 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1020 if (NULL == pExtent ||
1021 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1024 // We need to insert a new extent at le. Start with
1025 // some sanity check on spanning
1027 if (NULL != pExtent &&
1028 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1029 pExtent->FileOffset.QuadPart))
1032 // File Extents overlaps pExtent
1034 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1035 pExtent->FileOffset.QuadPart);
1037 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1041 // File offset is entirely in front of this extent. Create
1042 // a new one (remember le is the previous list entry)
1044 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1047 if (NULL == pExtent)
1050 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1053 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1055 pExtent->FileOffset = pFileExtents->FileOffset;
1056 pExtent->CacheOffset = pFileExtents->CacheOffset;
1057 pExtent->Size = pFileExtents->Length;
1059 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1060 AFS_TRACE_LEVEL_VERBOSE,
1061 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1062 Fcb->ObjectInformation->FileId.Cell,
1063 Fcb->ObjectInformation->FileId.Volume,
1064 Fcb->ObjectInformation->FileId.Vnode,
1065 Fcb->ObjectInformation->FileId.Unique,
1066 pFileExtents->FileOffset.QuadPart,
1067 pFileExtents->CacheOffset.QuadPart,
1068 pFileExtents->Length);
1070 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1072 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1074 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1076 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1081 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1087 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1088 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1089 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1092 // Do not move the cursor - we will do it next time
1096 // And into the (upper) skip lists - Again, do not move the cursor
1098 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1100 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1102 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1103 #if AFS_VALIDATE_EXTENTS
1104 VerifyExtentsLists(Fcb);
1109 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1112 if (pExtent->Size != pFileExtents->Length)
1115 ASSERT (pExtent->Size == pFileExtents->Length);
1117 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1121 // Move both cursors forward.
1123 // First the extent pointer
1126 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1129 // Then the skip lists cursors forward if needed
1131 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1133 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1136 // Check sanity before
1138 #if AFS_VALIDATE_EXTENTS
1139 VerifyExtentsLists(Fcb);
1143 // Skip list should point to us
1145 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1147 // Move forward cursor
1149 pSkipEntries[i] = pSkipEntries[i]->Flink;
1151 // Check sanity before
1153 #if AFS_VALIDATE_EXTENTS
1154 VerifyExtentsLists(Fcb);
1160 // And then the cursor in the supplied array
1166 // setup pExtent if there is one
1168 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1170 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1180 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1183 // Sanity check on spanning
1185 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1186 pFileExtents->FileOffset.QuadPart)
1189 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1190 pFileExtents->FileOffset.QuadPart);
1192 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1196 // Move le and pExtent forward
1198 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1202 // Then the check the skip lists cursors
1204 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1206 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1210 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1211 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1212 // - We are not the last on the list. In that case we have to be strictly less than
1214 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1216 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1217 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1224 // setup pExtent if there is one
1227 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1229 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1239 // All done, signal that we are done drop the lock, exit
1244 if( !NT_SUCCESS( ntStatus))
1248 // If we failed the service is going to drop all extents so trim away the
1252 AFSTrimSpecifiedExtents( Fcb,
1257 #if AFS_VALIDATE_EXTENTS
1258 VerifyExtentsLists(Fcb);
1261 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1265 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1266 AFS_TRACE_LEVEL_VERBOSE,
1267 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1268 &pNPFcb->Specific.File.ExtentsResource,
1269 PsGetCurrentThread());
1271 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1278 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1280 AFSFcb *pFcb = NULL;
1281 AFSVolumeCB *pVolumeCB = NULL;
1282 NTSTATUS ntStatus = STATUS_SUCCESS;
1283 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1284 ULONGLONG ullIndex = 0;
1285 AFSObjectInfoCB *pObjectInfo = NULL;
1291 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1292 AFS_TRACE_LEVEL_VERBOSE,
1293 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1294 &pDevExt->Specific.RDR.VolumeTreeLock,
1295 PsGetCurrentThread());
1297 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1299 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1300 AFS_TRACE_LEVEL_VERBOSE,
1301 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1302 SetExtents->FileId.Cell,
1303 SetExtents->FileId.Volume,
1304 SetExtents->FileId.Vnode,
1305 SetExtents->FileId.Unique);
1308 // Locate the volume node
1311 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1313 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1315 (AFSBTreeEntry **)&pVolumeCB);
1317 if( pVolumeCB != NULL)
1320 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1321 AFS_TRACE_LEVEL_VERBOSE,
1322 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1323 pVolumeCB->ObjectInfoTree.TreeLock,
1324 PsGetCurrentThread());
1326 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1328 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1329 AFS_TRACE_LEVEL_VERBOSE,
1330 "AFSProcessSetFileExtents Increment count on volume %08lX Cnt %d\n",
1335 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1337 if( !NT_SUCCESS( ntStatus) ||
1341 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1342 AFS_TRACE_LEVEL_ERROR,
1343 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1344 SetExtents->FileId.Cell,
1345 SetExtents->FileId.Volume,
1346 SetExtents->FileId.Vnode,
1347 SetExtents->FileId.Unique,
1350 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1353 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1356 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1358 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1359 AFS_TRACE_LEVEL_VERBOSE,
1360 "AFSProcessSetFileExtents Decrement count on volume %08lX Cnt %d\n",
1365 // Now locate the Object in this volume
1368 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1370 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1372 (AFSBTreeEntry **)&pObjectInfo);
1374 if( pObjectInfo != NULL)
1378 // Reference the node so it won't be torn down
1381 lCount = AFSObjectInfoIncrement( pObjectInfo);
1383 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1384 AFS_TRACE_LEVEL_VERBOSE,
1385 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1390 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1392 if( !NT_SUCCESS( ntStatus) ||
1393 pObjectInfo == NULL)
1396 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1397 AFS_TRACE_LEVEL_ERROR,
1398 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1400 SetExtents->FileId.Cell,
1401 SetExtents->FileId.Volume,
1402 SetExtents->FileId.Vnode,
1403 SetExtents->FileId.Unique,
1406 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1409 pFcb = pObjectInfo->Fcb;
1412 // If we have a result failure then don't bother trying to set the extents
1415 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1418 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1419 AFS_TRACE_LEVEL_ERROR,
1420 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1421 SetExtents->FileId.Cell,
1422 SetExtents->FileId.Volume,
1423 SetExtents->FileId.Vnode,
1424 SetExtents->FileId.Unique,
1425 SetExtents->ResultStatus);
1427 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1428 AFS_TRACE_LEVEL_VERBOSE,
1429 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1430 &pFcb->NPFcb->Specific.File.ExtentsResource,
1431 PsGetCurrentThread());
1433 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1436 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1438 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1442 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1443 AFS_TRACE_LEVEL_VERBOSE,
1444 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1445 &pFcb->NPFcb->Specific.File.ExtentsResource,
1446 PsGetCurrentThread());
1448 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1450 try_return( ntStatus);
1453 ntStatus = AFSProcessExtentsResult ( pFcb,
1454 SetExtents->ExtentCount,
1455 SetExtents->FileExtents );
1459 if( pObjectInfo != NULL)
1462 lCount = AFSObjectInfoDecrement( pObjectInfo);
1464 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1465 AFS_TRACE_LEVEL_VERBOSE,
1466 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1476 // Helper fuctions for Usermode initiation of release of extents
1479 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1481 OUT AFSFileExtentCB *FileExtents,
1482 IN ULONG BufferSize,
1483 OUT ULONG *ExtentCount,
1484 OUT BOOLEAN *DirtyExtents)
1489 ULONG ulExtentCount = 0;
1490 NTSTATUS ntStatus = STATUS_SUCCESS;
1491 BOOLEAN bReleaseAll = FALSE;
1492 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1497 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1499 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1502 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1503 AFS_TRACE_LEVEL_VERBOSE,
1504 "AFSReleaseSpecifiedExtents Buffer too small\n");
1506 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1509 RtlZeroMemory( FileExtents, BufferSize);
1512 *DirtyExtents = FALSE;
1515 // iterate until we have dealt with all we were asked for or
1516 // are at the end of the list. Note that this deals (albeit
1517 // badly) with out of order extents
1520 pExtent = AFSExtentForOffset( Fcb,
1521 &Extents->FileExtents[0].FileOffset,
1524 if (NULL == pExtent)
1526 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1530 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1534 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1535 ( Extents->FileId.Cell == 0 &&
1536 Extents->FileId.Volume == 0 &&
1537 Extents->FileId.Vnode == 0 &&
1538 Extents->FileId.Unique == 0))
1544 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1545 ulExtentCount < Extents->ExtentCount)
1549 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1554 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1557 // Skip forward through the extent list until we get
1558 // to the one we want
1564 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1567 // We don't have the extent asked for so return UNKNOWN
1570 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1571 AFS_TRACE_LEVEL_VERBOSE,
1572 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1573 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1574 Extents->FileExtents[ulExtentCount].Length);
1576 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1578 FileExtents[*ExtentCount].Length = 0;
1579 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1580 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1582 *ExtentCount = (*ExtentCount) + 1;
1587 // Reset where we are looking
1590 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1594 else if( pExtent->ActiveCount > 0)
1597 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1598 AFS_TRACE_LEVEL_VERBOSE,
1599 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1600 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1601 Extents->FileExtents[ulExtentCount].Length);
1603 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1605 FileExtents[*ExtentCount].Length = 0;
1606 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1607 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1609 *ExtentCount = (*ExtentCount) + 1;
1614 // Reset where we are looking
1617 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1626 // If the extent is currently active then skip it
1629 if( pExtent->ActiveCount > 0)
1638 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1640 FileExtents[*ExtentCount].Length = pExtent->Size;
1641 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1642 FileExtents[*ExtentCount].DirtyOffset = 0;
1643 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1644 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1646 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1647 AFS_TRACE_LEVEL_VERBOSE,
1648 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1650 Fcb->ObjectInformation->FileId.Cell,
1651 Fcb->ObjectInformation->FileId.Volume,
1652 Fcb->ObjectInformation->FileId.Vnode,
1653 Fcb->ObjectInformation->FileId.Unique,
1654 FileExtents[*ExtentCount].FileOffset.QuadPart,
1655 FileExtents[*ExtentCount].Length);
1657 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1660 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1663 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1666 AFSRemoveEntryDirtyList( Fcb,
1669 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1671 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1673 *DirtyExtents = TRUE;
1676 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1680 // move forward all three cursors
1684 *ExtentCount = (*ExtentCount) + 1;
1699 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1702 AFSFcb *pFcb = NULL;
1703 AFSVolumeCB *pVolumeCB = NULL;
1704 AFSDeviceExt *pRDRDeviceExt = NULL;
1705 AFSDeviceExt *pControlDeviceExt = NULL;
1706 BOOLEAN bLocatedEntry = FALSE;
1707 AFSObjectInfoCB *pCurrentObject = NULL;
1708 BOOLEAN bReleaseVolumeListLock = FALSE;
1711 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1712 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1714 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1715 AFS_TRACE_LEVEL_VERBOSE,
1716 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1717 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1718 PsGetCurrentThread());
1720 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1723 bReleaseVolumeListLock = TRUE;
1725 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1727 while( pVolumeCB != NULL)
1731 // The Volume list may move under our feet. Lock it.
1734 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1735 AFS_TRACE_LEVEL_VERBOSE,
1736 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1737 pVolumeCB->ObjectInfoTree.TreeLock,
1738 PsGetCurrentThread());
1740 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1742 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1743 AFS_TRACE_LEVEL_VERBOSE,
1744 "AFSFindFcbToClean Increment count on volume %08lX Cnt %d\n",
1748 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1750 bReleaseVolumeListLock = FALSE;
1752 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1755 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1757 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1758 AFS_TRACE_LEVEL_VERBOSE,
1759 "AFSFindFcbToClean Decrement count on volume %08lX Cnt %d\n",
1763 if( NULL == LastFcb)
1766 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1771 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1776 while( pCurrentObject != NULL)
1779 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1782 // If the FCB is a candidate we try to lock it (but without waiting - which
1783 // means we are deadlock free
1787 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1793 AFSLockForExtentsTrim( pFcb);
1798 if( !AFSLockForExtentsTrimNoWait( pFcb))
1801 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1810 // Need to be sure there are no current flushes in the queue
1813 if( pFcb->Specific.File.ExtentCount == 0)
1816 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1817 AFS_TRACE_LEVEL_VERBOSE,
1818 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1819 &pFcb->NPFcb->Specific.File.ExtentsResource,
1820 PsGetCurrentThread());
1822 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1824 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1831 if( pFcb->Specific.File.QueuedFlushCount > 0)
1834 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1835 AFS_TRACE_LEVEL_VERBOSE,
1836 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1837 &pFcb->NPFcb->Specific.File.ExtentsResource,
1838 PsGetCurrentThread());
1840 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1844 AFSWaitOnQueuedFlushes( pFcb);
1849 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1857 if( pFcb->OpenHandleCount > 0)
1860 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1861 AFS_TRACE_LEVEL_VERBOSE,
1862 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1863 &pFcb->NPFcb->Specific.File.ExtentsResource,
1864 PsGetCurrentThread());
1866 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1868 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1876 // A hit a very palpable hit. Pin it
1879 lCount = AFSObjectInfoIncrement( pCurrentObject);
1881 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1882 AFS_TRACE_LEVEL_VERBOSE,
1883 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1887 bLocatedEntry = TRUE;
1892 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1897 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1904 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1907 bReleaseVolumeListLock = TRUE;
1909 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1912 if( bReleaseVolumeListLock)
1915 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1922 AFSProcessExtentFailure( PIRP Irp)
1924 AFSExtentFailureCB *pFailureCB = NULL;
1925 NTSTATUS ntStatus = STATUS_SUCCESS;
1926 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1927 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1928 AFSVolumeCB *pVolumeCB = NULL;
1929 ULONGLONG ullIndex = 0;
1930 AFSObjectInfoCB *pObjectInfo = NULL;
1935 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1938 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1939 AFS_TRACE_LEVEL_ERROR,
1940 "AFSProcessExtentFailure Input buffer too small\n");
1942 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1945 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1947 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1948 AFS_TRACE_LEVEL_ERROR,
1949 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1950 pFailureCB->FileId.Cell,
1951 pFailureCB->FileId.Volume,
1952 pFailureCB->FileId.Vnode,
1953 pFailureCB->FileId.Unique,
1954 pFailureCB->FailureStatus);
1956 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1959 // Locate the volume node
1962 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1964 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1966 (AFSBTreeEntry **)&pVolumeCB);
1968 if( pVolumeCB != NULL)
1971 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1972 AFS_TRACE_LEVEL_VERBOSE,
1973 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1974 pVolumeCB->ObjectInfoTree.TreeLock,
1975 PsGetCurrentThread());
1977 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1979 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1980 AFS_TRACE_LEVEL_VERBOSE,
1981 "AFSProcessExtentFailure Increment count on volume %08lX Cnt %d\n",
1986 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1988 if( !NT_SUCCESS( ntStatus) ||
1992 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1993 AFS_TRACE_LEVEL_ERROR,
1994 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1995 ullIndex, ntStatus);
1997 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2000 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2003 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2005 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2006 AFS_TRACE_LEVEL_VERBOSE,
2007 "AFSProcessExtentFailure Decrement count on volume %08lX Cnt %d\n",
2011 // Now locate the Object in this volume
2014 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
2016 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2018 (AFSBTreeEntry **)&pObjectInfo);
2020 if( pObjectInfo != NULL &&
2021 pObjectInfo->Fcb != NULL)
2025 // Reference the node so it won't be torn down
2028 lCount = AFSObjectInfoIncrement( pObjectInfo);
2030 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2031 AFS_TRACE_LEVEL_VERBOSE,
2032 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2037 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2039 if( !NT_SUCCESS( ntStatus) ||
2040 pObjectInfo == NULL ||
2041 pObjectInfo->Fcb == NULL)
2044 if( pObjectInfo == NULL)
2046 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2047 AFS_TRACE_LEVEL_ERROR,
2048 "AFSProcessExtentFailure Invalid file index %I64X\n",
2053 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2054 AFS_TRACE_LEVEL_ERROR,
2055 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2059 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2062 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2063 AFS_TRACE_LEVEL_VERBOSE,
2064 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2065 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2066 PsGetCurrentThread());
2068 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2071 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2073 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2074 &pFailureCB->AuthGroup,
2077 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2081 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2082 AFS_TRACE_LEVEL_VERBOSE,
2083 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2084 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2085 PsGetCurrentThread());
2087 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2089 lCount = AFSObjectInfoDecrement( pObjectInfo);
2091 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2092 AFS_TRACE_LEVEL_VERBOSE,
2093 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2106 AFSProcessReleaseFileExtents( IN PIRP Irp)
2108 NTSTATUS ntStatus = STATUS_SUCCESS;
2109 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2110 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2111 AFSFcb *pFcb = NULL;
2112 AFSVolumeCB *pVolumeCB = NULL;
2113 AFSDeviceExt *pDevExt;
2114 AFSReleaseFileExtentsCB *pExtents;
2115 AFSReleaseFileExtentsResultCB *pResult = NULL;
2116 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2118 ULONGLONG ullIndex = 0;
2119 AFSObjectInfoCB *pObjectInfo = NULL;
2120 BOOLEAN bLocked = FALSE;
2121 BOOLEAN bDirtyExtents = FALSE;
2128 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2130 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2132 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2133 sizeof( AFSReleaseFileExtentsCB))
2136 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2137 AFS_TRACE_LEVEL_ERROR,
2138 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2140 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2143 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2144 sizeof(AFSReleaseFileExtentsResultCB))
2147 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2148 AFS_TRACE_LEVEL_ERROR,
2149 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2152 // Must have space for one extent in one file
2155 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2158 if (pExtents->ExtentCount == 0)
2161 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2162 AFS_TRACE_LEVEL_ERROR,
2163 "AFSProcessReleaseFileExtents Extent count zero\n");
2165 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2168 if (pExtents->FileId.Cell != 0 ||
2169 pExtents->FileId.Volume != 0 ||
2170 pExtents->FileId.Vnode != 0 ||
2171 pExtents->FileId.Unique != 0)
2174 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2175 AFS_TRACE_LEVEL_VERBOSE,
2176 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2177 pExtents->FileId.Cell,
2178 pExtents->FileId.Volume,
2179 pExtents->FileId.Vnode,
2180 pExtents->FileId.Unique);
2182 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2183 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2184 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2185 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2186 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2189 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2190 AFS_TRACE_LEVEL_ERROR,
2191 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2192 pExtents->FileId.Cell,
2193 pExtents->FileId.Volume,
2194 pExtents->FileId.Vnode,
2195 pExtents->FileId.Unique);
2197 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2200 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2201 AFS_TRACE_LEVEL_VERBOSE,
2202 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2203 &pDevExt->Specific.RDR.VolumeTreeLock,
2204 PsGetCurrentThread());
2206 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2209 // Locate the volume node
2212 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2214 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2216 (AFSBTreeEntry **)&pVolumeCB);
2218 if( pVolumeCB != NULL)
2221 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2222 AFS_TRACE_LEVEL_VERBOSE,
2223 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2224 pVolumeCB->ObjectInfoTree.TreeLock,
2225 PsGetCurrentThread());
2227 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2229 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2230 AFS_TRACE_LEVEL_VERBOSE,
2231 "AFSProcessReleaseFileExtents Increment count on volume %08lX Cnt %d\n",
2236 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2238 if( !NT_SUCCESS( ntStatus) ||
2242 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2243 AFS_TRACE_LEVEL_ERROR,
2244 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2245 ullIndex, ntStatus);
2247 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2250 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2253 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2255 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2256 AFS_TRACE_LEVEL_VERBOSE,
2257 "AFSProcessReleaseFileExtents Decrement count on volume %08lX Cnt %d\n",
2262 // Now locate the Object in this volume
2265 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2267 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2269 (AFSBTreeEntry **)&pObjectInfo);
2271 if( pObjectInfo != NULL)
2275 // Reference the node so it won't be torn down
2278 lCount = AFSObjectInfoIncrement( pObjectInfo);
2280 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2281 AFS_TRACE_LEVEL_VERBOSE,
2282 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2287 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2289 if( !NT_SUCCESS( ntStatus) ||
2290 pObjectInfo == NULL)
2293 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2294 AFS_TRACE_LEVEL_ERROR,
2295 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2298 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2301 pFcb = pObjectInfo->Fcb;
2306 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2307 AFS_TRACE_LEVEL_ERROR,
2308 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2309 pExtents->FileId.Cell,
2310 pExtents->FileId.Volume,
2311 pExtents->FileId.Vnode,
2312 pExtents->FileId.Unique);
2314 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2317 AFSLockForExtentsTrim( pFcb );
2325 // Locate an Fcb to trim down
2328 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2329 AFS_TRACE_LEVEL_VERBOSE,
2330 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2332 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2337 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2343 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2344 AFS_TRACE_LEVEL_ERROR,
2345 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2347 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2350 pObjectInfo = pFcb->ObjectInformation;
2356 // Allocate a scratch buffer to move in the extent information
2359 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2360 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2362 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2364 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2365 AFS_TRACE_LEVEL_ERROR,
2366 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2368 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2371 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2373 AFS_EXTENTS_RESULT_TAG);
2374 if (NULL == pResult)
2377 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2378 AFS_TRACE_LEVEL_ERROR,
2379 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2381 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2385 // Set up the header (for an array of one)
2387 pResult->FileCount = 1;
2388 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2389 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2392 // Setup the first (and only) file
2394 pFile = pResult->Files;
2395 pFile->FileId = pObjectInfo->FileId;
2396 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2399 // Stash away the auth group
2402 RtlZeroMemory( &stAuthGroup,
2405 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2410 if( !NT_SUCCESS( ntStatus))
2412 try_return( ntStatus);
2415 RtlCopyMemory( &pFile->AuthGroup,
2420 // Update the metadata for this call
2423 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2424 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2425 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2426 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2427 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2429 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2431 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2435 &pFile->ExtentCount,
2438 if (!NT_SUCCESS(ntStatus))
2441 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2442 AFS_TRACE_LEVEL_ERROR,
2443 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2446 try_return( ntStatus );
2449 if( pExtents->ExtentCount == 0)
2452 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2453 AFS_TRACE_LEVEL_WARNING,
2454 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2457 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2459 if( pExtents->ExtentCount > 0)
2461 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2464 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2473 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2474 AFS_TRACE_LEVEL_VERBOSE,
2475 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2476 &pFcb->NPFcb->Specific.File.ExtentsResource,
2477 PsGetCurrentThread());
2479 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2482 if( NULL != pResult &&
2483 Irp->AssociatedIrp.SystemBuffer != pResult)
2486 AFSExFreePoolWithTag(pResult, AFS_EXTENTS_RESULT_TAG);
2489 if (NT_SUCCESS(ntStatus))
2491 Irp->IoStatus.Information = ulSz;
2495 Irp->IoStatus.Information = 0;
2498 Irp->IoStatus.Status = ntStatus;
2500 if( pObjectInfo != NULL)
2503 lCount = AFSObjectInfoDecrement( pObjectInfo);
2505 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2506 AFS_TRACE_LEVEL_VERBOSE,
2507 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2517 AFSWaitForExtentMapping( AFSFcb *Fcb,
2520 NTSTATUS ntStatus = STATUS_SUCCESS;
2521 LARGE_INTEGER liTimeOut;
2522 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2527 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2529 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2533 // If this isn't the same authgroup which caused the failure
2534 // then try to request them again
2537 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2539 sizeof( GUID)) == sizeof( GUID))
2542 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2544 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2546 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2549 try_return( ntStatus);
2553 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2555 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2561 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2565 // If this isn't the same authgroup which caused the failure
2566 // or the System Process,
2567 // then try to request the extents again
2570 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2572 sizeof( GUID)) == sizeof( GUID) ||
2573 ullProcessId == (ULONGLONG)AFSSysProcess)
2576 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2578 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2580 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2583 try_return( ntStatus);
2587 if( ntStatus == STATUS_TIMEOUT)
2590 ntStatus = STATUS_SUCCESS;
2602 AFSFlushExtents( IN AFSFcb *Fcb,
2605 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2606 AFSExtent *pExtent, *pNextExtent;
2608 AFSReleaseExtentsCB *pRelease = NULL;
2610 ULONG initialDirtyCount = 0;
2611 BOOLEAN bExtentsLocked = FALSE;
2614 NTSTATUS ntStatus = STATUS_SUCCESS;
2615 LARGE_INTEGER liLastFlush;
2616 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2617 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2618 GUID *pAuthGroup = AuthGroup;
2622 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2625 // Save, then reset the flush time
2628 liLastFlush = Fcb->Specific.File.LastServerFlush;
2630 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2635 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2637 if( pAuthGroup == NULL ||
2638 RtlCompareMemory( pAuthGroup,
2639 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2640 sizeof( GUID)) == sizeof( GUID))
2643 RtlZeroMemory( &stAuthGroup,
2646 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2651 if( !NT_SUCCESS( ntStatus))
2653 try_return( ntStatus);
2656 pAuthGroup = &stAuthGroup;
2660 // Lock extents while we count and set up the array to send to
2664 AFSLockForExtentsTrim( Fcb);
2666 bExtentsLocked = TRUE;
2669 // Clear our queued flush event
2672 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2675 // Look for a start in the list to flush entries
2680 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2682 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2684 AFS_EXTENT_RELEASE_TAG);
2685 if( NULL == pRelease)
2688 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2691 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2693 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2696 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2698 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2701 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2705 // Update the metadata for this call
2708 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2709 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2710 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2711 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2712 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2716 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2719 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2721 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2724 if ( pExtent == NULL)
2730 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2732 if ( pExtent->ActiveCount > 0)
2734 pExtent = pNextExtent;
2738 AFSRemoveEntryDirtyList( Fcb, pExtent);
2740 pExtent->DirtyList.fLink = NULL;
2741 pExtent->DirtyList.bLink = NULL;
2743 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2746 // Clear the flag in advance of the write. If we do
2747 // things this was we know that the clear is
2748 // pessimistic (any write which happens from now on
2749 // will set the flag dirty again).
2752 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2754 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2756 pRelease->FileExtents[count].Length = pExtent->Size;
2757 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2758 pRelease->FileExtents[count].DirtyOffset = 0;
2759 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2760 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2763 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2765 sizeof(pExtent->MD5));
2767 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2770 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2771 AFS_TRACE_LEVEL_VERBOSE,
2772 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2774 Fcb->ObjectInformation->FileId.Cell,
2775 Fcb->ObjectInformation->FileId.Volume,
2776 Fcb->ObjectInformation->FileId.Vnode,
2777 Fcb->ObjectInformation->FileId.Unique,
2778 pExtent->FileOffset.QuadPart,
2781 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2788 pExtent = pNextExtent;
2791 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2794 // If we are done then get out
2800 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2801 AFS_TRACE_LEVEL_VERBOSE,
2802 "AFSFlushExtents No more dirty extents found\n");
2808 // Fire off the request synchronously
2811 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2813 pRelease->ExtentCount = count;
2815 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2816 AFS_TRACE_LEVEL_VERBOSE,
2817 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2818 &pNPFcb->Specific.File.ExtentsResource,
2819 PsGetCurrentThread());
2821 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2822 bExtentsLocked = FALSE;
2824 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2828 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2829 AFS_REQUEST_FLAG_SYNCHRONOUS,
2832 &Fcb->ObjectInformation->FileId,
2838 if( !NT_SUCCESS(ntStatus))
2842 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2843 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2846 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2847 AFS_TRACE_LEVEL_ERROR,
2848 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2849 Fcb->ObjectInformation->FileId.Cell,
2850 Fcb->ObjectInformation->FileId.Volume,
2851 Fcb->ObjectInformation->FileId.Vnode,
2852 Fcb->ObjectInformation->FileId.Unique,
2856 AFSLockForExtentsTrim( Fcb);
2858 bExtentsLocked = TRUE;
2863 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2865 ASSERT( lCount >= 0);
2870 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2875 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2882 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2883 AFS_TRACE_LEVEL_VERBOSE,
2884 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2885 &pNPFcb->Specific.File.ExtentsResource,
2886 PsGetCurrentThread());
2888 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2893 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
2901 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2903 IN BOOLEAN bReleaseAll)
2905 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2908 AFSReleaseExtentsCB *pRelease = NULL;
2910 ULONG initialDirtyCount = 0;
2911 BOOLEAN bExtentsLocked = FALSE;
2914 NTSTATUS ntStatus = STATUS_SUCCESS;
2915 LARGE_INTEGER liLastFlush;
2916 ULONG ulRemainingExtentLength = 0;
2917 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2918 GUID *pAuthGroup = AuthGroup;
2922 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2925 // Save, then reset the flush time
2928 liLastFlush = Fcb->Specific.File.LastServerFlush;
2930 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2935 if( pAuthGroup == NULL ||
2936 RtlCompareMemory( pAuthGroup,
2937 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2938 sizeof( GUID)) == sizeof( GUID))
2941 RtlZeroMemory( &stAuthGroup,
2944 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2949 if( !NT_SUCCESS( ntStatus))
2951 try_return( ntStatus);
2954 pAuthGroup = &stAuthGroup;
2958 // Look for a start in the list to flush entries
2963 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2965 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2967 AFS_EXTENT_RELEASE_TAG);
2968 if( NULL == pRelease)
2971 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2974 if( Fcb->OpenHandleCount > 0 &&
2979 // Don't release everything ...
2982 ulRemainingExtentLength = 1024;
2985 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2988 AFSLockForExtentsTrim( Fcb);
2990 bExtentsLocked = TRUE;
2992 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2995 // Update the metadata for this call
2998 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2999 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3000 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3001 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3002 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3006 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3008 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3009 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3012 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3016 if( pExtent->ActiveCount > 0)
3022 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3024 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3025 AFS_TRACE_LEVEL_VERBOSE,
3026 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3028 Fcb->ObjectInformation->FileId.Cell,
3029 Fcb->ObjectInformation->FileId.Volume,
3030 Fcb->ObjectInformation->FileId.Vnode,
3031 Fcb->ObjectInformation->FileId.Unique,
3032 pExtent->FileOffset.QuadPart,
3035 pRelease->FileExtents[count].Length = pExtent->Size;
3036 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3037 pRelease->FileExtents[count].DirtyOffset = 0;
3038 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3039 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3042 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3044 sizeof(pExtent->MD5));
3046 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3049 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3052 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3055 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3058 AFSRemoveEntryDirtyList( Fcb,
3061 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3063 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3066 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3076 // If we are done then get out
3082 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3083 AFS_TRACE_LEVEL_VERBOSE,
3084 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3090 // Fire off the request synchronously
3093 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3095 pRelease->ExtentCount = count;
3098 // Drop the extents lock for the duration of the call to
3099 // the network. We have pinned the extents so, even
3100 // though we might get extents added during this period,
3101 // but none will be removed. Hence we can carry on from
3105 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3106 AFS_TRACE_LEVEL_VERBOSE,
3107 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3108 &pNPFcb->Specific.File.ExtentsResource,
3109 PsGetCurrentThread());
3111 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3112 bExtentsLocked = FALSE;
3114 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3115 AFS_REQUEST_FLAG_SYNCHRONOUS,
3118 &Fcb->ObjectInformation->FileId,
3124 if( !NT_SUCCESS(ntStatus))
3128 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3129 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3132 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3133 AFS_TRACE_LEVEL_ERROR,
3134 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3135 Fcb->ObjectInformation->FileId.Cell,
3136 Fcb->ObjectInformation->FileId.Volume,
3137 Fcb->ObjectInformation->FileId.Vnode,
3138 Fcb->ObjectInformation->FileId.Unique,
3148 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3149 AFS_TRACE_LEVEL_VERBOSE,
3150 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3151 &pNPFcb->Specific.File.ExtentsResource,
3152 PsGetCurrentThread());
3154 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3159 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3167 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3170 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3173 AFSReleaseExtentsCB *pRelease = NULL;
3175 ULONG initialDirtyCount = 0;
3176 BOOLEAN bExtentsLocked = FALSE;
3179 NTSTATUS ntStatus = STATUS_SUCCESS;
3180 LARGE_INTEGER liLastFlush;
3181 ULONG ulRemainingExtentLength = 0;
3182 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3183 GUID *pAuthGroup = AuthGroup;
3186 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3189 // Save, then reset the flush time
3192 liLastFlush = Fcb->Specific.File.LastServerFlush;
3194 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3199 if( pAuthGroup == NULL ||
3200 RtlCompareMemory( pAuthGroup,
3201 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3202 sizeof( GUID)) == sizeof( GUID))
3205 RtlZeroMemory( &stAuthGroup,
3208 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3213 if( !NT_SUCCESS( ntStatus))
3215 try_return( ntStatus);
3218 pAuthGroup = &stAuthGroup;
3222 // Look for a start in the list to flush entries
3227 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3229 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3231 AFS_EXTENT_RELEASE_TAG);
3232 if( NULL == pRelease)
3235 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3238 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3241 AFSLockForExtentsTrim( Fcb);
3243 bExtentsLocked = TRUE;
3245 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3248 // Update the metadata for this call
3251 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3252 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3253 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3254 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3255 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3259 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3261 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3262 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3265 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3269 if( pExtent->ActiveCount > 0 ||
3270 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3275 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3277 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3278 AFS_TRACE_LEVEL_VERBOSE,
3279 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3281 Fcb->ObjectInformation->FileId.Cell,
3282 Fcb->ObjectInformation->FileId.Volume,
3283 Fcb->ObjectInformation->FileId.Vnode,
3284 Fcb->ObjectInformation->FileId.Unique,
3285 pExtent->FileOffset.QuadPart,
3288 pRelease->FileExtents[count].Length = pExtent->Size;
3289 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3290 pRelease->FileExtents[count].DirtyOffset = 0;
3291 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3292 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3295 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3297 sizeof(pExtent->MD5));
3299 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3309 // If we are done then get out
3315 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3316 AFS_TRACE_LEVEL_VERBOSE,
3317 "AFSReleaseCleanExtents No more dirty extents found\n");
3323 // Fire off the request synchronously
3326 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3328 pRelease->ExtentCount = count;
3331 // Drop the extents lock for the duration of the call to
3332 // the network. We have pinned the extents so, even
3333 // though we might get extents added during this period,
3334 // but none will be removed. Hence we can carry on from
3338 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3339 AFS_TRACE_LEVEL_VERBOSE,
3340 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3341 &pNPFcb->Specific.File.ExtentsResource,
3342 PsGetCurrentThread());
3344 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3345 bExtentsLocked = FALSE;
3347 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3348 AFS_REQUEST_FLAG_SYNCHRONOUS,
3351 &Fcb->ObjectInformation->FileId,
3357 if( !NT_SUCCESS(ntStatus))
3361 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3362 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3365 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3366 AFS_TRACE_LEVEL_ERROR,
3367 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3368 Fcb->ObjectInformation->FileId.Cell,
3369 Fcb->ObjectInformation->FileId.Volume,
3370 Fcb->ObjectInformation->FileId.Vnode,
3371 Fcb->ObjectInformation->FileId.Unique,
3381 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3382 AFS_TRACE_LEVEL_VERBOSE,
3383 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3384 &pNPFcb->Specific.File.ExtentsResource,
3385 PsGetCurrentThread());
3387 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3392 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3400 AFSMarkDirty( IN AFSFcb *Fcb,
3401 IN AFSExtent *StartExtent,
3402 IN ULONG ExtentsCount,
3403 IN LARGE_INTEGER *StartingByte,
3404 IN BOOLEAN DerefExtents)
3407 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3408 AFSExtent *pExtent = StartExtent;
3409 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3411 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3414 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3415 AFS_TRACE_LEVEL_VERBOSE,
3416 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3417 &Fcb->NPFcb->Specific.File.ExtentsResource,
3418 PsGetCurrentThread());
3420 ASSERT( ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource));
3422 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3428 // Find the insertion point
3431 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3436 else if( StartingByte->QuadPart == 0)
3444 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3446 while( pCurrentExtent != NULL)
3449 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3450 pCurrentExtent->DirtyList.fLink == NULL)
3456 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3460 while( ulCount < ExtentsCount)
3463 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3465 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3468 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3469 AFS_TRACE_LEVEL_VERBOSE,
3470 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3471 pExtent->FileOffset.QuadPart,
3474 pExtent->DirtyList.fLink = NULL;
3475 pExtent->DirtyList.bLink = NULL;
3480 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3482 pExtent->DirtyList.bLink = NULL;
3484 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3486 pNPFcb->Specific.File.DirtyListHead = pExtent;
3488 pCurrentExtent = pExtent;
3490 bInsertHead = FALSE;
3492 else if( bInsertTail)
3495 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3498 pNPFcb->Specific.File.DirtyListHead = pExtent;
3503 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3505 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3508 pNPFcb->Specific.File.DirtyListTail = pExtent;
3513 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3515 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3517 if( pExtent->DirtyList.fLink == NULL)
3520 pNPFcb->Specific.File.DirtyListTail = pExtent;
3525 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3528 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3530 pCurrentExtent = pExtent;
3533 pExtent->Flags |= AFS_EXTENT_DIRTY;
3536 // Up the dirty count
3539 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3544 pCurrentExtent = pExtent;
3547 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3548 AFS_TRACE_LEVEL_VERBOSE,
3549 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3551 pExtent->ActiveCount);
3555 ASSERT( pExtent->ActiveCount > 0);
3556 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3559 pExtent = pNextExtent;
3564 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
3569 "EXCEPTION - AFSMarkDirty\n");
3571 AFSDumpTraceFilesFnc();
3574 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3576 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3577 AFS_TRACE_LEVEL_VERBOSE,
3578 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3579 &Fcb->NPFcb->Specific.File.ExtentsResource,
3580 PsGetCurrentThread());
3590 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3593 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3597 NextExtent(AFSExtent *Extent, ULONG SkipList)
3600 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3603 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3606 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3609 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3613 // Check the ordering of the extents lists
3615 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3617 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3619 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3621 LARGE_INTEGER lastOffset;
3623 lastOffset.QuadPart = 0;
3625 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3626 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3631 pExtent = ExtentFor(pLe, listNo);
3634 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3635 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3636 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3639 ASSERT(pLe->Flink->Blink == pLe);
3640 ASSERT(pLe->Blink->Flink == pLe);
3643 // Should follow on from previous
3645 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3646 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3649 // Should match alignment criteria
3651 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3654 // "lower" lists should be populated
3656 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3658 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3666 AFSTrimExtents( IN AFSFcb *Fcb,
3667 IN PLARGE_INTEGER FileSize)
3670 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3673 BOOLEAN locked = FALSE;
3674 NTSTATUS ntStatus = STATUS_SUCCESS;
3675 LARGE_INTEGER liAlignedOffset = {0,0};
3676 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3677 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3684 // Get an aligned offset
3687 if( FileSize != NULL)
3690 liAlignedOffset = *FileSize;
3693 if( liAlignedOffset.QuadPart > 0 &&
3694 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3698 // Align UP to the next cache block size
3701 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3705 // Ensure that no one is working with the extents and grab the
3709 AFSLockForExtentsTrim( Fcb);
3713 if( 0 == Fcb->Specific.File.ExtentCount)
3717 // Update the request extent status
3720 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3722 try_return( ntStatus = STATUS_SUCCESS);
3726 // We are truncating from a specific length in the file. If the offset
3727 // is non-zero then go find the first extent to remove
3730 if( 0 == FileSize->QuadPart)
3733 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3738 pExtent = AFSExtentForOffset( Fcb,
3742 if( NULL == pExtent)
3745 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3749 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3753 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3756 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3759 // Only trim down extents beyond the aligned offset
3764 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3767 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3770 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3773 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3777 AFSRemoveEntryDirtyList( Fcb,
3780 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3782 ASSERT(dirtyCount >= 0);
3785 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3788 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3789 AFS_TRACE_LEVEL_VERBOSE,
3790 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3792 Fcb->ObjectInformation->FileId.Cell,
3793 Fcb->ObjectInformation->FileId.Volume,
3794 Fcb->ObjectInformation->FileId.Vnode,
3795 Fcb->ObjectInformation->FileId.Unique,
3796 pExtent->FileOffset.QuadPart,
3799 ASSERT( pExtent->ActiveCount == 0);
3807 // Update the request extent status
3810 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3817 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3818 AFS_TRACE_LEVEL_VERBOSE,
3819 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3820 &Fcb->NPFcb->Specific.File.ExtentsResource,
3821 PsGetCurrentThread());
3823 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3831 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3833 IN AFSFileExtentCB *Result)
3836 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3839 AFSFileExtentCB *pFileExtents = Result;
3840 NTSTATUS ntStatus = STATUS_SUCCESS;
3841 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3842 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3848 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3850 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3854 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3857 // Only trim down extents beyond the aligned offset
3862 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3865 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3868 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3871 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3876 AFSRemoveEntryDirtyList( Fcb,
3879 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3881 ASSERT( dirtyCount >= 0);
3885 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3889 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3890 AFS_TRACE_LEVEL_VERBOSE,
3891 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3893 Fcb->ObjectInformation->FileId.Cell,
3894 Fcb->ObjectInformation->FileId.Volume,
3895 Fcb->ObjectInformation->FileId.Vnode,
3896 Fcb->ObjectInformation->FileId.Unique,
3897 pExtent->FileOffset.QuadPart,
3900 ASSERT( pExtent->ActiveCount == 0);
3906 // Next extent we are looking for
3916 // Update the request extent status
3919 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3926 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3927 IN ULONG ExtentsCount)
3930 AFSExtent *pExtent = StartExtent;
3931 AFSExtent *pNextExtent;
3935 while( ulCount < ExtentsCount)
3938 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3940 lCount = InterlockedIncrement( &pExtent->ActiveCount);
3942 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3943 AFS_TRACE_LEVEL_VERBOSE,
3944 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
3948 pExtent = pNextExtent;
3957 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
3958 IN ULONG ExtentsCount)
3961 AFSExtent *pExtent = StartExtent;
3962 AFSExtent *pNextExtent;
3966 while( ulCount < ExtentsCount)
3969 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3971 ASSERT( pExtent->ActiveCount > 0);
3973 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3975 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3976 AFS_TRACE_LEVEL_VERBOSE,
3977 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
3981 pExtent = pNextExtent;
3990 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
3991 IN AFSExtent *Extent)
3994 if( Extent->DirtyList.fLink == NULL)
3997 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
3999 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
4002 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
4008 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
4011 if( Extent->DirtyList.bLink == NULL)
4014 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
4016 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
4019 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
4025 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
4033 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
4034 AFSByteRange ** pByteRangeList)
4037 ULONG ulByteRangeMax;
4038 ULONG ulByteRangeCount = 0;
4039 AFSByteRange *ByteRangeList;
4040 AFSExtent *pExtent, *pNextExtent;
4042 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
4044 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
4046 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
4047 ulByteRangeMax * sizeof( AFSByteRange),
4050 if ( ByteRangeList == NULL)
4053 (*pByteRangeList) = NULL;
4055 try_return( ulByteRangeCount = DWORD_MAX);
4058 RtlZeroMemory( ByteRangeList,
4059 ulByteRangeMax * sizeof( AFSByteRange));
4062 // The for loop populates the ByteRangeList entries with values that are
4063 // the gaps in the DirtyList. In other words, if a range is not present
4064 // in the DirtyList it will be represented in the ByteRangeList array.
4067 for ( ulByteRangeCount = 0,
4068 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4069 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4070 pExtent = pNextExtent)
4073 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4076 // The first time the for() is entered the ulByteRangeCount will be zero and
4077 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4078 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4079 // FileOffset of the Extent.
4081 // Future passes through the loop behave in a similar fashion but
4082 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4085 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4088 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4089 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4095 // Having processed the current dirty extent, the following while loop
4096 // searches for the next clean gap between dirty extents.
4099 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4102 pExtent = pNextExtent;
4104 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4108 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4109 // The Length is left at zero and will be assigned either when the for loop continues or
4110 // when the for loop exits.
4113 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4117 // Assign the Length of the final clean range to match the file length.
4120 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4121 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4123 (*pByteRangeList) = ByteRangeList;
4127 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4129 return ulByteRangeCount;
4134 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4135 IN AFSExtent *StartExtent,
4136 IN ULONG ExtentsCount,
4137 IN void *SystemBuffer,
4138 IN LARGE_INTEGER *ByteOffset,
4142 NTSTATUS ntStatus = STATUS_SUCCESS;
4143 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4144 AFSExtent *pExtent = StartExtent;
4145 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4147 char *pCurrentBuffer = (char *)SystemBuffer;
4148 char *pMD5Buffer = NULL;
4149 ULONG ulCurrentLen = 0;
4150 void *pExtentBuffer = NULL;
4151 LARGE_INTEGER liByteOffset;
4152 ULONG ulBytesRead = 0;
4157 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4158 AFS_TRACE_LEVEL_VERBOSE,
4159 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4160 &Fcb->NPFcb->Specific.File.ExtentsResource,
4161 PsGetCurrentThread());
4163 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4167 liByteOffset.QuadPart = ByteOffset->QuadPart;
4169 while( ulCount < ExtentsCount)
4172 RtlZeroMemory( pExtent->MD5,
4173 sizeof( pExtent->MD5));
4175 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4177 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4178 ByteCount < pExtent->Size)
4181 if( pExtentBuffer == NULL)
4184 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4186 AFS_GENERIC_MEMORY_9_TAG);
4188 if( pExtentBuffer == NULL)
4195 RtlZeroMemory( pExtentBuffer,
4198 RtlCopyMemory( pExtentBuffer,
4202 pMD5Buffer = (char *)pExtentBuffer;
4204 ulCurrentLen = ByteCount;
4206 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4209 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4211 AFS_GENERIC_MEMORY_10_TAG);
4213 if( pExtentBuffer == NULL)
4219 RtlZeroMemory( pExtentBuffer,
4222 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4226 RtlCopyMemory( pExtentBuffer,
4227 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4230 ASSERT( pExtent->CacheOffset.HighPart == 0);
4231 RtlCopyMemory( pExtentBuffer,
4232 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4236 ulBytesRead = pExtent->Size;
4241 ntStatus = AFSReadCacheFile( pExtentBuffer,
4242 &pExtent->CacheOffset,
4246 if( !NT_SUCCESS( ntStatus))
4253 pMD5Buffer = (char *)pExtentBuffer;
4255 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4257 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4264 ulCurrentLen = pExtent->Size;
4266 pMD5Buffer = pCurrentBuffer;
4269 AFSGenerateMD5( pMD5Buffer,
4273 pExtent = pNextExtent;
4277 ByteCount -= ulCurrentLen;
4279 pCurrentBuffer += ulCurrentLen;
4281 liByteOffset.QuadPart += ulCurrentLen;
4284 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4285 AFS_TRACE_LEVEL_VERBOSE,
4286 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4287 &Fcb->NPFcb->Specific.File.ExtentsResource,
4288 PsGetCurrentThread());
4291 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
4296 "EXCEPTION - AFSSetupMD5Hash\n");
4298 AFSDumpTraceFilesFnc();
4301 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4303 if( pExtentBuffer != NULL)
4306 AFSExFreePoolWithTag( pExtentBuffer, AFS_GENERIC_MEMORY_9_TAG);